checkbox.py (14407B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\checkbox.py 2 import logging 3 import math 4 import uthread 5 from carbon.client.script.environment.AudioUtil import PlaySound 6 from carbonui import fontconst, uiconst 7 from carbonui.primitives.container import Container 8 from carbonui.primitives.containerAutoSize import ContainerAutoSize 9 from carbonui.primitives.fill import Fill 10 from carbonui.primitives.frame import Frame 11 from carbonui.primitives.sprite import Sprite 12 from carbonui.text.color import TextColor 13 from carbonui.uianimations import animations 14 from carbonui.util.various_unsorted import GetAttrs, GetBrowser 15 from eve.client.script.ui import eveThemeColor 16 from eve.client.script.ui.control.eveLabel import EveLabelMedium 17 logger = logging.getLogger(__name__) 18 19 class Checkbox(ContainerAutoSize): 20 default_enabled = True 21 DIODE_SIZE = 16 22 DIODE_TEXT_GAP_SIZE = 8 23 LABEL_COLOR_IDLE = TextColor.NORMAL 24 LABEL_COLOR_HOVER = TextColor.HIGHLIGHT 25 LABEL_COLOR_DISABLED = TextColor.DISABLED 26 CHECK_MARK_COLOR_DISABLED = TextColor.DISABLED 27 CHECK_MARK_COLOR_IDLE = eveThemeColor.THEME_FOCUS 28 default_alignMode = uiconst.TOPLEFT 29 default_fontsize = fontconst.EVE_MEDIUM_FONTSIZE 30 default_width = 0 31 default_height = 24 32 default_minWidth = 24 33 default_minHeight = 24 34 default_checkedTexture = 'res:/UI/Texture/classes/checkbox/checked.png' 35 default_align = uiconst.TOTOP 36 default_text = '' 37 default_checked = 0 38 default_callback = None 39 default_state = uiconst.UI_NORMAL 40 default_wrapLabel = True 41 default_cursor = uiconst.UICURSOR_SELECT 42 default_fontStyle = None 43 default_fontFamily = None 44 default_fontPath = None 45 default_setting = None 46 default_settingsPath = ('user', 'ui') 47 default_settingsKey = None 48 49 def ApplyAttributes(self, attributes): 50 self._callback = None 51 if 'callback' in attributes: 52 self._callback = attributes.pop('callback') 53 super(Checkbox, self).ApplyAttributes(attributes) 54 text = attributes.get('text', self.default_text) 55 self.checkedTexture = attributes.get('checkedTexture', self.default_checkedTexture) 56 self._enabled = attributes.get('enabled', self.default_enabled) 57 self.wrapLabel = attributes.get('wrapLabel', self.default_wrapLabel) 58 self.fontStyle = attributes.get('fontStyle', self.default_fontStyle) 59 self.fontFamily = attributes.get('fontFamily', self.default_fontFamily) 60 self.fontPath = attributes.get('fontPath', self.default_fontPath) 61 self.fontsize = attributes.get('fontsize', self.default_fontsize) 62 isChecked = attributes.get('checked', self.default_checked) 63 self.setting = attributes.get('setting', self.default_setting) 64 self.settingsKey = attributes.get('settingsKey', self.default_settingsKey) 65 self.settingsPath = attributes.get('settingsPath', self.default_settingsPath) 66 self.underlay = None 67 self._hovered = False 68 self._checked = False 69 self.isTabStop = 1 70 self.checkboxCont = None 71 if self.settingsKey is not None: 72 self.name = self.settingsKey if isinstance(self.settingsKey, (str, unicode)) else repr(self.settingsKey) 73 self.ConstructLayout() 74 if self.setting is not None: 75 isChecked = self._GetIsCheckedSettingValue() 76 self.setting.on_change.connect(self._on_setting_changed) 77 self.SetChecked(isChecked, 0) 78 self.SetLabelText(text) 79 self._update_enabled(animate=False) 80 self._update_checkmark_color() 81 82 def Close(self): 83 super(Checkbox, self).Close() 84 try: 85 if self.setting: 86 self.setting.on_change.disconnect(self._on_setting_changed) 87 except Exception as e: 88 logger.exception(e) 89 90 def _on_setting_changed(self, value, *args): 91 self.SetChecked(value, report=False) 92 93 @property 94 def checked(self): 95 return self._checked 96 97 @checked.setter 98 def checked(self, value): 99 if self._checked != value: 100 self.SetChecked(value) 101 102 def ConstructLayout(self): 103 self.ConstructLabel() 104 self.ConstructCheckboxCont() 105 106 def ConstructLabel(self): 107 self.label = EveLabelMedium(name='text', parent=self, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, left=self.DIODE_SIZE + self.DIODE_TEXT_GAP_SIZE, maxLines=1 if not self.wrapLabel else None, color=self._get_label_color()) 108 109 def _get_label_color(self): 110 if self.hovered: 111 return self.LABEL_COLOR_HOVER 112 elif self.enabled: 113 return self.LABEL_COLOR_IDLE 114 else: 115 return self.LABEL_COLOR_DISABLED 116 117 def _update_label_color(self, animate = True): 118 if self.label: 119 if animate: 120 duration = uiconst.TIME_ENTRY if self.hovered else uiconst.TIME_EXIT 121 animations.SpColorMorphTo(self.label, endColor=self._get_label_color(), duration=duration) 122 else: 123 self.label.SetRGBA(*self._get_label_color()) 124 125 def OnColorThemeChanged(self): 126 super(Checkbox, self).OnColorThemeChanged() 127 self._update_checkmark_color() 128 129 def Enable(self): 130 self.enabled = True 131 132 def Disable(self): 133 self.enabled = False 134 135 @property 136 def enabled(self): 137 return self._enabled 138 139 @enabled.setter 140 def enabled(self, value): 141 if self._enabled != value: 142 self._enabled = value 143 self._update_enabled() 144 145 @property 146 def disabled(self): 147 return not self._enabled 148 149 @disabled.setter 150 def disabled(self, value): 151 self.enabled = not value 152 153 @property 154 def hovered(self): 155 return self._hovered 156 157 def _update_enabled(self, animate = True): 158 if self.enabled: 159 self.underlay.Enable() 160 else: 161 self.underlay.Disable() 162 self._update_checkmark_color() 163 self._update_label_color(animate) 164 165 def ToggleState(self): 166 self.SetChecked(not self._checked) 167 168 def OnChar(self, char, flag): 169 if char == uiconst.VK_SPACE: 170 uthread.pool('checkbox::OnChar', self.ToggleState) 171 return 1 172 173 def OnSetFocus(self, *args): 174 if self and not self.destroyed and self.parent and self.parent.name == 'inlines': 175 if self.parent.parent and self.parent.parent.sr.node: 176 browser = GetBrowser(self) 177 if browser: 178 uthread.new(browser.ShowObject, self) 179 180 def SetValue(self, value): 181 self.SetChecked(value) 182 183 def GetValue(self): 184 return self._checked 185 186 def SetLabelText(self, labeltext): 187 self.label.text = labeltext 188 if self.align not in (uiconst.TOTOP, uiconst.TOBOTTOM): 189 self.ChangeWidth() 190 191 def ChangeWidth(self, *args): 192 self.width = max(20, self.label.padLeft + self.label.left + self.label.textwidth + self.label.padRight) + 1 193 194 def UpdateUIScaling(self, value, oldValue): 195 super(Checkbox, self).UpdateUIScaling(value, oldValue) 196 self.ChangeWidth() 197 198 def GetLabelText(self): 199 return self.label.GetText() 200 201 def SetTextColor(self, color): 202 self.label.SetTextColor(color) 203 204 def GetSettingsKey(self): 205 if self.setting: 206 return self.setting.settings_key 207 else: 208 return self.settingsKey 209 210 def SetSettingsKey(self, settingsKey): 211 self.settingsKey = settingsKey 212 213 def GetSettingsPath(self): 214 return self.settingsPath 215 216 def UpdateSettings(self): 217 if self.setting: 218 if self._checked: 219 self.setting.enable() 220 else: 221 self.setting.disable() 222 elif self.settingsPath: 223 self._ApplySettingOld(self._checked) 224 225 def _ApplySettingOld(self, value): 226 setting = GetAttrs(settings, *self.settingsPath) 227 try: 228 setting.Set(self.settingsKey, value) 229 except: 230 logger.error('Failed to assign setting to: %s, %s' % (self.settingsPath, self.settingsKey)) 231 232 def _GetSettingValue(self): 233 return self.setting.is_enabled() 234 235 def _GetIsCheckedSettingValue(self): 236 return self._GetSettingValue() 237 238 def ConstructCheckboxCont(self): 239 if self.checkboxCont: 240 self.checkboxCont.Close() 241 diodeAlign = uiconst.TOPLEFT 242 self.checkboxCont = Container(name='diode', parent=self, align=diodeAlign, state=uiconst.UI_DISABLED, pos=(0, 243 (self.minHeight - self.DIODE_SIZE) / 2, 244 16, 245 16)) 246 self._ConstructCheckmark() 247 248 def _ConstructCheckmark(self): 249 self.checkMark = Sprite(name='self_ok', parent=self.checkboxCont, align=uiconst.CENTER, state=uiconst.UI_HIDDEN, pos=(0, 0, 16, 16), texturePath=self.checkedTexture) 250 self.underlay = CheckboxUnderlay(parent=self.checkboxCont, enabled=self._enabled) 251 252 def _update_checkmark_color(self): 253 color = self.CHECK_MARK_COLOR_IDLE if self._enabled else self.CHECK_MARK_COLOR_DISABLED 254 self.checkMark.SetRGBA(*color) 255 256 def IsRightAligned(self): 257 return self.GetAlign() in (uiconst.TOPRIGHT, uiconst.CENTERRIGHT) 258 259 def SetChecked(self, isChecked, report = 1): 260 isChecked = isChecked or 0 261 self._checked = int(isChecked) 262 self.checkMark.state = uiconst.UI_DISABLED if self._checked else uiconst.UI_HIDDEN 263 if report: 264 if isChecked: 265 PlaySound(uiconst.SOUND_SETDESELECTED) 266 else: 267 PlaySound(uiconst.SOUND_SETSELECTED) 268 self.UpdateSettings() 269 self.OnChange() 270 if isChecked: 271 self.underlay.Select(animate=report) 272 else: 273 self.underlay.Deselect(animate=report) 274 275 def OnChange(self): 276 if self._callback: 277 self._callback(self) 278 279 def SetCallback(self, callback): 280 self._callback = callback 281 282 def SetLabel(self, labeltext): 283 self.SetLabelText(labeltext) 284 285 def GetTooltipPosition(self, *args, **kwds): 286 l, t, w, h = self.GetAbsolute() 287 label = self.label 288 if label.text: 289 return (l, 290 t, 291 label.padLeft + label.left + label.textwidth, 292 h) 293 else: 294 return (l, 295 t, 296 w, 297 h) 298 299 def OnClick(self, *args): 300 if not self.disabled: 301 self.ToggleState() 302 303 def OnMouseEnter(self, *args): 304 self._hovered = True 305 if self.disabled: 306 return 307 PlaySound(uiconst.SOUND_BUTTON_HOVER) 308 self._update_label_color() 309 if self.underlay: 310 self.underlay.OnMouseEnter() 311 312 def OnMouseExit(self, *args): 313 self._hovered = False 314 if self.disabled: 315 return 316 self._update_label_color() 317 if self.underlay: 318 self.underlay.OnMouseExit() 319 320 def OnMouseDown(self, mouseBtn = None): 321 if self.disabled or mouseBtn != uiconst.MOUSELEFT: 322 return 323 if self.underlay: 324 self.underlay.OnMouseDown() 325 326 def OnMouseUp(self, mouseBtn = None): 327 super(Checkbox, self).OnMouseUp(mouseBtn) 328 if self.disabled or mouseBtn != uiconst.MOUSELEFT: 329 return 330 if self.underlay: 331 self.underlay.OnMouseUp() 332 333 def UpdateAlignment(self, budgetLeft = 0, budgetTop = 0, budgetWidth = 0, budgetHeight = 0, updateChildrenOnly = False): 334 budget = super(Checkbox, self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth, budgetHeight, updateChildrenOnly) 335 if self.align in uiconst.ALIGNMENTS_WITH_RELEVANT_WIDTH: 336 self.label.clear_set_width() 337 else: 338 width, _ = self.GetCurrentAbsoluteSize() 339 self.label.width = width - self.label.left 340 measurer = self.label.measurer 341 approximateGlyphHeight = int(math.ceil(9.0 / 13.0 * self.ReverseScaleDpi(measurer.fontSize))) 342 glyphDistanceFromTop = self.ReverseScaleDpi(measurer.ascender) - approximateGlyphHeight 343 self.label.top = round((self.minHeight - approximateGlyphHeight) / 2.0 - glyphDistanceFromTop) 344 if self.label._alignmentDirty: 345 size_changed = budget[4] 346 budget = super(Checkbox, self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth, budgetHeight, updateChildrenOnly=False) 347 budget = budget[:4] + (size_changed or budget[4],) 348 return budget 349 350 351 class CheckboxUnderlay(Container): 352 UNDERLAY_OPACITY_NORMAL = 1.0 353 UNDERLAY_OPACITY_DISABLED = 0.5 354 355 def __init__(self, parent = None, bgParent = None, align = uiconst.TOALL, padding = 0, enabled = True): 356 self._hover = None 357 self._highlight = None 358 self._underlay = None 359 super(CheckboxUnderlay, self).__init__(parent=parent, bgParent=bgParent, align=align, padding=padding) 360 self._hover = Frame(parent=self, align=uiconst.TOALL, texturePath='res:/UI/Texture/classes/checkbox/underlay_hover.png', color=eveThemeColor.THEME_FOCUS, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.3, cornerSize=8, opacity=0.0) 361 self._highlight = Fill(parent=self, align=uiconst.TOALL, padding=1, opacity=0.0) 362 self._underlay = Frame(parent=self, align=uiconst.TOALL, texturePath='res:/UI/Texture/classes/checkbox/underlay.png', cornerSize=3, opacity=self.UNDERLAY_OPACITY_NORMAL if enabled else self.UNDERLAY_OPACITY_DISABLED) 363 364 def OnColorThemeChanged(self): 365 super(CheckboxUnderlay, self).OnColorThemeChanged() 366 self._hover.SetRGBA(*(eveThemeColor.THEME_FOCUS[:3] + (self._hover.opacity,))) 367 368 def Enable(self): 369 self._underlay.opacity = self.UNDERLAY_OPACITY_NORMAL 370 371 def Disable(self): 372 self._underlay.opacity = self.UNDERLAY_OPACITY_DISABLED 373 374 def Select(self, animate = True): 375 pass 376 377 def Deselect(self, animate = True): 378 pass 379 380 def OnMouseEnter(self, *args): 381 if self._hover is not None: 382 animations.FadeIn(self._hover, duration=0.1) 383 384 def OnMouseExit(self, *args): 385 if self._hover is not None: 386 animations.FadeOut(self._hover, duration=0.3) 387 388 def OnMouseDown(self, *args): 389 animations.FadeIn(self._highlight, duration=uiconst.TIME_ENTRY) 390 391 def OnMouseUp(self, *args): 392 animations.FadeOut(self._highlight, duration=uiconst.TIME_MOUSEUP)