skyhookWnd.py (28305B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\skyhook\skyhookWnd.py 2 import carbonui.text.styles 3 import datetimeutils 4 import gametime 5 import numbers 6 import carbonui 7 import eveicon 8 import evetypes 9 import uthread2 10 from carbon.common.script.sys.serviceConst import ROLE_PROGRAMMER 11 from carbon.common.script.util.timerstuff import AutoTimer 12 from carbonui import TextColor, TextAlign 13 from carbonui.button.group import ButtonGroup 14 from carbonui.control.button import Button 15 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 16 from carbonui.control.window import Window 17 import carbonui.uiconst as uiconst 18 from carbonui.primitives.container import Container 19 from carbonui.primitives.containerAutoSize import ContainerAutoSize 20 from carbonui.primitives.fill import Fill 21 from carbonui.primitives.gridcontainer import GridContainer 22 from carbonui.primitives.layoutGrid import LayoutGrid 23 from carbonui.primitives.sprite import Sprite 24 from const import MIN 25 from eve.client.script.ui import eveColor, eveThemeColor 26 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel 27 from eve.client.script.ui.control.gauge import Gauge 28 from eve.client.script.ui.control.gaugeCircular import GaugeCircular 29 from eve.client.script.ui.control.itemIcon import ItemIcon 30 from eve.client.script.ui.control.toggleSwitch import ToggleSwitch 31 from eve.client.script.ui.shared.skyhook import NOT_AVAILABLE 32 from eve.client.script.ui.shared.skyhook.uiController import CurrentSkyhookUiController 33 from eve.common.script.util.eveFormat import FmtISK 34 from eveexceptions import ExceptionEater 35 from eveservices.menu import GetMenuService 36 from eveui import animation 37 from inventorycommon.typeHelpers import GetAveragePrice 38 from localization import GetByLabel 39 import logging 40 from localization.formatters import FormatTimeIntervalShortWritten 41 from player_messaging.client.ui_message import prompt_player_fsd_dialog 42 from sovereignty.skyhook.shared.skyhook_type_inference import is_reagent_skyhook 43 from spacecomponents.client.components.orbitalSkyhook import IsCharacterAuthorisedToTakeFromSkyhook 44 logger = logging.getLogger(__name__) 45 46 def OpenSkyhookWindow(itemID): 47 wnd = SkyhookWnd.GetIfOpen() 48 if wnd and not wnd.destroyed: 49 wnd.Maximize() 50 if not wnd.dataController.IsSameItemID(itemID): 51 wnd.LoadWindow(itemID) 52 else: 53 SkyhookWnd.Open(itemID=itemID) 54 55 56 PRODUCING_THREAD = 'producingThread' 57 ONLINE_STATE_THREAD = 'onlineStateThread' 58 REAGENTS_QTY_THREAD = 'reagentsQtyThread' 59 REAGENTS_TYPES_THREAD = 'reagentsTypesThread' 60 61 class SkyhookWnd(Window): 62 __guid__ = 'SkyhookWnd' 63 default_minSize = [520, 250] 64 default_windowID = 'obitalSkyhookWnd' 65 default_captionLabelPath = 'UI/OrbitalSkyhook/OrbitalSkyhook' 66 default_iconNum = 'res:/ui/Texture/WindowIcons/skyhook.png' 67 __notifyevents__ = ['OnReagentsUpdated', 'OnSessionChanged'] 68 69 def DebugReload(self, *args): 70 itemID = self.dataController.itemID 71 self.Close() 72 OpenSkyhookWindow(itemID) 73 74 def ApplyAttributes(self, attributes): 75 self.threadedLoader = ThreadedLoader() 76 self._reagentsLoaded = False 77 self.regentStorageLabel = None 78 self.constructionDone = False 79 self.progressThread = None 80 super(SkyhookWnd, self).ApplyAttributes(attributes) 81 itemID = attributes.itemID 82 self.dataController = self.CreateDataController(itemID) 83 self.product = None 84 self.ConstructUI() 85 self.LoadWindow(itemID) 86 87 def CreateDataController(self, itemID): 88 isAuthorisedToTake = IsCharacterAuthorisedToTakeFromSkyhook(itemID) 89 controller = CurrentSkyhookUiController(itemID, isAuthorisedToTake) 90 controller.on_linked_ship_updated.connect(self.OnLinkedShipChanged) 91 return controller 92 93 def ConstructUI(self): 94 bottomPad = 8 95 self.topSection = ContainerAutoSize(name='topSection', parent=self.content, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, padBottom=bottomPad) 96 padding = self.content_padding[0] 97 self.topSection.bgFill = Fill(bgParent=self.topSection, color=eveThemeColor.THEME_FOCUSDARK, opacity=0.25, padding=(-padding, 98 0, 99 -padding, 100 -bottomPad)) 101 topCont = ContainerAutoSize(parent=self.topSection, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, top=6, padLeft=8, PadTop=4) 102 self.buttonCont = ContainerAutoSize(parent=topCont, align=carbonui.Align.TORIGHT, left=8) 103 self.onlineOfflineCont = OnlineOfflineCont(parent=self.buttonCont, dataController=self.dataController, align=carbonui.Align.TORIGHT, alignMode=uiconst.TOPLEFT) 104 self.processingTimer = ProcessingTimer(parent=self.topSection, align=carbonui.Align.TOPRIGHT, alignMode=uiconst.TOPLEFT, dataController=self.dataController, pickState=carbonui.PickState.ON, top=40, left=8) 105 self.nameLabel = carbonui.text.styles.TextHeadline(parent=topCont, align=carbonui.Align.TOTOP) 106 self.ownerValueLabel, _ = self.ConstructLabelContainers(self.topSection, GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/Owner'), top=16) 107 self.supplyingValueLabel, _ = self.ConstructLabelContainers(self.topSection, GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/Supplying')) 108 self.producingValueLabel, _ = self.ConstructLabelContainers(self.topSection, GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/Producing')) 109 self.producingRichnessSprite = Sprite(name='producingRichnessSprite', parent=self.producingValueLabel.parent, pos=(4, 0, 16, 16), align=carbonui.Align.CENTERLEFT, opacity=0.75) 110 self.producingValueLabel.left = 20 111 self.vulnerabilityValueLabel, self.vulnerabilityCont = self.ConstructLabelContainers(self.topSection, GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/VulnerabilityLabel')) 112 self.vulnerabilityValueLabel.display = False 113 self.vulnerabilityCont.display = False 114 self.ConstructReagentSection() 115 self.btnGroup = ButtonGroup(parent=self.content, align=uiconst.BOTTOMRIGHT, pos=(8, 8, 0, 0)) 116 self.takeBtn = Button(label=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/TakeReagents', volume=0), func=self.TakeReagents, enabled=False) 117 self.btnGroup.add_button(self.takeBtn) 118 self.btnGroup.display = False 119 self.constructionDone = True 120 121 def ConstructLabelContainers(self, parent, headerText, labelClass = carbonui.text.styles.TextBody, textAlign = TextAlign.LEFT, top = 1): 122 minLineHeight = 20 123 lineCont = ContainerAutoSize(name='lineCont', parent=parent, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, top=top, minHeight=minLineHeight, padLeft=8) 124 headerCont = ContainerAutoSize(name='headerCont', parent=lineCont, align=carbonui.Align.TOLEFT) 125 headerLabel = labelClass(name='headerLabel', parent=headerCont, text=headerText, align=carbonui.Align.TOPLEFT, color=TextColor.SECONDARY) 126 rightLineCont = ContainerAutoSize(name='rightLineCont', parent=lineCont, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, minHeight=minLineHeight) 127 valueLabel = labelClass(name='valueLabel', parent=rightLineCont, text='', align=carbonui.Align.TOTOP, padLeft=4, state=uiconst.UI_NORMAL, textAlign=textAlign) 128 loadingWheelAlign = carbonui.Align.CENTERRIGHT if textAlign == TextAlign.RIGHT else carbonui.Align.CENTERLEFT 129 valueLabel.loadingWheel = LoadingWheel(parent=rightLineCont, align=loadingWheelAlign, pos=(8, 0, 16, 16), opacity=0.0) 130 return (valueLabel, lineCont) 131 132 def ConstructReagentSection(self): 133 self.bayCont = ContainerAutoSize(name='bayCont', parent=self.content, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, minHeight=16, padRight=8, padLeft=8) 134 self.bayCont.loadingWheel = LoadingWheel(parent=self.bayCont, align=carbonui.Align.CENTERTOP, pos=(0, 0, 16, 16)) 135 self.typesCont = ContainerAutoSize(name='typesCont', parent=self.bayCont, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, minHeight=16) 136 self.bayCont.display = False 137 138 def TakeReagents(self, *args): 139 with self.takeBtn.busy_context: 140 self.dataController.ExtractReagentsToShip() 141 142 def UpdateTakeBtn(self, qty): 143 self.dataController.selectedQty = qty 144 volume = self.dataController.GetSelectedVolume() 145 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/TakeReagents', volume=volume) 146 self.takeBtn.SetLabel(text) 147 self.UpdateTakeBtnState() 148 149 def UpdateTakeBtnState(self): 150 self.takeBtn.enabled = self._reagentsLoaded and self.dataController.selectedQty > 0 and not self.dataController.linkedShipID 151 152 def LoadWindow(self, itemID): 153 if not self.dataController.IsSameItemID(itemID): 154 with ExceptionEater('Failed disconnecting signal'): 155 self.dataController.on_linked_ship_updated.disconnect(self.OnLinkedShipChanged) 156 self.dataController = self.CreateDataController(itemID) 157 self.onlineOfflineCont.SetDataController(self.dataController) 158 self.nameLabel.text = self.dataController.GetSkyhookName() 159 self.ownerValueLabel.text = self.dataController.GetOwnerName() 160 self.supplyingValueLabel.text = self.dataController.GetResourceDestName() 161 self.threadedLoader.StartLoading(self.LoadProducing_thread) 162 self.onlineOfflineCont.LoadCont() 163 self.btnGroup.display = False 164 self.bayCont.display = False 165 if self.dataController.isAuthorisedToTake: 166 self.threadedLoader.StartLoading(self.LoadAuthorized_thread) 167 168 def LoadProducing_thread(self): 169 animation.fade_in(self.producingValueLabel.loadingWheel) 170 animation.fade_in(self.vulnerabilityValueLabel.loadingWheel) 171 try: 172 self.producingValueLabel.text = '' 173 self.product = self.dataController.GetProduct() 174 productName, texturePath, hintLabel, textHint = self.dataController.GetProductNameAndRichnessTexture() 175 if self.destroyed: 176 return 177 self.producingValueLabel.text = productName 178 self.producingValueLabel.hint = textHint if textHint else '' 179 self.producingValueLabel.left = 20 if texturePath else 0 180 self.producingRichnessSprite.SetTexturePath(texturePath) 181 self.producingRichnessSprite.hint = GetByLabel(hintLabel) if hintLabel else '' 182 if is_reagent_skyhook(self.product): 183 self.vulnerabilityValueLabel.display = True 184 self.vulnerabilityCont.display = True 185 self.UpdateVulnerabilityTime() 186 self.UpdateWindowSize() 187 finally: 188 animation.fade_out(self.producingValueLabel.loadingWheel, duration=0.1) 189 animation.fade_out(self.vulnerabilityValueLabel.loadingWheel, duration=0.1) 190 191 def LoadAuthorized_thread(self): 192 onlineState = self.dataController.GetOnlineState() 193 if not onlineState or onlineState == NOT_AVAILABLE: 194 return 195 reagentTypeID = self.dataController.GetPlanetReagentType() 196 if reagentTypeID and reagentTypeID != NOT_AVAILABLE: 197 self.btnGroup.display = True 198 self.bayCont.display = True 199 self.threadedLoader.StartLoading(self.LoadStorage_thread) 200 self.UpdateWindowSize() 201 else: 202 self.bayCont.display = False 203 204 def LoadStorage_thread(self): 205 self._reagentsLoaded = False 206 if not self.bayCont: 207 return 208 animation.fade_in(self.bayCont.loadingWheel) 209 try: 210 self.typesCont.Flush() 211 typeID, secureAmount, insecureAmount = self.dataController.GetReagentsInSkyhook() 212 secureMaxAmount, insecureMaxAmount = self.dataController.GetStorageQtyAndCapacity() 213 if self.destroyed: 214 return 215 if typeID is NOT_AVAILABLE: 216 carbonui.text.styles.TextBody(name='failureLabel', parent=self.typesCont, text=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NoDataAvailable'), align=carbonui.Align.TOTOP, color=TextColor.SECONDARY, textAlign=TextAlign.CENTER) 217 return 218 storageGrid = GridContainer(name='storageGrid', parent=self.typesCont, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, height=REAGENT_ICON_SIZE, contentSpacing=(16, 1), columns=2) 219 StorageCont(parent=storageGrid, labelText=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/SecureBay', units=secureAmount), typeID=typeID, amount=secureAmount, maxAmount=secureMaxAmount, top=10) 220 StorageCont(parent=storageGrid, labelText=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/SurplusBay', units=insecureAmount), typeID=typeID, amount=insecureAmount, maxAmount=insecureMaxAmount, top=10) 221 ReagentTypeCont(parent=self.typesCont, typeID=typeID, amount=secureAmount, onEditChangeFunc=self.UpdateTakeBtn, top=10) 222 self._reagentsLoaded = True 223 self.UpdateTakeBtnState() 224 self.UpdateWindowSize() 225 finally: 226 animation.fade_out(self.bayCont.loadingWheel, duration=0.1) 227 self.progressThread = AutoTimer(500.0, self.UpdateProgress_thread) 228 229 def UpdateProgress_thread(self): 230 if self.destroyed: 231 if self.progressThread: 232 self.progressThread.KillTimer() 233 self.progressThread = None 234 return 235 if is_reagent_skyhook(self.product): 236 self.UpdateVulnerabilityTime() 237 nextTimestamp, amount, progress, isFull = self.dataController.GetNextReagentHarvestTimeAndAmount() 238 if nextTimestamp == NOT_AVAILABLE and amount == NOT_AVAILABLE and progress == NOT_AVAILABLE and isFull is False: 239 return 240 timeRemaining = nextTimestamp - gametime.GetWallclockTime() 241 self.processingTimer.SetValue(progress, timeRemaining) 242 243 def _CalcTimeDeltaFromNowAndClampToOneMinute(self, time): 244 now = gametime.GetWallclockTime() 245 delta = time - now 246 delta = max(MIN, delta) 247 return delta 248 249 def UpdateVulnerabilityTime(self): 250 vulnerabiltyData = self.dataController.GetTheftVulnerabilityForSkyhook() 251 if vulnerabiltyData is None: 252 self.vulnerabilityValueLabel.text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NoDataAvailable') 253 return 254 end_blue = datetimeutils.datetime_to_filetime(vulnerabiltyData.end) 255 start_blue = datetimeutils.datetime_to_filetime(vulnerabiltyData.start) 256 vulnerable = vulnerabiltyData.vulnerable 257 if vulnerable: 258 delta = self._CalcTimeDeltaFromNowAndClampToOneMinute(end_blue) 259 countdown = FormatTimeIntervalShortWritten(delta, 'day', 'minute') 260 vulnerabilityText = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/VulnerableToTheft', countdown=countdown) 261 color = eveColor.DANGER_RED 262 else: 263 delta = self._CalcTimeDeltaFromNowAndClampToOneMinute(start_blue) 264 countdown = FormatTimeIntervalShortWritten(delta, 'day', 'minute') 265 vulnerabilityText = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/SecureFromTheft', countdown=countdown) 266 self.vulnerabilityValueLabel.text = vulnerabilityText 267 color = TextColor.NORMAL 268 self.vulnerabilityValueLabel.text = vulnerabilityText 269 self.vulnerabilityValueLabel.SetTextColor(color) 270 271 def UpdateWindowSize(self): 272 newHeight = self.sr.headerParent.height + self.content_padding[1] + self.content_padding[3] + 30 273 newHeight += self.topSection.height 274 if self.bayCont.display: 275 newHeight += self.bayCont.height 276 if self.btnGroup.display: 277 newHeight += self.btnGroup.height 278 self.SetMinSize([self.minsize[0], max(self.minsize[1], newHeight)]) 279 280 def OnReagentsUpdated(self, planetID, skyhookID): 281 if skyhookID != self.dataController.itemID or not self.constructionDone: 282 return 283 self.LoadWindow(skyhookID) 284 285 def OnLinkedShipChanged(self, linkItemID, linkedShipID): 286 self.UpdateTakeBtnState() 287 288 def OnSessionChanged(self, isRemote, session, change): 289 if 'solarsystemid' in change or 'structureid' in change: 290 self.Close() 291 292 def Close(self, setClosed = False, *args, **kwds): 293 with ExceptionEater('Failed disconnecting signal'): 294 self.dataController.on_linked_ship_updated.disconnect(self.OnLinkedShipChanged) 295 self.dataController = None 296 super(SkyhookWnd, self).Close(setClosed=setClosed, *args, **kwds) 297 298 def GetMenuMoreOptions(self): 299 menu_data = super(SkyhookWnd, self).GetMenuMoreOptions() 300 if session.role & ROLE_PROGRAMMER: 301 menu_data.AddEntry('QA Reload', self.DebugReload) 302 return menu_data 303 304 305 class ThreadedLoader(object): 306 307 def __init__(self): 308 self.threadDict = {} 309 310 def StartLoading(self, func): 311 funcName = func.__name__ 312 existingThread = self.threadDict.pop(funcName, None) 313 if existingThread: 314 existingThread.kill() 315 self.threadDict[funcName] = uthread2.start_tasklet(self._CallFunc_thread, func, funcName) 316 317 def _CallFunc_thread(self, func, funcName): 318 try: 319 func() 320 finally: 321 self.threadDict.pop(funcName, None) 322 323 324 REAGENT_ICON_SIZE = 64 325 326 class StorageCont(ContainerAutoSize): 327 default_align = carbonui.Align.TOTOP 328 default_alignMode = carbonui.Align.TOTOP 329 default_minHeight = REAGENT_ICON_SIZE 330 331 def ApplyAttributes(self, attributes): 332 super(StorageCont, self).ApplyAttributes(attributes) 333 typeID = attributes.typeID 334 amount = attributes.amount 335 maxAmount = attributes.maxAmount 336 labelText = attributes.labelText 337 self.ConstructUI(typeID, labelText, amount, maxAmount) 338 339 def ConstructUI(self, typeID, labelText, amount, maxAmount): 340 self.storageLabel = carbonui.text.styles.TextBody(name='storageLabel', parent=self, text=labelText, align=carbonui.Align.TOTOP, color=TextColor.SECONDARY) 341 self.gauge = Gauge(parent=self, color=eveThemeColor.THEME_FOCUS, align=uiconst.TOTOP, gaugeHeight=20, padLeft=0, padTop=8) 342 self.gauge.SetValue(float(amount) / maxAmount if maxAmount != 0 else 1) 343 self.gauge.SetValueText(GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/CurrentVolumeAndMax', maxVolume=maxAmount * evetypes.GetVolume(typeID), volume=amount * evetypes.GetVolume(typeID))) 344 345 346 class ProcessingTimer(ContainerAutoSize): 347 348 def ApplyAttributes(self, attributes): 349 super(ProcessingTimer, self).ApplyAttributes(attributes) 350 self.time_text = '' 351 self.dataController = attributes.dataController 352 self.ConstructUI() 353 354 def ConstructUI(self): 355 self.gaugeCont = ContainerAutoSize(name='gaugeCont', parent=self, pickState=carbonui.PickState.OFF) 356 self.gauge = GaugeCircular(parent=self.gaugeCont, colorStart=eveThemeColor.THEME_FOCUS, colorEnd=eveThemeColor.THEME_FOCUS, align=carbonui.Align.CENTER, radius=20, showMarker=False, glowBrightness=0.8) 357 self.gauge.display = False 358 self.icon = Sprite(parent=self.gaugeCont, texturePath=eveicon.inventory, align=carbonui.Align.CENTER, width=16, height=16, opacity=0.75, state=uiconst.UI_NORMAL) 359 self.icon.display = False 360 self.loadingWheel = LoadingWheel(parent=self, align=carbonui.Align.CENTER, pos=(0, 4, 16, 16), opacity=0.0) 361 animation.fade_in(self.loadingWheel) 362 self.storageLabel = carbonui.text.styles.TextDetail(name='storageLabel', parent=self, text='', color=TextColor.SECONDARY, align=carbonui.Align.CENTER, top=30) 363 364 def SetValue(self, value, time_left): 365 self.gauge.SetValue(value, False) 366 self.time_text = FormatTimeIntervalShortWritten(time_left, showFrom='hour', showTo='second') 367 self.storageLabel.text = self.time_text 368 self.gauge.display = True 369 self.icon.display = True 370 animation.fade_out(self.loadingWheel) 371 372 def LoadTooltipPanel(self, tooltipPanel, *args): 373 tooltipPanel.LoadStandardSpacing() 374 securedAmount, unsecuredAmount = self.dataController.GetNextReagentHarvestAmounts() 375 securedText = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/SecureBay', units=securedAmount) 376 surplusText = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/SurplusBay', units=unsecuredAmount) 377 tooltipPanel.AddLabelMedium(text=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NextOutput', countdown=self.time_text)) 378 tooltipPanel.AddLabelMedium(text=securedText, align=carbonui.Align.TOPLEFT) 379 tooltipPanel.AddLabelMedium(text=surplusText, align=carbonui.Align.TOPLEFT) 380 381 382 class ReagentTypeCont(ContainerAutoSize): 383 default_align = carbonui.Align.TOTOP 384 default_alignMode = carbonui.Align.TOTOP 385 default_minHeight = REAGENT_ICON_SIZE 386 387 def ApplyAttributes(self, attributes): 388 super(ReagentTypeCont, self).ApplyAttributes(attributes) 389 self.onEditChangeFunc = attributes.onEditChangeFunc 390 typeID = attributes.typeID 391 amount = attributes.amount 392 self.ContructUI() 393 self.LoadType(typeID, amount) 394 395 def ContructUI(self): 396 spriteCont = Container(name='spriteCont', parent=self, align=carbonui.Align.TOLEFT, width=REAGENT_ICON_SIZE) 397 self.reagentSprite = ItemIcon(name='reagentSprite', parent=spriteCont, align=carbonui.Align.CENTERLEFT, pos=(0, 398 0, 399 REAGENT_ICON_SIZE, 400 REAGENT_ICON_SIZE), state=uiconst.UI_NORMAL) 401 amountCont = ContainerAutoSize(name='amountCont', parent=self, align=carbonui.Align.TORIGHT, minHeight=REAGENT_ICON_SIZE) 402 restCont = ContainerAutoSize(name='restCont', parent=self, align=carbonui.Align.TOTOP, alignMode=carbonui.Align.TOTOP, padLeft=10) 403 self.typeNameLabel = carbonui.text.styles.TextBody(name='valueLabel', parent=restCont, text='', align=carbonui.Align.TOTOP) 404 self.secureLabel = carbonui.text.styles.TextDetail(name='secureLabel', parent=restCont, text=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/ReagentsAvailable'), align=carbonui.Align.TOTOP, top=10, color=TextColor.SECONDARY) 405 self.secureValueLabel = carbonui.text.styles.TextBody(name='secureValueLabel', parent=restCont, text='', align=carbonui.Align.TOTOP) 406 self.amountEdit = SingleLineEditInteger(name='amountEdit', parent=amountCont, align=uiconst.CENTERRIGHT, width=100, OnChange=self.OnEditChanged) 407 408 def OnEditChanged(self, *args): 409 self.onEditChangeFunc(self.amountEdit.GetValue()) 410 411 def LoadType(self, typeID, amount): 412 self.reagentSprite.SetTypeID(typeID) 413 self.typeNameLabel.text = evetypes.GetName(typeID) 414 self.amountEdit.SetValue(amount) 415 self.amountEdit.SetMaxValue(amount) 416 averagePrice = GetAveragePrice(typeID) 417 if averagePrice is None: 418 averagePrice = 0 419 self.secureValueLabel.text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/ProcessedUnits', units=amount, price=FmtISK(averagePrice)) 420 self.reagentSprite.GetMenu = lambda *args: GetMenuService().GetMenuFromItemIDTypeID(None, typeID) 421 self.reagentSprite.OnClick = lambda *args: sm.GetService('info').ShowInfo(typeID=typeID) 422 423 424 class OnlineOfflineCont(ContainerAutoSize): 425 426 def ApplyAttributes(self, attributes): 427 self.toggleSwitch = None 428 self.threadedLoader = ThreadedLoader() 429 super(OnlineOfflineCont, self).ApplyAttributes(attributes) 430 self._dataController = attributes.dataController 431 self.unknowStateLabel = carbonui.text.styles.TextDetail(name='unknowStateLabel', parent=self, text=GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/UnknownOnlineState'), align=carbonui.Align.TOPLEFT) 432 self.unknowStateLabel.display = False 433 self.loadingWheel = LoadingWheel(parent=self, align=carbonui.Align.TOPLEFT, pos=(8, 0, 16, 16), opacity=0.0) 434 self.onlineBtnGrid = LayoutGrid(parent=self, cellSpacing=3, top=8) 435 436 def LoadCont(self): 437 self.threadedLoader.StartLoading(self.LoadOnlineState_thread) 438 439 def LoadOnlineState_thread(self): 440 animation.fade_in(self.loadingWheel) 441 try: 442 self.onlineBtnGrid.Flush() 443 self.unknowStateLabel.display = False 444 onlineState = self._dataController.GetOnlineState() 445 if onlineState == NOT_AVAILABLE: 446 self.unknowStateLabel.display = True 447 elif self.CanEditSkyhookOnlineState(onlineState): 448 self.AddToggleButtons(onlineState) 449 else: 450 self.ReloadReadOnlyStatus(onlineState) 451 finally: 452 animation.fade_out(self.loadingWheel, duration=0.1) 453 454 def CanEditSkyhookOnlineState(self, onlineState): 455 if not self._dataController.HasConfigRoles(): 456 return False 457 if not onlineState: 458 return True 459 reagentTypeID = self._dataController.GetPlanetReagentType() 460 if reagentTypeID > 0: 461 return False 462 return True 463 464 def AddToggleButtons(self, onlineState): 465 self.toggleSwitch = ToggleSwitch(parent=self.onlineBtnGrid, align=carbonui.Align.TOPLEFT, adjustSize=True, checked=bool(onlineState), onText=GetByLabel('UI/SystemMenu/DisplayAndGraphics/Common/On').upper(), offText=GetByLabel('UI/SystemMenu/DisplayAndGraphics/Common/Off').upper(), confirmFunc=self.ConfirmOnlineStateChange) 466 self.toggleSwitch.GetHint = self.GetToggleSwitchHint 467 self.toggleSwitch.on_switch_changed.connect(self.ChangeOnlineState) 468 469 def UpdateToggleSwitch(self): 470 onlineState = self._dataController.GetOnlineState() 471 self.toggleSwitch.SetValue(onlineState, report=False) 472 473 def SetDataController(self, dataController): 474 self._dataController = dataController 475 476 def ReloadReadOnlyStatus(self, onlineState): 477 onlineState = self._dataController.GetOnlineState() 478 if onlineState == NOT_AVAILABLE: 479 self.unknowStateLabel.display = True 480 if onlineState: 481 text = GetByLabel('UI/Common/Online') 482 iconColor = eveColor.SUCCESS_GREEN 483 hint = '' 484 else: 485 text = GetByLabel('UI/Common/Offline') 486 iconColor = eveColor.DANGER_RED 487 hint = GetByLabel('Tooltips/StructureUI/SkyhookIsOfflineNonOwner') 488 STATUS_ICON_SIZE = 14 489 onlineStateIcon = Sprite(name='onlineStateIcon', parent=self.onlineBtnGrid, align=carbonui.Align.CENTERLEFT, pos=(0, 490 0, 491 STATUS_ICON_SIZE, 492 STATUS_ICON_SIZE), state=uiconst.UI_NORMAL, texturePath='res:/UI/Texture/classes/Contacts/onlineIcon.png', outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.8, hint=hint) 493 onlineStateIcon.SetRGBA(*iconColor) 494 label = carbonui.text.styles.TextDetail(parent=self.onlineBtnGrid, text=text, align=carbonui.Align.CENTERLEFT, state=uiconst.UI_NORMAL) 495 label.hint = hint 496 497 def ChangeOnlineState(self, toggleSwitch, onlineState): 498 with toggleSwitch.busy_context: 499 if onlineState: 500 self._dataController.SetOnline() 501 else: 502 self._dataController.SetOffline() 503 self.UpdateToggleSwitch() 504 505 def GetToggleSwitchHint(self): 506 onlineState = self._dataController.GetOnlineState() 507 if onlineState == NOT_AVAILABLE: 508 return '' 509 if onlineState: 510 labelPath = 'Tooltips/StructureUI/SkyhookTurnOffline' 511 else: 512 labelPath = 'Tooltips/StructureUI/SkyhookTurnOnline' 513 return GetByLabel(labelPath) 514 515 def ConfirmOnlineStateChange(self, currentState): 516 if not currentState: 517 return True 518 if isinstance(self._dataController.GetProduct(), numbers.Number): 519 if prompt_player_fsd_dialog('SkyhookOfflineConfirmReagent', {}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES: 520 return False 521 elif prompt_player_fsd_dialog('SkyhookOfflineConfirmResources', {}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES: 522 return False 523 return True 524 525 def Close(self): 526 with ExceptionEater('Closing OnlineOfflineCont'): 527 if self.toggleSwitch: 528 self.toggleSwitch.on_switch_changed.connect(self.ChangeOnlineState) 529 self.dataController = None 530 super(OnlineOfflineCont, self).Close()