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

historyBar.py (15952B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\historyBar.py
      2 import carbonui.const as uiconst
      3 import uthread
      4 from carbon.client.script.environment.AudioUtil import PlaySound
      5 from carbon.common.script.util import timerstuff
      6 from carbonui.primitives.container import Container
      7 from carbonui.primitives.fill import Fill
      8 from carbonui.primitives.frame import Frame
      9 from carbonui.primitives.sprite import Sprite
     10 from carbonui.uicore import uicore
     11 from carbonui.control.buttonIcon import ButtonIcon
     12 from eveexceptions import ExceptionEater
     13 from menu import MenuLabel
     14 from signals import Signal
     15 from signals.signalUtil import ChangeSignalConnect
     16 UPDATE_CODE_INIT = 1
     17 UPDATE_CODE_ADD = 2
     18 UPDATE_CODE_REMOVE = 3
     19 UPDATE_CODE_CLEAR = 4
     20 UPDATE_CODE_SELECTED = 5
     21 UPDATE_CODE_CORRECTION = 6
     22 
     23 class HistoryBar(Container):
     24     default_name = 'historyBar'
     25     default_left = 0
     26     default_top = 0
     27     default_width = 400
     28     default_height = 17
     29     default_align = uiconst.CENTER
     30     default_btnSize = 9
     31     default_bitWidth = 7
     32     default_bitGap = 3
     33 
     34     def ApplyAttributes(self, attributes):
     35         Container.ApplyAttributes(self, attributes)
     36         self.bitChangeCheck = attributes.bitChangeCheck
     37         self.btnSize = attributes.get('btnSize', self.default_btnSize)
     38         self.callback = attributes.callback
     39         self.bitHintFunc = attributes.bitHintFunc
     40         self.isAllowedToLoadFunc = attributes.isAllowedToLoadFunc
     41         self.historyController = attributes.get('historyController', HistoryController())
     42         self.bitHeight = attributes.get('bitHeight', self.height - 6)
     43         self.bitWidth = attributes.get('bitWidth', self.default_bitWidth)
     44         self.bitGap = attributes.get('bitGap', self.default_bitGap)
     45         self._scrolling = False
     46         self._mouseOffset = 0
     47         self.ConstructButtons()
     48         self.ConstructBar()
     49         self.UpdateHistory(updateCode=UPDATE_CODE_INIT)
     50         self.ChangeSignalConnection()
     51 
     52     def ChangeSignalConnection(self, connect = True):
     53         signalAndCallback = [(self.historyController.on_history_updated, self.OnHistoryUpdated), (self.historyController.on_history_correction_triggered, self.OnCorrectPosition)]
     54         ChangeSignalConnect(signalAndCallback, connect)
     55 
     56     def OnHistoryUpdated(self, updateCode = None):
     57         self.UpdateHistory(updateCode=updateCode)
     58 
     59     def ConstructButtons(self):
     60         fullSize = self.btnSize + 10
     61         leftBtnCont = Container(name='leftBtnCont', parent=self, align=uiconst.TOLEFT, width=fullSize, opacity=0.75)
     62         self.leftBtn = ButtonIcon(name='leftBtn', parent=leftBtnCont, align=uiconst.CENTERRIGHT, width=fullSize, height=fullSize, iconSize=self.btnSize, texturePath='res:/ui/texture/shared/arrows/arrowLeft.png', func=self.OnButtonClicked, args=(-1,), iconClass=Sprite)
     63         rightBtnCont = Container(name='leftBtnCont', parent=self, align=uiconst.TORIGHT, width=fullSize, opacity=0.75)
     64         self.rightBtn = ButtonIcon(name='rightBtn', parent=rightBtnCont, align=uiconst.CENTERLEFT, width=fullSize, height=fullSize, iconSize=self.btnSize, texturePath='res:/ui/texture/shared/arrows/arrowRight.png', func=self.OnButtonClicked, args=(1,), iconClass=Sprite)
     65 
     66     def ConstructBar(self):
     67         self.mainPar = Container(name='mainPar', parent=self, clipChildren=True, state=uiconst.UI_NORMAL)
     68         Frame(parent=self.mainPar, color=(0.5, 0.5, 0.5, 0.2))
     69         Fill(parent=self.mainPar, color=(0.0, 0.0, 0.0, 0.25))
     70         self.mainPar.GetMenu = self.GetHistoryBarMenu
     71         self.scrollHandleCont = Container(name='scrollHandleCont', parent=self.mainPar, align=uiconst.CENTERLEFT, height=self.height)
     72         self.bitParent = Container(name='bitParent', parent=self.mainPar, align=uiconst.CENTERLEFT, height=self.height - 6)
     73         self.bits = []
     74         self.scrollHandle = Container(parent=self.scrollHandleCont, align=uiconst.TOPLEFT, pos=(0,
     75          1,
     76          self.bitWidth,
     77          self.height - 2), color=(1.0, 1.0, 1.0, 1.0), state=uiconst.UI_NORMAL)
     78         self.scrollHandle.cursor = uiconst.UICURSOR_POINTER_MENU
     79         Fill(parent=self.scrollHandle, color=(1.0, 1.0, 1.0, 1.0))
     80         self.scrollHandle.OnMouseDown = self.SH_MouseDown
     81         self.scrollHandle.OnMouseUp = self.SH_MouseUp
     82         self.scrollHandle.GetMenu = self.GetScrollHandleMenu
     83 
     84     def UpdateHistory(self, updateCode = None):
     85         history = self.historyController.GetHistory()
     86         if history is not None:
     87             self.LoadHistory(len(history), updateCode)
     88 
     89     def GetCurrentIndexAndMaxIndex(self):
     90         lastLitIdx = self.historyController.lastLitIdx
     91         if lastLitIdx and self.bits:
     92             currentIndex = min(lastLitIdx, len(self.bits) - 1)
     93         else:
     94             currentIndex = 0
     95         return (currentIndex, len(self.bits) - 1)
     96 
     97     def OnButtonClicked(self, direction, *args):
     98         PlaySound(uiconst.SOUND_BUTTON_CLICK)
     99         if self.bitChangeCheck and not self.bitChangeCheck():
    100             return
    101         self.ButtonScroll(direction)
    102 
    103     def ButtonScroll(self, direction):
    104         currentIndex, maxIndex = self.GetCurrentIndexAndMaxIndex()
    105         if currentIndex + direction > maxIndex:
    106             return
    107         newIndex = max(0, min(len(self.bits), direction + currentIndex))
    108         self.historyController.lastLitIdx = newIndex
    109         self.SettleScrollHandle(UPDATE_CODE_SELECTED)
    110         self.UpdateBitsState()
    111         self.UpdatePosition()
    112 
    113     def LoadHistory(self, historyLength, updateCode = None):
    114         self.bitParent.Flush()
    115         self.bits = []
    116         litBit = None
    117         widthForBit = self.bitWidth + self.bitGap
    118         for i in xrange(historyLength):
    119             bit = HistoryBit(bitIdx=i, parent=self.bitParent, name='bit_%s' % i, pos=(i * widthForBit,
    120              0,
    121              widthForBit,
    122              self.bitHeight), callback=self.OnClickBit, bitGap=self.bitGap)
    123             bit.GetMenu = (self.GetBitMenu, i)
    124             bit.GetHint = lambda bitIdx = i: self.GetBitHint(bitIdx)
    125             if i == self.historyController.lastLoadIdx:
    126                 litBit = bit
    127             self.bits.append(bit)
    128 
    129         self.historyController.lastLoadIdx = None
    130         self.UpdateContentWidth()
    131         if litBit is None:
    132             initing = updateCode == UPDATE_CODE_INIT
    133             self.ScrollTo(1.0, initing=initing)
    134         else:
    135             self.historyController.lastLitIdx = litBit.bitIdx
    136             self.SettleScrollHandle(updateCode=updateCode)
    137             self.UpdateBitsState()
    138         self.UpdatePosition()
    139 
    140     def OnClickBit(self, bit, *args):
    141         PlaySound(uiconst.SOUND_BUTTON_CLICK)
    142         if self.bitChangeCheck and not self.bitChangeCheck():
    143             return
    144         self.historyController.lastLitIdx = bit.bitIdx
    145         self.SettleScrollHandle(UPDATE_CODE_SELECTED)
    146         self.UpdateBitsState()
    147 
    148     def GetBitHint(self, bitIdx):
    149         if self.bitHintFunc:
    150             bitData = self.historyController.GetHistoryFromIdx(bitIdx)
    151             return self.bitHintFunc(bitData)
    152 
    153     def UpdateContentWidth(self):
    154         widthForBit = self.bitWidth + self.bitGap
    155         self.bitParent.width = len(self.bits) * widthForBit + self.bitGap
    156         self.scrollHandleCont.width = self.bitParent.width
    157 
    158     def ScrollTo(self, portion, initing = False):
    159         l, t, w, h = self.mainPar.GetAbsolute()
    160         self.scrollHandle.left = int((self.bitParent.width - self.scrollHandle.width) * portion) + self.bitGap
    161         self.UpdatePosition()
    162         updateCode = UPDATE_CODE_INIT if initing else None
    163         self.SettleScrollHandle(updateCode)
    164 
    165     def SH_MouseDown(self, *args):
    166         if self.bitChangeCheck and not self.bitChangeCheck():
    167             return
    168         l, t, w, h = self.scrollHandle.GetAbsolute()
    169         self._mouseOffset = uicore.uilib.x - l
    170         self._scrolling = True
    171         self.scrollTimer = timerstuff.AutoTimer(5, self.DragScroll)
    172 
    173     def SH_MouseUp(self, *args):
    174         if self.bitChangeCheck and not self.bitChangeCheck():
    175             return
    176         self._scrolling = False
    177         self._mouseOffset = 0
    178         self.scrollTimer = None
    179         self.SettleScrollHandle(UPDATE_CODE_SELECTED)
    180 
    181     def SettleScrollHandle(self, updateCode = None):
    182         initing = updateCode == UPDATE_CODE_INIT
    183         lastLitIdx = self.historyController.lastLitIdx
    184         if lastLitIdx is not None:
    185             lastLit = self.bits[lastLitIdx]
    186             if not initing:
    187                 if updateCode == UPDATE_CODE_SELECTED and self.callback and self.isAllowedToLoadFunc:
    188                     currentBitData = self.historyController.GetHistoryFromIdx(self.historyController.currentIndex)
    189                     toBeLoaded = self.historyController.GetHistoryFromIdx(lastLitIdx)
    190                     if not self.isAllowedToLoadFunc(currentBitData, toBeLoaded):
    191                         return
    192                 self.historyController.currentIndex = lastLitIdx
    193                 self.historyController.lastLoadIdx = lastLitIdx
    194                 if self.callback:
    195                     historyBitData = self.historyController.GetHistoryFromLastLit()
    196                     uthread.new(self.callback, historyBitData, updateCode)
    197             self.scrollHandle.left = lastLit.left + self.bitGap
    198         else:
    199             self.scrollHandle.left = -2
    200         self.leftBtn.Enable()
    201         self.rightBtn.Enable()
    202         self.scrollHandle.Show()
    203         if self.historyController.IsOnFirstBit():
    204             self.leftBtn.Disable()
    205             self.leftBtn.UpdateIconState()
    206         if self.historyController.IsOnLastBit():
    207             self.rightBtn.Disable()
    208             self.rightBtn.UpdateIconState()
    209         if self.historyController.lastLitIdx is None:
    210             self.leftBtn.Disable()
    211             self.rightBtn.Disable()
    212             self.scrollHandle.Hide()
    213 
    214     def DragScroll(self, *args):
    215         l, t, w, h = self.mainPar.GetAbsolute()
    216         bl, bt, bw, bh = self.bitParent.GetAbsolute()
    217         self.scrollHandle.left = min(bw - self.scrollHandle.width, max(0, uicore.uilib.x - self._mouseOffset - bl))
    218         self.UpdatePosition()
    219 
    220     def UpdatePosition(self):
    221         l, t, w, h = self.mainPar.GetAbsolute()
    222         sl, st, sw, sh = self.scrollHandle.GetAbsolute()
    223         if self.bitParent.width <= w:
    224             self.bitParent.left = 0
    225         elif sl < l:
    226             self.bitParent.left += l - sl
    227         elif sl + sw > l + w:
    228             self.bitParent.left -= sl + sw - (l + w)
    229         self.scrollHandleCont.left = self.bitParent.left
    230         self.UpdateBitsState()
    231 
    232     def UpdateBitsState(self):
    233         self.historyController.lastLitIdx = None
    234         l, t, w, h = self.bitParent.GetAbsolute()
    235         for bit in self.bits:
    236             bitVale = bit.left + self.bitGap + self.bitWidth / 2
    237             handleValue = self.scrollHandle.left + self.scrollHandle.width / 2
    238             if bitVale > handleValue:
    239                 bit.SetFaded()
    240             else:
    241                 bit.SetNormal()
    242                 self.historyController.lastLitIdx = bit.bitIdx
    243 
    244     def OnCorrectPosition(self, currentHistoryData):
    245         lastLoaded = self.historyController.GetHistoryFromLastLit()
    246         if currentHistoryData != lastLoaded:
    247             self.historyController.lastLitIdx = None
    248             self.SettleScrollHandle(UPDATE_CODE_CORRECTION)
    249 
    250     def GetScrollHandleMenu(self):
    251         if self.historyController.lastLitIdx is None:
    252             return []
    253         m = self.GetBitMenu(self.historyController.lastLitIdx)
    254         return m
    255 
    256     def GetBitMenu(self, bitIdx, *args):
    257         m = [(MenuLabel('UI/Commands/Remove'), self.historyController.RemoveFromHistory, (bitIdx,))]
    258         m += self.GetHistoryBarMenu()
    259         return m
    260 
    261     def GetHistoryBarMenu(self):
    262         return [(MenuLabel('/Carbon/UI/Controls/Common/ClearHistory'), self.ClearHistory)]
    263 
    264     def ClearHistory(self):
    265         self.historyController.ClearHistory()
    266 
    267     def Close(self):
    268         with ExceptionEater('closingHistoryBar'):
    269             self.ChangeSignalConnection(connect=False)
    270         Container.Close(self)
    271 
    272 
    273 class HistoryBit(Container):
    274     default_state = uiconst.UI_NORMAL
    275     default_align = uiconst.TOPLEFT
    276     default_bitGap = 0
    277 
    278     def ApplyAttributes(self, attributes):
    279         Container.ApplyAttributes(self, attributes)
    280         self.bitIdx = attributes.get('bitIdx')
    281         self.idx = self.bitIdx
    282         bitGap = attributes.get('bitGap', self.default_bitGap)
    283         self.callback = attributes.get('callback', None)
    284         fillColor = (1.0, 1.0, 1.0, 1.0)
    285         self.bitFill = Fill(name='bitFill', parent=self, color=fillColor, padding=(bitGap,
    286          0,
    287          0,
    288          0))
    289 
    290     def GetNomalOpacity(self):
    291         if self.bitIdx % 2:
    292             return 0.7
    293         return 0.5
    294 
    295     def SetFaded(self):
    296         self.bitFill.opacity = 0.25
    297 
    298     def SetNormal(self):
    299         self.bitFill.opacity = self.GetNomalOpacity()
    300 
    301     def OnClick(self, *args):
    302         if self.callback:
    303             self.callback(self)
    304 
    305     def OnMouseEnter(self):
    306         PlaySound(uiconst.SOUND_BUTTON_HOVER)
    307         self.bitFill.padTop = -2
    308         self.bitFill.padBottom = -2
    309 
    310     def OnMouseExit(self, *args):
    311         self.bitFill.padTop = 0
    312         self.bitFill.padBottom = 0
    313 
    314 
    315 class HistoryController(object):
    316 
    317     def __init__(self, history = None, overwriteHistory = True):
    318         self.overwriteHistory = overwriteHistory
    319         self.ResetVariables()
    320         if history:
    321             self.history = history[:]
    322         self.on_history_updated = Signal(signalName='on_history_updated')
    323         self.on_history_correction_triggered = Signal(signalName='on_history_correction_triggered')
    324 
    325     def ResetVariables(self):
    326         self._currentIndex = None
    327         self._lastLoadIndex = None
    328         self._lastLitIdx = None
    329         self.history = []
    330 
    331     @property
    332     def currentIndex(self):
    333         return self._currentIndex
    334 
    335     @currentIndex.setter
    336     def currentIndex(self, value):
    337         self._currentIndex = value
    338 
    339     @property
    340     def lastLoadIdx(self):
    341         return self._lastLoadIndex
    342 
    343     @lastLoadIdx.setter
    344     def lastLoadIdx(self, value):
    345         self._lastLoadIndex = value
    346 
    347     @property
    348     def lastLitIdx(self):
    349         return self._lastLitIdx
    350 
    351     @lastLitIdx.setter
    352     def lastLitIdx(self, value):
    353         self._lastLitIdx = value
    354 
    355     def LoadHistory(self, history):
    356         self.history = history
    357 
    358     def AddToHistory(self, value, sendSignal = True):
    359         if self.overwriteHistory:
    360             if self.lastLitIdx:
    361                 self.history = self.history[:self.lastLitIdx + 1]
    362         self.history.append(value)
    363         self.lastLoadIdx = len(self.history) - 1
    364         if sendSignal:
    365             self.on_history_updated(UPDATE_CODE_ADD)
    366 
    367     def RemoveFromHistory(self, idx):
    368         if idx <= len(self.history) - 1:
    369             self.history.pop(idx)
    370             if self.lastLitIdx > idx:
    371                 self.lastLitIdx = max(0, self.lastLitIdx - 1)
    372             if self.lastLoadIdx > idx:
    373                 self.lastLoadIdx = max(0, self.lastLoadIdx - 1)
    374             if self.currentIndex > idx:
    375                 self.currentIndex = max(0, self.currentIndex - 1)
    376             self.on_history_updated(UPDATE_CODE_REMOVE)
    377 
    378     def ClearHistory(self, sendSignal = True):
    379         self.ResetVariables()
    380         if sendSignal:
    381             self.on_history_updated(UPDATE_CODE_CLEAR)
    382 
    383     def GetHistory(self):
    384         return self.history
    385 
    386     def GetHistoryFromLastLit(self):
    387         return self.GetHistoryFromIdx(self.lastLitIdx)
    388 
    389     def GetHistoryFromIdx(self, idx):
    390         historyIdx = max(0, min(len(self.history) - 1, idx))
    391         if historyIdx <= len(self.history) - 1:
    392             return self.history[historyIdx]
    393 
    394     def IsOnFirstBit(self):
    395         return self.lastLitIdx == 0
    396 
    397     def IsOnLastBit(self):
    398         return self.lastLitIdx == len(self.history) - 1
    399 
    400     def TriggerHistoryCorrection(self, historyData):
    401         self.on_history_correction_triggered(historyData)