tooltipHandler.py (11656B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\tooltips\tooltipHandler.py 2 import uthread 3 import log 4 import blue 5 import weakref 6 import carbonui.const as uiconst 7 from carbonui.control.contextMenu.menuUtil import ObjectHasMenu 8 from carbonui.uianimations import animations 9 from carbonui.util.mouseTargetObject import MouseTargetObject 10 from eve.client.script.ui.control.pointerPanel import FadeOutPanelAndClose 11 from eve.client.script.ui.control.tooltips import TooltipPanel, TooltipGeneric, TooltipPersistentPanel 12 from eve.client.script.ui.tooltips.tooltipUtil import RefreshTooltipForOwner as RefreshTooltipForOwnerUtil 13 from carbonui.uicore import uicore 14 FADEOUT_FAST = 0.1 15 LOAD_ABORTED = 1 16 LOAD_LOADED = 2 17 LOAD_NOTLOADED = 3 18 SLEEPTIME_COOLDOWN = 500 19 TOOLTIP_DELAY_MIN = 5 20 TOOLTIP_DELAY_MAX = 3005 21 TOOLTIP_SETTINGS_GENERIC = 'tooltipDelayGeneric' 22 TOOLTIP_DELAY_GENERIC = 250 23 TOOLTIP_DELAY_GAMEPLAY = 250 24 TOOLTIP_SETTINGS_MODULE = 'tooltipDelayModule' 25 TOOLTIP_DELAY_MODULE = 700 26 TOOLTIP_SETTINGS_BRACKET = 'tooltipDelayBracket' 27 TOOLTIP_DELAY_BRACKET = 50 28 29 class TooltipHandler(object): 30 lastMouseOver = None 31 lastMousePosition = (-1, -1) 32 lastCloseTime = None 33 lastAuxiliaryTooltipStr = None 34 tooltipPanel = None 35 tooltipHint = None 36 dirty = True 37 tooltipThread = None 38 persistentTooltips = None 39 40 def __init__(self, *args, **kwds): 41 self.persistentTooltips = weakref.WeakKeyDictionary() 42 43 def RefreshTooltipForOwner(self, owner): 44 return RefreshTooltipForOwnerUtil(owner) 45 46 def GetPersistentTooltipByOwner(self, owner): 47 if owner.destroyed: 48 return 49 if owner in self.persistentTooltips: 50 panel = self.persistentTooltips[owner] 51 if not (panel.destroyed or panel.beingDestroyed): 52 return panel 53 54 def LoadPersistentTooltip(self, owner, loadFunction = None, loadArguments = None, parent = None, customPointDirection = None, customTooltipClass = None): 55 if owner.destroyed: 56 return 57 currentTooltip = self.GetPersistentTooltipByOwner(owner) 58 if currentTooltip and not (currentTooltip.destroyed or currentTooltip.beingDestroyed): 59 FadeOutPanelAndClose(currentTooltip, duration=FADEOUT_FAST) 60 tooltipClass = customTooltipClass or TooltipPersistentPanel 61 if parent is None: 62 parent = uicore.layer.menu 63 tooltipPanel = tooltipClass(parent=parent, owner=owner, idx=0, state=uiconst.UI_DISABLED, pointerDirection=customPointDirection) 64 self.persistentTooltips[owner] = tooltipPanel 65 loadFunction = loadFunction or getattr(tooltipPanel, 'LoadTooltip', None) 66 if loadFunction and loadArguments: 67 loadFunction(*loadArguments) 68 elif loadFunction: 69 loadFunction(tooltipPanel, owner) 70 uthread.new(tooltipPanel.ShowPanel, owner) 71 return tooltipPanel 72 73 def RefreshTooltip(self): 74 if self.dirty: 75 uthread.new(self._UpdateTooltip) 76 77 def FlagTooltipsDirty(self, *args, **kwds): 78 if not uicore.isRunning: 79 return 80 self.dirty = True 81 82 UpdateTooltip = FlagTooltipsDirty 83 84 def HaveVisibleTooltipPanel(self): 85 return self.tooltipPanel and not (self.tooltipPanel.destroyed or self.tooltipPanel.beingDestroyed) 86 87 def HaveVisibleTooltipHint(self): 88 return self.tooltipHint and not (self.tooltipHint.destroyed or self.tooltipHint.beingDestroyed) 89 90 def _CloseTooltipPanel(self): 91 if self.HaveVisibleTooltipPanel(): 92 FadeOutPanelAndClose(self.tooltipPanel, duration=FADEOUT_FAST) 93 self.tooltipPanel = None 94 95 def _CloseTooltipHint(self): 96 if self.HaveVisibleTooltipHint(): 97 FadeOutPanelAndClose(self.tooltipHint, duration=FADEOUT_FAST) 98 self.tooltipHint = None 99 100 def LoadTooltipImmediate(self): 101 uthread.new(self._UpdateTooltip, True) 102 103 def _UpdateTooltip(self, immediate = False): 104 currentMouseOver = uicore.uilib.mouseOver 105 currentAuxiliaryTooltipStr = uicore.uilib.auxiliaryTooltip 106 if ObjectHasMenu(currentMouseOver) and not self.IsUnderTooltip(currentMouseOver): 107 self.CloseTooltip() 108 return 109 self.dirty = False 110 if currentMouseOver is self.lastMouseOver and not self.HaveVisibleTooltipPanel() and self.HaveVisibleTooltipHint(): 111 hint = self.GetHintFromUIObject(currentMouseOver) 112 if hint: 113 self.tooltipHint.SetTooltipString(hint, currentMouseOver) 114 return 115 if uicore.uilib.GetMouseCapture(): 116 return 117 currentPosition = (uicore.uilib.x, uicore.uilib.y) 118 newPosition = currentPosition != self.lastMousePosition 119 self.lastMousePosition = currentPosition 120 if not newPosition and (self.HaveVisibleTooltipPanel() or self.HaveVisibleTooltipHint()): 121 showInstant = True 122 else: 123 showInstant = False 124 if not immediate: 125 sleepTime = self._GetSleepTime(currentMouseOver) 126 blue.synchro.SleepWallclock(sleepTime) 127 if currentMouseOver is not uicore.uilib.mouseOver: 128 return 129 newMouseOver = currentMouseOver is not self.lastMouseOver or currentAuxiliaryTooltipStr is not self.lastAuxiliaryTooltipStr 130 self.lastMouseOver = currentMouseOver 131 self.lastAuxiliaryTooltipStr = currentAuxiliaryTooltipStr 132 panelLoaded = LOAD_NOTLOADED 133 if self.HaveVisibleTooltipPanel() and self.tooltipPanel.owner is currentMouseOver: 134 return 135 if newMouseOver or self.tooltipPanel and (self.tooltipPanel.destroyed or self.tooltipPanel.beingDestroyed): 136 panelLoaded = self._LoadTooltipPanel(currentMouseOver, showInstant) 137 if panelLoaded == LOAD_ABORTED: 138 return 139 if panelLoaded == LOAD_NOTLOADED: 140 self.UpdateTooltipHint(currentMouseOver) 141 142 def UpdateTooltipHint(self, currentMouseOver): 143 hint = self.GetHintFromUIObject(currentMouseOver) 144 if hint: 145 if self.HaveVisibleTooltipPanel() and not self.IsUnderTooltip(currentMouseOver): 146 FadeOutPanelAndClose(self.tooltipPanel, duration=FADEOUT_FAST) 147 if not self.tooltipHint or self.tooltipHint.destroyed or self.tooltipHint.beingDestroyed: 148 self.tooltipHint = TooltipGeneric(parent=uicore.layer.hint, idx=0) 149 animations.FadeTo(self.tooltipHint, startVal=0.0, endVal=1.0, duration=0.2, curveType=uiconst.ANIM_SMOOTH) 150 self.tooltipHint.SetTooltipString(hint, currentMouseOver) 151 else: 152 self._CloseTooltipHint() 153 154 def _GetSleepTime(self, currentMouseOver): 155 tooltipDelay = None 156 if hasattr(currentMouseOver, 'GetTooltipDelay'): 157 tooltipDelay = currentMouseOver.GetTooltipDelay() 158 if tooltipDelay is None: 159 tooltipDelay = settings.user.ui.Get(TOOLTIP_SETTINGS_GENERIC, TOOLTIP_DELAY_GENERIC) 160 initTime = int(max(TOOLTIP_DELAY_MIN, min(tooltipDelay, TOOLTIP_DELAY_MAX))) 161 if hasattr(currentMouseOver, 'GetTooltipRenewTime'): 162 renewTime = currentMouseOver.GetTooltipRenewTime() 163 else: 164 renewTime = initTime / 5 165 if self.HaveVisibleTooltipPanel() or self.HaveVisibleTooltipHint(): 166 sleepTime = renewTime 167 elif self.lastCloseTime and blue.os.TimeDiffInMs(self.lastCloseTime, blue.os.GetWallclockTime()) < SLEEPTIME_COOLDOWN: 168 sleepTime = renewTime 169 else: 170 sleepTime = initTime 171 return sleepTime 172 173 def CloseTooltip(self): 174 self._CloseTooltipPanel() 175 self._CloseTooltipHint() 176 self.lastMouseOver = None 177 178 def _LoadTooltipPanel(self, owner, showInstant = False): 179 tooltipPanelClassInfo = getattr(owner, 'tooltipPanelClassInfo', None) 180 if not tooltipPanelClassInfo and hasattr(owner, 'GetTooltipPanelClassInfo'): 181 tooltipPanelClassInfo = owner.GetTooltipPanelClassInfo() 182 tooltipLoadFunction = None 183 if getattr(owner, 'sr', None) and getattr(owner.sr, 'node', None): 184 node = owner.sr.node 185 tooltipLoadFunction = getattr(node, 'LoadTooltipPanel', None) 186 if tooltipLoadFunction is None: 187 tooltipLoadFunction = getattr(owner, 'LoadTooltipPanel', None) 188 tooltipConstructMethod = getattr(owner, 'ConstructTooltipPanel', None) 189 panelLoaded = LOAD_NOTLOADED 190 if tooltipLoadFunction or tooltipPanelClassInfo or tooltipConstructMethod: 191 if tooltipPanelClassInfo: 192 tooltipPanel = tooltipPanelClassInfo.CreateTooltip(parent=uicore.layer.menu, owner=owner, idx=0) 193 elif tooltipConstructMethod: 194 tooltipPanel = tooltipConstructMethod() 195 if tooltipPanel is None: 196 tooltipPanel = self.NoTooltipPanelConstructorExists(owner) 197 else: 198 tooltipPanel.SetParent(uicore.layer.menu) 199 tooltipPanel.owner = owner 200 tooltipPanel.opacity = 0.0 201 else: 202 tooltipPanel = self.NoTooltipPanelConstructorExists(owner) 203 if not tooltipPanel or tooltipPanel.destroyed: 204 return LOAD_ABORTED 205 tooltipPanel.SetOrder(0) 206 preTooltipPanel = self.tooltipPanel 207 self.tooltipPanel = tooltipPanel 208 if tooltipPanelClassInfo: 209 tooltipPanel.LoadTooltip() 210 elif tooltipLoadFunction: 211 try: 212 tooltipLoadFunction(tooltipPanel, owner) 213 except: 214 tooltipPanel.Close() 215 raise 216 217 if owner.destroyed or tooltipPanel.destroyed: 218 return LOAD_ABORTED 219 if len(tooltipPanel.children): 220 panelLoaded = LOAD_LOADED 221 if preTooltipPanel and not (preTooltipPanel.destroyed or preTooltipPanel.beingDestroyed): 222 FadeOutPanelAndClose(preTooltipPanel, duration=FADEOUT_FAST) 223 self._CloseTooltipHint() 224 if showInstant: 225 tooltipPanel.opacity = 1.0 226 if tooltipPanel.pickState == uiconst.TR2_SPS_ON: 227 MouseTargetObject(tooltipPanel) 228 uthread.new(tooltipPanel.ShowPanel, owner) 229 else: 230 tooltipPanel.Close() 231 self.tooltipPanel = preTooltipPanel 232 return panelLoaded 233 234 def NoTooltipPanelConstructorExists(self, owner): 235 tooltipPanel = TooltipPanel(parent=uicore.layer.menu, owner=owner, state=uiconst.UI_DISABLED) 236 tooltipPanel.columns = 1 237 tooltipPanel.margin = 0 238 tooltipPanel.cellPadding = 0 239 tooltipPanel.cellSpacing = 0 240 return tooltipPanel 241 242 def GetHintFromUIObject(self, uiObject): 243 hint = uiObject.GetHint() 244 if hint is None and getattr(uiObject, 'sr', None): 245 hint = uiObject.sr.Get('hint', None) 246 if hint and not isinstance(hint, (str, unicode)): 247 log.LogWarn('Tooltips only supports hints as strings', hint) 248 return 249 if uicore.uilib.auxiliaryTooltip: 250 if hint: 251 hint += '<br>' + uicore.uilib.auxiliaryTooltip 252 else: 253 hint = uicore.uilib.auxiliaryTooltip 254 return hint 255 256 def IsUnderTooltip(self, uiObject): 257 parent = uiObject.parent 258 if not parent: 259 return False 260 if isinstance(parent, TooltipPanel): 261 return True 262 return self.IsUnderTooltip(parent)