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

slider.py (17833B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\slider.py
      2 import uthread2
      3 from carbon.client.script.environment.AudioUtil import PlaySound
      4 from carbon.common.script.util.mathCommon import FloatCloseEnough
      5 from carbonui.primitives.fill import Fill
      6 from carbonui.primitives.frame import Frame
      7 from carbonui.uianimations import animations
      8 from eve.client.script.ui import eveColor, eveThemeColor
      9 from eve.client.script.ui.control.eveLabel import EveLabelMedium
     10 from eve.client.script.ui.control.themeColored import SpriteThemeColored, FrameThemeColored
     11 import carbonui.const as uiconst
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.line import Line
     14 from carbonui.util.various_unsorted import GetAttrs
     15 from carbonui.uicore import uicore
     16 from signals import Signal
     17 MOUSE_WHEEL_SPEED = 0.0005
     18 BAR_PADDING = 5
     19 
     20 class Slider(Container):
     21     default_align = uiconst.TOTOP
     22     default_height = 16
     23     default_barHeight = 6
     24     default_handleSize = 12
     25     default_minValue = 0.0
     26     default_maxValue = 1.0
     27     default_value = None
     28     default_config = ''
     29     default_setting = None
     30     default_label = None
     31     default_minLabel = None
     32     default_maxLabel = None
     33     default_increments = None
     34     default_snapToIncrements = True
     35     default_isEvenIncrements = False
     36     default_getHintFunc = None
     37     default_mouseWheelEnabled = True
     38     default_isInteger = False
     39     default_callback = None
     40     default_on_dragging = None
     41 
     42     def ApplyAttributes(self, attributes):
     43         super(Slider, self).ApplyAttributes(attributes)
     44         self.value = attributes.get('value', self.default_value)
     45         self.maxValue = attributes.get('maxValue', self.default_maxValue)
     46         self.minValue = attributes.get('minValue', self.default_minValue)
     47         self.handle_size = attributes.get('handleSize', self.default_handleSize)
     48         self._labelText = attributes.get('label', self.default_label)
     49         self._minLabelText = attributes.get('minLabel', self.default_minLabel)
     50         self._maxLabelText = attributes.get('maxLabel', self.default_maxLabel)
     51         self._mouseWheelEnabled = attributes.get('mouseWheelEnabled', self.default_mouseWheelEnabled)
     52         self.barHeight = attributes.get('barHeight', self.default_barHeight)
     53         self.isInteger = attributes.get('isInteger', self.default_isInteger)
     54         self.incrementValues = attributes.get('increments', self.default_increments) or []
     55         self.snapToIncrements = attributes.get('snapToIncrements', self.default_snapToIncrements)
     56         self.isEvenIncrementsSlider = attributes.get('isEvenIncrementsSlider', self.default_isEvenIncrements) and bool(self.incrementValues)
     57         self.config = attributes.get('config', self.default_config)
     58         self.setting = attributes.get('setting', self.default_setting)
     59         if self.setting:
     60             self.minValue = self.setting.min_value
     61             self.maxValue = self.setting.max_value
     62         self._getHintFunc = attributes.get('getHintFunc', self.default_getHintFunc)
     63         callback_func = attributes.get('callback', self.default_callback)
     64         on_dragging_func = attributes.get('on_dragging', self.default_on_dragging)
     65         self.isDragging = False
     66         self._hasMouseMovedOver = False
     67         self.handle = None
     68         self.handleOffset = 0
     69         self.incrementValuesNormalized = []
     70         self.tickLines = []
     71         self._ConstructBarCont()
     72         self._ConstructHandle()
     73         self.ticksCont = Container(name='ticksCont', parent=self.barCont)
     74         self._ConstructBackground()
     75         self._ConstructLabel()
     76         self._ConstructMinMaxLabels()
     77         self.SetIncrements(self.incrementValues)
     78         self._InitializeValue()
     79         self._ConstructSignals(callback_func, on_dragging_func)
     80 
     81     def _ConstructMinMaxLabels(self):
     82         if not (self._minLabelText or self._maxLabelText):
     83             return
     84         self.maxLabel = EveLabelMedium(parent=self, align=uiconst.BOTTOMLEFT, text=self._minLabelText)
     85         self.minLabel = EveLabelMedium(parent=self, align=uiconst.BOTTOMRIGHT, text=self._maxLabelText)
     86         _, textHeight = EveLabelMedium.MeasureTextSize(self._minLabelText or '' + self._maxLabelText or '')
     87         self.height += textHeight
     88 
     89     def _ConstructSignals(self, callback_func, on_dragging_func):
     90         self.callback = Signal('Slider.callback')
     91         if callback_func:
     92             self.callback.connect(callback_func)
     93         self.on_dragging = Signal('Slider.on_dragging')
     94         if on_dragging_func:
     95             self.on_dragging.connect(on_dragging_func)
     96 
     97     def _InitializeValue(self):
     98         if self.setting:
     99             value = self.setting.get()
    100         elif self.config:
    101             value = self._GetValueFromSetting()
    102         elif self.value is not None:
    103             value = self.value
    104         else:
    105             value = self.minValue
    106         self.SetValue(value)
    107 
    108     def _GetValueFromSetting(self):
    109         if len(self.config) == 3:
    110             cfgName, prefsType, defaultValue = self.config
    111             if prefsType is not None:
    112                 si = GetAttrs(settings, *prefsType)
    113                 if si is not None:
    114                     value = si.Get(cfgName, defaultValue)
    115                 else:
    116                     value = defaultValue
    117             else:
    118                 value = defaultValue
    119         else:
    120             value = settings.user.ui.Get(self.config, (self.maxValue - self.minValue) * 0.5)
    121             if value is None:
    122                 value = 0.0
    123         return value
    124 
    125     def _ConstructBarCont(self):
    126         self.barCont = Container(parent=self, name='barCont', align=uiconst.TOTOP, state=uiconst.UI_NORMAL, height=self.barHeight + 2 * BAR_PADDING)
    127         self.barCont.OnClick = self.OnSliderClicked
    128         self.barCont.OnMouseMove = self.OnSliderMouseMove
    129         self.barCont.OnMouseExit = self.OnMouseBarExit
    130         self.barCont.OnMouseWheel = self.OnMouseWheel
    131         self.barCont.GetHint = self.GetHint
    132         self.barCont.GetTooltipPosition = self.GetTooltipPosition
    133 
    134     def _ConstructBackground(self):
    135         bgCont = Container(name='bgCont', padding=(0,
    136          BAR_PADDING,
    137          0,
    138          BAR_PADDING), parent=self.barCont)
    139         Frame(bgParent=bgCont, name='bgFrame', texturePath='res:/UI/Texture/Classes/Slider/bgFrame.png', color=eveColor.MATTE_BLACK, cornerSize=3)
    140         Frame(bgParent=bgCont, name='bgFrame', texturePath='res:/UI/Texture/Classes/Slider/bgFill.png', color=eveColor.BLACK, opacity=0.6, cornerSize=3)
    141 
    142     def OnSliderClicked(self, *args):
    143         _, newValue = self._FindNewValue()
    144         self.SetValue(newValue)
    145         self._OnEndUserAction()
    146 
    147     def _OnEndUserAction(self):
    148         if self.setting:
    149             self.setting.set(self.GetValue())
    150         self._ApplyConfigSetting()
    151         self.callback(self)
    152 
    153     def OnSliderMouseMove(self, *args):
    154         self._hasMouseMovedOver = True
    155         if not self.incrementValues or not self.snapToIncrements:
    156             return
    157         _, value = self._FindNewValue()
    158         if value not in self.incrementValues or not self.tickLines:
    159             return
    160         valueIndex = self.incrementValues.index(value)
    161         self._ApplyTickOpacity(valueIndex)
    162 
    163     def _ApplyTickOpacity(self, valueIndex = None):
    164         for i, tick in enumerate(self.tickLines):
    165             isSelected = i == valueIndex
    166             tick.opacity = self._GetTickOpacity(i, isSelected)
    167 
    168     def _GetTickOpacity(self, i, isSelected = False):
    169         if isSelected:
    170             return 1.5
    171         elif self.incrementValuesNormalized[i] in (0.0, 1.0):
    172             return 0.0
    173         else:
    174             return 1.0
    175 
    176     def _ConstructHandle(self):
    177         self.handleOffset = 4
    178         self.handle = Container(name='handle', parent=self.barCont, state=uiconst.UI_NORMAL, align=uiconst.CENTERLEFT, pos=(0,
    179          0,
    180          self.handle_size,
    181          self.handle_size))
    182         self.handleFill = Fill(name='handleFill', parent=self.handle, align=uiconst.CENTER, pos=(0, 0, 4, 8), outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.0, color=eveThemeColor.THEME_FOCUS)
    183         self.handle.OnMouseEnter = self.OnHandleMouseEnter
    184         self.handle.OnMouseDown = self.OnHandleMouseDown
    185         self.handle.OnMouseUp = self.OnHandleMouseUp
    186         self.handle.OnMouseMove = self.OnHandleMouseMove
    187         self.handle.GetHint = self.GetHint
    188 
    189     def _ConstructLabel(self):
    190         if self._labelText:
    191             self.label = EveLabelMedium(parent=self, top=13, state=uiconst.UI_NORMAL, hint=self.hint, text=self._labelText)
    192         else:
    193             self.label = None
    194 
    195     def ReconstructIncrements(self):
    196         for tick in self.tickLines:
    197             tick.Close()
    198 
    199         self.tickLines = []
    200         if self.incrementValues:
    201             w, _ = self.GetAbsoluteSize()
    202             maxX = self._GetMaxX()
    203             for i, valueNormalized in enumerate(self.incrementValuesNormalized):
    204                 left = valueNormalized
    205                 line = self._ConstructTickLine(i, left)
    206                 self.tickLines.append(line)
    207 
    208     def _ConstructTickLine(self, i, left):
    209         padding = BAR_PADDING + 2
    210         return Line(parent=self.ticksCont, name='tickLine', align=uiconst.TOPLEFT_PROP, color=eveColor.SMOKE_BLUE, opacity=self._GetTickOpacity(i), left=left, width=1, top=7, height=self.barHeight - 4)
    211 
    212     def SetIncrements(self, values):
    213         self.incrementValues = values
    214         numIncrements = len(self.incrementValues)
    215         self.incrementValuesNormalized = []
    216         for idx, value in enumerate(self.incrementValues):
    217             if self.isEvenIncrementsSlider:
    218                 normalizedValue = float(idx) / (numIncrements - 1)
    219             else:
    220                 normalizedValue = (value - self.minValue) / float(self.maxValue - self.minValue)
    221             self.incrementValuesNormalized.append(normalizedValue)
    222 
    223         self.ReconstructIncrements()
    224 
    225     def GetValue(self):
    226         return self.value
    227 
    228     def _UpdateHandlePosition(self, nValue, useIncrements = True):
    229         maxX = self._GetMaxX()
    230         leftPercentage = max(0, nValue)
    231         if self.incrementValues and useIncrements and self.snapToIncrements:
    232             leftPercentage = self._FindClosest(leftPercentage, self.incrementValuesNormalized)
    233         left = leftPercentage * maxX
    234         self.handle.left = int(left) - self.handleOffset
    235 
    236     def SetValue(self, value):
    237         self.value = self._GetSanitizedValue(value, useIncrements=False)
    238         self._UpdateHandlePosition(self.GetNormalizedValue(), useIncrements=False)
    239 
    240     def _GetSanitizedValue(self, value, useIncrements = False):
    241         if self.incrementValues and useIncrements and self.snapToIncrements:
    242             value = self._FindClosest(round(value, 2), self.incrementValues)
    243         value = max(self.minValue, min(self.maxValue, value))
    244         if self.isInteger:
    245             value = round(value)
    246         return value
    247 
    248     def GetNormalizedValue(self):
    249         if self.isEvenIncrementsSlider:
    250             valueIndex = self.incrementValues.index(self.value)
    251             percentage = self.incrementValuesNormalized[valueIndex]
    252             return percentage
    253         else:
    254             return float(self.value - self.minValue) / (-self.minValue + self.maxValue)
    255 
    256     def _FindClosest(self, check, values):
    257         mindiff = values[-1] - values[0]
    258         found = mindiff
    259         for value in values:
    260             diff = abs(value - check)
    261             if diff < mindiff:
    262                 mindiff = diff
    263                 found = value
    264 
    265         return found
    266 
    267     def OnColorThemeChanged(self):
    268         super(Slider, self).OnColorThemeChanged()
    269         self.handleFill.SetRGBA(*eveThemeColor.THEME_FOCUS)
    270 
    271     def OnMouseWheel(self, delta, *args):
    272         if not self._hasMouseMovedOver or not self._mouseWheelEnabled:
    273             return False
    274         if self.incrementValues and self.snapToIncrements:
    275             value = self._GetMouseWheelNewValueIncrements(delta)
    276         else:
    277             value = self._GetMouseWheelNewValue(delta)
    278         if value is not None:
    279             self.SetValue(value)
    280             self._OnEndUserAction()
    281 
    282     def _GetMouseWheelNewValue(self, delta):
    283         change = MOUSE_WHEEL_SPEED * delta * (self.maxValue - self.minValue)
    284         newValue = self._GetSanitizedValue(self.GetValue() + change)
    285         return newValue
    286 
    287     def _GetMouseWheelNewValueIncrements(self, delta):
    288         currentValue = self.GetValue()
    289         if delta < 0:
    290             if currentValue <= self.incrementValues[0]:
    291                 newValue = None
    292             else:
    293                 newValue = max((x for x in self.incrementValues if x < currentValue and not FloatCloseEnough(x, currentValue)))
    294         elif currentValue >= self.incrementValues[-1]:
    295             newValue = None
    296         else:
    297             newValue = min((x for x in self.incrementValues if x > currentValue and not FloatCloseEnough(x, currentValue)))
    298         return newValue
    299 
    300     def OnMouseBarExit(self):
    301         self._ApplyTickOpacity(-1)
    302 
    303     def OnMouseEnter(self, *args):
    304         animations.MorphScalar(self.handleFill, 'glowBrightness', startVal=self.handleFill.glowBrightness, endVal=1.0, duration=0.1)
    305 
    306     def OnMouseExit(self, *args):
    307         self._hasMouseMovedOver = False
    308         animations.MorphScalar(self.handleFill, 'glowBrightness', startVal=self.handleFill.glowBrightness, endVal=0.0, duration=0.5)
    309 
    310     def OnHandleMouseEnter(self, *args):
    311         PlaySound(uiconst.SOUND_BUTTON_HOVER)
    312 
    313     def OnHandleMouseDown(self, *args):
    314         self.isDragging = True
    315         self._ApplyTickOpacity(-1)
    316         uthread2.StartTasklet(self._TooltipUpdateThread)
    317         animations.SpColorMorphTo(self.handleFill, self.handleFill.GetRGBA(), eveColor.WHITE, duration=0.1)
    318         animations.MorphScalar(self.handleFill, 'glowBrightness', self.handleFill.glowBrightness, 0.3, duration=0.1)
    319 
    320     def _TooltipUpdateThread(self):
    321         while self.isDragging:
    322             uicore.uilib.tooltipHandler.UpdateTooltipHint(self)
    323             uthread2.Yield()
    324 
    325     def OnHandleMouseUp(self, *args):
    326         PlaySound(uiconst.SOUND_BUTTON_CLICK)
    327         uicore.uilib.UnclipCursor()
    328         self.isDragging = False
    329         self._OnEndUserAction()
    330         animations.SpColorMorphTo(self.handleFill, self.handleFill.GetRGBA(), eveThemeColor.THEME_FOCUS, duration=0.3)
    331         animations.MorphScalar(self.handleFill, 'glowBrightness', self.handleFill.glowBrightness, 1.0, duration=0.3, curveType=uiconst.ANIM_OVERSHOT5)
    332 
    333     def _ApplyConfigSetting(self):
    334         if self.config:
    335             if len(self.config) == 3:
    336                 cfgName, prefsType, defaultValue = self.config
    337                 if prefsType:
    338                     si = GetAttrs(settings, *prefsType)
    339                     if si is not None:
    340                         value = si.Set(cfgName, self.value)
    341             else:
    342                 settings.user.ui.Set(self.config, self.value)
    343 
    344     def OnHandleMouseMove(self, *args):
    345         if self.isDragging:
    346             PlaySound(uiconst.SOUND_VALUECHANGE_TICK)
    347             localMousePos, value = self._FindNewValue()
    348             if self.handle.left + self.handleOffset == localMousePos:
    349                 return
    350             self.handle.left = localMousePos - self.handleOffset
    351             self.value = self._GetSanitizedValue(value, useIncrements=True)
    352             self._UpdateHandlePosition(self.GetNormalizedValue(), useIncrements=True)
    353             self.on_dragging(self)
    354 
    355     def _FindNewValue(self):
    356         l, _, w, _ = self.GetAbsolute()
    357         hw = self._GetHandleWidth()
    358         maxX = self._GetMaxX()
    359         localMousePos = uicore.uilib.x - l - hw / 2
    360         localMousePos = max(0, min(maxX, localMousePos))
    361         localMousePercentagePos = min(1, max(0, float(localMousePos) / maxX))
    362         if self.isEvenIncrementsSlider:
    363             numIncrements = len(self.incrementValuesNormalized)
    364             eachStep = float(maxX) / (numIncrements - 1)
    365             localMousePercentagePos = self._FindClosest(localMousePercentagePos, self.incrementValuesNormalized)
    366             partIndex = self.incrementValuesNormalized.index(localMousePercentagePos)
    367             localMousePos = partIndex * eachStep
    368             value = self.incrementValues[partIndex]
    369         else:
    370             if self.incrementValues and self.snapToIncrements:
    371                 localMousePercentagePos = self._FindClosest(localMousePercentagePos, self.incrementValuesNormalized)
    372                 localMousePos = localMousePercentagePos * maxX
    373             value = self.minValue + localMousePercentagePos * (self.maxValue - self.minValue)
    374         return (localMousePos, value)
    375 
    376     def _GetMaxX(self):
    377         w, _ = self.GetAbsoluteSize()
    378         maxX = w - self._GetHandleWidth()
    379         return maxX
    380 
    381     def _GetHandleWidth(self):
    382         return self.handle.width - 2 * self.handleOffset
    383 
    384     def Enable(self, *args):
    385         self.SetState(uiconst.UI_NORMAL)
    386         animations.FadeIn(self)
    387 
    388     def Disable(self, *args):
    389         self.SetState(uiconst.UI_DISABLED)
    390         animations.FadeTo(self, startVal=self.opacity, endVal=0.5)
    391 
    392     def GetHint(self):
    393         if self._getHintFunc:
    394             return self._getHintFunc(self)
    395         else:
    396             return super(Slider, self).GetHint()
    397 
    398     def GetTooltipPosition(self):
    399         return self.handle.GetAbsolute()
    400 
    401     def SetLabel(self, text):
    402         self._labelText = text
    403         if not self.label:
    404             self._ConstructLabel()
    405         else:
    406             self.label.SetText(text)
    407 
    408     def UpdateAlignment(self, budgetLeft = 0, budgetTop = 0, budgetWidth = 0, budgetHeight = 0, updateChildrenOnly = False):
    409         ret = super(Slider, self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth, budgetHeight, updateChildrenOnly)
    410         if self.value is not None:
    411             self._UpdateHandlePosition(self.GetNormalizedValue())
    412         return ret