activeitem.py (35909B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\activeitem.py 2 from collections import OrderedDict 3 import blue 4 import telemetry 5 import carbonui.const as uiconst 6 import eveformat.client 7 import evetypes 8 import localization 9 import structures 10 import uthread 11 import utillib 12 from brennivin import itertoolsext 13 from carbon.common.script.util.format import FmtDate, FmtDist 14 from carbon.common.script.util.timerstuff import AutoTimer 15 from carbonui import fontconst, TextColor 16 from carbonui.control.contextMenu.menuConst import DISABLED_ENTRY0 17 from carbonui.control.contextMenu.menuEntryData import MenuEntryData 18 from carbonui.window.widget import WidgetWindow 19 from carbonui.primitives.container import Container 20 from carbonui.primitives.fill import Fill 21 from eve.client.script.parklife import states as state 22 from eve.client.script.ui.control import eveIcon, eveLabel 23 from eve.client.script.ui.inflight import actionPanelDefaults 24 from eve.client.script.ui.inflight.selectedItemConst import ICON_ID_AND_CMD_BY_ACTIONID, RESET_ACTIONS 25 from eve.client.script.ui.services import menuAction 26 from eve.client.script.ui.services.menuSvcExtras.movementFunctions import GetDefaultWarpToLabel 27 from eve.client.script.ui.shared import killRights 28 from eve.client.script.ui.shared.pointerTool import pointerToolConst 29 from eve.client.script.ui.util import uix 30 from eve.common.lib import appConst as const 31 from eve.common.script.sys import idCheckers 32 from eve.common.script.util import eveFormat 33 from eveservices.menu import GetMenuService, StartMenuService 34 from menu import MenuLabel 35 from npcs.client.components.entity_bounty import get_entity_bounty 36 from spacecomponents.client.components import cargobay 37 from spacecomponents.common.helper import HasCargoBayComponent 38 from spacecomponents.common.helper import HasItemTrader 39 from uihider import UiHiderMixin 40 41 class ActiveItem(UiHiderMixin, WidgetWindow): 42 __guid__ = 'form.ActiveItem' 43 uniqueUiName = pointerToolConst.UNIQUE_NAME_SELECTED_ITEM_VIEW 44 __notifyevents__ = ['OnDronesSelected', 45 'ProcessSessionChange', 46 'OnStateChange', 47 'DoBallRemove', 48 'OnDistSettingsChange', 49 'OnPlanetViewChanged', 50 'DoBallsRemove', 51 'OnActiveTrackingChange'] 52 default_minSize = (256, 100) 53 default_windowID = 'selecteditemview' 54 default_open = True 55 default_isKillable = False 56 default_captionLabelPath = 'UI/Inflight/ActiveItem/SelectedItem' 57 58 @staticmethod 59 def default_left(*args): 60 return actionPanelDefaults.GetActiveItemLeft() 61 62 @staticmethod 63 def default_top(*args): 64 return actionPanelDefaults.GetActiveItemTop() 65 66 @staticmethod 67 def default_width(): 68 return actionPanelDefaults.GetActiveItemWidth() 69 70 @staticmethod 71 def default_height(): 72 return actionPanelDefaults.GetActiveItemHeight() 73 74 def ApplyAttributes(self, attributes): 75 super(ActiveItem, self).ApplyAttributes(attributes) 76 panelname = attributes.panelname 77 self.scope = uiconst.SCOPE_INFLIGHT 78 self.canAnchorToOthers = 0 79 self.lastActionSerial = None 80 self.lastSessionChange = None 81 self.laseUpdateWidth = None 82 self.lastIcon = None 83 self.lastBountyCheck = None 84 self.bounty = None 85 self.sr.actions = None 86 self.sr.updateTimer = None 87 self.itemIDs = [] 88 self.panelname = panelname 89 self.lastActionDist = None 90 self.lastCloakingStatus = False 91 self.sr.noSelectedHint = None 92 self.sr.blink = None 93 self.UpdateActions() 94 self._ConstructGroupData() 95 if self.destroyed: 96 return 97 self.sr.toparea = Container(name='toparea', align=uiconst.TOTOP, parent=self.sr.main, height=36) 98 self.sr.utilMenuArea = Container(name='utilMenuArea', align=uiconst.TORIGHT, parent=self.sr.toparea, width=20) 99 self.utilMenu = killRights.KillRightsUtilMenu(menuAlign=uiconst.TOPRIGHT, parent=self.sr.utilMenuArea, align=uiconst.TOPRIGHT) 100 self.sr.utilMenuArea.display = False 101 self.sr.actions = Container(name='actions', align=uiconst.TOTOP, parent=self.sr.main, left=0, top=0) 102 self.sr.actions.isTabStop = 1 103 self.sr.iconpar = Container(name='iconpar', align=uiconst.TOPLEFT, parent=self.sr.toparea, width=32, height=32, left=1, top=2, state=uiconst.UI_HIDDEN) 104 self.sr.icon = eveIcon.Icon(parent=self.sr.iconpar, align=uiconst.TOALL) 105 self.sr.icon.OnClick = (self.ShowInfo, self.sr.icon) 106 self.sr.icon.GetMenu = (self.GetIconMenu, self.sr.icon) 107 self.sr.icon.GetDragData = self.GetShipDragData 108 self.sr.chariconpar = Container(name='chariconpar', align=uiconst.TOPLEFT, parent=self.sr.toparea, width=32, height=32, left=37, top=2, state=uiconst.UI_HIDDEN) 109 self.sr.charicon = eveIcon.Icon(parent=self.sr.chariconpar, align=uiconst.TOALL) 110 self.sr.charicon.GetDragData = self.GetCharDragData 111 self.sr.charicon.OnClick = (self.ShowInfo, self.sr.charicon) 112 self.sr.pushCont = Container(name='push', width=39, parent=self.sr.toparea, align=uiconst.TOLEFT) 113 self.sr.text = eveLabel.EveLabelSmall(text='', parent=self.sr.toparea, align=uiconst.TOTOP, left=const.defaultPadding, top=const.defaultPadding, state=uiconst.UI_NORMAL) 114 self.inited = 1 115 self.bountySvc = sm.GetService('bountySvc') 116 selected = None 117 stateSvc = sm.GetServiceIfRunning('stateSvc') 118 if stateSvc: 119 selected = stateSvc.GetExclState(state.selected) 120 if selected: 121 self.OnMultiSelect([selected]) 122 else: 123 self.UpdateAll() 124 125 def _ConstructGroupData(self): 126 self.postorder = ['UI/Inflight/OrbitObject', 127 'UI/Inflight/Submenus/KeepAtRange', 128 ('UI/Inflight/LockTarget', 'UI/Inflight/UnlockTarget'), 129 ('UI/Inflight/LookAtObject', 'UI/Inflight/ResetCamera'), 130 'UI/Inflight/SetAsCameraInterest', 131 'UI/Commands/ShowInfo'] 132 self.typeActions = {const.typeUpwellSmallStargate: ['UI/Inflight/JumpUsingBridge', 'UI/Inflight/BoardStructure', 'UI/Inflight/AccessHangarTransfer']} 133 for typeID in structures.FLEX_STRUCTURE_TYPES: 134 if typeID not in self.typeActions: 135 self.typeActions[typeID] = [] 136 self.typeActions[typeID].extend(['UI/Inflight/BoardStructure', 'UI/Inflight/AccessHangarTransfer']) 137 138 self.groups = {const.groupStation: ['UI/Inflight/DockInStation'], 139 const.groupWreck: ['UI/Commands/OpenCargo'], 140 const.groupCargoContainer: ['UI/Commands/OpenCargo'], 141 const.groupMissionContainer: ['UI/Commands/OpenCargo'], 142 const.groupSecureCargoContainer: ['UI/Commands/OpenCargo'], 143 const.groupAuditLogSecureContainer: ['UI/Commands/OpenCargo'], 144 const.groupFreightContainer: ['UI/Commands/OpenCargo'], 145 const.groupSpawnContainer: ['UI/Commands/OpenCargo'], 146 const.groupSpewContainer: ['UI/Commands/OpenCargo'], 147 const.groupDeadspaceOverseersBelongings: ['UI/Commands/OpenCargo'], 148 const.groupPlanetaryCustomsOffices: ['UI/PI/Common/AccessCustomOffice'], 149 const.groupOrbitalConstructionPlatforms: ['UI/DustLink/OpenUpgradeHold'], 150 const.groupMoon: ['UI/Inflight/WarpToMoonMiningPoint'], 151 const.groupReprocessingArray: ['UI/Inflight/POS/AccessPOSRefinery'], 152 const.groupCompressionArray: ['UI/Inflight/POS/AccessPOSCompression'], 153 const.groupMobileReactor: ['UI/Inflight/POS/AccessPOSStorage'], 154 const.groupControlTower: ['UI/Inflight/POS/AccessPOSFuelBay', 'UI/Inflight/POS/AccessPOSStrontiumBay'], 155 const.groupSilo: ['UI/Inflight/POS/AccessPOSStorage'], 156 const.groupAssemblyArray: ['UI/Inflight/POS/AccessPOSStorage'], 157 const.groupMobileLaboratory: ['UI/Inflight/POS/AccessPOSStorage'], 158 const.groupCorporateHangarArray: ['UI/Inflight/POS/AccessPOSStorage'], 159 const.groupPersonalHangar: ['UI/Inflight/POS/AccessPOSStorage'], 160 const.groupMobileMissileSentry: ['UI/Inflight/POS/AccessPOSAmmo'], 161 const.groupMobileHybridSentry: ['UI/Inflight/POS/AccessPOSAmmo'], 162 const.groupMobileProjectileSentry: ['UI/Inflight/POS/AccessPOSAmmo'], 163 const.groupMobileLaserSentry: ['UI/Inflight/POS/AccessPOSCrystalStorage'], 164 const.groupShipMaintenanceArray: ['UI/Inflight/POS/AccessPOSVessels'], 165 const.groupStargate: ['UI/Inflight/Jump'], 166 const.groupWormhole: ['UI/Inflight/EnterWormhole'], 167 const.groupWarpGate: ['UI/Inflight/ActivateGate'], 168 const.groupAbyssalTraces: ['UI/Inflight/ActivateGate'], 169 const.groupBillboard: ['UI/Commands/ReadNews'], 170 const.groupAgentsinSpace: ['UI/Chat/StartConversation'], 171 const.groupDestructibleAgentsInSpace: ['UI/Chat/StartConversation'], 172 const.groupMiningDrone: ['UI/Drones/MineWithDrone', 'UI/Drones/ReturnDroneAndOrbit', ('UI/Drones/LaunchDrones', 'UI/Drones/ReturnDroneToBay', 'UI/Drones/ScoopDroneToBay')], 173 const.groupSalvageDrone: ['UI/Drones/Salvage', 'UI/Drones/ReturnDroneAndOrbit', ('UI/Drones/LaunchDrones', 'UI/Drones/ReturnDroneToBay', 'UI/Drones/ScoopDroneToBay')]} 174 structureOptions = ['UI/Inflight/DockInStation', 'UI/Inflight/AccessHangarTransfer'] 175 self.categories = {const.categoryShip: ['UI/Inflight/BoardShip'], 176 const.categoryStructure: structureOptions, 177 const.categoryDrone: ['UI/Drones/EngageTarget', 'UI/Drones/ReturnDroneAndOrbit', ('UI/Drones/LaunchDrones', 'UI/Drones/ReturnDroneToBay', 'UI/Drones/ScoopDroneToBay')]} 178 179 def UpdateActions(self): 180 self.actions = ICON_ID_AND_CMD_BY_ACTIONID.copy() 181 self.subMenus = ['UI/Inflight/MoonMiningPoint'] 182 183 def Blink(self, on_off = 1): 184 if on_off and self.sr.blink is None: 185 self.sr.blink = Fill(parent=self.sr.top, padding=(1, 1, 1, 1), color=(1.0, 1.0, 1.0, 0.25)) 186 if on_off: 187 sm.GetService('ui').BlinkSpriteA(self.sr.blink, 0.25, 500, None, passColor=0) 188 elif self.sr.blink: 189 sm.GetService('ui').StopBlink(self.sr.blink) 190 b = self.sr.blink 191 self.sr.blink = None 192 b.Close() 193 194 def BlinkBtn(self, key): 195 for btn in self.sr.actions.children: 196 if btn.name.replace(' ', '').lower() == key.replace(' ', '').lower(): 197 sm.GetService('ui').BlinkSpriteA(btn.children[0], 1.0, 500, None, passColor=0) 198 else: 199 sm.GetService('ui').StopBlink(btn.children[0]) 200 201 def OnResizeUpdate(self, *args): 202 self.CheckActions(forceSizeUpdate=1, ignoreScaling=1) 203 204 def OnActiveTrackingChange(self, isActivelyTracking): 205 self.AdjustUIToActiveTrackingStatus(isActivelyTracking) 206 207 def AdjustUIToActiveTrackingStatus(self, isTracking): 208 caption = localization.GetByLabel('UI/Inflight/ActiveItem/SelectedItem') 209 if isTracking: 210 caption += ' - ' + localization.GetByLabel('UI/Inflight/ActiveItem/Tracking') 211 self.SetCaption(caption) 212 213 @telemetry.ZONE_METHOD 214 def CheckActions(self, forceSizeUpdate = 0, ignoreScaling = 0): 215 if self.destroyed or not self.sr.actions: 216 return 217 self.sr.toparea.height = max(40, self.sr.text.textheight + self.sr.text.top * 2) 218 scaling = getattr(self, 'scaling', 0) if ignoreScaling == 0 else 0 219 if forceSizeUpdate and not scaling and self.ImVisible(): 220 l, t, w, h = self.GetAbsolute() 221 al, at = self.sr.actions.GetAbsolutePosition() 222 maxHeight = t + h - at - 8 223 self.LayoutButtons(self.sr.actions, uiconst.UI_PICKCHILDREN, maxHeight) 224 gl, gt, gr, gb = self.GetGroupRect(self.sr.actions.children) 225 diff = gb - (t + h - 6) 226 if diff > 0: 227 self.SetHeight_PushOrPullWindowsBelow(self.height + diff) 228 229 @telemetry.ZONE_METHOD 230 def LayoutButtons(self, parent, state = None, maxHeight = None): 231 if parent is None: 232 return 233 l, t, w, h = parent.GetAbsolute() 234 colwidth = 33 235 if w <= colwidth: 236 return 237 perRow = w / colwidth 238 isSmall = len(parent.children) / float(perRow) > 2.0 239 iconSize = 24 if isSmall else 32 240 if maxHeight and iconSize > maxHeight: 241 iconSize = 24 242 if len(parent.children) * (iconSize + 1) + 1 > w: 243 iconSize = 24 244 left = 1 245 top = 0 246 parent.height = iconSize + 1 247 for icon in parent.children: 248 if l + left + iconSize + 1 >= l + w: 249 left = 1 250 top += iconSize + 1 251 parent.height += iconSize + 1 252 icon.left = left 253 icon.top = top 254 icon.width = iconSize 255 icon.height = iconSize 256 if state is not None: 257 icon.state = state 258 left += iconSize + 1 259 260 def _OnClose(self, *args): 261 self.sr.updateTimer = None 262 263 def ProcessSessionChange(self, isRemote, session, change): 264 self.lastActionSerial = None 265 self.lastActionDist = None 266 self.lastCloakingStatus = None 267 self.lastSessionChange = blue.os.GetWallclockTime() 268 269 def OnDronesSelected(self, itemIDs): 270 self.OnMultiSelect(itemIDs) 271 272 def OnMultiSelect(self, itemIDs): 273 self.itemIDs = itemIDs 274 self.lastActionSerial = None 275 self.lastActionDist = None 276 self.lastBountyCheck = None 277 self.bounty = None 278 if self.ImVisible(): 279 uthread.pool('ActiveItem::UpdateAll', self.UpdateAll, 1) 280 281 def OnStateChange(self, itemID, flag, true, *args): 282 if itemID != session.shipid and not self.destroyed: 283 uthread.new(self._OnStateChange, itemID, flag, true) 284 285 @telemetry.ZONE_METHOD 286 def _OnStateChange(self, itemID, flag, true): 287 if flag == state.selected and true: 288 self.OnMultiSelect([itemID]) 289 if itemID in self.itemIDs and flag not in (state.selected, state.mouseOver): 290 self.lastActionSerial = None 291 self.lastActionDist = None 292 self.UpdateAll() 293 294 def OnDistSettingsChange(self): 295 uthread.new(self._OnDistSettingsChange) 296 297 @telemetry.ZONE_METHOD 298 def _OnDistSettingsChange(self): 299 self.ResetLastActionAndCloakingAndUpdateAll() 300 301 def ResetLastActionAndCloakingAndUpdateAll(self): 302 self.lastActionSerial = None 303 self.lastCloakingStatus = None 304 self.UpdateAll(1) 305 306 def TryGetInvItem(self, itemID): 307 if session.shipid is None: 308 return 309 ship = sm.GetService('invCache').GetInventoryFromId(session.shipid) 310 if ship: 311 for invItem in ship.List(): 312 if invItem.itemID == itemID: 313 return invItem 314 315 def GetItem(self, itemID): 316 item = uix.GetBallparkRecord(itemID) 317 if not item: 318 item = self.TryGetInvItem(itemID) 319 return item 320 321 def Load(self, itemID): 322 pass 323 324 def OnTabSelect(self, *args): 325 if not getattr(self, 'inited', 0): 326 return 327 self.ResetLastActionAndCloakingAndUpdateAll() 328 329 def OnExpanded(self, *args): 330 if not getattr(self, 'inited', 0): 331 return 332 super(ActiveItem, self).OnExpanded(*args) 333 self.ResetLastActionAndCloakingAndUpdateAll() 334 335 def OnEndMaximize_(self, *args): 336 if not getattr(self, 'inited', 0): 337 return 338 self.ResetLastActionAndCloakingAndUpdateAll() 339 340 def FadeInSelf(self): 341 self.opacity = 0.001 342 super(ActiveItem, self).FadeInSelf() 343 if not getattr(self, 'inited', 0): 344 return 345 self.ResetLastActionAndCloakingAndUpdateAll() 346 347 def ShowNoSelectedHint(self, hint = None): 348 if self.sr.noSelectedHint is None and hint: 349 self.sr.noSelectedHint = eveLabel.EveCaptionMedium(text=hint, parent=self.sr.main, align=uiconst.RELATIVE, left=16, top=18, width=256, color=TextColor.SECONDARY) 350 elif self.sr.noSelectedHint: 351 if hint: 352 self.sr.noSelectedHint.text = hint 353 self.sr.noSelectedHint.state = uiconst.UI_DISABLED 354 else: 355 self.sr.noSelectedHint.state = uiconst.UI_HIDDEN 356 357 def FlushContent(self): 358 self.SetText('') 359 self.ShowNoSelectedHint(localization.GetByLabel('UI/Inflight/ActiveItem/NoObjectSelected')) 360 self.sr.actions.Flush() 361 self.sr.iconpar.state = uiconst.UI_HIDDEN 362 self.sr.chariconpar.state = uiconst.UI_HIDDEN 363 364 @telemetry.ZONE_METHOD 365 def UpdateAll(self, updateActions = 0): 366 if not self or self.destroyed: 367 return 368 if session.shipid in self.itemIDs: 369 self.itemIDs.remove(session.shipid) 370 bp = sm.GetService('michelle').GetBallpark() 371 if not self.ImVisible() or not bp or not self.itemIDs: 372 self.sr.updateTimer = None 373 self.FlushContent() 374 return 375 goForSlim = 1 376 slimItems = [] 377 invItems = [] 378 fleetMember = None 379 for itemID in self.itemIDs: 380 blue.pyos.BeNice() 381 if sm.GetService('fleet').IsMember(itemID): 382 fleetMember = cfg.eveowners.Get(itemID) 383 break 384 slimItem = None 385 if goForSlim: 386 slimItem = uix.GetBallparkRecord(itemID) 387 if slimItem: 388 slimItems.append(slimItem) 389 if not slimItem: 390 invItem = self.TryGetInvItem(itemID) 391 if invItem: 392 invItems.append(invItem) 393 goForSlim = 0 394 395 if not slimItems and not invItems and not fleetMember: 396 self.itemIDs = [] 397 self.lastActionSerial = None 398 self.lastActionDist = None 399 self.FlushContent() 400 return 401 if not self or self.destroyed: 402 return 403 text = '' 404 blue.pyos.BeNice() 405 updateActions = updateActions or 0 406 typeID = None 407 fleetSlim = None 408 if fleetMember: 409 multi = 1 410 text = fleetMember.name 411 typeID = fleetMember.typeID 412 fleetSlim = self.GetSlimItemForCharID(fleetMember.id) 413 blue.pyos.BeNice() 414 elif invItems: 415 text = uix.GetItemName(invItems[0]) 416 typeID = invItems[0].typeID 417 multi = len(invItems) 418 blue.pyos.BeNice() 419 elif slimItems: 420 text = uix.GetSlimItemName(slimItems[0]) 421 typeID = slimItems[0].typeID 422 multi = len(slimItems) 423 if multi == 1: 424 slimItem = slimItems[0] 425 itemID = slimItem.itemID 426 ball = bp.GetBall(itemID) 427 if not ball: 428 self.itemIDs = [] 429 self.sr.updateTimer = None 430 self.FlushContent() 431 return 432 if slimItem.groupID == const.groupStargate: 433 text = u'{text} ({security_status})'.format(text=text, security_status=eveformat.solar_system_security_status(slimItem.jumps[0].locationID)) 434 dist = ball.surfaceDist 435 if dist is not None: 436 md = None 437 myball = bp.GetBall(session.shipid) 438 if myball: 439 md = myball.mode 440 if self.lastCloakingStatus is None or self.lastCloakingStatus != myball.isCloaked: 441 updateActions = 1 442 self.lastCloakingStatus = myball.isCloaked 443 text += '<br>' + localization.GetByLabel('UI/Inflight/ActiveItem/SelectedItemDistance', distToItem=FmtDist(dist, maxdemicals=1)) 444 if not self.lastActionDist or md != self.lastActionDist[1] or self.CheckDistanceUpdate(self.lastActionDist[0], dist): 445 self.lastActionDist = (dist, md) 446 updateActions = 1 447 sec = slimItem.securityStatus 448 if sec: 449 text += '<br>' + localization.GetByLabel('UI/Inflight/ActiveItem/SelectedItemSecurity', secStatus=sec) 450 if slimItem.categoryID == const.categoryStructure: 451 timerText = self.GetStructureTimerText(slimItem) 452 if timerText: 453 text += timerText 454 updateActions = 1 455 blue.pyos.BeNice() 456 corpID = None 457 charID = None 458 categoryID = None 459 bountyItemID = None 460 bountyTypeID = None 461 bountySlim = None 462 displayUtilMenu = False 463 if multi > 1: 464 text += '<br>' + localization.GetByLabel('UI/Inflight/ActiveItem/MultipleItems', itemCount=multi) 465 blue.pyos.BeNice() 466 elif multi == 1: 467 if slimItems: 468 slim = slimItems[0] 469 if slim.categoryID == const.categoryShip: 470 if idCheckers.IsCharacter(slim.charID): 471 charID = slim.charID 472 categoryID = slim.categoryID 473 if slim.categoryID == const.categoryEntity: 474 bountyTypeID = slim.typeID 475 bountySlim = slim 476 elif slim.charID: 477 bountyItemID = slim.charID 478 bountySlim = slim 479 killRightID, price = self.bountySvc.GetBestKillRight(slim.charID) 480 self.utilMenu.UpdateKillRightInfo(killRightID, price, slim.charID, slim.itemID) 481 stateSvc = sm.GetService('stateSvc') 482 if killRightID is not None and not (stateSvc.CheckSuspect(slim) or stateSvc.CheckCriminal(slim)) and slim.categoryID != const.categoryStructure: 483 displayUtilMenu = True 484 blue.pyos.BeNice() 485 self.sr.utilMenuArea.display = displayUtilMenu 486 self.utilMenu.display = displayUtilMenu 487 if self.lastIcon != (typeID, itemID, charID): 488 uthread.pool('ActiveItem::GetIcon', self.GetIcon, typeID, itemID, charID, corpID, categoryID) 489 self.lastIcon = (typeID, itemID, charID) 490 else: 491 self.sr.iconpar.state = uiconst.UI_PICKCHILDREN 492 if categoryID == const.categoryShip and charID: 493 self.sr.chariconpar.state = uiconst.UI_PICKCHILDREN 494 if (bountyItemID, bountyTypeID) != self.lastBountyCheck: 495 bounty, bountyHint, reducedBountyIndication = self.CheckBounty(bountyTypeID, bountySlim) 496 blue.pyos.BeNice() 497 if bounty: 498 self.bounty = localization.GetByLabel('UI/Common/BountyAmount', bountyAmount=eveFormat.FmtISK(bounty, 0)) 499 else: 500 self.bounty = None 501 self.lastBountyCheck = (bountyItemID, bountyTypeID) 502 self.lastBountyInfo = (bountyHint, reducedBountyIndication) 503 else: 504 bountyHint, reducedBountyIndication = self.lastBountyInfo 505 if self.bounty: 506 text += '<br>' 507 text += self.bounty 508 if reducedBountyIndication: 509 text += reducedBountyIndication 510 if updateActions: 511 self.ReloadActions(slimItems, invItems, fleetMember, fleetSlim) 512 else: 513 self.CheckActions(1) 514 self.SetText(text, bountyHint) 515 self.ShowNoSelectedHint() 516 blue.pyos.BeNice() 517 self.laseUpdateWidth = self.absoluteRight - self.absoluteLeft 518 if not self.sr.updateTimer and not invItems: 519 self.sr.updateTimer = AutoTimer(500, self.UpdateAll) 520 521 def GetStructureTimerText(self, slimItem): 522 timerText = '' 523 isVulnerable = structures.STATE_VULNERABILITY.get(slimItem.state, None) 524 if isVulnerable is not False: 525 return timerText 526 if slimItem.timer: 527 start, end, paused = slimItem.timer 528 if paused: 529 end = end + blue.os.GetWallclockTime() - paused 530 stateText = localization.GetByLabel(structures.STATE_LABELS[slimItem.state]) 531 label = localization.GetByLabel('UI/Inflight/ActiveItem/InStateUntil', structureState=stateText, timestamp=FmtDate(end)) 532 timerText = '<br>%s' % label 533 return timerText 534 535 @telemetry.ZONE_METHOD 536 def DoBallsRemove(self, pythonBalls, isRelease): 537 for ball, slimItem, terminal in pythonBalls: 538 self.DoBallRemove(ball, slimItem, terminal) 539 540 def DoBallRemove(self, ball, slimItem, terminal): 541 if self.ImVisible() and ball and ball.id in self.itemIDs: 542 uthread.pool('ActiveItem::UpdateAll', self.UpdateAll, 1) 543 544 def SetText(self, text, hint = None): 545 if text != self.sr.text.text: 546 self.sr.text.text = text 547 self.sr.text.hint = hint 548 self.CheckActions(1) 549 550 def GetIcon(self, typeID, itemID, charID, corpID, categoryID): 551 self.sr.icon.LoadIconByTypeID(typeID, itemID=itemID, ignoreSize=True) 552 self.sr.icon.typeID = typeID 553 self.sr.icon.itemID = itemID 554 self.sr.icon.categoryID = categoryID 555 self.sr.iconpar.state = uiconst.UI_PICKCHILDREN 556 self.sr.chariconpar.state = uiconst.UI_HIDDEN 557 self.sr.pushCont.width = 39 558 if categoryID == const.categoryShip and charID: 559 typeID = cfg.eveowners.Get(charID).typeID 560 self.sr.charicon.LoadIconByTypeID(typeID, itemID=charID, ignoreSize=True) 561 self.sr.charicon.typeID = typeID 562 self.sr.charicon.itemID = charID 563 self.sr.pushCont.width = 75 564 self.sr.chariconpar.state = uiconst.UI_PICKCHILDREN 565 566 def GetShipDragData(self): 567 categoryID = self.sr.icon.categoryID 568 if categoryID != const.categoryShip: 569 return [] 570 typeID = self.sr.icon.typeID 571 fakeNode = utillib.KeyVal() 572 fakeNode.__guid__ = 'listentry.Item' 573 fakeNode.typeID = typeID 574 fakeNode.itemID = self.sr.icon.itemID 575 label = evetypes.GetName(typeID) 576 charID = self.sr.charicon.itemID 577 if charID: 578 label = '%s (%s)' % (cfg.eveowners.Get(charID).name, label) 579 fakeNode.genericDisplayLabel = label 580 return [fakeNode] 581 582 def GetCharDragData(self, *args): 583 charID = self.sr.charicon.itemID 584 if not charID: 585 return [] 586 fakeNode = utillib.KeyVal() 587 fakeNode.charID = charID 588 fakeNode.typeID = self.sr.charicon.typeID 589 fakeNode.itemID = charID 590 fakeNode.info = cfg.eveowners.Get(charID) 591 fakeNode.__guid__ = 'listentry.User' 592 return [fakeNode] 593 594 def CheckBounty(self, bountyTypeID, slimItem): 595 bounty = None 596 bountyHint = None 597 reducedBountyIndication = None 598 if bountyTypeID: 599 bountyAmount = get_entity_bounty(bountyTypeID, slimItem.itemID) 600 if bountyAmount: 601 bounty, bountyHint, reducedBountyIndication = self.GetNpcBounty(bountyAmount) 602 elif slimItem: 603 if self.bountySvc.CanHaveBounty(slimItem): 604 bounty = self.bountySvc.GetBounty(slimItem.charID, slimItem.corpID, slimItem.allianceID) 605 return (bounty, bountyHint, reducedBountyIndication) 606 607 def GetNpcBounty(self, bountyAmount): 608 return (bountyAmount, None, None) 609 610 def GetSlimItemForCharID(self, charID): 611 ballpark = sm.GetService('michelle').GetBallpark() 612 if ballpark: 613 for itemID, rec in ballpark.slimItems.iteritems(): 614 if rec.charID == charID: 615 return rec 616 617 def ShowInfo(self, btn, *args): 618 if btn and btn.typeID: 619 sm.GetService('info').ShowInfo(btn.typeID, btn.itemID) 620 621 def GetIconMenu(self, btn, *args): 622 if btn and btn.typeID: 623 return GetMenuService().GetMenuFromItemIDTypeID(getattr(btn, 'itemID', None), btn.typeID) 624 625 def CheckDistanceUpdate(self, lastdist, dist): 626 diff = abs(lastdist - dist) 627 if not diff: 628 return False 629 elif dist: 630 return bool(diff / dist > 0.01) 631 else: 632 return bool(lastdist != dist) 633 634 def ImVisible(self): 635 return bool(not self.IsCollapsed() and not self.IsMinimized() and self.opacity > 0 and self.display) 636 637 @telemetry.ZONE_METHOD 638 def ReloadActions(self, slimItems, invItems, fleetMember, fleetSlim): 639 if not self or self.destroyed: 640 return 641 if not self.ImVisible(): 642 self.sr.updateTimer = None 643 return 644 itemIDsAtStart = self.itemIDs[:] 645 actions = [] 646 if invItems: 647 data = [ (invItem, 0, None) for invItem in invItems ] 648 actions = StartMenuService().InvItemMenu(data) 649 elif slimItems: 650 if len(slimItems) == 1: 651 actions = GetMenuService().UnmergedCelestialMenu(slimItems[0]) 652 else: 653 actions = GetMenuService().CelestialMenu([ (slimItem.itemID, 654 None, 655 slimItem, 656 None, 657 None) for slimItem in slimItems ]) 658 elif fleetSlim: 659 actions = GetMenuService().CelestialMenu(fleetSlim.itemID, slimItem=fleetSlim) 660 elif fleetMember: 661 actions = GetMenuService().CharacterMenu(fleetMember.id) 662 if itemIDsAtStart != self.itemIDs: 663 return 664 reasonsWhyNotAvailable = getattr(actions, 'reasonsWhyNotAvailable', {}) 665 warptoLabel = GetDefaultWarpToLabel()[0] 666 if not self or self.destroyed: 667 return 668 allActions = self.GetAllActionsFromMenus(actions) 669 serial = '' 670 valid = {} 671 for each in allActions: 672 name = self._FindNameForAction(each) 673 if name in self.actions: 674 valid[name] = each 675 if type(each[1]) not in (str, unicode): 676 serial += '%s_' % name 677 678 blue.pyos.BeNice() 679 if serial != self.lastActionSerial: 680 if self.absoluteLeft == 0: 681 blue.pyos.synchro.Yield() 682 if self.destroyed: 683 return 684 self.sr.actions.Flush() 685 self.sr.actions.height = 0 686 typeID = None 687 groupID = None 688 categoryID = None 689 if slimItems: 690 typeID = slimItems[0].typeID 691 groupID = slimItems[0].groupID 692 categoryID = slimItems[0].categoryID 693 elif invItems: 694 typeID = invItems[0].typeID 695 groupID = invItems[0].groupID 696 categoryID = invItems[0].categoryID 697 isAlignDisabled = type(valid.get('UI/Inflight/AlignTo', ('', ''))[1]) in (str, unicode) 698 if isAlignDisabled: 699 approachLabelPath = 'UI/Inflight/ApproachObject' 700 else: 701 approachLabelPath = 'UI/Inflight/AlignTo' 702 order = [approachLabelPath, warptoLabel] 703 if typeID and typeID in self.typeActions: 704 order += self.typeActions[typeID] 705 elif groupID and groupID in self.groups: 706 order += self.groups[groupID] 707 elif categoryID and categoryID in self.categories: 708 order += self.categories[categoryID] 709 item = self.ChooseItem(slimItems, invItems) 710 if item: 711 if HasCargoBayComponent(typeID) and not HasItemTrader(typeID): 712 if cargobay.IsAccessibleByCharacter(item, session.charid): 713 order.append('UI/Commands/OpenCargo') 714 if HasItemTrader(typeID): 715 order.append('UI/Inflight/SpaceComponents/ItemTrader/Access') 716 order = itertoolsext.remove_duplicates_and_preserve_order(order) 717 order += self.postorder 718 if groupID == const.groupPlanet: 719 order += [('UI/PI/Common/ViewInPlanetMode', 'UI/PI/Common/ExitPlanetMode')] 720 for actionName in order: 721 if actionName is None: 722 continue 723 if isinstance(actionName, tuple): 724 action = None 725 for each in actionName: 726 tryaction = valid.get(each, None) 727 if tryaction and type(tryaction[1]) not in (str, unicode): 728 actionName = each 729 action = tryaction 730 break 731 732 if action is None: 733 actionName = actionName[0] 734 if actionName in valid: 735 action = valid.get(actionName) 736 elif actionName in reasonsWhyNotAvailable: 737 action = (actionName, reasonsWhyNotAvailable.get(actionName)) 738 else: 739 action = (actionName, localization.GetByLabel('UI/Menusvc/MenuHints/NoReasonGiven')) 740 elif actionName in valid: 741 action = valid.get(actionName) 742 elif actionName in reasonsWhyNotAvailable: 743 action = (actionName, reasonsWhyNotAvailable.get(actionName)) 744 else: 745 action = (actionName, localization.GetByLabel('UI/Menusvc/MenuHints/NoReasonGiven')) 746 disabled = type(action[1]) in (str, unicode) 747 if isinstance(action[0], MenuLabel): 748 actionID = action[0][0] 749 else: 750 actionID = action[0] 751 par = Container(parent=self.sr.actions, align=uiconst.TOPLEFT, width=32, height=32, state=uiconst.UI_HIDDEN) 752 actionObject = self.actions[actionID] 753 par.name = actionObject.uniqueUiName or actionID 754 cmdName = actionObject.cmdName or '' 755 icon = menuAction.Action(icon=actionObject.iconPath, parent=par, align=uiconst.TOALL, disabled=disabled) 756 icon.uniqueUiName = actionObject.uniqueUiName 757 icon.actionID = actionID 758 icon.action = action 759 icon.itemIDs = self.itemIDs[:] 760 icon.cmdName = cmdName 761 if disabled: 762 icon.opacity = 0.5 763 if actionID in RESET_ACTIONS: 764 eveIcon.Icon(icon='ui_44_32_8', parent=par, pos=(1, 1, 0, 0), align=uiconst.TOALL, state=uiconst.UI_DISABLED, idx=0) 765 766 self.lastActionSerial = serial 767 self.CheckActions(1) 768 769 def GetAllActionsFromMenus(self, actions): 770 allActionsDict = OrderedDict() 771 subMenuActions = [] 772 for each in actions: 773 if not each or self._IsDisabledEntry(each): 774 continue 775 name = self._FindNameForAction(each) 776 allActionsDict[name] = each 777 if name in self.subMenus: 778 for eachSubOption in each[1]: 779 subMenuActions.append(eachSubOption) 780 781 for eachSubOption in subMenuActions: 782 name = self._FindNameForAction(eachSubOption) 783 if name not in allActionsDict: 784 allActionsDict[name] = eachSubOption 785 786 allActions = allActionsDict.values() 787 return allActions 788 789 def _IsDisabledEntry(self, each): 790 if isinstance(each, MenuEntryData): 791 return each.IsEnabled() 792 else: 793 return each[1] == DISABLED_ENTRY0 794 795 def _FindNameForAction(self, each): 796 if isinstance(each[0], tuple): 797 name = each[0][0] 798 else: 799 name = each[0] 800 return name 801 802 def ChooseItem(self, slimItems, invItems): 803 if slimItems: 804 return slimItems[0] 805 if invItems: 806 return invItems[0] 807 808 def OnPlanetViewChanged(self, newPlanetID, oldPlanetID): 809 for planetID in (newPlanetID, oldPlanetID): 810 if planetID in self.itemIDs: 811 self.OnMultiSelect(self.itemIDs)