NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

expandablemenu.py (13471B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\expandablemenu.py
      2 import random
      3 import blue
      4 import mathext
      5 import uthread
      6 from carbon.client.script.environment.AudioUtil import PlaySound
      7 from carbonui import uiconst
      8 from carbonui.primitives.container import Container
      9 from carbonui.primitives.fill import Fill
     10 from eve.client.script.ui.control import eveIcon, eveLabel
     11 from eve.client.script.ui.control.themeColored import FillThemeColored
     12 
     13 class ExpandableMenuContainer(Container):
     14     __guid__ = 'xtriui.ExpandableMenuContainer'
     15     sizecallback = None
     16     multipleExpanded = False
     17     headerApperance = 'default'
     18 
     19     def _OnClose(self):
     20         self.sizecallback = None
     21         self.sr.menus = None
     22         self.sr.menusByLabel = None
     23         self.sr.menusByName = {}
     24 
     25     def Load(self, menuData, prefsKey = None):
     26         self.sr.menus = []
     27         self.sr.menusByLabel = {}
     28         self.sr.menusByName = {}
     29         self.singleton = bool(len(menuData) == 1)
     30         for data in menuData:
     31             menuName = data[9] if len(data) > 9 else None
     32             em = ExpandableMenu(parent=self, align=uiconst.TOTOP, height=18, state=uiconst.UI_NORMAL, name=data[9] if len(data) > 9 else data[0], padBottom=4)
     33             em.prefsKey = prefsKey
     34             self.sr.menus.append(em)
     35             self.sr.menusByLabel[data[0]] = em
     36             if menuName:
     37                 self.sr.menusByName[menuName] = em
     38             em.Load(*data[:9])
     39 
     40         if prefsKey and not self.multipleExpanded:
     41             active = settings.user.ui.Get('expandableMenu', {}).get(prefsKey, None)
     42             if active:
     43                 for each in self.children:
     44                     if each.name == active:
     45                         uthread.new(each.Expand)
     46 
     47             else:
     48                 uthread.new(self.children[0].Expand)
     49 
     50     def AutoCollapseIfNeeded(self, ignoreMenu = None):
     51         if getattr(self, '_autoCollapsing', False):
     52             return
     53         self._autoCollapsing = True
     54         blue.pyos.synchro.SleepWallclock(10)
     55         expanded = []
     56         totalHeight = 0
     57         for each in self.children:
     58             if not each.display:
     59                 continue
     60             totalHeight += each.height + each.padTop + each.padBottom
     61             if isinstance(each, ExpandableMenu) and each._expanded and each is not ignoreMenu:
     62                 expanded.append(each)
     63 
     64         pl, pt, pw, ph = self.GetAbsolute()
     65         collapseMenus = []
     66         random.shuffle(expanded)
     67         while totalHeight > ph and expanded:
     68             collapse = expanded.pop()
     69             collapseMenus.append(collapse)
     70             totalHeight -= collapse.height
     71 
     72         for each in collapseMenus:
     73             each.Collapse()
     74 
     75         self._autoCollapsing = False
     76 
     77     def ExpandMenuByLabel(self, label):
     78         if label in self.sr.menusByLabel:
     79             self.sr.menusByLabel[label].Expand()
     80 
     81     def ShowMenuByLabel(self, label):
     82         return self._ChangeDisplayOfMenu(label, displayOn=True)
     83 
     84     def HideMenuByLabel(self, label):
     85         return self._ChangeDisplayOfMenu(label, displayOn=False)
     86 
     87     def IsMenuExpanded(self, menuName):
     88         if menuName in self.sr.menusByName:
     89             menu = self.sr.menusByName[menuName]
     90             return menu.IsExpanded()
     91         return False
     92 
     93     def _ChangeDisplayOfMenu(self, label, displayOn = True):
     94         panel = self.sr.menusByLabel.get(label)
     95         if panel:
     96             panel.display = displayOn
     97 
     98     def _OnSizeChange_NoBlock(self, *args, **kwds):
     99         Container._OnSizeChange_NoBlock(self, *args, **kwds)
    100         for each in self.children:
    101             if not each._changing and each._expanded:
    102                 endHeight = each.GetExpandedHeight()
    103                 each.height = endHeight
    104                 each.sr.content.height = endHeight - each.GetCollapsedHeight() - each.sr.content.top
    105 
    106 
    107 class ExpandableMenu(Container):
    108     __guid__ = 'xtriui.ExpandableMenu'
    109     default_name = 'ExpandableMenu'
    110     default_clipChildren = True
    111 
    112     def AddHeaderContent(self, content, hideOnMaximize = 1):
    113         self._hideHeaderContentOnMaximize = hideOnMaximize
    114         self.sr.headerContent = content
    115         self.sr.headerParent.children.append(content)
    116         if self.sr.content.state == uiconst.UI_HIDDEN:
    117             self.sr.headerContent.opacity = 1.0
    118         elif hideOnMaximize:
    119             self.sr.headerContent.opacity = 0.0
    120 
    121     def Load(self, label, content, callback, dropCallback = None, maxHeight = None, headerContent = None, hideHeaderContentOnMaximize = 1, expandedByDefault = 1, uniqueUiName = None):
    122         self._changing = False
    123         self._break = False
    124         self._expanded = False
    125         self._maxHeight = maxHeight
    126         self._loaded = False
    127         self._lastExpandedHeight = None
    128         self._hideHeaderContentOnMaximize = hideHeaderContentOnMaximize
    129         self.uniqueUiName = uniqueUiName
    130         headerParent = Container(parent=self, name='headerParent', align=uiconst.TOTOP, state=uiconst.UI_PICKCHILDREN, height=24, padBottom=-1)
    131         self.sr.headerParent = headerParent
    132         contentParent = Container(parent=self, name='contentParent', align=uiconst.TOALL, state=uiconst.UI_NORMAL, pos=(0, 1, 0, 1))
    133         self.sr.content = content
    134         self.sr.callback = callback
    135         if dropCallback:
    136             self.OnDropData = dropCallback
    137         t = eveLabel.EveLabelMedium(text=label, parent=headerParent, state=uiconst.UI_DISABLED, left=22, align=uiconst.CENTERLEFT, idx=0)
    138         self.sr.headerLabel = t
    139         self._headerLabel = label
    140         expander = eveIcon.Icon(icon='ui_38_16_228', align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, left=4, top=1)
    141         expander.SetAlpha(0.8)
    142         headerParent.children.append(expander)
    143         self.sr.backgroundFrame = Fill(bgParent=headerParent, opacity=0.05)
    144         self.sr.expanderIcon = expander
    145         headerParent.height = max(20, t.textheight + 2)
    146         self._minHeight = headerParent.height
    147         if content:
    148             contentParent.children.append(content)
    149         if headerContent:
    150             self.AddHeaderContent(headerContent, hideHeaderContentOnMaximize)
    151         if self.parent.multipleExpanded:
    152             current = settings.user.ui.Get('multipleExpandableMenu', {})
    153             if self.prefsKey in current and self.name in current[self.prefsKey]:
    154                 lastHeight, expanded = current[self.prefsKey][self.name]
    155                 if expanded:
    156                     uthread.new(self.Expand, lastHeight, startup=True)
    157                     return
    158             elif expandedByDefault:
    159                 uthread.new(self.Expand, startup=True)
    160                 return
    161         self.Collapse(startup=1)
    162         self._loaded = True
    163 
    164     def SetHeader(self, newlabel, addon = 0, hint = None):
    165         if addon:
    166             newlabel = self._headerLabel + newlabel
    167         self.sr.headerLabel.text = '<b>' + newlabel + '</b>'
    168         if hint:
    169             self.sr.headerLabel.state = uiconst.UI_NORMAL
    170             self.sr.headerLabel.hint = hint
    171             self.sr.headerLabel.OnClick = self.OnClick
    172         else:
    173             self.sr.headerLabel.state = uiconst.UI_DISABLED
    174 
    175     def OnClick(self, *args):
    176         if not self._changing:
    177             if self._expanded:
    178                 PlaySound(uiconst.SOUND_COLLAPSE)
    179                 self.Collapse()
    180             else:
    181                 PlaySound(uiconst.SOUND_EXPAND)
    182                 self.Expand()
    183 
    184     def OnMouseEnter(self, *args):
    185         PlaySound(uiconst.SOUND_BUTTON_HOVER)
    186 
    187     def IsExpanded(self):
    188         return self._expanded
    189 
    190     def Expand(self, lastHeight = None, time = None, startup = False, *args):
    191         if self._changing:
    192             return
    193         self._changing = True
    194         if not self.parent.multipleExpanded:
    195             for each in self.parent.children[:]:
    196                 if isinstance(each, ExpandableMenu) and each is not self:
    197                     uthread.new(each.Collapse)
    198 
    199         if self.sr.callback:
    200             self.sr.callback(not self._loaded)
    201         self.sr.content.align = uiconst.TOTOP
    202         self._loaded = True
    203         sh = self.height
    204         endHeight = self.GetExpandedHeight()
    205         self.sr.expanderIcon.LoadIcon('ui_38_16_229')
    206         self.sr.content.state = uiconst.UI_NORMAL
    207         self.sr.content.height = endHeight - self.GetCollapsedHeight() - self.sr.content.top
    208         if time == -1:
    209             self.height = endHeight
    210             self.sr.content.opacity = 1.0
    211             if self.parent.sizecallback:
    212                 self.parent.sizecallback(self)
    213         else:
    214             start, ndt = blue.os.GetWallclockTime(), 0.0
    215             time = time or 250.0
    216             while ndt != 1.0:
    217                 ndt = max(ndt, min(blue.os.TimeDiffInMs(start, blue.os.GetWallclockTime()) / time, 1.0))
    218                 self.height = sh + int((endHeight - sh) * ndt)
    219                 self.sr.content.opacity = 1.0 * ndt
    220                 if self.sr.headerContent and self._hideHeaderContentOnMaximize:
    221                     self.sr.headerContent.opacity = 1.0 - 1.0 * ndt
    222                 if self.parent.sizecallback:
    223                     self.parent.sizecallback(self)
    224                 blue.pyos.synchro.Yield()
    225                 if self.destroyed or self._break:
    226                     break
    227 
    228         if self.destroyed:
    229             return
    230         self.height = endHeight
    231         self._changing = False
    232         self._break = False
    233         self._expanded = True
    234         self._lastExpandedHeight = self.height
    235         self.sr.content.opacity = 1.0
    236         if self.sr.headerContent and self._hideHeaderContentOnMaximize:
    237             self.sr.headerContent.opacity = 0.0
    238         if startup:
    239             uthread.new(self.parent.AutoCollapseIfNeeded)
    240         else:
    241             uthread.new(self.parent.AutoCollapseIfNeeded, ignoreMenu=self)
    242         self.Register()
    243         if not startup:
    244             sm.ScatterEvent('OnExpandableMenuItemExpanded', self.name)
    245 
    246     def Register(self):
    247         if self.prefsKey:
    248             if self.parent.multipleExpanded:
    249                 current = settings.user.ui.Get('multipleExpandableMenu', {})
    250                 if self.prefsKey not in current:
    251                     current[self.prefsKey] = {}
    252                 current[self.prefsKey][self.name] = (self._lastExpandedHeight, self._expanded)
    253                 settings.user.ui.Set('multipleExpandableMenu', current)
    254             else:
    255                 current = settings.user.ui.Get('expandableMenu', {})
    256                 if self._expanded:
    257                     current[self.prefsKey] = self.name
    258                 elif self.prefsKey in current and current[self.prefsKey] == self.name:
    259                     del current[self.prefsKey]
    260                 settings.user.ui.Set('expandableMenu', current)
    261 
    262     def Collapse(self, startup = 0):
    263         if self._changing:
    264             self._break = True
    265         self._changing = True
    266         sh = self.height
    267         endHeight = self.GetCollapsedHeight()
    268         pl, pt, pw, ph = self.parent.GetAbsolute()
    269         self.sr.expanderIcon.LoadIcon('ui_38_16_228')
    270         if not startup:
    271             if self.sr.headerContent:
    272                 sho = self.sr.headerContent.opacity
    273             start, ndt = blue.os.GetWallclockTime(), 0.0
    274             time = 250.0
    275             while ndt != 1.0:
    276                 ndt = max(ndt, min(blue.os.TimeDiffInMs(start, blue.os.GetWallclockTime()) / time, 1.0))
    277                 self.height = sh - int((sh - endHeight) * ndt)
    278                 self.sr.content.opacity = 1.0 - 1.0 * ndt
    279                 if self.sr.headerContent and self._hideHeaderContentOnMaximize:
    280                     self.sr.headerContent.opacity = mathext.lerp(sho, 1.0, ndt)
    281                 if self.parent.sizecallback:
    282                     self.parent.sizecallback(self)
    283                 blue.pyos.synchro.Yield()
    284                 if self.destroyed or self._break:
    285                     break
    286 
    287         if self.destroyed:
    288             return
    289         self._changing = False
    290         self._break = False
    291         self.height = endHeight
    292         self._expanded = False
    293         self.sr.content.state = uiconst.UI_HIDDEN
    294         self.sr.content.opacity = 0.0
    295         if self.sr.headerContent:
    296             self.sr.headerContent.opacity = 1.0
    297         if not startup:
    298             self.Register()
    299             sm.ScatterEvent('OnExpandableMenuItemCollapsed', self.name)
    300 
    301     def GetCollapsedHeight(self):
    302         return self._minHeight
    303 
    304     def GetExpandedHeight(self):
    305         endHeight = self.GetMaxHeight()
    306         if not endHeight and not self.parent.multipleExpanded:
    307             pw, ph = self.parent.GetAbsoluteSize()
    308             total = 0
    309             for each in self.parent.children:
    310                 if isinstance(each, ExpandableMenu):
    311                     total += each.GetCollapsedHeight()
    312 
    313             endHeight = ph - total
    314         return endHeight
    315 
    316     def GetMaxHeight(self):
    317         if hasattr(self.sr.content, 'GetTotalHeight'):
    318             totalHeight = self.sr.content.top + self.sr.content.GetTotalHeight() + self.GetCollapsedHeight() + 5
    319             if self._maxHeight:
    320                 return min(totalHeight, self._maxHeight)
    321             return totalHeight
    322         if hasattr(self.sr.content, 'GetContentHeight'):
    323             totalHeight = self.sr.content.top + self.sr.content.GetContentHeight() + self.GetCollapsedHeight() + 5
    324             if self._maxHeight:
    325                 return min(totalHeight, self._maxHeight)
    326             return totalHeight
    327         return self._maxHeight