menuEntryView.py (16839B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\contextMenu\menuEntryView.py 2 import carbonui 3 import carbonui.text.styles 4 import trinity 5 import uthread2 6 from carbon.client.script.environment.AudioUtil import PlaySound 7 from carbonui import uiconst, Align 8 from carbonui.control.checkbox import Checkbox 9 from carbonui.control.contextMenu.menuEntryUnderlay import MenuEntryUnderlay 10 from carbonui.control.contextMenu.menuUtil import FlashEntrySelection 11 from carbonui.control.radioButton import RadioButton 12 from carbonui.control.slider import Slider 13 from carbonui.primitives.container import Container 14 from carbonui.primitives.containerAutoSize import ContainerAutoSize 15 from carbonui.primitives.fill import Fill 16 from carbonui.primitives.sprite import Sprite 17 from carbonui.text.color import TextColor 18 from carbonui.uianimations import animations 19 from carbonui.uicore import uicore 20 from eve.client.script.ui import eveColor 21 from eve.client.script.ui.services.tutoriallib import TutorialColor 22 PAD_LEFT = 4 23 LABELVERTICALPADDING = 4 24 LABELHORIZONTALPADDING = 8 25 26 class BaseMenuEntryView(Container): 27 28 def ApplyAttributes(self, attributes): 29 super(BaseMenuEntryView, self).ApplyAttributes(attributes) 30 self.iconSize = attributes.iconSize 31 self.menuEntryData = attributes.menuEntryData 32 self.underlay = None 33 self.highlightFrame = None 34 self.icon = None 35 self.ConstructLayout() 36 self.UpdateHeight() 37 if not self.menuEntryData.IsEnabled(): 38 self.SetDisabled() 39 40 def IsInteractable(self): 41 return self.menuEntryData.IsEnabled() 42 43 def SetDisabled(self): 44 self.label.SetRGBA(0.5, 0.5, 0.5, 1.0) 45 46 def UpdateHeight(self): 47 self.height = self._GetHeight() 48 49 def _GetHeight(self): 50 return max(self.iconSize, self.label.textheight + LABELVERTICALPADDING) 51 52 def GetRequiredWidth(self): 53 width = self.label.textwidth + self.label.left 54 if self.menuEntryData.HasSubMenuData(): 55 width += 16 56 return width 57 58 def ConstructLayout(self): 59 self.ConstructLabel() 60 61 def ConstructUnderlay(self, *args): 62 self.underlay = MenuEntryUnderlay(parent=self, padding=(1, 1, 0, 0)) 63 64 def OnMouseEnter(self, *args): 65 if not self.IsInteractable(): 66 return 67 if self.underlay is None: 68 self.ConstructUnderlay() 69 self.underlay.OnMouseEnter() 70 71 def HideHilite(self): 72 if self.underlay: 73 self.underlay.HideHilite() 74 75 def OnMouseExit(self, *args): 76 if self.underlay: 77 self.underlay.OnMouseExit() 78 79 def ConstructLabel(self, *args): 80 left = self._GetLabelLeft() 81 self.label = carbonui.text.styles.TextBody(parent=self, pos=(left, 82 0, 83 0, 84 0), align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, text=self.menuEntryData.GetTextDescriptive()) 85 86 def _GetLabelLeft(self): 87 if self.iconSize and self.menuEntryData: 88 return PAD_LEFT + self.iconSize + 8 89 else: 90 return PAD_LEFT 91 92 def GetHint(self): 93 return self.menuEntryData.GetHint() 94 95 def GetTooltipPointer(self): 96 return uiconst.POINT_RIGHT_2 97 98 99 class MenuEntryView(BaseMenuEntryView): 100 default_cursor = uiconst.UICURSOR_SELECT 101 102 def ApplyAttributes(self, attributes): 103 super(MenuEntryView, self).ApplyAttributes(attributes) 104 self.subMenuView = None 105 106 def ConstructLayout(self): 107 super(MenuEntryView, self).ConstructLayout() 108 self.ConstructSubMenuIcon() 109 self.CheckConstructIcon() 110 111 def ConstructSubMenuIcon(self, *args): 112 if self.menuEntryData.HasSubMenuData(): 113 self.subMenuIcon = Sprite(parent=self, align=uiconst.CENTERRIGHT, state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/Icons/1_16_14.png', color=TextColor.NORMAL, pos=(0, 0, 16, 16), outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.0) 114 else: 115 self.subMenuIcon = None 116 117 def IsInteractable(self): 118 return super(MenuEntryView, self).IsInteractable() and self.menuEntryData.HasFunction() 119 120 def Highlight(self): 121 if self.highlightFrame is None: 122 self.highlightFrame = Fill(parent=self, color=TutorialColor.HINT_FRAME, opacity=0.0) 123 animations.FadeTo(self.highlightFrame, 0.0, 0.8, duration=1.6, curveType=uiconst.ANIM_WAVE, loops=uiconst.ANIM_REPEAT) 124 125 def ClearHighlight(self): 126 if self.highlightFrame is not None: 127 uicore.animations.StopAllAnimations(self.highlightFrame) 128 self.highlightFrame.Close() 129 self.pulseThread = None 130 131 def CheckConstructIcon(self): 132 if not self.iconSize: 133 return 134 if self.menuEntryData.HasGroupIcon(): 135 self.ConstructGroupIcon() 136 elif self.menuEntryData.HasIcon(): 137 self.ConstructIcon() 138 139 def ConstructGroupIcon(self): 140 iconTexturePath, bgTexturePath, bgColor = self.menuEntryData.GetGroupIconData() 141 self.icon = Container(name='iconCont', parent=self, pos=(PAD_LEFT, 142 0, 143 self.iconSize, 144 self.iconSize), align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED) 145 Sprite(name='icon', bgParent=self.icon, texturePath=iconTexturePath) 146 if bgTexturePath: 147 Sprite(name='iconBG', bgParent=self.icon, texturePath=bgTexturePath, color=bgColor, outputMode=trinity.Tr2SpriteTarget.GLOW, opacity=0.75) 148 Sprite(name='iconBG', bgParent=self.icon, texturePath=bgTexturePath, color=bgColor) 149 150 def ConstructIcon(self): 151 self.icon = Sprite(name='icon', parent=self, pos=(PAD_LEFT, 152 0, 153 self.iconSize, 154 self.iconSize), align=uiconst.CENTERLEFT, texturePath=self.menuEntryData.GetIcon(), state=uiconst.UI_DISABLED, color=TextColor.NORMAL) 155 156 def SetDisabled(self): 157 super(MenuEntryView, self).SetDisabled() 158 if self.icon: 159 self.icon.opacity = 0.5 160 161 def _OnClose(self): 162 if self.subMenuView is not None and not self.subMenuView.destroyed: 163 self.subMenuView.Close() 164 self.subMenuView = None 165 Container._OnClose(self) 166 167 def OnMouseDown(self, *etc): 168 if not self.menuEntryData.HasFunction() or not self.menuEntryData.IsEnabled(): 169 return 170 self._AnimMouseDown() 171 if self.underlay: 172 self.underlay.OnMouseDown() 173 174 def _AnimMouseDown(self): 175 animations.SpColorMorphTo(self.label, self.label.GetRGBA(), eveColor.BLACK, duration=uiconst.TIME_MOUSEDOWN) 176 if self.icon and isinstance(self.icon, Sprite): 177 animations.SpColorMorphTo(self.icon, self.icon.GetRGBA(), eveColor.BLACK, duration=uiconst.TIME_MOUSEDOWN) 178 if self.subMenuIcon: 179 animations.SpColorMorphTo(self.subMenuIcon, self.subMenuIcon.GetRGBA(), eveColor.BLACK, duration=uiconst.TIME_MOUSEDOWN) 180 181 def OnMouseUp(self, *etc): 182 if not self.menuEntryData.IsEnabled(): 183 return 184 if self.underlay: 185 self.underlay.OnMouseUp() 186 if not self.IsMouseOverEntry(): 187 return 188 if not self.menuEntryData.IsEnabled(): 189 return 190 PlaySound('msg_MenuActivate_play') 191 if self.menuEntryData.HasFunction(): 192 uthread2.start_tasklet(self.menuEntryData.ExecuteFunction) 193 uthread2.start_tasklet(self._OnFunctionCalled) 194 195 def _OnFunctionCalled(self): 196 from carbonui.control.contextMenu.menuUtil import CloseContextMenus 197 pos = self.GetAbsolute() 198 CloseContextMenus() 199 FlashEntrySelection(pos) 200 201 def OnMouseEnter(self, *args): 202 if not self.menuEntryData.IsEnabled(): 203 return 204 super(MenuEntryView, self).OnMouseEnter() 205 if self.menuEntryData.IsSubMenuDynamic(): 206 uthread2.start_tasklet(self._ContinouslyReconstrureSubMenuThread) 207 else: 208 uthread2.start_tasklet(self.CheckReconstructSubMenu) 209 if self.menuEntryData.HasSubMenuData() or self.menuEntryData.HasFunction(): 210 self._AnimMouseEnter() 211 if self.subMenuIcon: 212 if not self.subMenuView: 213 PlaySound(uiconst.SOUND_EXPAND) 214 else: 215 PlaySound(uiconst.SOUND_ENTRY_HOVER) 216 217 def _AnimMouseEnter(self): 218 animations.SpColorMorphTo(self.label, startColor=self.label.GetRGBA(), endColor=TextColor.HIGHLIGHT, duration=uiconst.TIME_ENTRY) 219 if self.icon and isinstance(self.icon, Sprite): 220 animations.SpColorMorphTo(self.icon, self.icon.GetRGBA(), TextColor.HIGHLIGHT, duration=uiconst.TIME_ENTRY) 221 if self.subMenuIcon: 222 animations.SpColorMorphTo(self.subMenuIcon, self.subMenuIcon.GetRGBA(), TextColor.HIGHLIGHT, duration=uiconst.TIME_ENTRY) 223 animations.MorphScalar(self.subMenuIcon, 'glowBrightness', self.subMenuIcon.glowBrightness, 0.5, duration=uiconst.TIME_ENTRY) 224 225 def _ContinouslyReconstrureSubMenuThread(self): 226 while not self.destroyed and self.IsMouseOverEntry(): 227 self.CheckReconstructSubMenu() 228 uthread2.Sleep(0.5) 229 230 def CheckReconstructSubMenu(self): 231 if self.destroyed: 232 return 233 self._CollapseSiblingSubMenus() 234 if self.IsMouseOverEntry() and self.menuEntryData.HasSubMenuData(): 235 self.ReconstructSubMenuView() 236 237 def HideHilite(self): 238 super(MenuEntryView, self).HideHilite() 239 240 def OnMouseExit(self, *args): 241 if not self.menuEntryData.IsEnabled(): 242 return 243 self._AnimMouseExit() 244 super(MenuEntryView, self).OnMouseExit(*args) 245 246 def _AnimMouseExit(self): 247 animations.SpColorMorphTo(self.label, self.label.GetRGBA(), TextColor.NORMAL, duration=uiconst.TIME_EXIT) 248 if self.icon and isinstance(self.icon, Sprite): 249 animations.SpColorMorphTo(self.icon, self.icon.GetRGBA(), TextColor.NORMAL, duration=uiconst.TIME_EXIT) 250 if self.subMenuIcon: 251 animations.SpColorMorphTo(self.subMenuIcon, self.subMenuIcon.GetRGBA(), TextColor.NORMAL, duration=uiconst.TIME_EXIT) 252 animations.MorphScalar(self.subMenuIcon, 'glowBrightness', self.subMenuIcon.glowBrightness, 0.0, duration=uiconst.TIME_EXIT) 253 254 def Collapse(self): 255 if self.subMenuView: 256 if not self.subMenuView.destroyed: 257 self.subMenuView.Collapse() 258 self.subMenuView = None 259 260 def ReconstructSubMenuView(self): 261 from carbonui.control.contextMenu.contextMenu import ContextSubMenu 262 from carbonui.control.contextMenu.menuUtil import CloseContextMenus 263 self._CollapseSiblingSubMenus() 264 if not self.IsMouseOverEntry(): 265 return 266 if self.subMenuView: 267 self.subMenuView.Close() 268 menuData = self.menuEntryData.GetSubMenuData() 269 if not menuData: 270 return 271 menu = ContextSubMenu(parent=uicore.layer.menu, parentEntry=self, menuData=menuData, idx=0) 272 if self.destroyed: 273 CloseContextMenus() 274 return 275 self.subMenuView = menu 276 277 def _CollapseSiblingSubMenus(self): 278 for menuEntryView in self.parent.children: 279 if menuEntryView != self and getattr(menuEntryView, 'subMenuView', None): 280 menuEntryView.Collapse() 281 282 def IsMouseOverEntry(self): 283 return uicore.uilib.mouseOver in (self, self.label) 284 285 286 class MenuEntryViewCaption(BaseMenuEntryView): 287 288 def UpdateAlignment(self, budgetLeft = 0, budgetTop = 0, budgetWidth = 0, budgetHeight = 0, updateChildrenOnly = False): 289 self.padTop = 16 if self.GetOrder() else 0 290 return super(MenuEntryViewCaption, self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth, budgetHeight, updateChildrenOnly) 291 292 def ConstructLabel(self, *args): 293 self.label = carbonui.text.styles.TextHeader(parent=self, pos=(PAD_LEFT, 294 0, 295 0, 296 0), align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, text=self.menuEntryData.GetTextDescriptive(), color=TextColor.HIGHLIGHT) 297 298 def SetDisabled(self): 299 pass 300 301 def _GetHeight(self): 302 return self.label.textheight + 8 303 304 305 class MenuEntryViewLabel(BaseMenuEntryView): 306 307 def UpdateAlignment(self, budgetLeft = 0, budgetTop = 0, budgetWidth = 0, budgetHeight = 0, updateChildrenOnly = False): 308 self.padTop = 8 if self.GetOrder() else 0 309 return super(MenuEntryViewLabel, self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth, budgetHeight, updateChildrenOnly) 310 311 def ConstructLabel(self, *args): 312 self.label = carbonui.text.styles.TextBody(parent=self, pos=(PAD_LEFT, 313 0, 314 0, 315 0), align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, text=self.menuEntryData.GetTextDescriptive(), color=TextColor.SECONDARY) 316 317 def SetDisabled(self): 318 pass 319 320 def _GetHeight(self): 321 return self.label.textheight + 8 322 323 324 class MenuEntryViewCheckbox(BaseMenuEntryView): 325 326 def ConstructLayout(self): 327 super(MenuEntryViewCheckbox, self).ConstructLayout() 328 self.ConstructButton() 329 self.menuEntryData.on_enabled_changed.connect(self._on_enabled_changed) 330 331 def ConstructButton(self): 332 self.checkbox = Checkbox(parent=self, align=uiconst.CENTERLEFT, setting=self.menuEntryData.setting, minHeight=Checkbox.DIODE_SIZE, padding=0, left=PAD_LEFT, text=self.menuEntryData.GetTextDescriptive(), enabled=self.menuEntryData.IsEnabled(), hint=self.menuEntryData.hint) 333 334 def SetDisabled(self): 335 self.checkbox.enabled = False 336 337 def GetRequiredWidth(self): 338 return self.checkbox.left + self.checkbox.width 339 340 def ConstructLabel(self, *args): 341 pass 342 343 def OnMouseEnter(self, *args): 344 super(MenuEntryViewCheckbox, self).OnMouseEnter(*args) 345 self.checkbox.OnMouseEnter() 346 347 def OnMouseExit(self, *args): 348 super(MenuEntryViewCheckbox, self).OnMouseExit(*args) 349 self.checkbox.OnMouseExit() 350 351 def OnClick(self, *args): 352 super(MenuEntryViewCheckbox, self).OnClick(*args) 353 self.checkbox.OnClick() 354 355 def OnMouseDown(self, *args): 356 super(MenuEntryViewCheckbox, self).OnMouseDown(*args) 357 self.checkbox.OnMouseDown(*args) 358 359 def OnMouseUp(self, *args): 360 super(MenuEntryViewCheckbox, self).OnMouseUp(*args) 361 self.checkbox.OnMouseUp(*args) 362 363 def _GetHeight(self): 364 return self.checkbox.height 365 366 def _on_enabled_changed(self, menu_entry_data): 367 self.checkbox.enabled = menu_entry_data.IsEnabled() 368 369 370 class MenuEntryViewRadioButton(MenuEntryViewCheckbox): 371 372 def ConstructButton(self): 373 self.checkbox = RadioButton(parent=self, align=uiconst.CENTERLEFT, minHeight=Checkbox.DIODE_SIZE, padding=0, left=PAD_LEFT, setting=self.menuEntryData.setting, retval=self.menuEntryData.value, text=self.menuEntryData.GetTextDescriptive(), enabled=self.menuEntryData.IsEnabled()) 374 375 376 class MenuEntryViewSlider(BaseMenuEntryView): 377 378 def ConstructLayout(self): 379 super(MenuEntryViewSlider, self).ConstructLayout() 380 self.ConstructSlider() 381 self.menuEntryData.on_enabled_changed.connect(self._on_enabled_changed) 382 383 def ConstructSlider(self): 384 self.content = ContainerAutoSize(name='content', parent=self, align=uiconst.TOTOP, width=256, padLeft=self._GetLabelLeft()) 385 labelContainer = ContainerAutoSize(parent=self.content, align=uiconst.TOTOP, alignMode=uiconst.TOTOP, padTop=4) 386 self.valueLabel = carbonui.text.styles.TextBody(parent=labelContainer, align=Align.TORIGHT, text=self._GetValueText(self.menuEntryData.setting.get())) 387 self.label = carbonui.text.styles.TextBody(parent=labelContainer, align=Align.TOTOP, text=self.menuEntryData.GetTextDescriptive()) 388 self.slider = Slider(parent=self.content, align=Align.TOTOP, setting=self.menuEntryData.setting, enabled=self.menuEntryData.IsEnabled(), minLabel=self.menuEntryData.min_label, maxLabel=self.menuEntryData.max_label, isInteger=self.menuEntryData.isInteger, padTop=2, callback=self._on_value_changed, on_dragging=self._on_value_changed) 389 390 def SetDisabled(self): 391 self.slider.enabled = False 392 393 def ConstructLabel(self, *args): 394 pass 395 396 def GetRequiredWidth(self): 397 return self.content.left + self.content.width 398 399 def _GetHeight(self): 400 _, height = self.label.MeasureTextSize(self.menuEntryData.GetTextDescriptive()) 401 return height + self.slider.height + 10 402 403 def _on_enabled_changed(self, menu_entry_data): 404 self.slider.enabled = menu_entry_data.IsEnabled() 405 406 def _on_value_changed(self, slider): 407 self.valueLabel.text = self._GetValueText(slider.value) 408 409 def IsInteractable(self): 410 return False 411 412 def _GetValueText(self, value): 413 import eveformat 414 return eveformat.number(value, decimal_places=0 if self.menuEntryData.isInteger else 2)