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

toggleSwitch.py (16020B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\toggleSwitch.py
      2 import math
      3 import carbonui
      4 import carbonui.text.styles
      5 import threadutils
      6 import trinity
      7 from carbon.client.script.environment.AudioUtil import PlaySound
      8 from carbonui import PickState
      9 from carbonui.control.button import BusyContext
     10 from carbonui.primitives.container import Container
     11 from carbonui.primitives.frame import Frame
     12 from carbonui.primitives.sprite import Sprite
     13 from carbonui.primitives.stretchspritehorizontal import StretchSpriteHorizontal
     14 from carbonui.primitives.transform import Transform
     15 from carbonui.uianimations import animations
     16 from carbonui.util.various_unsorted import IsUnder
     17 from eve.client.script.ui import eveColor, eveThemeColor
     18 from localization import GetByLabel
     19 import carbonui.const as uiconst
     20 from signals import Signal
     21 from carbonui.uicore import uicore
     22 ON_FRAME_OPACITY = 0.6
     23 
     24 class BaseToggleSwitch(Container):
     25     default_width = 24
     26     default_height = 16
     27     default_minWidth = 24
     28     default_minHeight = 24
     29     default_enabled = True
     30     default_align = carbonui.Align.TOPLEFT
     31     default_state = carbonui.uiconst.UI_NORMAL
     32     default_clipChildren = True
     33     default_checked = False
     34     default_setting = None
     35     default_onText = GetByLabel('UI/SystemMenu/DisplayAndGraphics/Common/On')
     36     default_offText = GetByLabel('UI/SystemMenu/DisplayAndGraphics/Common/Off')
     37     default_handleSize = 12
     38     handleLabelOffset = 4
     39     labelVerticalPadding = 2
     40     handleTexturePath = 'res:/UI/Texture/classes/toggleSwitch/handle.png'
     41     handleTextureChecked = handleTexturePath
     42     __busy_context = None
     43 
     44     def ApplyAttributes(self, attributes):
     45         self.onFrame = None
     46         self.offFrame = None
     47         super(BaseToggleSwitch, self).ApplyAttributes(attributes)
     48         self.onText = attributes.get('onText', self.default_onText)
     49         self.offText = attributes.get('offText', self.default_offText)
     50         handleSize = attributes.get('handleSize', self.default_handleSize)
     51         setting = attributes.get('setting', self.default_setting)
     52         enabled = attributes.get('enabled', self.default_enabled)
     53         self.confirmFunc = attributes.get('confirmFunc', None)
     54         self.switchController = SwitchController(setting, enabled, handleSize)
     55         self.switchController.on_set_checked.connect(self.SetChecked)
     56         self.switchController.on_busy_changed.connect(self.UpdateBusy)
     57         self.on_switch_changed = Signal(signalName='on_switch_changed')
     58         isChecked = attributes.get('checked', self.default_checked)
     59         self.isTabStop = 1
     60         self.ConstructLayout()
     61         if self.switchController.HasSettings():
     62             isChecked = self.switchController.GetIsCheckedSettingValue()
     63         self.SetChecked(isChecked, 0)
     64         self.UpdateBusy()
     65 
     66     def ConstructLayout(self):
     67         self.ConstructSliderHandle()
     68         self._ConstructFrame()
     69 
     70     def ConstructSliderHandle(self):
     71         handleSize = self.switchController.handleSize
     72         self.sliderHandle = Container(name='sliderHandle', parent=self, fillCenter=True, align=carbonui.Align.CENTERLEFT, pos=(self.handleLabelOffset,
     73          0,
     74          handleSize,
     75          handleSize))
     76         self.sliderHandleSprite = Sprite(parent=self.sliderHandle, pos=(0,
     77          0,
     78          handleSize,
     79          handleSize), align=carbonui.Align.CENTER, texturePath=self.handleTexturePath, state=uiconst.UI_DISABLED)
     80 
     81     def _ConstructFrame(self):
     82         pass
     83 
     84     def SetChecked(self, isChecked, report = 1):
     85         isChecked = isChecked or 0
     86         self.switchController.ForceSetCheckedValue(int(isChecked))
     87         self.SetCheckLook(bool(report))
     88         if report:
     89             if isChecked:
     90                 PlaySound(uiconst.SOUND_SETDESELECTED)
     91             else:
     92                 PlaySound(uiconst.SOUND_SETSELECTED)
     93             self.switchController.UpdateSettings()
     94             self.on_switch_changed(self, self.switchController.checked)
     95 
     96     def SetCheckLook(self, animate = False):
     97         isChecked = self.switchController.checked
     98         self.sliderHandle.StopAnimations()
     99         if isChecked:
    100             newLeft = self.width - self.switchController.handleSize - self.handleLabelOffset
    101             handleTexturePath = self.handleTextureChecked
    102             handleOpacity = 1.0
    103         else:
    104             newLeft = self.handleLabelOffset
    105             handleTexturePath = self.handleTexturePath
    106             handleOpacity = 0.75
    107         self.sliderHandleSprite.texturePath = handleTexturePath
    108         self.sliderHandleSprite.opacity = handleOpacity
    109         if animate:
    110             animations.MorphScalar(self.sliderHandle, 'left', startVal=self.sliderHandle.left, endVal=newLeft, duration=0.2)
    111         else:
    112             self.sliderHandle.left = newLeft
    113         self.onFrame.display = bool(isChecked)
    114         self.offFrame.display = not bool(isChecked)
    115 
    116     def SetValue(self, value, report = True):
    117         if report:
    118             self.checked = value
    119         else:
    120             self.switchController.ForceSetCheckedValue(value)
    121 
    122     def OnClick(self, *args):
    123         if not self.switchController.disabled:
    124             if self.WasConfirmed():
    125                 self.ToggleState()
    126 
    127     def WasConfirmed(self):
    128         if self.confirmFunc:
    129             return self.confirmFunc(self.checked)
    130         return True
    131 
    132     def ToggleState(self):
    133         self.SetChecked(not self.switchController.checked)
    134 
    135     def OnMouseEnter(self, *args):
    136         self.switchController.hovered = True
    137         if self.switchController.disabled:
    138             return
    139         self.UpdateOpacity()
    140 
    141     def OnMouseExit(self, *args):
    142         self.switchController.hovered = False
    143         if self.switchController.disabled:
    144             return
    145         self.UpdateOpacity()
    146 
    147     def UpdateOpacity(self):
    148         onFrameOpacity, offFrameOpacity = self._GetOpacityValues()
    149         self.onFrame.opacity = onFrameOpacity
    150         self.offFrame.opacity = offFrameOpacity
    151 
    152     def _GetOpacityValues(self):
    153         mouseOver = uicore.uilib.mouseOver
    154         overSwitch = mouseOver and (mouseOver == self or mouseOver.IsUnder(self))
    155         if overSwitch:
    156             return self._GetMouseOverOpacity()
    157         else:
    158             return self._GetIdleOpacity()
    159 
    160     def _GetMouseOverOpacity(self):
    161         return (0.9, 1.5)
    162 
    163     def _GetIdleOpacity(self):
    164         return (ON_FRAME_OPACITY, 1.0)
    165 
    166     def GetHint(self):
    167         hintList = []
    168         if self.switchController.checked:
    169             onlineStatus = self.onText
    170         else:
    171             onlineStatus = self.offText
    172         hintList.append(GetByLabel('UI/Control/ToggleSwitchCurrentOnlineStatus', onlineStatus=onlineStatus))
    173         if not self.switchController.disabled:
    174             hintList.append(GetByLabel('UI/Control/ToggleSwitchClickToToggle'))
    175         return '<br>'.join(hintList)
    176 
    177     def OnColorThemeChanged(self):
    178         super(BaseToggleSwitch, self).OnColorThemeChanged()
    179         self.onFrame.SetRGBA(*(eveThemeColor.THEME_FOCUS[:3] + (self.onFrame.opacity,)))
    180 
    181     @property
    182     def checked(self):
    183         return self.switchController.checked
    184 
    185     @checked.setter
    186     def checked(self, value):
    187         self.switchController.checked = value
    188 
    189     @property
    190     def busy(self):
    191         return self.switchController.busy
    192 
    193     @busy.setter
    194     def busy(self, value):
    195         self.switchController.busy = value
    196 
    197     @property
    198     def busy_context(self):
    199         if self.__busy_context is None:
    200             self.__busy_context = BusyContext(self)
    201         return self.__busy_context
    202 
    203     def UpdateBusy(self):
    204         if self.destroyed:
    205             return
    206         if self.switchController.busy:
    207             self.Disable()
    208         else:
    209             self.Enable()
    210 
    211 
    212 class ToggleSwitch(BaseToggleSwitch):
    213     default_adjustSize = True
    214     _arrowsCont = None
    215     handleTextureChecked = 'res:/UI/Texture/classes/toggleSwitch/handleCheckedSmall.png'
    216 
    217     def ApplyAttributes(self, attributes):
    218         super(ToggleSwitch, self).ApplyAttributes(attributes)
    219         adjustSize = attributes.get('adjustSize', self.default_adjustSize)
    220         if adjustSize:
    221             self.AdjustSize(attributes)
    222 
    223     def AdjustSize(self, attributes):
    224         textwidthOn, textheightOn = self.onLabel.MeasureTextSize(self.onText)
    225         textwidthOff, textheightOff = self.offLabel.MeasureTextSize(self.offText)
    226         maxTextheight = max(textheightOn, textheightOff)
    227         self.switchController.handleSize = max(self.switchController.handleSize, maxTextheight - 4)
    228         maxLabelWidth = max(textwidthOn, textwidthOff)
    229         self.width = max(self.width, maxLabelWidth + self.switchController.handleSize + 2.5 * self.handleLabelOffset)
    230         self.height = max(self.height, maxTextheight + 2 * self.labelVerticalPadding)
    231         self.UpdateHandleSizes()
    232         self.SetCheckLook()
    233 
    234     def UpdateHandleSizes(self):
    235         handleSize = self.switchController.handleSize
    236         for element in (self.sliderHandle, self.sliderHandleSprite):
    237             element.width = handleSize
    238             element.height = handleSize
    239 
    240     def ConstructLayout(self):
    241         super(ToggleSwitch, self).ConstructLayout()
    242         self.ConstructLabels()
    243 
    244     def ConstructLabels(self):
    245         self.onLabel = carbonui.text.styles.TextDetail(parent=self, text=self.onText, align=carbonui.Align.CENTERLEFT, left=self.handleLabelOffset)
    246         self.offLabel = carbonui.text.styles.TextDetail(parent=self, text=self.offText, align=carbonui.Align.CENTERRIGHT, left=self.handleLabelOffset)
    247 
    248     def _ConstructFrame(self):
    249         self.onFrame = Frame(name='onFrame', bgParent=self, frameConst=('res:/UI/Texture/classes/toggleSwitch/backgroundFill.png', 8, 0), opacity=ON_FRAME_OPACITY, color=eveThemeColor.THEME_FOCUSDARK)
    250         self.offFrame = Frame(name='offFrame', bgParent=self, frameConst=('res:/UI/Texture/classes/toggleSwitch/backgroundFrame.png', 8, 0), color=eveThemeColor.THEME_FOCUSDARK)
    251 
    252     def SetCheckLook(self, animate = False):
    253         super(ToggleSwitch, self).SetCheckLook(animate)
    254         self.onLabel.display = bool(self.switchController.checked)
    255         self.offLabel.display = not bool(self.switchController.checked)
    256 
    257     def OnColorThemeChanged(self):
    258         super(ToggleSwitch, self).OnColorThemeChanged()
    259         self.offFrame.SetRGBA(*(eveThemeColor.THEME_FOCUS[:3] + (self.offFrame.opacity,)))
    260 
    261     def UpdateBusy(self):
    262         if self.destroyed:
    263             return
    264         if self.switchController.busy:
    265             self.PrepareBusyArrows()
    266             self._arrowsCont._start_arrow_animation()
    267             self.Disable()
    268         else:
    269             if self._arrowsCont is not None:
    270                 self._arrowsCont._stop_arrow_animation()
    271             self.Enable()
    272 
    273     def PrepareBusyArrows(self):
    274         if self._arrowsCont is None:
    275             self._arrowsCont = ArrowCont(parent=self, switchController=self.switchController)
    276         return self._arrowsCont
    277 
    278 
    279 class ToggleSwitchCompact(BaseToggleSwitch):
    280     default_handleSize = 8
    281     handleLabelOffset = 0
    282     default_width = 16
    283     handleTexturePath = 'res:/UI/Texture/classes/toggleSwitch/handleSmall.png'
    284 
    285     def _ConstructFrame(self):
    286         cont = Container(name='cont', parent=self, align=uiconst.VERTICALLY_CENTERED, height=4, opacity=0.8)
    287         self.onFrame = StretchSpriteHorizontal(name='onFrame', parent=cont, align=uiconst.TOTOP_NOPUSH, texturePath='res:/UI/Texture/classes/toggleSwitch/compactBackground.png', height=4, leftEdgeSize=3, rightEdgeSize=3, color=eveThemeColor.THEME_FOCUS)
    288         self.offFrame = StretchSpriteHorizontal(name='offFrame', parent=cont, align=uiconst.TOTOP_NOPUSH, texturePath='res:/UI/Texture/classes/toggleSwitch/compactBackground.png', height=4, leftEdgeSize=3, rightEdgeSize=3, color=eveColor.MATTE_BLACK)
    289 
    290 
    291 class SwitchController(object):
    292 
    293     def __init__(self, setting, enabled, handleSize):
    294         self._setting = setting
    295         self._enabled = enabled
    296         self._handleSize = handleSize
    297         self._hovered = False
    298         self._checked = False
    299         self._busy = False
    300         self.on_set_checked = Signal()
    301         self.on_busy_changed = Signal()
    302 
    303     def UpdateSettings(self):
    304         if self._setting:
    305             if self._checked:
    306                 self._setting.enable()
    307             else:
    308                 self._setting.disable()
    309 
    310     def _GetSettingValue(self):
    311         return self._setting.is_enabled()
    312 
    313     def GetIsCheckedSettingValue(self):
    314         return self._GetSettingValue()
    315 
    316     def HasSettings(self):
    317         return self._setting is not None
    318 
    319     @property
    320     def handleSize(self):
    321         return self._handleSize
    322 
    323     @handleSize.setter
    324     def handleSize(self, value):
    325         self._handleSize = value
    326 
    327     @property
    328     def hovered(self):
    329         return self._hovered
    330 
    331     @hovered.setter
    332     def hovered(self, value):
    333         self._hovered = value
    334 
    335     @property
    336     def checked(self):
    337         return self._checked
    338 
    339     @checked.setter
    340     def checked(self, value):
    341         if self._checked != value:
    342             self.SetChecked(value)
    343 
    344     def ForceSetCheckedValue(self, value):
    345         self._checked = value
    346 
    347     def SetChecked(self, value):
    348         self.on_set_checked(value)
    349 
    350     @property
    351     def disabled(self):
    352         return not self._enabled
    353 
    354     @disabled.setter
    355     def disabled(self, value):
    356         self._enabled = not value
    357 
    358     @property
    359     def busy(self):
    360         return self._busy
    361 
    362     @busy.setter
    363     def busy(self, value):
    364         if value != self._busy:
    365             self._busy = value
    366             self.on_busy_changed()
    367 
    368 
    369 BUSY_ANIMATION_DURATION = 2.0
    370 ARROWS_TEXTURE = 'res:/UI/Texture/Classes/Industry/CenterBar/arrows.png'
    371 ARROWS_TEXTURE_SEGMENT_COUNT = 6
    372 ARROWS_TEXTURE_MASK = 'res:/UI/Texture/Classes/Industry/CenterBar/arrowMask.png'
    373 
    374 class ArrowCont(Transform):
    375     default_name = 'arrowCont'
    376     default_align = carbonui.Align.TOALL
    377     default_rotationCenter = (0.5, 0.5)
    378 
    379     def ApplyAttributes(self, attributes):
    380         super(ArrowCont, self).ApplyAttributes(attributes)
    381         self.switchController = attributes.switchController
    382         self._arrows = Sprite(name='arrows', parent=self, texturePath=ARROWS_TEXTURE_MASK, textureSecondaryPath=ARROWS_TEXTURE, spriteEffect=trinity.TR2_SFX_MODULATE, color=eveColor.LED_GREY, idx=0, align=carbonui.Align.TOALL, state=uiconst.UI_DISABLED)
    383         self._arrows.tileXSecondary = True
    384         x_translation = 1.0 / float(ARROWS_TEXTURE_SEGMENT_COUNT)
    385         self._arrows.translationSecondary = (-x_translation, 0)
    386 
    387     @threadutils.threaded
    388     def _start_arrow_animation(self):
    389         if self.destroyed:
    390             return
    391         self._animate_reset_arrow()
    392         if self.switchController.busy:
    393             animations.FadeIn(self._arrows)
    394             self._loop_arrow_animation()
    395 
    396     def _stop_arrow_animation(self):
    397         if self.destroyed:
    398             return
    399         self._animate_reset_arrow()
    400         if not self.switchController.busy:
    401             self._arrows.opacity = 0.0
    402             animations.StopAnimation(self._arrows, 'translationSecondary')
    403 
    404     def _loop_arrow_animation(self):
    405         if not self.switchController.busy and not self.destroyed:
    406             return
    407         x_translation = 1.0 / float(ARROWS_TEXTURE_SEGMENT_COUNT)
    408         animations.MorphVector2(self._arrows, 'translationSecondary', (x_translation, 0.0), (-x_translation, 0.0), duration=BUSY_ANIMATION_DURATION, curveType=uiconst.ANIM_LINEAR, loops=uiconst.ANIM_REPEAT)
    409 
    410     def _animate_reset_arrow(self):
    411         x_translation = 1.0 / float(ARROWS_TEXTURE_SEGMENT_COUNT)
    412         diff = math.fabs(-x_translation - self._arrows.translationSecondary[0])
    413         if diff > 0.001:
    414             duration = diff / x_translation / 2.0 * BUSY_ANIMATION_DURATION
    415             animations.MorphVector2(self._arrows, 'translationSecondary', self._arrows.translationSecondary, (-x_translation, 0.0), duration=duration, curveType=uiconst.ANIM_LINEAR)
    416         if self.switchController.checked:
    417             self.rotation = 0
    418         else:
    419             self.rotation = math.pi