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

rangeSelector.py (18724B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\rangeSelector.py
      2 from carbon.common.script.util.mathCommon import FloatCloseEnough
      3 from carbonui import uiconst
      4 from carbonui.primitives.container import Container
      5 from carbonui.primitives.gridcontainer import GridContainer
      6 from carbonui.primitives.line import Line
      7 from carbonui.primitives.sprite import Sprite
      8 from eve.client.script.ui.control import eveLabel
      9 from eve.client.script.ui.control.themeColored import SpriteThemeColored, FillThemeColored
     10 from carbonui.uicore import uicore
     11 MAINSIDEMARGIN = 6
     12 RANGECOLOR = (0.6,
     13  0.6,
     14  0.6,
     15  1)
     16 OUTOFRANGECOLOR = (0.2,
     17  0.2,
     18  0.2,
     19  1)
     20 
     21 class RangeSelector(Container):
     22     default_state = uiconst.UI_NORMAL
     23 
     24     def ApplyAttributes(self, attributes):
     25         Container.ApplyAttributes(self, attributes)
     26         self._fixedFromProportion = None
     27         self._fixedToProportion = None
     28         self._minRange = None
     29         self._maxRange = None
     30         rangeParent = Container(parent=self, align=uiconst.TOTOP, height=attributes.barHeight or 9, padding=(MAINSIDEMARGIN,
     31          8,
     32          MAINSIDEMARGIN,
     33          0), state=uiconst.UI_NORMAL)
     34         rangeParent.OnMouseDown = (self.StartMoveRange, rangeParent)
     35         rangeParent.OnMouseUp = (self.StopMoveRange, rangeParent)
     36         rangeParent.OnMouseMove = (self.MoveRange, rangeParent)
     37         for name in ('from', 'to'):
     38             parent = Container(parent=rangeParent)
     39             rangeContainer = SizeCappedContainer(name='rangeContainer', parent=parent, align=uiconst.TOLEFT_PROP)
     40             rangeContainer._background = FillThemeColored(bgParent=rangeContainer, opacity=0.8)
     41             rangeContainer._pointer = SpriteThemeColored(parent=rangeContainer, align=uiconst.TOPRIGHT, pos=(-8, -7, 16, 16))
     42             setattr(self, '_' + name + 'Range', rangeContainer)
     43             configName = '_' + name + 'Handle'
     44             handle = Container(parent=self, name=configName, align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL, pos=(0,
     45              0,
     46              MAINSIDEMARGIN * 2,
     47              32), idx=0)
     48             handle.OnMouseDown = (self.StartMoveHandle, handle)
     49             handle.OnMouseUp = (self.StopMoveHandle, handle)
     50             handle.OnMouseMove = (self.MoveHandle, handle)
     51             setattr(self, configName, handle)
     52 
     53         self._background = FillThemeColored(name='backgroundFill', bgParent=rangeParent, opacity=0.8)
     54         self._incrementsParent = Container(parent=self, align=uiconst.TOTOP, height=16, padding=(MAINSIDEMARGIN,
     55          2,
     56          MAINSIDEMARGIN,
     57          0), name='_incrementsParent')
     58         self._increments = None
     59         self._callbackData = None
     60         self._fromProportion = attributes.fromProportion or 0.0
     61         self._toProportion = attributes.toProportion or 1.0
     62         self._canInvert = bool(attributes.canInvert)
     63         self.height = 48
     64         self.UpdateRanges()
     65         self.UpdateHandles()
     66         self.OnIncrementChange = attributes.OnIncrementChange
     67         self.OnChange = attributes.OnChange
     68         self.OnEndDragChange = attributes.OnEndDragChange
     69 
     70     def StartMoveHandle(self, handle, btn):
     71         l, t, w, h = handle.GetAbsolute()
     72         handle.grab = (uicore.uilib.x - l, uicore.uilib.y - t)
     73 
     74     def StopMoveHandle(self, handle, btn):
     75         self._EnforceMaxRange(handle)
     76         handle.grab = None
     77         if self._increments and (self._fromProportion == self._toProportion or self._toProportion == 0 and self._fromProportion == 1.0):
     78             if handle is self._toHandle:
     79                 for increment, incrementData in self._increments:
     80                     if increment - self._minRange >= self._toProportion:
     81                         self._toProportion = increment
     82                         self.UpdateRanges()
     83                         self.UpdateHandles()
     84                         self._DoOnChangeCallback(onEndDrag=True)
     85                         return
     86 
     87                 self._toProportion = self._increments[1][0]
     88                 self.UpdateRanges()
     89                 self.UpdateHandles()
     90                 self._DoOnChangeCallback(onEndDrag=True)
     91                 return
     92             if handle is self._fromHandle:
     93                 for increment, incrementData in reversed(self._increments):
     94                     if increment + self._minRange <= self._fromProportion:
     95                         self._fromProportion = increment
     96                         self.UpdateRanges()
     97                         self.UpdateHandles()
     98                         self._DoOnChangeCallback(onEndDrag=True)
     99                         return
    100 
    101                 self._fromProportion = self._increments[-2][0]
    102                 self.UpdateRanges()
    103                 self.UpdateHandles()
    104                 self._DoOnChangeCallback(onEndDrag=True)
    105                 return
    106         if self.OnEndDragChange:
    107             self._DoOnChangeCallback(onEndDrag=True)
    108 
    109     def _EnforceMaxRange(self, handle):
    110         if not self._increments or self._maxRange is None:
    111             return
    112         if not self.IsOverMaxRange(self._fromProportion, self._toProportion):
    113             return
    114         if handle is self._toHandle:
    115             nextIncrements = self.GetNextIncrements(self._toProportion, 'toHandle')
    116             for prop in nextIncrements:
    117                 if not self.IsOverMaxRange(self._fromProportion, prop):
    118                     self._toProportion = prop
    119                     break
    120 
    121         elif handle is self._fromHandle:
    122             nextIncrements = self.GetNextIncrements(self._fromProportion, 'fromHandle')
    123             for prop in nextIncrements:
    124                 if not self.IsOverMaxRange(prop, self._toProportion):
    125                     self._fromProportion = prop
    126                     break
    127 
    128         self.UpdateRanges()
    129         self.UpdateHandles()
    130 
    131     def GetNextIncrements(self, prop, handleName):
    132         lowerThanProp = []
    133         higherThanProp = []
    134         for increment, _ in self._increments:
    135             if increment >= prop:
    136                 higherThanProp.append(increment)
    137             else:
    138                 lowerThanProp.append(increment)
    139 
    140         if handleName == 'fromHandle':
    141             return higherThanProp + lowerThanProp
    142         else:
    143             lowerThanProp.reverse()
    144             higherThanProp.reverse()
    145             return lowerThanProp + higherThanProp
    146 
    147     def IsOverMaxRange(self, fromProp, toProp):
    148         if self._maxRange is None:
    149             return False
    150         adjustedToProp = self.GetAdjustedToProporations(fromProp, toProp)
    151         rangeProp = adjustedToProp - fromProp
    152         if FloatCloseEnough(rangeProp, self._maxRange):
    153             return False
    154         return rangeProp > self._maxRange
    155 
    156     def GetAdjustedToProporations(self, fromProp, toProp):
    157         if fromProp > toProp:
    158             return toProp + 1.0
    159         return toProp
    160 
    161     def MoveHandle(self, handle, *args):
    162         if getattr(handle, 'grab', None):
    163             x, y = handle.grab
    164             l, t, w, h = handle.parent.GetAbsolute()
    165             handle.left = pos = min(w - handle.width, max(0, uicore.uilib.x - x - l))
    166             r = w - handle.width
    167             proportion = pos / float(r)
    168             incrementData = None
    169             closest = self.RoundToIncrement(proportion)
    170             if closest is not None:
    171                 proportion = closest
    172             if not self._canInvert:
    173                 if handle is self._fromHandle:
    174                     self._fromProportion = min(proportion, self._toProportion)
    175                 if handle is self._toHandle:
    176                     self._toProportion = max(proportion, self._fromProportion)
    177             else:
    178                 if handle is self._fromHandle:
    179                     self._fromProportion = proportion
    180                 if handle is self._toHandle:
    181                     self._toProportion = proportion
    182             self.UpdateRanges()
    183             self.UpdateHandles()
    184             self._DoOnChangeCallback()
    185 
    186     def StartMoveRange(self, rangeParent, btn):
    187         l, t, w, h = rangeParent.GetAbsolute()
    188         rangeParent.startProportion = ((uicore.uilib.x - l) / float(w), self._fromProportion, self._toProportion)
    189 
    190     def StopMoveRange(self, rangeParent, btn):
    191         rangeParent.startProportion = None
    192         if self.OnEndDragChange:
    193             self._DoOnChangeCallback(onEndDrag=True)
    194 
    195     def MoveRange(self, rangeParent, *args):
    196         if getattr(rangeParent, 'startProportion', None):
    197             l, t, w, h = rangeParent.GetAbsolute()
    198             newProportion = (uicore.uilib.x - l) / float(w)
    199             startProportion, fromProportion, toProportion = rangeParent.startProportion
    200             diff = newProportion - startProportion
    201             if fromProportion > toProportion:
    202                 if diff < 0:
    203                     self._toProportion = max(0.0, toProportion + diff)
    204                     self._fromProportion = self._toProportion + (fromProportion - toProportion)
    205                 else:
    206                     self._fromProportion = min(1.0, fromProportion + diff)
    207                     self._toProportion = self._fromProportion - (fromProportion - toProportion)
    208             elif diff < 0:
    209                 self._fromProportion = max(0.0, fromProportion + diff)
    210                 self._toProportion = self._fromProportion + (toProportion - fromProportion)
    211             else:
    212                 self._toProportion = min(1.0, toProportion + diff)
    213                 self._fromProportion = self._toProportion - (toProportion - fromProportion)
    214             closest = self.RoundToIncrement(self._fromProportion)
    215             if closest is not None:
    216                 self._fromProportion = closest
    217             closest = self.RoundToIncrement(self._toProportion)
    218             if closest is not None:
    219                 self._toProportion = closest
    220             self.UpdateRanges()
    221             self.UpdateHandles()
    222             self._DoOnChangeCallback()
    223 
    224     def SetMinRange(self, minRange):
    225         self._minRange = minRange
    226         self.UpdateRanges()
    227         self.UpdateHandles()
    228 
    229     def SetMaxRange(self, maxRange):
    230         isChanging = self._maxRange != maxRange
    231         self._maxRange = maxRange
    232         self._EnforceMaxRange(self._toHandle)
    233         self.UpdateRanges()
    234         self.UpdateHandles()
    235         if isChanging:
    236             self._DoOnChangeCallback(True)
    237 
    238     def SetFixedRange(self, fixedFromProportion = None, fixedToProportion = None):
    239         self._fixedFromProportion = fixedFromProportion
    240         if fixedFromProportion is not None:
    241             self._fromProportion = fixedFromProportion
    242             self._fromHandle.display = False
    243             self._fromRange._pointer.display = False
    244         else:
    245             self._fromHandle.display = True
    246             self._fromRange._pointer.display = True
    247         self._fixedToProportion = fixedToProportion
    248         if fixedToProportion is not None:
    249             self._toProportion = fixedToProportion
    250             self._toHandle.display = False
    251             self._toRange._pointer.display = False
    252         else:
    253             self._toHandle.display = True
    254             self._toRange._pointer.display = True
    255         self.UpdateRanges()
    256         self.UpdateHandles()
    257 
    258     def SetIncrements(self, increments):
    259         self._incrementsParent.Flush()
    260         maxMarkerSize = 0
    261         labels = []
    262         self._increments = []
    263         if increments:
    264             last = increments.pop(-1)
    265             stepSize = 1.0 / len(increments)
    266             c = GridContainer(parent=self._incrementsParent, lines=1, columns=len(increments))
    267             i = 0
    268             for incrementData in increments:
    269                 label = incrementData[0]
    270                 markerSize = incrementData[1]
    271                 inc = Container(parent=c, align=uiconst.TOALL)
    272                 if markerSize:
    273                     maxMarkerSize = max(maxMarkerSize, markerSize)
    274                     Line(parent=inc, align=uiconst.TOPLEFT, width=1, height=markerSize)
    275                     self._increments.append((i * stepSize, incrementData))
    276                 if label:
    277                     if label.startswith('res:'):
    278                         s = Sprite(parent=inc, texturePath=label, width=16, height=16, align=uiconst.CENTER, idx=0, top=-2, color=(1, 1, 1, 0.7))
    279                         labels.append(s)
    280                     else:
    281                         l = eveLabel.EveLabelSmall(parent=inc, text=label, left=-MAINSIDEMARGIN)
    282                         if i == 0:
    283                             l.left = max(-MAINSIDEMARGIN, -l.textwidth / 2)
    284                         else:
    285                             l.left = -l.textwidth / 2
    286                         labels.append(l)
    287                 i += 1
    288 
    289             label = last[0]
    290             markerSize = last[1]
    291             inc = Container(parent=self._incrementsParent, align=uiconst.TORIGHT, width=1, idx=0)
    292             if markerSize:
    293                 maxMarkerSize = max(maxMarkerSize, markerSize)
    294                 Line(parent=inc, align=uiconst.TOPLEFT, width=1, height=markerSize)
    295                 self._increments.append((i * stepSize, last))
    296             if label:
    297                 if label.startswith('res:'):
    298                     s = Sprite(parent=inc, texturePath=label, width=16, height=16, align=uiconst.CENTER, idx=0, top=-2, color=(1, 1, 1, 0.7))
    299                     labels.append(s)
    300                 else:
    301                     l = eveLabel.EveLabelSmall(parent=inc, text=label, align=uiconst.TOPRIGHT)
    302                     l.left = max(-MAINSIDEMARGIN, -l.textwidth / 2)
    303                     labels.append(l)
    304         self._EnforceMaxRange(self._toHandle)
    305         maxHeight = 0
    306         for l in labels:
    307             l.top += maxMarkerSize
    308             maxHeight = max(l.top + l.height, maxHeight)
    309 
    310         self._incrementsParent.height = maxHeight
    311         self.height = sum([ each.height + each.padTop + each.padBottom for each in self.children if each.align == uiconst.TOTOP ])
    312 
    313     def RoundToIncrement(self, proportion, getIncrementData = False):
    314         closest = None
    315         closestDiff = None
    316         closestData = None
    317         if self._increments:
    318             for increment, incrementData in self._increments:
    319                 diff = abs(proportion - increment)
    320                 if closestDiff is None or diff < closestDiff:
    321                     closest = increment
    322                     closestDiff = diff
    323                     closestData = incrementData
    324 
    325         if getIncrementData:
    326             return (closest, closestData)
    327         return closest
    328 
    329     def UpdateRanges(self):
    330         if self._fixedFromProportion is not None:
    331             fromProportion = self._fixedFromProportion
    332         else:
    333             fromProportion = self._fromProportion
    334         if self._fixedToProportion is not None:
    335             toProportion = self._fixedToProportion
    336         else:
    337             toProportion = self._toProportion
    338         self._fromRange.width = fromProportion
    339         self._toRange.width = toProportion
    340         if fromProportion > toProportion:
    341             self._toRange.parent.SetOrder(0)
    342             self._toRange._background.SetColorType(uiconst.COLORTYPE_UIHILIGHT)
    343             self._toRange._pointer.LoadTexture('res:/UI/Texture/classes/RangeSelector/rightPointer.png')
    344             self._toRange._pointer.top = -7
    345             self._fromRange._background.SetColorType(uiconst.COLORTYPE_UIBASECONTRAST)
    346             self._fromRange._pointer.LoadTexture('res:/UI/Texture/classes/RangeSelector/leftPointerDown.png')
    347             self._fromRange._pointer.top = 0
    348             self._background.SetColorType(uiconst.COLORTYPE_UIHILIGHT)
    349         else:
    350             self._fromRange.parent.SetOrder(0)
    351             self._fromRange._background.SetColorType(uiconst.COLORTYPE_UIBASECONTRAST)
    352             self._fromRange._pointer.LoadTexture('res:/UI/Texture/classes/RangeSelector/leftPointer.png')
    353             self._fromRange._pointer.top = -7
    354             self._toRange._background.SetColorType(uiconst.COLORTYPE_UIHILIGHT)
    355             self._toRange._pointer.LoadTexture('res:/UI/Texture/classes/RangeSelector/rightPointerDown.png')
    356             self._toRange._pointer.top = 0
    357             self._background.SetColorType(uiconst.COLORTYPE_UIBASECONTRAST)
    358 
    359     def UpdateHandles(self):
    360         l, t, w, h = self.GetAbsolute()
    361         r = w - self._fromHandle.width
    362         if self._fixedFromProportion is not None:
    363             fromProportion = self._fixedFromProportion
    364         else:
    365             fromProportion = self._fromProportion
    366         if self._fixedToProportion is not None:
    367             toProportion = self._fixedToProportion
    368         else:
    369             toProportion = self._toProportion
    370         self._fromHandle.left = int(r * fromProportion)
    371         self._toHandle.left = int(r * toProportion)
    372 
    373     def _DoOnChangeCallback(self, onEndDrag = False):
    374         if self._callbackData != (self._fromProportion, self._toProportion):
    375             if self.OnChange:
    376                 self.OnChange(self._fromProportion, self._toProportion)
    377             if self.OnIncrementChange:
    378                 fromIncr, fromData = self.RoundToIncrement(self._fromProportion, getIncrementData=True)
    379                 toIncr, toData = self.RoundToIncrement(self._toProportion, getIncrementData=True)
    380                 self.OnIncrementChange(self, fromData, toData, fromIncr, toIncr)
    381             self._callbackData = (self._fromProportion, self._toProportion)
    382         if onEndDrag and self.OnEndDragChange:
    383             fromIncr, fromData = self.RoundToIncrement(self._fromProportion, getIncrementData=True)
    384             toIncr, toData = self.RoundToIncrement(self._toProportion, getIncrementData=True)
    385             self.OnEndDragChange(self, fromData, toData, fromIncr, toIncr)
    386 
    387     def _OnSizeChange_NoBlock(self, *args):
    388         self.UpdateHandles()
    389 
    390 
    391 class SizeCappedContainer(Container):
    392 
    393     @apply
    394     def displayRect():
    395         fget = Container.displayRect.fget
    396 
    397         def fset(self, value):
    398             Container.displayRect.fset(self, value)
    399             ro = self.renderObject
    400             if ro:
    401                 ro.displayWidth = max(0.0001, self._displayWidth)
    402                 ro.displayHeight = max(0.0001, self._displayHeight)
    403 
    404         return property(**locals())
    405 
    406     @apply
    407     def displayWidth():
    408         fget = Container.displayWidth.fget
    409 
    410         def fset(self, value):
    411             Container.displayWidth.fset(self, value)
    412             ro = self.renderObject
    413             if ro:
    414                 ro.displayWidth = max(0.0001, self._displayWidth)
    415 
    416         return property(**locals())
    417 
    418     @apply
    419     def displayHeight():
    420         fget = Container.displayHeight.fget
    421 
    422         def fset(self, value):
    423             Container.displayHeight.fset(self, value)
    424             ro = self.renderObject
    425             if ro:
    426                 ro.displayHeight = max(0.0001, self._displayHeight)
    427 
    428         return property(**locals())