NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

moonmining.py (116411B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\moonmining.py
      2 import logging
      3 import math
      4 import sys
      5 import dogma.data
      6 import evetypes
      7 import blue
      8 import uthread
      9 import utillib
     10 from carbon.common.script.net import moniker
     11 from carbon.common.script.sys.serviceConst import ROLE_GML, ROLE_WORLDMOD
     12 from carbon.common.script.util.commonutils import GetAttrs
     13 from carbon.common.script.util.format import FmtDate
     14 from carbonui.control.combo import Combo
     15 from carbonui.control.scrollentries import SE_BaseClassCore
     16 from carbonui.control.window import Window
     17 from carbonui.primitives.container import Container
     18 from carbonui.primitives.fill import Fill
     19 from carbonui.primitives.frame import Frame
     20 from carbonui.primitives.line import Line
     21 from carbonui.util.various_unsorted import ParanoidDecoMethod
     22 from carbonui.button.group import ButtonGroup, ButtonSizeMode
     23 from carbonui.control.button import Button
     24 from carbonui.control.checkbox import Checkbox
     25 from eve.client.script.ui.control.entries.generic import Generic
     26 from eve.client.script.ui.control.entries.header import Header
     27 from eve.client.script.ui.control.entries.util import GetFromClass
     28 from eve.client.script.ui.control.listgroup import ListGroup
     29 from eve.client.script.ui.util import uix
     30 from eve.common.lib import appConst as const
     31 from carbon.common.script.util import timerstuff
     32 from carbonui import fontconst
     33 from carbonui.control.singlelineedits.singleLineEditFloat import SingleLineEditFloat
     34 from carbonui.control.singlelineedits.singleLineEditPassword import SingleLineEditPassword
     35 from controltowerresources.data import get_resources_for_tower_by_purpose
     36 from eve.client.script.ui.control import eveIcon, eveLabel, eveScroll
     37 from eve.client.script.parklife import states as state
     38 import carbonui.const as uiconst
     39 import localization
     40 import telemetry
     41 from carbonui.control.tabGroup import TabGroup
     42 from eve.common.script.mgt.entityConst import POS_STRUCTURE_STATE
     43 from carbonui.uicore import uicore
     44 from eveexceptions import UserError
     45 from eveservices.menu import GetMenuService
     46 from eveuniverse.security import is_high_sec_or_higher_solar_system
     47 from menu import MenuLabel
     48 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     49 log = logging.getLogger(__name__)
     50 structProgressMap = {const.pwnStructureStateAnchoring: const.pwnStructureStateAnchored,
     51  const.pwnStructureStateOnlining: const.pwnStructureStateOnline,
     52  const.pwnStructureStateUnanchoring: const.pwnStructureStateUnanchored,
     53  const.pwnStructureStateReinforced: const.pwnStructureStateOnline,
     54  const.pwnStructureStateOperating: const.pwnStructureStateOnline}
     55 MINWNDWIDTH = 496
     56 
     57 class MoonMining(Window):
     58     __guid__ = 'form.MoonMining'
     59     __notifyevents__ = ['OnSlimItemChange',
     60      'DoBallsAdded',
     61      'DoBallRemove',
     62      'DoBallClear',
     63      'OnMoonProcessChange',
     64      'OnBallparkCall',
     65      'DoBallsRemove']
     66     default_windowID = 'moon'
     67     default_captionLabelPath = 'UI/Inflight/MoonMining/ControlTowerManager'
     68 
     69     def ApplyAttributes(self, attributes):
     70         Window.ApplyAttributes(self, attributes)
     71         slimItem = attributes.slimItem
     72         self.notifySettings = None
     73         try:
     74             self.connectionsChanged = 0
     75             self.godma = sm.GetService('godma')
     76             self.scope = uiconst.SCOPE_INGAME
     77             self.sr.main = self.GetChild('main')
     78             self.moon = None
     79             if slimItem:
     80                 if slimItem.ownerID != session.corpid:
     81                     self.CloseByUser()
     82                     return
     83                 self.slimItem = slimItem
     84                 self.sr.name = uix.GetSlimItemName(self.slimItem)
     85                 self.capacity = self.godma.GetType(self.slimItem.typeID).capacity
     86                 self.capacitySecondary = self.godma.GetType(self.slimItem.typeID).capacitySecondary
     87                 self.tower = self.GetShell(self.slimItem.itemID)
     88                 cfg.eveowners.Prime([self.slimItem.ownerID])
     89                 self.sr.owner = cfg.eveowners.Get(self.slimItem.ownerID).name
     90                 self.posMgr = moniker.Moniker('posMgr', session.solarsystemid)
     91                 self.pwn = sm.GetService('pwn')
     92                 self.GetMoon()
     93             else:
     94                 self.sr.name = 'testing'
     95                 self.sr.owner = cfg.eveowners.Get(session.charid).name
     96             self.sr.powerSupply = 0
     97             self.sr.cpuSupply = 0
     98             self.sr.powerConsumption = 0
     99             self.sr.cpuConsumption = 0
    100             self.doClear = True
    101             self.sr.top = Container(name='top', align=uiconst.TOTOP, parent=self.sr.main, padLeft=const.defaultPadding, clipChildren=1)
    102             self.sr.picParent = Container(name='picpar', parent=self.sr.top, align=uiconst.TOPLEFT, width=64, height=64, left=const.defaultPadding, top=const.defaultPadding)
    103             self.sr.icon = eveIcon.Icon(parent=self.sr.picParent, align=uiconst.TOALL, padding=(1, 1, 1, 1))
    104             Frame(parent=self.sr.picParent, color=(1.0, 1.0, 1.0, 0.5))
    105             if slimItem:
    106                 self.sr.icon.LoadIconByTypeID(self.slimItem.typeID, ignoreSize=True)
    107             Container(name='push', align=uiconst.TOLEFT, width=83, parent=self.sr.top)
    108             Container(name='push', align=uiconst.TOTOP, height=2, parent=self.sr.top)
    109             r = Container(name='rightstats', parent=self.sr.top, align=uiconst.TORIGHT, width=100)
    110             h = Container(name='info', parent=self.sr.top, align=uiconst.TOALL, pos=(0, 0, 0, 0))
    111             self.sr.status = eveLabel.EveLabelSmall(text='', parent=r, top=20, left=8, width=100, state=uiconst.UI_NORMAL, align=uiconst.TOPRIGHT)
    112             title = eveLabel.EveLabelMediumBold(text=self.sr.name, parent=h, maxLines=1, state=uiconst.UI_NORMAL, bold=True)
    113             top = title.textheight
    114             towerLocationLabel = localization.GetByLabel('UI/Inflight/MoonMining/TowerLocation')
    115             self.sr.locationtext = eveLabel.EveLabelSmallBold(text=towerLocationLabel, parent=h, top=top, state=uiconst.UI_NORMAL)
    116             top += self.sr.locationtext.textheight - 2
    117             towerOwnerLabel = localization.GetByLabel('UI/Inflight/MoonMining/TowerOwner')
    118             t = eveLabel.EveLabelSmallBold(text=towerOwnerLabel, parent=h, top=top, state=uiconst.UI_NORMAL)
    119             t = eveLabel.EveLabelSmall(text=self.sr.owner, parent=h, left=55, top=top, state=uiconst.UI_NORMAL, bold=True)
    120             top += t.textheight + 2
    121             icontop = top
    122             gaugeLeft = 70
    123             textLeft = 140
    124             t = eveLabel.EveLabelSmallBold(text=localization.GetByLabel('UI/Inflight/MoonMining/TowerShield'), parent=h, left=0, top=top)
    125             self.sr.shieldgauge = self.GetGauge(h, gaugeLeft, top + 1, (0.8, 0.8, 1.0, 0.5))
    126             self.sr.shieldtext = eveLabel.EveLabelSmall(text='', parent=h, left=textLeft, top=top)
    127             top += t.textheight - 2
    128             t = eveLabel.EveLabelSmallBold(text=localization.GetByLabel('UI/Inflight/MoonMining/TowerArmor'), parent=h, left=0, top=top)
    129             self.sr.armorgauge = self.GetGauge(h, gaugeLeft, top + 1, (0.6, 0.6, 1.0, 0.5))
    130             self.sr.armortext = eveLabel.EveLabelSmall(text='', parent=h, left=textLeft, top=top)
    131             top += t.textheight - 2
    132             t = eveLabel.EveLabelSmallBold(text=localization.GetByLabel('UI/Inflight/MoonMining/TowerStructure'), parent=h, left=0, top=top)
    133             self.sr.structuregauge = self.GetGauge(h, gaugeLeft, top + 1, (0.4, 0.4, 1.0, 0.5))
    134             self.sr.structuretext = eveLabel.EveLabelSmall(text='', parent=h, left=textLeft, top=top)
    135             top += t.textheight - 2
    136             t = eveLabel.EveLabelSmallBold(text=localization.GetByLabel('UI/Inflight/MoonMining/TowerPower'), parent=h, left=0, top=top)
    137             self.sr.powergauge = self.GetGauge(h, gaugeLeft, top + 1, (1.0, 1.0, 0.0, 0.5))
    138             self.sr.powertext = eveLabel.EveLabelSmall(text='', parent=h, left=textLeft, top=top)
    139             top += t.textheight - 2
    140             t = eveLabel.EveLabelSmallBold(text=localization.GetByLabel('UI/Inflight/MoonMining/TowerCPU'), parent=h, left=0, top=top)
    141             self.sr.cpugauge = self.GetGauge(h, gaugeLeft, top + 1, (0.0, 0.0, 1.0, 0.5))
    142             self.sr.cputext = eveLabel.EveLabelSmall(text='', parent=h, left=textLeft, top=top)
    143             top += t.textheight
    144             self.sr.top.height = top
    145             iconsize = 24
    146             eveIcon.Icon(icon='ui_22_32_20', parent=r, pos=(0,
    147              icontop - 5,
    148              iconsize,
    149              iconsize), hint=dogma.data.get_attribute_display_name(const.attributeShieldEmDamageResonance), ignoreSize=True)
    150             eveIcon.Icon(icon='ui_22_32_19', parent=r, pos=(0,
    151              icontop + 15,
    152              iconsize,
    153              iconsize), hint=dogma.data.get_attribute_display_name(const.attributeShieldExplosiveDamageResonance), ignoreSize=True)
    154             eveIcon.Icon(icon='ui_22_32_17', parent=r, pos=(50,
    155              icontop - 5,
    156              iconsize,
    157              iconsize), hint=dogma.data.get_attribute_display_name(const.attributeShieldKineticDamageResonance), ignoreSize=True)
    158             eveIcon.Icon(icon='ui_22_32_18', parent=r, pos=(50,
    159              icontop + 15,
    160              iconsize,
    161              iconsize), hint=dogma.data.get_attribute_display_name(const.attributeShieldThermalDamageResonance), ignoreSize=True)
    162             self.sr.emkinText = eveLabel.EveLabelSmall(text='', parent=r, left=20, top=icontop, width=100, tabs=[50], state=uiconst.UI_DISABLED)
    163             self.sr.emkinText._tabMargin = 0
    164             self.sr.expthermText = eveLabel.EveLabelSmall(text='', parent=r, left=20, top=icontop + 20, width=100, tabs=[50], state=uiconst.UI_DISABLED)
    165             self.sr.expthermText._tabMargin = 0
    166             blue.pyos.synchro.Yield()
    167             btns = [(localization.GetByLabel('UI/Inflight/POS/AnchorObject'),
    168               self.Anchor,
    169               (),
    170               84),
    171              (localization.GetByLabel('UI/Inflight/MoonMining/Structures/Unanchor'),
    172               self.Unanchor,
    173               (),
    174               84),
    175              (localization.GetByLabel('UI/Inflight/MoonMining/PutOnline'),
    176               self.Online,
    177               (),
    178               84),
    179              (localization.GetByLabel('UI/Inflight/MoonMining/PutOffline'),
    180               self.Offline,
    181               (),
    182               84)]
    183             self.sr.structuresbuttons = ButtonGroup(btns=btns, parent=self.sr.main)
    184             self.sr.structuresbuttons.state = uiconst.UI_HIDDEN
    185             btns = [(localization.GetByLabel('UI/Common/Buttons/Apply'),
    186               self.ProdApply,
    187               (),
    188               84), (localization.GetByLabel('UI/Inflight/MoonMining/Processes/Reload'),
    189               self.ProdReload,
    190               (),
    191               84), (localization.GetByLabel('UI/Inflight/MoonMining/Processes/ClearLinks'),
    192               self.ProdClearLinks,
    193               (),
    194               84)]
    195             if session.role & ROLE_GML:
    196                 btns.append((localization.GetByLabel('UI/Inflight/MoonMining/Processes/RunCycle'),
    197                  self.RunProcessCycle,
    198                  (),
    199                  84))
    200             self.sr.productionbuttons = ButtonGroup(btns=btns, parent=self.sr.main)
    201             self.sr.productionbuttons.state = uiconst.UI_HIDDEN
    202             btns = [(localization.GetByLabel('UI/Inflight/MoonMining/Processes/Open'),
    203               self.OpenResources,
    204               (),
    205               84)]
    206             self.sr.fuelbuttons = ButtonGroup(btns=btns, parent=self.sr.main)
    207             self.sr.fuelbuttons.state = uiconst.UI_HIDDEN
    208             btns = [(localization.GetByLabel('UI/Inflight/POS/AssumeStructureControl'),
    209               self.AssumeControl,
    210               (),
    211               84), (localization.GetByLabel('UI/Inflight/POS/RelinquishPOSControl'),
    212               self.RelinquishControl,
    213               (),
    214               84)]
    215             self.sr.controlbuttons = ButtonGroup(btns=btns, parent=self.sr.main, button_size_mode=ButtonSizeMode.DYNAMIC)
    216             self.sr.controlbuttons.state = uiconst.UI_HIDDEN
    217             self.accessCont = Container(name='access', align=uiconst.TOBOTTOM, state=uiconst.UI_HIDDEN, height=90, parent=self.sr.main, clipChildren=True)
    218             self.sr.scroll = eveScroll.Scroll(name='structures', align=uiconst.TOALL, parent=self.sr.main, padding=(const.defaultPadding,
    219              const.defaultPadding,
    220              const.defaultPadding,
    221              const.defaultPadding))
    222             self.sr.scroll.sr.id = 'moonmining'
    223             self.sr.scroll.selectionScrolling = False
    224             content = self.sr.scroll.sr.content
    225             content.OnDropData = self.OnTowerDropData
    226             self.sr.standingspanel = Container(name='standings', align=uiconst.TOALL, state=uiconst.UI_HIDDEN, parent=self.sr.main, pos=(0, 0, 0, 0))
    227             self.sr.forcefieldpanel = Container(name='forcefield', align=uiconst.TOALL, state=uiconst.UI_HIDDEN, parent=self.sr.main, pos=(0, 0, 0, 0))
    228             self.sr.structurepanel = Container(name='structure', align=uiconst.TOALL, state=uiconst.UI_HIDDEN, parent=self.sr.main, pos=(0, 0, 0, 0))
    229             self.sr.processpanel = Container(name='structure', align=uiconst.TOALL, state=uiconst.UI_HIDDEN, parent=self.sr.main, pos=(0, 0, 0, 0))
    230             tabs = []
    231             structuretabs = []
    232             processtabs = []
    233             if session.corprole & const.corpRoleStarbaseConfig:
    234                 forceFieldLabel = localization.GetByLabel('UI/Generic/General')
    235                 defenseLabel = localization.GetByLabel('UI/Inflight/MoonMining/Defense/Defense')
    236                 tabs = [[forceFieldLabel,
    237                   self.sr.forcefieldpanel,
    238                   self,
    239                   ('force', None)], [defenseLabel,
    240                   self.sr.standingspanel,
    241                   self,
    242                   ('standings', None)]]
    243             if (const.corpRoleStarbaseConfig | const.corpRoleStarbaseCaretaker | const.corpRoleInfrastructureTacticalOfficer) & session.corprole:
    244                 structuresLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/Structures')
    245                 tabs.extend([[structuresLabel,
    246                   self.sr.structurepanel,
    247                   self,
    248                   ('structures', None)]])
    249                 if (const.corpRoleStarbaseConfig | const.corpRoleStarbaseCaretaker) & session.corprole:
    250                     processesLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/Processes')
    251                     tabs.extend([[processesLabel,
    252                       self.sr.processpanel,
    253                       self,
    254                       ('process', None)]])
    255                     structuretabs.append([structuresLabel,
    256                      self.sr.scroll,
    257                      self,
    258                      ('structures_structures', 'structures'),
    259                      self.sr.structuresbuttons])
    260                     if const.corpRoleStarbaseConfig & session.corprole:
    261                         controlTowersLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/ControlTowers')
    262                         noOtherStructuresLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/NoOtherNamedStructures')
    263                         cachedFor5MinLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/CachedFor5Min')
    264                         structuretabs.extend([[controlTowersLabel,
    265                           self.sr.scroll,
    266                           self,
    267                           ('structures_othertowers', 'othertowers'),
    268                           None,
    269                           noOtherStructuresLabel + '<br><br>' + cachedFor5MinLabel]])
    270                     fuelLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/Fuel')
    271                     productionLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/Production')
    272                     processtabs.extend([[fuelLabel,
    273                       self.sr.scroll,
    274                       self,
    275                       ('process_fuel', 'fuel'),
    276                       self.sr.fuelbuttons], [productionLabel,
    277                       self.sr.scroll,
    278                       self,
    279                       ('process_production', 'production'),
    280                       self.sr.productionbuttons]])
    281                 if session.corprole & const.corpRoleStarbaseConfig:
    282                     accessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/Access')
    283                     structuretabs.insert(1, [accessLabel,
    284                      self.sr.scroll,
    285                      self,
    286                      ('structures_access', 'access'),
    287                      self.accessCont])
    288                 if session.corprole & const.corpRoleInfrastructureTacticalOfficer:
    289                     label = localization.GetByLabel('UI/Inflight/MoonMining/Structures/Control')
    290                     structuretabs.insert(2, [label,
    291                      self.sr.scroll,
    292                      self,
    293                      ('structures_control', 'control'),
    294                      self.sr.controlbuttons])
    295             self.SetMinSize([MINWNDWIDTH, 420])
    296             self.sr.structuretabs = TabGroup(name='structuretabs', parent=self.sr.main, idx=1)
    297             self.sr.processtabs = TabGroup(name='processtabs', parent=self.sr.main, idx=1)
    298             self.sr.maintabs = TabGroup(name='tabparent', parent=self.sr.main, idx=1)
    299             self.sr.maintabs.Startup(tabs, 'pospanel', autoselecttab=0)
    300             self.sr.structuretabs.Startup(structuretabs, 'moonminingstructuretabs', autoselecttab=0)
    301             self.sr.processtabs.Startup(processtabs, 'moonminingprocesstabs', autoselecttab=0)
    302             self.sr.maintabs.AutoSelect()
    303             self.invReady = 1
    304             if slimItem:
    305                 self.sr.updateTimer = timerstuff.AutoTimer(1000, self.UpdateDamage)
    306                 self.UpdateStructures()
    307         except UserError:
    308             raise
    309         except Exception as e:
    310             log.exception(e)
    311 
    312     def _OnClose(self, *args):
    313         self.godma = None
    314         self.posMgr = None
    315         self.slimItem = None
    316         self.capacity = None
    317         self.tower = None
    318 
    319     def OnTabDeselect(self):
    320         if self.connectionsChanged:
    321             if prompt_player_fsd_dialog('ApplyStructureConnections', {}, uiconst.YESNO) == uiconst.ID_YES:
    322                 self.ProdApply()
    323             self.connectionsChanged = 0
    324 
    325     def Load(self, args):
    326         key, flag = args
    327         if self.sr.Get('cookie', None) is not None:
    328             sm.GetService('inv').Unregister(self.sr.cookie)
    329             self.sr.cookie = None
    330         if key in ('standings', 'force'):
    331             self.sr.fuelbuttons.state = uiconst.UI_HIDDEN
    332             self.sr.productionbuttons.state = uiconst.UI_HIDDEN
    333             self.sr.structuresbuttons.state = uiconst.UI_HIDDEN
    334             self.accessCont.state = uiconst.UI_HIDDEN
    335             self.sr.controlbuttons.state = uiconst.UI_HIDDEN
    336         if key == 'structures':
    337             self.sr.structuretabs.state = uiconst.UI_NORMAL
    338             self.sr.processtabs.state = uiconst.UI_HIDDEN
    339             self.sr.structuretabs.AutoSelect()
    340             self.sr.fuelbuttons.state = uiconst.UI_HIDDEN
    341             self.sr.productionbuttons.state = uiconst.UI_HIDDEN
    342         elif key[:11] == 'structures_':
    343             self.ShowStructureTab(flag)
    344         elif key == 'process':
    345             self.sr.structuretabs.state = uiconst.UI_HIDDEN
    346             self.sr.processtabs.state = uiconst.UI_NORMAL
    347             self.sr.processtabs.AutoSelect()
    348             self.sr.structuresbuttons.state = uiconst.UI_HIDDEN
    349             self.accessCont.state = uiconst.UI_HIDDEN
    350             self.sr.controlbuttons.state = uiconst.UI_HIDDEN
    351         elif key[:8] == 'process_':
    352             self.ShowProcessTab(flag)
    353         elif key == 'standings':
    354             self.sr.structuretabs.state = uiconst.UI_HIDDEN
    355             self.sr.processtabs.state = uiconst.UI_HIDDEN
    356             self.sr.scroll.state = uiconst.UI_HIDDEN
    357             self.ShowStandings()
    358         elif key == 'force':
    359             self.sr.structuretabs.state = uiconst.UI_HIDDEN
    360             self.sr.processtabs.state = uiconst.UI_HIDDEN
    361             self.sr.scroll.state = uiconst.UI_HIDDEN
    362             self.ShowForce()
    363 
    364     def ShowStructureTab(self, flag):
    365         self.sr.scroll.ShowHint('')
    366         self.sr.scroll.multiSelect = 0
    367         if flag == 'access':
    368             self.ShowAccess()
    369         elif flag == 'control':
    370             self.sr.scroll.multiSelect = 1
    371             self.ShowControl()
    372         elif flag == 'structures':
    373             self.ShowStructures()
    374         elif flag == 'othertowers':
    375             self.ShowOtherTowers()
    376 
    377     def ShowProcessTab(self, flag):
    378         if flag == 'production':
    379             self.ShowProduction()
    380         elif flag == 'fuel':
    381             self.ShowFuel()
    382 
    383     def ShowOtherTowers(self):
    384         ct = sm.RemoteSvc('posMgr').GetControlTowers()
    385         if self.sr.Get('showing', '') != 'othertowers' or len(ct) != len(self.sr.scroll.GetNodes()):
    386             scrolllist = []
    387             sollist = {}
    388             primeloc = []
    389             if ct:
    390                 for row in ct:
    391                     typeID, structureID, solarSystemID = row[0:3]
    392                     if structureID == self.slimItem.itemID:
    393                         continue
    394                     primeloc.append(structureID)
    395                     if solarSystemID not in sollist:
    396                         sollist[solarSystemID] = [(typeID, structureID)]
    397                     else:
    398                         sollist[solarSystemID].append((typeID, structureID))
    399 
    400                 cfg.evelocations.Prime(primeloc)
    401             if sollist:
    402                 for solarSystemID, structureIDs in sollist.iteritems():
    403                     jumps = int(sm.GetService('clientPathfinderService').GetJumpCountFromCurrent(solarSystemID))
    404                     label = localization.GetByLabel('UI/Inflight/MoonMining/Structures/SolarSystemNameAndJumps', solarsystemID=solarSystemID, structureQuantity=len(structureIDs), jumps=jumps)
    405                     scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetTowerGroupSubContent,
    406                      'label': label,
    407                      'id': ('TowerSel', solarSystemID),
    408                      'groupItems': structureIDs,
    409                      'toSystem': solarSystemID,
    410                      'iconMargin': 2,
    411                      'showlen': 0,
    412                      'sublevel': 0,
    413                      'state': 'locked'}))
    414 
    415                 scrolllist = localization.util.Sort(scrolllist, key=lambda x: x.label)
    416             headers = [localization.GetByLabel('UI/Common/Name'), localization.GetByLabel('UI/Common/Type'), localization.GetByLabel('UI/Common/Distance')]
    417             if not len(scrolllist):
    418                 self.sr.scroll.ShowHint(localization.GetByLabel('UI/Inflight/MoonMining/Structures/NoOtherControlTowers'))
    419                 headers = []
    420             self.sr.scroll.state = uiconst.UI_NORMAL
    421             self.sr.scroll.sr.id = 'moonmining_othertowers'
    422             self.sr.scroll.Load(contentList=scrolllist, headers=headers)
    423         self.sr.showing = 'othertowers'
    424 
    425     def GetTowerGroupSubContent(self, nodedata, newitems = 0):
    426         scrolllist = []
    427         fromSystem = cfg.evelocations.Get(session.solarsystemid)
    428         for typeID, itemID in nodedata.groupItems:
    429             toSystem = cfg.evelocations.Get(nodedata.toSystem)
    430             dist = uix.GetLightYearDistance(fromSystem, toSystem)
    431             if dist is None:
    432                 distanceInLightYearsLabel = localization.GetByLabel('UI/Standings/Unknown')
    433             else:
    434                 distanceInLightYearsLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/DistanceInLightYears', distance=dist)
    435             locName = cfg.evelocations.Get(itemID).name
    436             lbl = evetypes.GetName(typeID)
    437             data = utillib.KeyVal()
    438             data.label = '%s<t>%s<t>%s' % (locName or lbl, lbl, distanceInLightYearsLabel)
    439             data.listvalue = typeID
    440             data.id = ('TowerSel', itemID)
    441             data.typeID = const.typeSolarSystem
    442             data.itemID = nodedata.toSystem
    443             data.sublevel = 1
    444             data.Set('sort_%s' % localization.GetByLabel('UI/Common/Name'), locName or lbl)
    445             data.Set('sort_%s' % localization.GetByLabel('UI/Common/Type'), lbl)
    446             data.Set('sort_%s' % localization.GetByLabel('UI/Common/Distance'), dist)
    447             scrolllist.append(GetFromClass(Generic, data=data))
    448 
    449         return localization.util.Sort(scrolllist, key=lambda x: x.label)
    450 
    451     def ShowControl(self):
    452         bp = sm.GetService('michelle').GetBallpark()
    453         if bp:
    454             structures = [ rec for itemID, rec in bp.slimItems.iteritems() if rec.categoryID == const.categoryStarbase and rec.groupID != const.groupControlTower and rec.ownerID == self.slimItem.ownerID ]
    455         scrolllist = []
    456         for structure in structures:
    457             controllable = [ ta for ta in dogma.data.get_type_attributes(structure.typeID) if ta.attributeID == const.attributePosPlayerControlStructure ]
    458             if controllable:
    459                 controllerID, controllerName = sm.GetService('pwn').GetControllerIDName(structure.itemID)
    460                 state = sm.GetService('pwn').GetStructureState(structure)
    461                 scrolllist.append(GetFromClass(StructureControl, {'label': [uix.GetSlimItemName(structure),
    462                            '<t>',
    463                            POS_STRUCTURE_STATE[state[0]],
    464                            '<t>',
    465                            controllerName],
    466                  'rec': structure,
    467                  'state': state[0],
    468                  'GetMenu': self.GetStructureMenu,
    469                  'StructureProgress': self.StructureProgress,
    470                  'args': (None,)}))
    471 
    472         if not len(scrolllist):
    473             self.sr.scroll.ShowHint(localization.GetByLabel('UI/Inflight/MoonMining/Structures/NoOtherStructuresInRange'))
    474         self.sr.scroll.sr.ignoreTabTrimming = False
    475         self.sr.scroll.sr.id = 'moonmining_control'
    476         nameLabel = localization.GetByLabel('UI/Common/Name')
    477         structureStateLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/StructureState')
    478         controlLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/Control')
    479         self.sr.scroll.Load(contentList=scrolllist, headers=[nameLabel, structureStateLabel, controlLabel])
    480         self.sr.showing = 'control'
    481 
    482     def ShowStructures(self):
    483         bp = sm.GetService('michelle').GetBallpark()
    484         if bp:
    485             structures = [ rec for itemID, rec in bp.slimItems.iteritems() if rec.categoryID == const.categoryStarbase and rec.groupID != const.groupControlTower and rec.ownerID == self.slimItem.ownerID ]
    486         if self.sr.Get('showing', '') != 'structures' or len(structures) != len(self.sr.scroll.GetNodes()):
    487             scrolllist = []
    488             for structure in structures:
    489                 state = sm.GetService('pwn').GetStructureState(structure)
    490                 cpu = self.godma.GetType(structure.typeID).cpu
    491                 power = self.godma.GetType(structure.typeID).power
    492                 data = utillib.KeyVal()
    493                 data.label = '%s<t>%s<t><right>%s<t><right>%s' % (uix.GetSlimItemName(structure),
    494                  POS_STRUCTURE_STATE[state[0]],
    495                  localization.GetByLabel('UI/Inflight/MoonMining/Structures/DisplayPowerUsage', powerUsage=power),
    496                  localization.GetByLabel('UI/Inflight/MoonMining/Structures/DisplayCPUUsage', cpuUsage=cpu))
    497                 data.rec = structure
    498                 data.state = state[0]
    499                 data.GetMenu = self.GetStructureMenu
    500                 data.StructureProgress = self.StructureProgress
    501                 data.power = power
    502                 data.cpu = cpu
    503                 data.Set('sort_%s' % localization.GetByLabel('UI/Inflight/MoonMining/Structures/StructureState'), POS_STRUCTURE_STATE[state[0]])
    504                 data.Set('sort_%s' % localization.GetByLabel('UI/Common/Power'), power)
    505                 data.Set('sort_%s' % localization.GetByLabel('UI/Common/Cpu'), cpu)
    506                 scrolllist.append(GetFromClass(Structure, data=data))
    507 
    508             if not len(scrolllist):
    509                 self.sr.scroll.ShowHint(localization.GetByLabel('UI/Inflight/MoonMining/Structures/NoOtherStructuresInRange'))
    510             self.sr.scroll.sr.ignoreTabTrimming = False
    511             self.sr.scroll.sr.id = 'moonmining_structures'
    512             nameLabel = localization.GetByLabel('UI/Common/Name')
    513             structureStateLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/StructureState')
    514             powerLabel = localization.GetByLabel('UI/Common/Power')
    515             cpuLabel = localization.GetByLabel('UI/Common/Cpu')
    516             self.sr.scroll.Load(contentList=scrolllist, headers=[nameLabel,
    517              structureStateLabel,
    518              powerLabel,
    519              cpuLabel])
    520         for entry in self.sr.scroll.GetNodes():
    521             for rec in structures:
    522                 if rec.itemID == entry.rec.itemID and rec != entry.rec:
    523                     entry.rec = rec
    524                     if entry.panel:
    525                         entry.panel.UpdateState()
    526                     break
    527 
    528         self.sr.showing = 'structures'
    529 
    530     def ShowProduction(self, force = 0):
    531         cycle = self.godma.GetType(self.slimItem.typeID).posControlTowerPeriod
    532         scrolllist = []
    533         scrolllist.append(GetFromClass(Header, {'label': localization.GetByLabel('UI/Inflight/MoonMining/Processes/MoonProduces')}))
    534         for typeID, quantity in self.res.iteritems():
    535             label = localization.GetByLabel('UI/Inflight/MoonMining/Processes/MoonProduct', itemTypeID=typeID, quantity=quantity, unitsProduced=self.godma.GetType(typeID).moonMiningAmount, cycleTime=cycle / 60000)
    536             scrolllist.append(GetFromClass(Generic, {'label': label,
    537              'typeID': typeID,
    538              'GetMenu': self.GetTypeMenu}))
    539 
    540         if len(scrolllist) == 1:
    541             if sm.GetService('pwn').GetStructureState(self.slimItem)[0].startswith('online'):
    542                 scrolllist.append(GetFromClass(Generic, {'label': localization.GetByLabel('UI/Inflight/MoonMining/Processes/NoHarvestableResources'),
    543                  'height': 24}))
    544             else:
    545                 scrolllist.append(GetFromClass(Generic, {'label': localization.GetByLabel('UI/Inflight/MoonMining/Processes/MineralScanImpossible'),
    546                  'height': 24}))
    547         self.sr.scroll.ShowHint()
    548         self.sr.scroll.sr.id = 'moonmining_production'
    549         self.sr.scroll.Load(contentList=scrolllist, scrollTo=self.sr.scroll.GetScrollProportion())
    550         self.sr.showing = 'production'
    551 
    552     def ShowStandings(self):
    553         if not self.sr.Get('standingsinited', 0):
    554             self.InitStandingsPanel()
    555         standing, status, statusDrop, war, standingOwnerID = self.sentrySettings = self.posMgr.GetTowerSentrySettings(self.slimItem.itemID)
    556         self.sentrySettings = self.sentrySettings['line']
    557         if session.allianceid is not None and standingOwnerID == session.allianceid:
    558             self.sr.alliancestandingcheckbox.SetChecked(1, 0)
    559         else:
    560             self.sr.alliancestandingcheckbox.SetChecked(0, 0)
    561         if standing is not None:
    562             self.sr.standingcheckbox1.SetChecked(1, 0)
    563             self.sr.standingedit1.SetValue(standing)
    564         else:
    565             self.sr.standingcheckbox1.SetChecked(0, 0)
    566             self.sr.standingedit1.SetValue(0.0)
    567         if status is not None:
    568             self.sr.standingcheckbox2.SetChecked(1, 0)
    569             self.sr.standingedit2.SetValue(status)
    570         else:
    571             self.sr.standingcheckbox2.SetChecked(0, 0)
    572             self.sr.standingedit2.SetValue(0.0)
    573         self.sr.standingcheckbox4.SetChecked(statusDrop, 0)
    574         self.sr.standingcheckbox6.SetChecked(war, 0)
    575         self.sr.showing = 'standings'
    576 
    577     def ShowForce(self):
    578         if not self.sr.Get('forcefieldinited', 0):
    579             self.InitForcefieldPanel()
    580         if not session.allianceid:
    581             self.sr.forcefieldcheckbox2.state = uiconst.UI_HIDDEN
    582         forcefield = self.GetForcefield()
    583         bp = sm.GetService('michelle').GetBallpark()
    584         ball = bp.GetBall(forcefield.itemID)
    585         log.info('Forcefield harmonic %s', ball.harmonic)
    586         if ball.harmonic not in (0, -1):
    587             self.sr.forcefieldtext1.text = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/ForceFieldActive')
    588         else:
    589             self.sr.forcefieldtext1.text = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/ForceFieldInactive')
    590         self.sr.forcefieldcheckbox1.SetChecked([0, 1][ball.corporationID != -1], 0)
    591         self.sr.forcefieldcheckbox2.SetChecked([0, 1][ball.allianceID != -1], 0)
    592         notifySettings = self.posMgr.GetTowerNotificationSettings(self.slimItem.itemID)
    593         self.fuelNotifyCheckbox.SetChecked(notifySettings.sendFuelNotifications, 0)
    594         self.calendarCheckbox.SetChecked(notifySettings.showInCalendar, 0)
    595         self.notifySettings = notifySettings
    596 
    597     def ShowFuel(self):
    598         if self.sr.Get('cookie', None) is None:
    599             self.sr.cookie = sm.GetService('inv').Register(self)
    600         if self.sr.Get('restypes', None) is None:
    601             self.sr.restypes = {}
    602         consumefactor = self.posMgr.GetConsumptionFactor(self.slimItem.itemID)
    603         securityRating = 0.0
    604         systemItem = sm.GetService('map').GetItem(session.solarsystemid2)
    605         factionID = None
    606         wormholeClassID = cfg.GetLocationWormholeClass(session.solarsystemid2)
    607         if systemItem is not None:
    608             factionID = systemItem.factionID
    609             securityRating = systemItem.security
    610         scrolllist = []
    611         try:
    612             container = self.tower.List()
    613             cycle = self.godma.GetType(self.slimItem.typeID).posControlTowerPeriod
    614             res = {}
    615             for row in container:
    616                 if row.typeID in res:
    617                     res[row.typeID] += row.stacksize
    618                 else:
    619                     res[row.typeID] = row.stacksize
    620 
    621             state = sm.GetService('pwn').GetStructureState(self.slimItem)[0]
    622             l = [(1, localization.GetByLabel('UI/Entities/States/Online')),
    623              (2, localization.GetByLabel('UI/Common/Power')),
    624              (3, localization.GetByLabel('UI/Common/Cpu')),
    625              (4, localization.GetByLabel('UI/Entities/States/Reinforced'))]
    626             for purposeID, caption in l:
    627                 resources = get_resources_for_tower_by_purpose(self.slimItem.typeID, purposeID)
    628                 if resources:
    629                     resources = localization.util.Sort(resources, key=lambda x: evetypes.GetName(x.resourceTypeID))
    630                     for resource in resources:
    631                         typeID = resource.resourceTypeID
    632                         if resource.factionID is not None and resource.factionID != factionID:
    633                             continue
    634                         if resource.minSecurityLevel is not None and resource.minSecurityLevel > securityRating:
    635                             continue
    636                         if typeID not in self.sr.restypes:
    637                             self.sr.restypes[typeID] = {'label': evetypes.GetName(resource.resourceTypeID),
    638                              'volume': self.godma.GetType(resource.resourceTypeID).volume}
    639                         factor = 0.0
    640                         if caption == localization.GetByLabel('UI/Entities/States/Online'):
    641                             factor = 1.0
    642                         if caption == localization.GetByLabel('UI/Entities/States/Reinforced'):
    643                             factor = 1.0
    644                             capacityToUse = self.capacitySecondary
    645                         else:
    646                             capacityToUse = self.capacity
    647                         if caption == localization.GetByLabel('UI/Common/Power') and self.sr.powerSupply != 0:
    648                             factor = 1.0 * self.sr.powerConsumption / self.sr.powerSupply
    649                         elif caption == localization.GetByLabel('UI/Common/Cpu') and self.sr.cpuSupply != 0:
    650                             factor = 1.0 * self.sr.cpuConsumption / self.sr.cpuSupply
    651                         label = self.sr.restypes[typeID]['label']
    652                         text = int(math.ceil(resource.quantity * factor * consumefactor))
    653                         capacity = capacityToUse
    654                         quantity = res.get(resource.resourceTypeID, 0)
    655                         size = self.sr.restypes[typeID]['volume']
    656                         typeid = resource.resourceTypeID
    657                         data = utillib.KeyVal()
    658                         quantity2 = max(text, 1.0)
    659                         if factor == 0.0:
    660                             cyclestext = localization.GetByLabel('UI/Inflight/MoonMining/Processes/UnusedFuel')
    661                         else:
    662                             cyclestext = long(int(quantity / quantity2) * cycle * 10000)
    663                             data.Set('sort_%s' % localization.GetByLabel('UI/Inflight/MoonMining/Processes/TimeLeft'), cyclestext)
    664                             cyclestext = FmtDate(cyclestext, 'ss')
    665                         label = '%s<t>%s<t><right>%s<t><right>%s<t><right>%s' % (caption,
    666                          label,
    667                          text,
    668                          quantity,
    669                          cyclestext)
    670                         data.label = data.name = label
    671                         data.showinfo = 1
    672                         data.typeID = typeid
    673                         data.OnDropData = self.OnTowerDropData
    674                         le = GetFromClass(Generic, data=data)
    675                         fuelPurposeLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/FuelPurpose')
    676                         nameLabel = localization.GetByLabel('UI/Common/Name')
    677                         quantityPerCycleLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/QuantityPerCycle')
    678                         quantityPresentLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/QuantityPresent')
    679                         timeLeftLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/TimeLeft')
    680                         headers = [fuelPurposeLabel,
    681                          nameLabel,
    682                          quantityPerCycleLabel,
    683                          quantityPresentLabel,
    684                          timeLeftLabel]
    685                         headers = [ each.replace('(', '<br>(') for each in headers ]
    686                         scrolllist.append(le)
    687 
    688         except Exception as e:
    689             sys.exc_clear()
    690 
    691         self.sr.scroll.ShowHint()
    692         if not len(scrolllist):
    693             self.sr.scroll.ShowHint(localization.GetByLabel('UI/Inflight/MoonMining/Processes/TooFarAwayFromControlTower'))
    694             headers = []
    695         self.sr.scroll.sr.id = 'moonmining_fuel'
    696         self.sr.scroll.Load(contentList=scrolllist, headers=headers)
    697         self.sr.showing = 'fuel'
    698 
    699     def ShowAccess(self):
    700         if not len(self.accessCont.children):
    701             options = [(localization.GetByLabel('UI/Inflight/MoonMining/Structures/RoleConfigStarbaseEquipment'), 0),
    702              (localization.GetByLabel('UI/Inflight/MoonMining/Structures/RoleStarbaseFuelTechnician'), 3),
    703              (localization.GetByLabel('UI/Common/Corporation'), 1),
    704              (localization.GetByLabel('UI/Common/Alliance'), 2)]
    705             self.sr.accessconfig = {}
    706             i = 5
    707             for config in ['anchor',
    708              'unanchor',
    709              'online',
    710              'offline']:
    711                 self.sr.accessconfig[config] = Combo(label=POS_STRUCTURE_STATE[config], parent=self.accessCont, options=options, name=config, pos=(i + 5,
    712                  14,
    713                  0,
    714                  0), align=uiconst.TOPLEFT)
    715                 self.sr.accessconfig[config].width = 110
    716                 i += 120
    717 
    718             btns = [(localization.GetByLabel('UI/Common/Buttons/Apply'),
    719               self.SaveAccess,
    720               (),
    721               84)]
    722             ButtonGroup(btns=btns, parent=self.accessCont)
    723         deployFlags, usageFlagsList = self.posMgr.GetStarbasePermissions(self.slimItem.itemID)
    724         self.sr.deployFlags = deployFlags
    725         self.sr.usageFlagsList = usageFlagsList
    726         self.sr.usageFlags = usageFlagsList.Index('structureID')
    727         for key in ['anchor',
    728          'unanchor',
    729          'online',
    730          'offline']:
    731             self.sr.accessconfig[key].SelectItemByValue(deployFlags[key])
    732 
    733         viewAccessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/ViewAccess')
    734         takeAccessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/TakeAccess')
    735         useAccessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/UseAccess')
    736         self.sr.scroll.sr.fixedColumns = {viewAccessLabel: 105,
    737          takeAccessLabel: 105,
    738          useAccessLabel: 105}
    739         self.sr.scroll.OnColumnChanged = self.OnAccessColumnChanged
    740         if self.sr.Get('showing', '') != 'access':
    741             bp = sm.GetService('michelle').GetBallpark()
    742             scrolllist = []
    743             if bp:
    744                 for structureID in self.sr.usageFlags:
    745                     scrolllist.append(GetFromClass(StructureAccess, {'label': uix.GetSlimItemName(bp.slimItems[structureID]),
    746                      'rec': bp.slimItems[structureID],
    747                      'flags': self.sr.usageFlags[structureID]}))
    748 
    749             if not len(scrolllist):
    750                 self.sr.scroll.ShowHint(localization.GetByLabel('UI/Inflight/MoonMining/Structures/NoOtherStructuresInRange'))
    751             self.sr.scroll.sr.ignoreTabTrimming = False
    752             self.sr.scroll.sr.id = 'moonmining_access'
    753             nameLabel = localization.GetByLabel('UI/Common/Name')
    754             viewAccessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/ViewAccess')
    755             takeAccessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/TakeAccess')
    756             useAccessLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/UseAccess')
    757             self.sr.scroll.Load(contentList=scrolllist, headers=[nameLabel,
    758              viewAccessLabel,
    759              takeAccessLabel,
    760              useAccessLabel])
    761             self.OnAccessColumnChanged()
    762         self.sr.showing = 'access'
    763 
    764     def SaveAccess(self, *args):
    765         for config in ['anchor',
    766          'unanchor',
    767          'online',
    768          'offline']:
    769             self.sr.deployFlags[config] = self.sr.accessconfig[config].GetValue() or 0
    770 
    771         self.posMgr.SetStarbasePermissions(self.slimItem.itemID, self.sr.deployFlags, self.sr.usageFlagsList)
    772 
    773     def OnAccessColumnChanged(self, *args):
    774         for entry in self.sr.scroll.GetNodes():
    775             if entry.panel and getattr(entry.panel, 'OnColumnChanged', None):
    776                 entry.panel.OnColumnChanged()
    777 
    778     def StructureProgress(self, where, label, stateTimestamp, stateDelay, parenttext = None, xoffset = 2, top = 3):
    779         sub = Container(name='progresscontainer', parent=where, align=uiconst.TOPRIGHT, width=88, height=12, left=xoffset, top=top)
    780         te = eveLabel.EveLabelSmall(text='xxx', parent=sub, width=86, left=2, top=0)
    781         p = Fill(parent=sub, align=uiconst.TOPLEFT, width=86, height=10, left=0, top=1, color=(1.0, 1.0, 1.0, 0.25))
    782         startTime = blue.os.GetWallclockTime()
    783         if stateDelay:
    784             stateDelay = float(stateDelay * 10000)
    785         endTime = 0
    786         if stateDelay:
    787             endTime = stateTimestamp + stateDelay
    788         while 1 and endTime:
    789             timeLeft = endTime - blue.os.GetWallclockTime()
    790             portion = timeLeft / stateDelay
    791             timeLeftSec = timeLeft / 1000.0
    792             if timeLeft <= 0:
    793                 parenttext.text = label
    794                 break
    795             te.text = FmtDate(long(timeLeft), 'ss')
    796             p.width = int(86 * portion)
    797             blue.pyos.synchro.Yield()
    798             if parenttext.destroyed:
    799                 return
    800 
    801         blue.pyos.synchro.SleepWallclock(250)
    802         sub.Flush()
    803         del where.children[-1]
    804         if parenttext.destroyed:
    805             return
    806         parenttext.text = ''
    807         blue.pyos.synchro.SleepWallclock(250)
    808         if parenttext.destroyed:
    809             return
    810         parenttext.text = label
    811         blue.pyos.synchro.SleepWallclock(250)
    812         if parenttext.destroyed:
    813             return
    814         parenttext.text = ''
    815         blue.pyos.synchro.SleepWallclock(250)
    816         if parenttext.destroyed:
    817             return
    818         parenttext.text = label
    819 
    820     def AssumeControl(self):
    821         selected = self.sr.scroll.GetSelected()
    822         if not len(selected) > 0:
    823             return
    824         if sm.GetService('viewState').IsViewActive('planet'):
    825             raise UserError('StructureNotControllablePlanetMode')
    826         structures = []
    827         for sel in selected:
    828             slimItem = sel.rec
    829             uthread.pool('MoonMining::_AssumeControl', self._AssumeControl, slimItem)
    830 
    831     def _AssumeControl(self, itemID, silent = False):
    832         self.pwn.AssumeStructureControl(itemID, silent)
    833 
    834     def RelinquishControl(self):
    835         selected = self.sr.scroll.GetSelected()
    836         if not len(selected) > 0:
    837             return
    838         structures = []
    839         for sel in selected:
    840             slimItem = sel.rec
    841             uthread.pool('MoonMining::_RelinquishControl', self._RelinquishControl, slimItem)
    842 
    843     def _RelinquishControl(self, itemID):
    844         self.pwn.RelinquishStructureControl(itemID)
    845 
    846     def GetGauge(self, where = None, left = 0, top = 0, color = (1.0, 1.0, 1.0, 0.25)):
    847         g = Container(name='gauge', align=uiconst.TOPLEFT, width=64, height=9, left=left, top=top, parent=where)
    848         Container(name='push', parent=g, align=uiconst.TOBOTTOM, height=2)
    849         g.name = ''
    850         Line(parent=g, align=uiconst.TOTOP, color=(1.0, 1.0, 1.0, 0.5))
    851         Line(parent=g, align=uiconst.TOBOTTOM, color=(1.0, 1.0, 1.0, 0.5))
    852         Line(parent=g, align=uiconst.TOLEFT, color=(1.0, 1.0, 1.0, 0.5))
    853         Line(parent=g, align=uiconst.TORIGHT, color=(1.0, 1.0, 1.0, 0.5))
    854         g.sr.bar = Fill(parent=g, align=uiconst.TOLEFT, color=color)
    855         Fill(parent=g, color=(1.0, 1.0, 1.0, 0.25))
    856         return g
    857 
    858     def UpdateHeader(self):
    859         if not self or self.destroyed or not self.slimItem:
    860             return
    861         state = self.pwn.GetStructureState(self.slimItem)
    862         statusText = POS_STRUCTURE_STATE[state[0]]
    863         color = ''
    864         if statusText == localization.GetByLabel('UI/Entities/States/Online'):
    865             color = '<color=0xff65c212>'
    866         elif statusText == localization.GetByLabel('UI/Inflight/MoonMining/Offline'):
    867             color = '<color=0xffd0371d>'
    868         self.sr.status.text = localization.GetByLabel('UI/Inflight/MoonMining/TowerStatus', colorCode=color, currentStatus=statusText)
    869         if self.moonID is not None:
    870             moonstr = cfg.evelocations.Get(self.moonID).name
    871         else:
    872             moonstr = localization.GetByLabel('UI/Inflight/MoonMining/NotAttachedToMoon', locationID=session.locationid)
    873         self.sr.locationtext.text = localization.GetByLabel('UI/Inflight/MoonMining/TowerLocated', moonLocation=moonstr)
    874         if state[0] == 'online' and len(self.res) == 0:
    875             self.GetMoon()
    876         allowedState = (const.pwnStructureStateAnchoring,
    877          const.pwnStructureStateOnlining,
    878          const.pwnStructureStateUnanchoring,
    879          const.pwnStructureStateReinforced)
    880         if state[0] in allowedState:
    881             displayState = structProgressMap.get(state[0], None)
    882             if displayState:
    883                 labelMap = {const.pwnStructureStateAnchored: localization.GetByLabel('UI/Entities/States/StatusCaptionAnchored'),
    884                  const.pwnStructureStateUnanchored: localization.GetByLabel('UI/Entities/States/StatusCaptionUnanchored'),
    885                  const.pwnStructureStateOnline: localization.GetByLabel('UI/Entities/States/StatusCaptionOnline')}
    886                 label = labelMap[displayState]
    887             else:
    888                 label = localization.GetByLabel('UI/Entities/States/StatusCaptionDone')
    889             uthread.new(self.StructureProgress, self.sr.locationtext.parent, label, state[1], state[2], self.sr.status, -78, self.sr.status.top - 12)
    890         self.UpdateDamage()
    891         bp = sm.GetService('michelle').GetBallpark()
    892         t = self.godma.GetType(self.slimItem.typeID)
    893         emRes = getattr(t, 'shieldEmDamageResonance', 1.0)
    894         exRes = getattr(t, 'shieldExplosiveDamageResonance', 1.0)
    895         kiRes = getattr(t, 'shieldKineticDamageResonance', 1.0)
    896         thRes = getattr(t, 'shieldThermalDamageResonance', 1.0)
    897         structures = [ rec for itemID, rec in bp.slimItems.iteritems() if rec.categoryID == const.categoryStarbase and rec.groupID == const.groupShieldHardeningArray and rec.ownerID == self.slimItem.ownerID and self.pwn.GetStructureState(rec)[0] == 'online' ]
    898         for structure in structures:
    899             s = self.godma.GetType(structure.typeID)
    900             emRes *= getattr(s, 'emDamageResonanceMultiplier', 1.0)
    901             exRes *= getattr(s, 'explosiveDamageResonanceMultiplier', 1.0)
    902             kiRes *= getattr(s, 'kineticDamageResonanceMultiplier', 1.0)
    903             thRes *= getattr(s, 'thermalDamageResonanceMultiplier', 1.0)
    904 
    905         emPercentageLabel = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=int(100 * (1.0 - emRes)))
    906         kiPercentageLabel = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=int(100 * (1.0 - kiRes)))
    907         exPercentageLabel = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=int(100 * (1.0 - exRes)))
    908         thPercentageLabel = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=int(100 * (1.0 - thRes)))
    909         self.sr.emkinText.text = '%s<t>%s' % (emPercentageLabel, kiPercentageLabel)
    910         self.sr.expthermText.text = '%s<t>%s' % (exPercentageLabel, thPercentageLabel)
    911         powerSupply = 0
    912         cpuSupply = 0
    913         powerConsumption = 0
    914         cpuConsumption = 0
    915         for itemID, ball in bp.slimItems.iteritems():
    916             if ball.categoryID == const.categoryStarbase and self.pwn.GetStructureState(ball)[0] in ('online', 'operating'):
    917                 powerSupply += getattr(self.godma.GetType(ball.typeID), 'powerOutput', 0)
    918                 cpuSupply += getattr(self.godma.GetType(ball.typeID), 'cpuOutput', 0)
    919                 powerConsumption += getattr(self.godma.GetType(ball.typeID), 'power', 0)
    920                 cpuConsumption += getattr(self.godma.GetType(ball.typeID), 'cpu', 0)
    921 
    922         if powerSupply == 0:
    923             self.sr.powergauge.sr.bar.width = 0
    924         else:
    925             self.sr.powergauge.sr.bar.width = int((self.sr.powergauge.width - 2) * powerConsumption / powerSupply)
    926         if cpuSupply == 0:
    927             self.sr.cpugauge.sr.bar.width = 0
    928         else:
    929             self.sr.cpugauge.sr.bar.width = int((self.sr.cpugauge.width - 2) * cpuConsumption / cpuSupply)
    930         self.sr.powertext.text = localization.GetByLabel('UI/Inflight/MoonMining/TowerPowerUsage', currentValue=powerConsumption, totalPower=powerSupply)
    931         self.sr.cputext.text = localization.GetByLabel('UI/Inflight/MoonMining/TowerCPUUsage', currentValue=cpuConsumption, totalCPU=cpuSupply)
    932         self.sr.powerSupply = powerSupply
    933         self.sr.cpuSupply = cpuSupply
    934         self.sr.powerConsumption = powerConsumption
    935         self.sr.cpuConsumption = cpuConsumption
    936 
    937     def UpdateDamage(self):
    938         if self.destroyed:
    939             return
    940         bp = sm.GetService('michelle').GetBallpark()
    941         damage = bp.GetDamageState(self.slimItem.itemID)
    942         if damage is None:
    943             return
    944         shield = min(damage[0], 1.0)
    945         armor = min(damage[1], 1.0)
    946         structure = min(damage[2], 1.0)
    947         barcolor = self.sr.shieldgauge.sr.bar.color
    948         if shield is None:
    949             barcolor.r, barcolor.g, barcolor.b = (1.0, 1.0, 0.1)
    950             self.sr.shieldgauge.sr.bar.width = int(self.sr.powergauge.width - 2)
    951             self.sr.shieldtext.text = '<color=0xffff0000>' + localization.GetByLabel('UI/Inflight/MoonMining/Reinforced') + '</color>'
    952         else:
    953             barcolor.r, barcolor.g, barcolor.b = (0.8, 0.8, 1.0)
    954             self.sr.shieldgauge.sr.bar.width = int(round((self.sr.powergauge.width - 2) * (shield or 0.0)))
    955             self.sr.shieldtext.text = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=int(shield * 100))
    956         self.sr.armorgauge.sr.bar.width = int(round((self.sr.powergauge.width - 2) * armor))
    957         self.sr.armortext.text = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=int(armor * 100))
    958         self.sr.structuregauge.sr.bar.width = int(round((self.sr.powergauge.width - 2) * structure))
    959         self.sr.structuretext.text = localization.GetByLabel('UI/Inflight/MoonMining/DisplayPercentage', percent=structure * 100)
    960 
    961     def UpdateStructures(self, rec = None):
    962         if self.destroyed:
    963             return
    964         self.UpdateHeader()
    965         if not self.sr.maintabs:
    966             return
    967         args = self.sr.maintabs.GetSelectedArgs()
    968         if not args:
    969             return
    970         panelID = args[0]
    971         if panelID == 'structures':
    972             if self.sr.structuretabs.GetSelectedArgs()[1] == 'structures':
    973                 self.ShowStructures()
    974             if self.sr.structuretabs.GetSelectedArgs()[1] == 'control':
    975                 self.ShowControl()
    976         elif panelID == 'process':
    977             if self.sr.processtabs.GetSelectedArgs()[1] == 'production':
    978                 self.ShowProduction()
    979             if self.sr.processtabs.GetSelectedArgs()[1] == 'fuel':
    980                 self.ShowFuel()
    981 
    982     def GetStructureMenu(self, entry):
    983         data = entry.sr.node
    984         return GetMenuService().CelestialMenu(data.rec.itemID, slimItem=data.rec)
    985 
    986     def GetTypeMenu(self, entry):
    987         data = entry.sr.node
    988         return [(localization.GetByLabel('UI/Commands/ShowInfo'), self.ShowInfo, (data.typeID,))]
    989 
    990     def GetMenuMoreOptions(self):
    991         menuData = super(MoonMining, self).GetMenuMoreOptions()
    992         menuData += self.TowerMenu()
    993         return menuData
    994 
    995     def TowerMenu(self):
    996         m = GetMenuService().GetMenuFromItemIDTypeID(self.slimItem.itemID, self.slimItem.typeID)
    997         return m
    998 
    999     def ShowInfo(self, typeID):
   1000         sm.GetService('info').ShowInfo(typeID)
   1001 
   1002     def OpenResources(self):
   1003         GetMenuService().OpenPOSFuelBay(self.slimItem.itemID)
   1004 
   1005     def Anchor(self):
   1006         sel = self.sr.scroll.GetSelected()
   1007         if len(sel) < 0:
   1008             return
   1009         itemID = None
   1010         if len(sel) > 0:
   1011             itemID = sel[0].rec.itemID
   1012         elif len(self.sr.scroll.GetNodes()) == 0:
   1013             itemID = self.slimItem.itemID
   1014         if itemID and sm.GetService('pwn').CanAnchorStructure(itemID):
   1015             sm.GetService('posAnchor').StartAnchorPosSelect(itemID)
   1016 
   1017     def Unanchor(self):
   1018         sel = self.sr.scroll.GetSelected()
   1019         structures = [ each.rec for each in sel ]
   1020         for rec in structures:
   1021             if sm.GetService('pwn').CanUnanchorStructure(rec.itemID):
   1022                 GetMenuService().UnanchorStructure(rec.itemID)
   1023 
   1024         if len(self.sr.scroll.GetNodes()) == 0:
   1025             if sm.GetService('pwn').CanUnanchorStructure(self.slimItem.itemID):
   1026                 GetMenuService().UnanchorStructure(self.slimItem.itemID)
   1027 
   1028     def Online(self):
   1029         sel = self.sr.scroll.GetSelected()
   1030         if len(sel) > 0:
   1031             GetMenuService().ToggleObjectOnline(sel[0].rec.itemID, 1)
   1032         if len(self.sr.scroll.GetNodes()) == 0:
   1033             GetMenuService().ToggleObjectOnline(self.slimItem.itemID, 1)
   1034 
   1035     def Offline(self):
   1036         sel = self.sr.scroll.GetSelected()
   1037         structures = [ each.rec for each in sel ]
   1038         dogmaLM = self.godma.GetDogmaLM()
   1039         for rec in structures:
   1040             GetMenuService().ToggleObjectOnline(rec.itemID, 0)
   1041 
   1042         if len(self.sr.scroll.GetNodes()) == 0:
   1043             GetMenuService().ToggleObjectOnline(self.slimItem.itemID, 0)
   1044 
   1045     def IsItemHere(self, rec):
   1046         return rec.locationID == self.slimItem.itemID
   1047 
   1048     def OnTowerDropData(self, dragObject, nodes):
   1049         for node in nodes:
   1050             self.TowerDropNode(node)
   1051 
   1052     def TowerDropNode(self, node):
   1053         if node.__guid__ not in ('xtriui.InvItem', 'xtriui.FittingSlot', 'listentry.InvItem'):
   1054             return
   1055         try:
   1056             if not getattr(node.rec, 'typeID', None):
   1057                 prompt_player_fsd_dialog('error')
   1058                 return
   1059             quantity = getattr(node.rec, 'quantity', 1)
   1060             return self.tower.Add(node.rec.itemID, node.rec.locationID, qty=quantity)
   1061         except UserError as what:
   1062             if what.args[0] == 'NotEnoughChargeSpace':
   1063                 if what.dict['capacity'] < 0:
   1064                     raise UserError('DestinationOverloaded')
   1065                 sys.exc_clear()
   1066             else:
   1067                 raise
   1068 
   1069     def InitStandingsPanel(self):
   1070         parent = self.sr.standingspanel
   1071         cont = Container(name='standingspanelcont', align=uiconst.TOALL, parent=parent, pos=(const.defaultPadding + 2,
   1072          const.defaultPadding + 2,
   1073          const.defaultPadding + 2,
   1074          const.defaultPadding + 2))
   1075         uix.GetContainerHeader(localization.GetByLabel('UI/Inflight/MoonMining/Defense/SentryGunSettings'), cont, 0)
   1076         Container(name='push', align=uiconst.TOLEFT, width=6, parent=cont)
   1077         Container(name='push', align=uiconst.TOLEFT, width=6, parent=cont)
   1078         s3a = Container(parent=cont, align=uiconst.TOTOP)
   1079         useAllianceStandingsLabel = localization.GetByLabel('UI/Inflight/MoonMining/Defense/UseAllianceStandings')
   1080         self.sr.alliancestandingcheckbox = Checkbox(text=useAllianceStandingsLabel, parent=s3a, settingsKey='')
   1081         s3a.height = self.sr.alliancestandingcheckbox.height
   1082         if not session.allianceid:
   1083             s3a.state = uiconst.UI_HIDDEN
   1084         s1 = Container(parent=cont, align=uiconst.TOTOP, top=const.defaultPadding)
   1085         attackIfStandingLowerThanLabel = localization.GetByLabel('UI/Inflight/MoonMining/Defense/AttackIfStandingLowerThan')
   1086         self.sr.standingcheckbox1 = Checkbox(text=attackIfStandingLowerThanLabel, parent=s1, settingsKey='', align=uiconst.TOPLEFT, pos=(0, 0, 250, 0))
   1087         self.sr.standingedit1 = SingleLineEditFloat(name='standing', parent=s1, setvalue=None, pos=(255, 0, 80, 0), minValue=-10, maxValue=10)
   1088         s1.height = max(self.sr.standingcheckbox1.height, self.sr.standingedit1.height)
   1089         s2 = Container(parent=cont, align=uiconst.TOTOP, top=const.defaultPadding)
   1090         securityStatusBelowLabel = localization.GetByLabel('UI/Inflight/MoonMining/Defense/AttackIfSecurityStatusBelow')
   1091         self.sr.standingcheckbox2 = Checkbox(text=securityStatusBelowLabel, parent=s2, settingsKey='', align=uiconst.TOPLEFT, pos=(0, 0, 250, 0))
   1092         self.sr.standingedit2 = SingleLineEditFloat(name='status', parent=s2, setvalue=None, pos=(255, 0, 80, 0), minValue=-10, maxValue=10)
   1093         s2.height = max(self.sr.standingcheckbox2.height, self.sr.standingedit2.height)
   1094         checkboxes = [(localization.GetByLabel('UI/Inflight/MoonMining/Defense/AttackIfSecurityStatusIsDropping'), 4, 'chkourstatus'), (localization.GetByLabel('UI/Inflight/MoonMining/Defense/AttackIfAtWar'), 6, 'chkwar')]
   1095         for label, key, name in checkboxes:
   1096             s = Container(parent=cont, align=uiconst.TOTOP, top=const.defaultPadding)
   1097             cb = Checkbox(text=label, parent=s, settingsKey='')
   1098             setattr(self.sr, 'standingcheckbox%s' % key, cb)
   1099             s.height = cb.height
   1100 
   1101         self.sr.standingsinited = 1
   1102         applyLabel = localization.GetByLabel('UI/Common/Buttons/Apply')
   1103         b = Button(parent=cont, label=applyLabel, align=uiconst.BOTTOMRIGHT, pos=(5, 5, 0, 0), func=self.SaveStandings)
   1104         if is_high_sec_or_higher_solar_system(session.solarsystemid2):
   1105             s1.state = uiconst.UI_HIDDEN
   1106             s2.state = uiconst.UI_HIDDEN
   1107 
   1108     def SaveStandings(self, *args):
   1109         standing = [None, self.sr.standingedit1.GetValue()][self.sr.standingcheckbox1.GetValue()]
   1110         status = [None, self.sr.standingedit2.GetValue()][self.sr.standingcheckbox2.GetValue()]
   1111         statusDrop = [False, True][self.sr.standingcheckbox4.GetValue()]
   1112         war = [False, True][self.sr.standingcheckbox6.GetValue()]
   1113         settings = [standing,
   1114          status,
   1115          statusDrop,
   1116          war]
   1117         useAllianceStandings = self.sr.alliancestandingcheckbox.GetValue()
   1118         if settings != getattr(self, 'sentrySettings', None):
   1119             self.posMgr.SetTowerSentrySettings(self.slimItem.itemID, standing, status, statusDrop, war, useAllianceStandings)
   1120             self.sentrySettings = settings
   1121 
   1122     def InitForcefieldPanel(self):
   1123         parent = self.sr.forcefieldpanel
   1124         cont = Container(name='forcefieldpanelcont', align=uiconst.TOALL, parent=parent, padding=const.defaultPadding)
   1125         uix.GetContainerHeader(localization.GetByLabel('UI/Inflight/MoonMining/ForceField/ForceFieldHarmonicSettings'), cont, 0)
   1126         Container(name='push', align=uiconst.TOLEFT, width=6, parent=cont)
   1127         Container(name='push', align=uiconst.TORIGHT, width=6, parent=cont)
   1128         s0 = Container(parent=cont, align=uiconst.TOTOP)
   1129         forceFieldStatusLabel = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/ForceFieldStatus')
   1130         statusText = eveLabel.EveLabelSmall(text=forceFieldStatusLabel, parent=s0, align=uiconst.CENTERLEFT)
   1131         noPasswordSetLabel = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/NoPasswordSet')
   1132         self.sr.forcefieldtext1 = eveLabel.EveLabelMedium(text=noPasswordSetLabel, parent=s0, left=80, top=3, width=350, height=32)
   1133         s0.height = max(statusText.textheight, self.sr.forcefieldtext1.textheight)
   1134         s1 = Container(parent=cont, align=uiconst.TOTOP, padTop=6)
   1135         passwordLabel = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/PasswordLabel')
   1136         passwordText = eveLabel.EveLabelSmall(text=passwordLabel, parent=s1, align=uiconst.CENTERLEFT)
   1137         self.sr.forcefieldedit1 = SingleLineEditPassword(name='password', parent=s1, setvalue=None, align=uiconst.TOTOP)
   1138         s1.height = max(passwordText.textheight, self.sr.forcefieldedit1.height) + 4
   1139         s2 = Container(parent=cont, align=uiconst.TOTOP)
   1140         confirmPasswordLabel = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/ConfirmPassword')
   1141         confirmText = eveLabel.EveLabelSmall(text=confirmPasswordLabel, parent=s2, align=uiconst.CENTERLEFT)
   1142         self.sr.forcefieldedit2 = SingleLineEditPassword(name='confirm', parent=s2, setvalue=None, align=uiconst.TOTOP)
   1143         s2.height = max(confirmText.textheight, self.sr.forcefieldedit2.height) + 4
   1144         self.sr.forcefieldedit1.padLeft = self.sr.forcefieldedit2.padLeft = max(70, statusText.width, passwordText.width, confirmText.width) + 10
   1145         self.sr.forcefieldtext1.left = self.sr.forcefieldedit1.padLeft
   1146         s3 = Container(parent=cont, align=uiconst.TOTOP)
   1147         corporationMemberUsageLabel = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/AllowCorporationMemberUsage')
   1148         self.sr.forcefieldcheckbox1 = Checkbox(text=corporationMemberUsageLabel, parent=s3, settingsKey='')
   1149         s3.height = self.sr.forcefieldcheckbox1.height + 4
   1150         s4 = Container(parent=cont, align=uiconst.TOTOP)
   1151         allianceMemberUsageLabel = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/AllowAllianceMemberUsage')
   1152         self.sr.forcefieldcheckbox2 = Checkbox(text=allianceMemberUsageLabel, parent=s4, settingsKey='')
   1153         if session.allianceid is None:
   1154             s4.height = 0
   1155         else:
   1156             s4.height = self.sr.forcefieldcheckbox2.height + 4
   1157         Container(name='push', align=uiconst.TOTOP, height=6, parent=cont)
   1158         uix.GetContainerHeader(localization.GetByLabel('UI/Inflight/MoonMining/Notifications'), cont, padHorizontal=-6)
   1159         s5 = Container(parent=cont, align=uiconst.TOTOP, padTop=6)
   1160         enableFuelNotificationLabel = localization.GetByLabel('UI/Inflight/MoonMining/SendFuelNotifications')
   1161         self.fuelNotifyCheckbox = Checkbox(text=enableFuelNotificationLabel, parent=s5, settingsKey='')
   1162         s5.height = self.fuelNotifyCheckbox.height + 4
   1163         s6 = Container(parent=cont, align=uiconst.TOTOP)
   1164         enableCalendarEntryLabel = localization.GetByLabel('UI/Inflight/MoonMining/ShowInCalendar')
   1165         self.calendarCheckbox = Checkbox(text=enableCalendarEntryLabel, parent=s6, settingsKey='')
   1166         s6.height = self.calendarCheckbox.height + 4
   1167         Line(parent=cont, align=uiconst.TOTOP, padLeft=-5, padRight=-5)
   1168         applyLabel = localization.GetByLabel('UI/Common/Buttons/Apply')
   1169         buttonCont = Container(parent=cont, align=uiconst.TOBOTTOM, height=26, bottomPadding=6, padLeft=-5, padRight=-5)
   1170         b = Button(parent=buttonCont, label=applyLabel, func=self.SaveForcefield, align=uiconst.CENTER)
   1171         buttonCont.height = max(26, b.height + 8)
   1172         totalHeight = sum([ each.height + each.padTop + each.padBottom for each in cont.children ]) + self.header_height + self.sr.top.height + self.sr.maintabs.height
   1173         self.SetMinSize([MINWNDWIDTH, totalHeight + 60])
   1174         self.sr.forcefieldinited = 1
   1175 
   1176     def SaveForcefield(self, *args):
   1177         password = self.sr.forcefieldedit1.GetValue() or ''
   1178         confirm = self.sr.forcefieldedit2.GetValue() or ''
   1179         forceField = self.GetForcefield()
   1180         allowCorp = True if self.sr.forcefieldcheckbox1.GetValue() else False
   1181         allowAlliance = True if self.sr.forcefieldcheckbox2.GetValue() else False
   1182         showInCalendar = True if self.calendarCheckbox.GetValue() else False
   1183         sendFuelNotifications = True if self.fuelNotifyCheckbox.GetValue() else False
   1184         if self.notifySettings is not None:
   1185             if self.notifySettings.showInCalendar != showInCalendar or self.notifySettings.sendFuelNotifications != sendFuelNotifications:
   1186                 self.posMgr.SetTowerNotifications(self.slimItem.itemID, showInCalendar, sendFuelNotifications)
   1187                 self.notifySettings.showInCalendar = showInCalendar
   1188                 self.notifySettings.sendFuelNotifications = sendFuelNotifications
   1189         else:
   1190             self.posMgr.SetTowerNotifications(self.slimItem.itemID, showInCalendar, sendFuelNotifications)
   1191             self.notifySettings = utillib.KeyVal(showInCalendar=showInCalendar, sendFuelNotifications=sendFuelNotifications)
   1192         if password == confirm:
   1193             if not len(password):
   1194                 if not forceField or forceField == self.slimItem:
   1195                     raise UserError('NoPasswordEntered')
   1196                 else:
   1197                     password = False
   1198             self.posMgr.SetTowerPassword(self.slimItem.itemID, password, allowCorp, allowAlliance)
   1199         else:
   1200             self.sr.forcefieldtext1.text = localization.GetByLabel('UI/Inflight/MoonMining/ForceField/PasswordAndConfirmMismatch')
   1201 
   1202     def GetShell(self, itemID):
   1203         tower = sm.GetService('invCache').GetInventoryFromId(itemID)
   1204         return tower
   1205 
   1206     def GetMoon(self):
   1207         self.res = {}
   1208         if self.moon is None:
   1209             try:
   1210                 self.moon = self.posMgr.GetMoonForTower(self.slimItem.itemID)
   1211             except UserError as e:
   1212                 self.CloseByUser()
   1213                 raise
   1214 
   1215         self.moonID = self.moon[0]
   1216         if self.moon[1] is not None:
   1217             for typeID, quantity in self.moon[1]:
   1218                 self.res[typeID] = quantity
   1219 
   1220     def GetForcefield(self):
   1221         bp = sm.GetService('michelle').GetBallpark()
   1222         forcefield = [ rec for itemID, rec in bp.slimItems.iteritems() if rec.groupID == const.groupForceField and rec.ownerID == self.slimItem.ownerID ]
   1223         if len(forcefield):
   1224             return forcefield[0]
   1225         else:
   1226             return self.slimItem
   1227 
   1228     def GetStructureConnections(self):
   1229         if not self.sr.Get('structureConnections'):
   1230             self.sr.structureConnections = {}
   1231 
   1232     def StructureCallback(self, typeID, fromItemID, toItemID, connect):
   1233         self.connectionsChanged = 1
   1234         if (typeID, fromItemID) in self.sr.structureConnections:
   1235             if not connect:
   1236                 del self.sr.structureConnections[typeID, fromItemID]
   1237                 self.ShowProduction()
   1238                 return
   1239         if fromItemID not in self.sr.structures or toItemID not in self.sr.structures:
   1240             return
   1241         if typeID in self.sr.structures[fromItemID].supplies and typeID in self.sr.structures[toItemID].demands and connect:
   1242             self.sr.structureConnections[typeID, fromItemID] = toItemID
   1243         self.ShowProduction()
   1244 
   1245     def ProdApply(self, *args):
   1246         if self.sr.Get('structures', None) is not None and self.sr.Get('structureConnections', None) is not None:
   1247             if not self.posMgr.LinkResourceForTower(self.slimItem.itemID, [ (k[1], v, k[0]) for k, v in self.sr.structureConnections.iteritems() ]):
   1248                 self.ShowProduction(force=1)
   1249             self.connectionsChanged = 0
   1250 
   1251     def SetStructureType(self, itemID, groupID, *args):
   1252         if groupID == const.groupSilo:
   1253             rec = sm.GetService('michelle').GetBallpark().slimItems[itemID]
   1254             temp = self.godma.GetTypeAttribute(rec.typeID, const.attributeCargoGroup)
   1255             if temp:
   1256                 tmp = {temp: []}
   1257                 cargoGroup2 = self.godma.GetTypeAttribute(rec.typeID, const.attributeCargoGroup2)
   1258                 if cargoGroup2:
   1259                     tmp[cargoGroup2] = []
   1260             else:
   1261                 tmp = {const.groupMoonMaterials: [],
   1262                  const.groupComposite: [],
   1263                  const.groupIntermediateMaterials: [],
   1264                  const.groupGasIsotopes: [],
   1265                  const.groupMineral: []}
   1266             for typeID in evetypes.Iterate():
   1267                 groupID = evetypes.GetGroupID(typeID)
   1268                 if groupID in tmp:
   1269                     tmp[groupID].append(typeID)
   1270 
   1271             wnd = SelectSiloType.Open(list=tmp)
   1272             if wnd.ShowModal() == uiconst.ID_OK:
   1273                 chosen = wnd.result
   1274             else:
   1275                 chosen = None
   1276         elif groupID == const.groupMoonMining:
   1277             rec = sm.GetService('michelle').GetBallpark().slimItems[itemID]
   1278             quality = self.godma.GetType(rec.typeID).harvesterQuality
   1279             used = [ structure.supplies.keys()[0] for structure in self.sr.structures.values() if len(structure.supplies) and structure.rec.groupID == const.groupMoonMining ]
   1280             tmplist = [(localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvestNone'), 0, 0)]
   1281             for t, q in self.res.iteritems():
   1282                 if t not in used:
   1283                     harvestType = localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvestType', mineralID=t, amount=min(quality, q))
   1284                     tmplist.append((harvestType, t, t))
   1285 
   1286             selectMoonMaterialLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/SelectMoonMaterial')
   1287             chosen = uix.ListWnd(tmplist, None, selectMoonMaterialLabel, None, 1, minChoices=1, isModal=1)
   1288             if chosen is not None:
   1289                 chosen = chosen[1]
   1290         if chosen is not None:
   1291             if chosen == 0:
   1292                 chosen = None
   1293             self.posMgr.ChangeStructureProvisionType(self.slimItem.itemID, itemID, chosen)
   1294             if len(self.sr.structures[itemID].supplies) and (self.sr.structures[itemID].supplies.keys()[0], itemID) in self.sr.structureConnections:
   1295                 del self.sr.structureConnections[self.sr.structures[itemID].supplies.keys()[0], itemID]
   1296             for k, v in self.sr.structureConnections.items():
   1297                 if v == itemID:
   1298                     del self.sr.structureConnections[k]
   1299 
   1300             if groupID == const.groupSilo:
   1301                 self.sr.structures[itemID].demands = {chosen: -1}
   1302                 self.sr.structures[itemID].supplies = {chosen: -1}
   1303             elif groupID == const.groupMoonMining:
   1304                 self.sr.structures[itemID].supplies = {chosen: -1}
   1305             self.ProdReload()
   1306 
   1307     def ProdReload(self):
   1308         self.ShowProduction(force=1)
   1309 
   1310     def ProdClearLinks(self):
   1311         if len(self.sr.structureConnections) == 0 or prompt_player_fsd_dialog('ProdClearLinks', {}, uiconst.YESNO) == uiconst.ID_YES:
   1312             self.sr.structureConnections = {}
   1313             self.ProdApply()
   1314             self.ShowProduction(force=1)
   1315 
   1316     def RunProcessCycle(self):
   1317         self.posMgr.RunMoonProcessCycleforTower(self.slimItem.itemID)
   1318         if uicore.uilib.Key(uiconst.VK_SHIFT):
   1319             resp = self.posMgr.GetMoonProcessInfoForTower(self.slimItem.itemID)
   1320             txt = ''
   1321             for entry in resp:
   1322                 txt += '%s, %s, %s, %s, %s, %s<br>' % entry
   1323 
   1324             prompt_player_fsd_dialog('RunProcessCycle', {'info': txt})
   1325 
   1326     def OnMoonProcessChange(self, towerID, structures):
   1327         if towerID == self.slimItem.itemID:
   1328             if self.sr.Get('showing', None) == 'production':
   1329                 self.ShowProduction()
   1330 
   1331     def OnSlimItemChange(self, oldItem, newItem):
   1332         if not self or self.destroyed:
   1333             return
   1334         if newItem.categoryID != const.categoryStarbase:
   1335             return
   1336         if newItem.posState == oldItem.posState and newItem.posTimestamp == oldItem.posTimestamp and newItem.controllerID == oldItem.controllerID and newItem.incapacitated == oldItem.incapacitated:
   1337             return
   1338         if newItem.itemID == self.slimItem.itemID:
   1339             self.slimItem = newItem
   1340             self.GetMoon()
   1341         if self.sr.Get('structures') and newItem.itemID in self.sr.structures:
   1342             self.sr.structures[newItem.itemID].rec = newItem
   1343         self.UpdateStructures(newItem)
   1344         state = self.pwn.GetStructureState(newItem)
   1345         if state[0] in ('anchoring', 'onlining', 'unanchoring', 'reinforced'):
   1346             uthread.pool('moonmining::StateChangeFinished', self.StateChangeFinished, newItem, state)
   1347 
   1348     def StateChangeFinished(self, rec, state):
   1349         blue.pyos.synchro.SleepWallclock(state[2])
   1350         if self and not self.destroyed:
   1351             self.UpdateStructures(rec)
   1352 
   1353     def OnInvChange(self, item = None, change = None):
   1354         if not self or self.destroyed:
   1355             return
   1356         if self.sr.maintabs and self.sr.maintabs.GetSelectedArgs()[0] == 'process':
   1357             if self.sr.processtabs and self.sr.processtabs.GetSelectedArgs()[1] == 'fuel':
   1358                 self.ShowFuel()
   1359 
   1360     def DoBallsAdded(self, *args, **kw):
   1361         import stackless
   1362         import blue
   1363         t = stackless.getcurrent()
   1364         timer = t.PushTimer(blue.pyos.taskletTimer.GetCurrent() + '::moonmining')
   1365         try:
   1366             return self.DoBallsAdded_(*args, **kw)
   1367         finally:
   1368             t.PopTimer(timer)
   1369 
   1370     def DoBallsAdded_(self, lst, ignoreMoons = 1, ignoreAsteroids = 1):
   1371         if not self or self.destroyed:
   1372             return
   1373         for ball, slimItem in lst:
   1374             if slimItem.categoryID == const.categoryStarbase:
   1375                 uthread.pool('moonmining::UpdateStructures', self.UpdateStructures)
   1376                 break
   1377             if slimItem.groupID == const.groupForceField:
   1378                 if self.sr.maintabs.GetSelectedArgs()[0] == 'force':
   1379                     uthread.pool('moonmining::UpdateStructures', self.ShowForce)
   1380                     break
   1381 
   1382     @telemetry.ZONE_METHOD
   1383     def DoBallsRemove(self, pythonBalls, isRelease):
   1384         for ball, slimItem, terminal in pythonBalls:
   1385             self.DoBallRemove(ball, slimItem, terminal)
   1386 
   1387     def DoBallRemove(self, ball, slimItem, terminal):
   1388         if not self or self.destroyed:
   1389             return
   1390         if slimItem is None:
   1391             log.warning('DoBallRemove::moonmining slimItem is None')
   1392             return
   1393         if ball:
   1394             log.info('DoBallRemove::moonmining %s', ball.id)
   1395         if slimItem.itemID == self.slimItem.itemID:
   1396             self.CloseByUser()
   1397             return
   1398         if slimItem.categoryID == const.categoryStarbase:
   1399             uthread.new(self.UpdateStructures)
   1400 
   1401     def DoBallClear(self, solitem):
   1402         if not self or self.destroyed:
   1403             return
   1404         self.CloseByUser()
   1405 
   1406     def OnBallparkCall(self, *args):
   1407         forcefield = self.GetForcefield()
   1408         if args[1][0] == forcefield.itemID:
   1409             if self.sr.maintabs.GetSelectedArgs()[0] == 'force':
   1410                 self.ShowForce()
   1411 
   1412 
   1413 class SelectSiloType(Window):
   1414     __guid__ = 'form.SelectSiloType'
   1415 
   1416     def ApplyAttributes(self, attributes):
   1417         Window.ApplyAttributes(self, attributes)
   1418         list = attributes.list
   1419         self.SetCaption(localization.GetByLabel('UI/Inflight/MoonMining/Processes/SelectSiloType'))
   1420         self.SetMinSize([256, 256])
   1421         self.DefineButtons(uiconst.OKCANCEL)
   1422         self.MakeUnMinimizable()
   1423         self.scroll = eveScroll.Scroll(parent=self.sr.main, padding=(const.defaultPadding,
   1424          const.defaultPadding,
   1425          const.defaultPadding,
   1426          const.defaultPadding))
   1427         scrolllist = []
   1428         for group in list:
   1429             label = evetypes.GetGroupNameByGroup(group)
   1430             scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetGroupSubContent,
   1431              'label': label,
   1432              'id': ('TypeSel', group),
   1433              'groupItems': list[group],
   1434              'iconMargin': 18,
   1435              'showlen': 1,
   1436              'sublevel': 1,
   1437              'state': 'locked'}))
   1438 
   1439         scrolllist = localization.util.Sort(scrolllist, key=lambda x: x.label)
   1440         self.scroll.state = uiconst.UI_NORMAL
   1441         self.scroll.Load(contentList=scrolllist)
   1442 
   1443     def GetGroupSubContent(self, nodedata, newitems = 0):
   1444         scrolllist = [ GetFromClass(Generic, data={'confirmOnDblClick': 1,
   1445          'label': evetypes.GetName(typeID),
   1446          'listvalue': typeID,
   1447          'id': ('TypeSel', typeID),
   1448          'OnDblClick': self.DblClickEntry}) for typeID in nodedata.groupItems ]
   1449         return localization.util.Sort(scrolllist, key=lambda x: x.label)
   1450 
   1451     def Cancel(self, *etc):
   1452         self.SetModalResult(uiconst.ID_CANCEL)
   1453 
   1454     def ClickOK(self, *args):
   1455         self.Confirm()
   1456 
   1457     def Confirm(self, *etc):
   1458         self.result = [ entry.listvalue for entry in self.scroll.GetSelected() ]
   1459         if not self.result:
   1460             info = localization.GetByLabel('UI/Inflight/MoonMining/Processes/MustSelectOne')
   1461             raise UserError('CustomInfo', {'info': info})
   1462         self.result = self.result[0]
   1463         self.SetModalResult(uiconst.ID_OK)
   1464 
   1465     def DblClickEntry(self, entry, *args):
   1466         if entry.confirmOnDblClick:
   1467             self.scroll.SelectNode(entry.sr.node)
   1468             self.Confirm()
   1469 
   1470 
   1471 class BaseStructure(SE_BaseClassCore):
   1472     __guid__ = 'listentry.BaseStructure'
   1473     __params__ = []
   1474 
   1475     def Startup(self, *args):
   1476         self.sr.resources = []
   1477         self.sr.products = []
   1478         sub = Container(name='sub', parent=self)
   1479         self.sr.resourcescont = Container(name='resources', align=uiconst.TOLEFT, width=32, parent=sub)
   1480         Line(parent=sub, align=uiconst.TOLEFT, color=(1.0, 1.0, 1.0, 0.5))
   1481         self.sr.productscont = Container(name='products', align=uiconst.TORIGHT, width=32, parent=sub)
   1482         Line(parent=sub, align=uiconst.TORIGHT, color=(1.0, 1.0, 1.0, 0.5))
   1483         self.sr.textcont = Container(name='textcol2', align=uiconst.TOALL, parent=sub, pos=(0, 0, 0, 0))
   1484         self.sr.textcontsub = Container(name='textcol2', align=uiconst.TOALL, parent=sub, pos=(0, 0, 0, 0))
   1485         self.sr.colorfill = Fill(parent=self.sr.textcontsub, color=(0.0, 1.0, 0.0, 0.0))
   1486         self.sr.textcol1 = Container(name='textcol1', align=uiconst.TOLEFT, width=150, parent=self.sr.textcont)
   1487         self.sr.textcol3 = Container(name='textcol3', align=uiconst.TORIGHT, width=75, parent=self.sr.textcont)
   1488         self.sr.textcol2 = Container(name='textcol2', align=uiconst.TOALL, parent=self.sr.textcont, clipChildren=1, pos=(0, 0, 0, 0))
   1489         self.sr.label = eveLabel.EveLabelMedium(text='', parent=self.sr.textcol1, left=4, top=4, state=uiconst.UI_DISABLED)
   1490         self.sr.label2 = eveLabel.EveLabelMedium(text='', parent=self.sr.textcol1, left=4, top=4, state=uiconst.UI_DISABLED)
   1491         self.sr.cycles = eveLabel.EveLabelSmall(text='1 cycle', parent=self.sr.textcol1, left=5, top=18, width=128, state=uiconst.UI_DISABLED)
   1492         self.sr.actionparent = Container(name='actionparent', align=uiconst.TORIGHT, left=2, width=102, parent=self.sr.textcol3)
   1493         self.sr.onlinebutton = Container(name='onlinebutton', parent=self.sr.actionparent, top=2, left=14, width=85, height=13, align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL)
   1494         self.sr.onlinebuttonText = eveLabel.EveLabelSmall(text='', parent=self.sr.onlinebutton, align=uiconst.CENTER, state=uiconst.UI_NORMAL)
   1495         if self.sr.node.slimitem.groupID in const.DEPRECATED_POS_MODULE_GROUPS:
   1496             self.sr.onlinebuttonText.OnClick = lambda : None
   1497         else:
   1498             self.sr.onlinebuttonText.OnClick = self.Online
   1499         Frame(parent=self.sr.onlinebutton, color=(1.0, 1.0, 1.0, 0.5))
   1500         self.sr.changebutton = Container(name='changebutton', parent=self.sr.actionparent, left=14, top=17, width=85, height=13, align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL)
   1501         self.sr.changebuttonText = eveLabel.EveLabelSmall(text=localization.GetByLabel('UI/Inflight/MoonMining/Processes/ChangeType'), parent=self.sr.changebutton, align=uiconst.CENTER, state=uiconst.UI_NORMAL)
   1502         Frame(parent=self.sr.changebutton, color=(1.0, 1.0, 1.0, 0.5))
   1503 
   1504     def Load(self, node):
   1505         self.sr.node = node
   1506         self.sr.colorfill.SetRGBA(*self.sr.node.color)
   1507         cycle = -2
   1508         for res in self.sr.node.resources.values():
   1509             if res[1] == 0:
   1510                 cycle = 0
   1511             else:
   1512                 cycle = [max(0, cycle, [int(math.ceil(float(res[0]) / res[1]) * res[2]), -1][res[2] == -1]), 0][cycle == 0]
   1513 
   1514         if cycle == -2:
   1515             cycle = 1
   1516         color = [(1.0, 1.0, 1.0, 1.0), (1.0, 0.0, 0.0, 1.0)][self.sr.node.Get('connected', 0)]
   1517         self.sr.cycles.SetRGBA(color[0], color[1], color[2])
   1518         self.sr.cycles.text = POS_STRUCTURE_STATE[self.sr.node.state]
   1519         if self.sr.node.state.startswith('reinforced'):
   1520             self.sr.onlinebutton.state = uiconst.UI_HIDDEN
   1521         else:
   1522             if self.sr.node.state.startswith('onl'):
   1523                 self.sr.onlinebuttonText.text = localization.GetByLabel('UI/Inflight/MoonMining/PutOffline')
   1524             else:
   1525                 self.sr.onlinebuttonText.text = localization.GetByLabel('UI/Inflight/MoonMining/PutOnline')
   1526             self.sr.onlinebutton.state = uiconst.UI_NORMAL
   1527         self.cycles = cycle
   1528         self.LoadResourceIcons()
   1529         self.LoadProductIcons()
   1530 
   1531     def LoadResourceIcons(self):
   1532         resources = self.sr.node.resources.items()
   1533         for i in xrange(5):
   1534             if i < len(resources):
   1535                 if len(self.sr.resources) <= i:
   1536                     icon = TypeIcon(parent=self.sr.resourcescont, align=uiconst.TOTOP, height=32)
   1537                     icon.Startup()
   1538                     self.sr.resources.append(icon)
   1539                 self.sr.resources[i].SetType(resources[i], 0)
   1540                 self.sr.resources[i].SetSide('resource')
   1541                 self.sr.resources[i].SetItemID(self.sr.node.slimitem.itemID)
   1542                 self.sr.resources[i].SetCallback(self.sr.node.structurecallback)
   1543                 self.sr.resources[i].SetScrollObject(self.sr.node.scrollObject)
   1544                 if i != 0:
   1545                     self.sr.resources[i].Line(1)
   1546                 else:
   1547                     self.sr.resources[i].Line(0)
   1548             elif len(self.sr.resources) > i:
   1549                 self.sr.resources[i].state = uiconst.UI_HIDDEN
   1550 
   1551         if len(resources) and len(resources) < len(self.sr.node.products):
   1552             if self.sr.Get('resline', None) is None:
   1553                 self.sr.resline = Line(parent=self.sr.resourcescont, align=uiconst.TOTOP)
   1554             else:
   1555                 self.sr.resline.state = uiconst.UI_DISABLED
   1556         elif self.sr.Get('resline', None) is not None:
   1557             self.sr.resline.state = uiconst.UI_HIDDEN
   1558 
   1559     def LoadProductIcons(self):
   1560         products = self.sr.node.products.items()
   1561         for i in xrange(5):
   1562             if i < len(products):
   1563                 if len(self.sr.products) <= i:
   1564                     icon = TypeIcon(parent=self.sr.productscont, align=uiconst.TOTOP, height=32)
   1565                     icon.Startup()
   1566                     self.sr.products.append(icon)
   1567                 self.sr.products[i].SetColor(self.sr.node.color)
   1568                 self.sr.products[i].SetType(products[i], 1)
   1569                 self.sr.products[i].SetSide('product')
   1570                 self.sr.products[i].SetItemID(self.sr.node.slimitem.itemID)
   1571                 self.sr.products[i].SetCallback(self.sr.node.structurecallback)
   1572                 self.sr.products[i].SetScrollObject(self.sr.node.scrollObject)
   1573                 if i != 0:
   1574                     self.sr.products[i].Line(1)
   1575                 else:
   1576                     self.sr.products[i].Line(0)
   1577             elif len(self.sr.products) > i:
   1578                 self.sr.products[i].state = uiconst.UI_HIDDEN
   1579 
   1580         if len(products) and len(products) < len(self.sr.node.resources):
   1581             if self.sr.Get('prodline', None) is None:
   1582                 self.sr.prodline = Line(parent=self.sr.productscont, align=uiconst.TOTOP)
   1583             else:
   1584                 self.sr.prodline.state = uiconst.UI_DISABLED
   1585         elif self.sr.Get('prodline', None) is not None:
   1586             self.sr.prodline.state = uiconst.UI_HIDDEN
   1587 
   1588     def GetMenu(self):
   1589         m = GetMenuService().GetMenuFromItemIDTypeID(self.sr.node.slimitem.itemID, self.sr.node.slimitem.typeID)
   1590         return m
   1591 
   1592     def Online(self, *args):
   1593         toggleTo = [1, 0][self.sr.node.state.startswith('onl')]
   1594         GetMenuService().ToggleObjectOnline(self.sr.node.slimitem.itemID, toggleTo)
   1595 
   1596     def GetHeight(self, *args):
   1597         node, width = args
   1598         icons = max(len(node.Get('resources', [None])), len(node.Get('products', [None])))
   1599         node.height = max(33, icons * 32 + 1)
   1600         return node.height
   1601 
   1602 
   1603 class Harvester(BaseStructure):
   1604     __guid__ = 'listentry.Harvester'
   1605 
   1606     def Startup(self, *args):
   1607         BaseStructure.Startup(self, args)
   1608         self.sr.typetext = eveLabel.EveLabelSmall(text='', parent=self.sr.textcol2, left=4, top=19, state=uiconst.UI_DISABLED, idx=0)
   1609 
   1610     def Load(self, node):
   1611         BaseStructure.Load(self, node)
   1612         self.sr.label2.text = self.sr.node.Get('label2', None) or localization.GetByLabel('UI/Inflight/MoonMining/Processes/Harvester')
   1613         currentStatusLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/CurrentStatus', status=POS_STRUCTURE_STATE[self.sr.node.state])
   1614         self.sr.hint = self.sr.label2.text + '<br>%s' % currentStatusLabel
   1615         mat = None
   1616         if len(self.sr.node.products):
   1617             k, v = self.sr.node.products.items()[0]
   1618             mat = (k, v[0], v[1])
   1619             if k is not None:
   1620                 self.sr.typetext.text = evetypes.GetName(k)
   1621             else:
   1622                 self.sr.typetext.text = localization.GetByLabel('UI/Inflight/MoonMining/Processes/NoMaterialSet')
   1623         if self.sr.node.connected:
   1624             linktext = '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterCorrectlyLinked')
   1625         else:
   1626             linktext = '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterNotLinked')
   1627         if not self.sr.node.state.startswith('online'):
   1628             if not mat:
   1629                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterNoMaterial')
   1630             else:
   1631                 harvesterOfflineLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterOffline', cycleTime=self.sr.node.cycle / 60000)
   1632                 if len(self.sr.node.products) and mat[0]:
   1633                     self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterCycleInformation', amount=mat[1] * sm.GetService('godma').GetType(mat[0]).moonMiningAmount, mineralID=mat[0], cycleTime=self.sr.node.cycle / 60000, harvesterOffline=harvesterOfflineLabel)
   1634                 else:
   1635                     self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterNotConfigured', harvesterOffline=harvesterOfflineLabel)
   1636                 self.sr.hint += linktext
   1637         elif self.sr.node.state.startswith('online - start'):
   1638             if mat:
   1639                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterStarted', cycleTime=self.sr.node.cycle / 60000, amount=mat[2] * sm.GetService('godma').GetType(mat[0]).moonMiningAmount, mineralID=mat[0])
   1640             else:
   1641                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterMustChangeType')
   1642             self.sr.hint += linktext
   1643         elif self.sr.node.state.startswith('online - active'):
   1644             harvesterActiveLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/HarvesterActive', miningAmount=mat[2] * sm.GetService('godma').GetType(mat[0]).moonMiningAmount, mineralID=mat[0], cycleTime=self.sr.node.cycle / 60000)
   1645             self.sr.hint += '<br><br>' + harvesterActiveLabel
   1646             self.sr.hint += linktext
   1647         self.sr.changebuttonText.OnClick = (self.sr.node.settype, self.sr.node.slimitem.itemID, self.sr.node.slimitem.groupID)
   1648         self.sr.changebutton.state = [uiconst.UI_HIDDEN, uiconst.UI_NORMAL][self.sr.node.state == 'anchored']
   1649         self.sr.onlinebutton.state = [uiconst.UI_NORMAL, uiconst.UI_HIDDEN][self.sr.typetext.text.startswith('<color')]
   1650 
   1651     def Online(self, *args):
   1652         if not len(self.sr.node.products) and not self.sr.node.state.startswith('onl'):
   1653             prompt_player_fsd_dialog('HarvestOnline')
   1654         else:
   1655             BaseStructure.Online(self, *args)
   1656 
   1657     def GetMenu(self):
   1658         changeHarvestedMaterialLabel = MenuLabel('UI/Inflight/MoonMining/Processes/ChangeHarvestedMaterial')
   1659         m = BaseStructure.GetMenu(self)
   1660         m += [(changeHarvestedMaterialLabel, self.sr.node.settype, (self.sr.node.slimitem.itemID, self.sr.node.slimitem.groupID))]
   1661         return m
   1662 
   1663 
   1664 class Silo(BaseStructure):
   1665     __guid__ = 'listentry.Silo'
   1666 
   1667     def Startup(self, *args):
   1668         BaseStructure.Startup(self, args)
   1669         g = Container(name='gauge', align=uiconst.TOPLEFT, width=48, height=7, left=4, top=7, parent=self.sr.textcol2, idx=0)
   1670         Container(name='push', parent=g, align=uiconst.TOBOTTOM, height=2)
   1671         g.name = ''
   1672         Line(parent=g, align=uiconst.TOTOP, color=(1.0, 1.0, 1.0, 0.5))
   1673         Line(parent=g, align=uiconst.TOBOTTOM, color=(1.0, 1.0, 1.0, 0.5))
   1674         Line(parent=g, align=uiconst.TOLEFT, color=(1.0, 1.0, 1.0, 0.5))
   1675         Line(parent=g, align=uiconst.TORIGHT, color=(1.0, 1.0, 1.0, 0.5))
   1676         g.sr.bar = Fill(parent=g, align=uiconst.TOLEFT, color=(1.0, 1.0, 1.0, 0.25))
   1677         Fill(parent=g, color=(1.0, 1.0, 1.0, 0.0))
   1678         self.sr.gauge = g
   1679         self.sr.typetext = eveLabel.EveLabelSmall(text='', parent=self.sr.textcol2, left=4, top=19, state=uiconst.UI_DISABLED, idx=0)
   1680 
   1681     def Load(self, node):
   1682         BaseStructure.Load(self, node)
   1683         self.sr.label2.text = self.sr.node.Get('label2', None) or localization.GetByLabel('UI/Inflight/MoonMining/Processes/Silo')
   1684         currentStatusLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/CurrentStatus', status=POS_STRUCTURE_STATE[self.sr.node.state])
   1685         self.sr.hint = self.sr.label2.text + '<br>%s' % currentStatusLabel
   1686         used2 = used1 = 0
   1687         if len(self.sr.node.resources):
   1688             k, v = self.sr.node.resources.items()[0]
   1689             amount = sm.GetService('godma').GetType(k).moonMiningAmount
   1690             if self.sr.node.Get('reaction', None):
   1691                 used1 = self.sr.node.reaction[1]
   1692                 used2 = self.sr.node.reaction[0]
   1693             self.sr.gaugetext.text = localization.GetByLabel('UI/Inflight/MoonMining/Processes/CapacityGauge', currentCapacity=max(round(used2, 1), 0), maxCapacity=max(round(used1, 1), 0))
   1694             self.sr.typetext.text = evetypes.GetName(k)
   1695             self.sr.gauge.sr.bar.width = int((self.sr.gauge.width - 2) * max(used2, 0) / max(used1, 1))
   1696             if not self.sr.node.state.startswith('online'):
   1697                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/SiloOffline', capacity=max(used1, 0), mineralID=k)
   1698                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/SiloOfflineAccess')
   1699             else:
   1700                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/SiloOnline', capacity=max(used1, 0), mineralID=k)
   1701                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/SiloOnlineAccess')
   1702         else:
   1703             self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/SiloNoStorageSet')
   1704             self.sr.gaugetext.text = ''
   1705             self.sr.typetext.text = ''
   1706         self.sr.changebuttonText.OnClick = (self.sr.node.settype, self.sr.node.slimitem.itemID, self.sr.node.slimitem.groupID)
   1707         self.sr.changebutton.state = [uiconst.UI_HIDDEN, uiconst.UI_NORMAL][self.sr.node.state == 'anchored']
   1708 
   1709     def GetMenu(self):
   1710         changeSiloTypeLabel = MenuLabel('UI/Inflight/MoonMining/Processes/ChangeSiloType')
   1711         m = BaseStructure.GetMenu(self)
   1712         m += [(changeSiloTypeLabel, self.sr.node.settype, (self.sr.node.slimitem.itemID, self.sr.node.slimitem.groupID))]
   1713         return m
   1714 
   1715 
   1716 class Reactor(BaseStructure):
   1717     __guid__ = 'listentry.Reactor'
   1718 
   1719     def Startup(self, *args):
   1720         BaseStructure.Startup(self, args)
   1721         self.sr.reaction = ReactionView(align=uiconst.TOPLEFT)
   1722         self.sr.reaction.top = 20
   1723         self.sr.reaction.left = 170
   1724         self.sr.reaction.width = 110
   1725         self.sr.reaction.height = 34
   1726         self.sr.reaction.state = uiconst.UI_NORMAL
   1727         self.children.insert(0, self.sr.reaction)
   1728         self.sr.reaction.Startup(const.flagCargo)
   1729         self.fetchingShell = 0
   1730 
   1731     def SetupReactionShell(self, itemID):
   1732         if self.destroyed:
   1733             return
   1734         self.fetchingShell = 1
   1735         self.sr.reaction.SetShell(sm.GetService('invCache').GetInventoryFromId(itemID))
   1736         if self.destroyed:
   1737             return
   1738         if self.sr.node and self.sr.node.slimitem.itemID != itemID:
   1739             self.SetupReactionShell(self.sr.node.slimitem.itemID)
   1740         else:
   1741             self.fetchingShell = 0
   1742 
   1743     def Load(self, node):
   1744         BaseStructure.Load(self, node)
   1745         self.sr.label2.text = self.sr.node.Get('label2', None) or localization.GetByLabel('UI/Inflight/MoonMining/Processes/Reactor')
   1746         currentStatusLabel = localization.GetByLabel('UI/Inflight/MoonMining/Processes/CurrentStatus', status=POS_STRUCTURE_STATE[self.sr.node.state])
   1747         self.sr.hint = self.sr.label2.text + '<br>%s' % currentStatusLabel
   1748         if not self.fetchingShell:
   1749             uthread.new(self.SetupReactionShell, self.sr.node.slimitem.itemID)
   1750         self.sr.reaction.SetLocation(self.sr.node.slimitem.itemID)
   1751         if self.sr.node.Get('reaction', None) is not None:
   1752             rec = utillib.KeyVal()
   1753             rec.typeID = self.sr.node.reaction[1]
   1754             rec.itemID = self.sr.node.reaction[0]
   1755             self.sr.reaction.SetItem(rec)
   1756         else:
   1757             self.sr.reaction.SetItem(None)
   1758         if len(self.sr.node.products):
   1759             k, v = self.sr.node.products.items()[0]
   1760             mat = (k, v[0], v[1])
   1761         else:
   1762             mat = None
   1763         if self.sr.node.connected:
   1764             linktext = '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorCorrectlyLinked')
   1765         else:
   1766             linktext = '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorNotLinked')
   1767         if not self.sr.node.state.startswith('online'):
   1768             self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorOfflineAccess')
   1769             if not self.sr.node.reaction:
   1770                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorNoReactionInstalled')
   1771             else:
   1772                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorOfflineWithReaction')
   1773         elif self.sr.node.state.startswith('online - start'):
   1774             self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorStarted')
   1775             self.sr.hint += linktext
   1776         elif self.sr.node.state.startswith('online - active'):
   1777             if mat is not None:
   1778                 self.sr.hint += '<br><br>' + localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorActive', reactionAmount=mat[2] * sm.GetService('godma').GetType(mat[0]).moonMiningAmount, reactionID=mat[0], cycleTime=self.sr.node.cycle / 60000)
   1779             self.sr.hint += linktext
   1780         else:
   1781             self.sr.hint += linktext
   1782         self.sr.changebutton.state = uiconst.UI_HIDDEN
   1783 
   1784     def GetHeight(self, *args):
   1785         node, width = args
   1786         icons = max(len(node.Get('resources', [None])), len(node.Get('products', [None])), 2)
   1787         node.height = max(33, icons * 32 + 1)
   1788         return node.height
   1789 
   1790 
   1791 class TypeIcon(Container):
   1792     __guid__ = 'xtriui.TypeIcon'
   1793     isDragObject = True
   1794 
   1795     def ApplyAttributes(self, attributes):
   1796         Container.ApplyAttributes(self, attributes)
   1797         self.rec = None
   1798         self.typeID = None
   1799         self.itemID = None
   1800         self.DisableDrag()
   1801         self.side = 'product'
   1802         self.scroll = None
   1803 
   1804     def Startup(self):
   1805         self.width = 32
   1806         self.height = 32
   1807         self.sr.icon = eveIcon.Icon(parent=self, align=uiconst.TOALL, state=uiconst.UI_DISABLED, size=32, ignoreSize=True)
   1808         self.sr.color = Fill(parent=self, color=(0.0, 0.0, 0.0, 0.0))
   1809         self.sr.highlight = Fill(parent=self, state=uiconst.UI_HIDDEN)
   1810         countcont = Container(parent=self, align=uiconst.TOPLEFT, left=16, top=24, width=16, height=8, idx=0)
   1811         self.sr.quantity = eveLabel.EveLabelSmall(text='', parent=countcont, left=2, width=14, height=8)
   1812         Line(parent=countcont, align=uiconst.TOLEFT, color=(1.0, 1.0, 1.0, 0.5))
   1813         Line(parent=countcont, align=uiconst.TOTOP, color=(1.0, 1.0, 1.0, 0.5))
   1814         Fill(parent=countcont, color=(0.0, 0.0, 0.0, 1.0))
   1815 
   1816     def SetColor(self, color):
   1817         if color is None:
   1818             color = (1.0, 1.0, 1.0, 0.25)
   1819         self.sr.color.SetRGBA(*color)
   1820         self.color = color
   1821 
   1822     def SetSide(self, side):
   1823         self.side = side
   1824 
   1825     def SetItemID(self, itemID):
   1826         self.itemID = itemID
   1827 
   1828     def SetType(self, t, drag):
   1829         typeID, v = t
   1830         quantity, used, cycle, color, connectID = v
   1831         self.typeID = typeID
   1832         self.connectID = connectID
   1833         self.drag = drag
   1834         self.UpdateDisplay(used, quantity)
   1835         self.SetColor(color)
   1836         if self.typeID is not None:
   1837             self.sr.icon.LoadIconByTypeID(typeID, ignoreSize=True)
   1838             self.state = uiconst.UI_NORMAL
   1839             self.sr.hint = evetypes.GetName(self.typeID)
   1840         else:
   1841             self.state = uiconst.UI_HIDDEN
   1842             self.sr.hint = localization.GetByLabel('UI/Inflight/MoonMining/Processes/NotConnected')
   1843         if drag:
   1844             self.EnableDrag()
   1845         else:
   1846             self.DisableDrag()
   1847 
   1848     def SetCallback(self, callback):
   1849         self.sr.callback = callback
   1850 
   1851     def SetScrollObject(self, scroll):
   1852         self.scroll = scroll
   1853 
   1854     def UpdateDisplay(self, used, quantity, typeID = None):
   1855         if typeID and typeID != self.typeID:
   1856             self.SetType(typeID, self.drag)
   1857         quantity = [quantity, -1][quantity > 9]
   1858         used = [used, -1][used > 9]
   1859         self.quantity = quantity
   1860         self.used = used
   1861         self.sr.quantity.text = [unicode(used), '-'][used == -1] + '/' + [unicode(quantity), '-'][quantity == -1]
   1862 
   1863     def Line(self, state):
   1864         if state:
   1865             if self.sr.Get('line', None) is None:
   1866                 self.sr.line = Line(parent=self, align=uiconst.TOTOP)
   1867         elif self.sr.Get('line', None) is not None:
   1868             self.sr.line.state = uiconst.UI_HIDDEN
   1869 
   1870     def ShowInfo(self, *args):
   1871         sm.GetService('info').ShowInfo(self.typeID, None)
   1872 
   1873     def Unfit(self, *args):
   1874         if self.sr.Get('callback', None) is not None:
   1875             if self.side == 'product':
   1876                 self.sr.callback(self.typeID, self.itemID, self.connectID, 0)
   1877             else:
   1878                 self.sr.callback(self.typeID, self.connectID, self.itemID, 0)
   1879 
   1880     def GetRemoteItem(self):
   1881         if self.scroll is None:
   1882             return
   1883         entries = [ entry for entry in self.scroll.GetNodes() if entry.panel and entry.slimitem and entry.slimitem.itemID == self.connectID ]
   1884         if not entries or not len(entries):
   1885             return
   1886         entry = entries[0]
   1887         items = None
   1888         if self.side == 'product':
   1889             if entry.panel.sr.resources is not None:
   1890                 items = [ item for item in entry.panel.sr.resources if item.typeID == self.typeID ]
   1891         elif entry.panel.sr.products is not None:
   1892             items = [ item for item in entry.panel.sr.products if item.typeID == self.typeID and item.state != uiconst.UI_HIDDEN ]
   1893         if not items or not len(items):
   1894             return
   1895         return items[0]
   1896 
   1897     GetRemoteItem = ParanoidDecoMethod(GetRemoteItem, ('parent',))
   1898 
   1899     def GetMenu(self):
   1900         m = []
   1901         if self.typeID:
   1902             m += [(MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo)]
   1903             if self.connectID:
   1904                 m += [(MenuLabel('UI/Inflight/MoonMining/Processes/RemoveConnection'), self.Unfit)]
   1905         return m
   1906 
   1907     def OnMouseEnter(self, *args):
   1908         self.sr.highlight.state = uiconst.UI_DISABLED
   1909         item = self.GetRemoteItem()
   1910         if item is not None:
   1911             item.sr.highlight.state = uiconst.UI_DISABLED
   1912 
   1913     def OnMouseExit(self, *args):
   1914         self.sr.highlight.state = uiconst.UI_HIDDEN
   1915         item = self.GetRemoteItem()
   1916         if item is not None:
   1917             item.sr.highlight.state = uiconst.UI_HIDDEN
   1918 
   1919     def OnDragEnter(self, dragObj, drag, *args):
   1920         if drag and getattr(drag[0], '__guid__', None) in ('xtriui.DragIcon',) and drag[0].data[0].__guid__ == 'xtriui.TypeIcon' and drag[0].data[0].typeID == self.typeID and drag[0].data[0].itemID != self.itemID and not self.IsDraggable():
   1921             self.sr.highlight.state = uiconst.UI_DISABLED
   1922 
   1923     def OnDragExit(self, *args):
   1924         self.sr.highlight.state = uiconst.UI_HIDDEN
   1925 
   1926     def OnDropData(self, dragObj, nodes):
   1927         node = nodes[0]
   1928         if node.__guid__ == 'xtriui.TypeIcon' and node.typeID == self.typeID and node.itemID != self.itemID and not self.IsDraggable():
   1929             if self.sr.Get('callback', None) is not None:
   1930                 uthread.new(self.sr.callback, self.typeID, node.itemID, self.itemID, 1)
   1931 
   1932     def GetDragData(self, *args):
   1933         fakeNode = utillib.KeyVal()
   1934         fakeNode.__guid__ = 'xtriui.TypeIcon'
   1935         fakeNode.typeID = self.typeID
   1936         fakeNode.itemID = self.itemID
   1937         fakeNode.color = self.color
   1938         fakeNode.quantity = fakeNode.stacksize = self.quantity
   1939         return [fakeNode]
   1940 
   1941 
   1942 class ReactionView(Container):
   1943     __guid__ = 'xtriui.ReactionView'
   1944     isDragObject = True
   1945 
   1946     def ApplyAttributes(self, attributes):
   1947         Container.ApplyAttributes(self, attributes)
   1948         self.isInvItem = 1
   1949         self.rec = None
   1950         self.DisableDrag()
   1951         self.height = self.width = 32
   1952         self.locationID = None
   1953         self.itemID = None
   1954         self.typeID = None
   1955 
   1956     def IsItemHere(self, item):
   1957         return item.locationID == self.locationID and evetypes.GetCategoryID(item.typeID) == const.categoryReaction
   1958 
   1959     def IsEmpty(self):
   1960         return self.rec is None
   1961 
   1962     def Startup(self, flag):
   1963         self.sr.highlight = Fill(parent=self, state=uiconst.UI_HIDDEN, align=uiconst.RELATIVE, left=2, top=2, width=32, height=32)
   1964         self.sr.icon = eveIcon.Icon(parent=self, align=uiconst.RELATIVE, left=2, top=2, size=32, state=uiconst.UI_DISABLED, typeID=self.typeID)
   1965         self.sr.reactiontext = eveLabel.EveLabelSmall(text='', parent=self, left=40, width=70, state=uiconst.UI_DISABLED)
   1966         self.flag = flag
   1967         sm.GetService('inv').Register(self)
   1968         self.invReady = 1
   1969 
   1970     def SetLocation(self, locationID):
   1971         self.locationID = locationID
   1972 
   1973     def SetShell(self, shell):
   1974         if not GetAttrs(self, 'sr'):
   1975             return
   1976         self.sr.shell = shell
   1977 
   1978     def SetItem(self, rec):
   1979         if rec is not None and rec.typeID:
   1980             self.typeID = rec.typeID
   1981             self.itemID = rec.itemID
   1982             self.sr.icon.LoadIconByTypeID(self.typeID, ignoreSize=True)
   1983             self.sr.icon.SetSize(32, 32)
   1984             self.sr.hint = self.sr.reactiontext.text = evetypes.GetName(self.typeID)
   1985         else:
   1986             self.typeID = None
   1987             self.itemID = None
   1988             self.sr.icon.LoadIcon('ui_5_64_10', ignoreSize=True)
   1989             self.sr.icon.SetSize(32, 32)
   1990             self.sr.reactiontext.text = localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorNoReaction')
   1991             self.sr.hint = localization.GetByLabel('UI/Inflight/MoonMining/Processes/ReactorNoReaction')
   1992         if rec:
   1993             self.EnableDrag()
   1994         else:
   1995             self.DisableDrag()
   1996 
   1997     def AddItem(self, rec):
   1998         self.SetItem(rec)
   1999         if getattr(self, 'OnReactionChanged', None) is not None:
   2000             self.OnReactionChanged(self.locationID, (self.itemID, self.typeID))
   2001 
   2002     def UpdateItem(self, item, *etc):
   2003         self.SetItem(item)
   2004 
   2005     def RemoveItem(self, item):
   2006         if item.itemID == self.itemID:
   2007             self.SetItem(None)
   2008             if getattr(self, 'OnReactionChanged', None) is not None:
   2009                 self.OnReactionChanged(self.locationID, None)
   2010 
   2011     def GetMenu(self):
   2012         m = []
   2013         if self.itemID and self.typeID:
   2014             if session.role & (ROLE_GML | ROLE_WORLDMOD):
   2015                 m += [(str(self.itemID), self.CopyItemIDToClipboard, (self.itemID,)), None]
   2016             m += [(MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo), (MenuLabel('UI/Inflight/MoonMining/Processes/ReactorRemoveReaction'), self.Unfit)]
   2017         return m
   2018 
   2019     def CopyItemIDToClipboard(self, itemID):
   2020         blue.pyos.SetClipboardData(str(itemID))
   2021 
   2022     def ShowInfo(self, *args):
   2023         sm.GetService('info').ShowInfo(self.typeID, self.itemID)
   2024 
   2025     def Unfit(self):
   2026         sm.GetService('invCache').GetInventoryFromId(session.shipid).Add(self.itemID, self.locationID, qty=None, flag=const.flagCargo)
   2027 
   2028     def OnDropData(self, dragObj, nodes):
   2029         for node in nodes:
   2030             self.DropNode(node)
   2031 
   2032     def DropNode(self, node):
   2033         if node.__guid__ not in ('xtriui.InvItem', 'xtriui.FittingSlot', 'listentry.InvItem'):
   2034             return
   2035         try:
   2036             if not getattr(node.rec, 'typeID', None) or node.rec.categoryID != const.categoryReaction:
   2037                 prompt_player_fsd_dialog('error')
   2038                 return
   2039             if getattr(node.rec, 'quantity', 1) == 1:
   2040                 quantity = 1
   2041             else:
   2042                 return
   2043             return self.sr.shell.Add(node.rec.itemID, node.rec.locationID, qty=quantity)
   2044         except UserError as what:
   2045             if what.args[0] == 'NotEnoughChargeSpace':
   2046                 if what.dict['capacity'] < 0:
   2047                     raise UserError('DestinationOverloaded')
   2048                 sys.exc_clear()
   2049             else:
   2050                 raise
   2051 
   2052     def GetCapacity(self):
   2053         return 0
   2054 
   2055     def OnMouseEnter(self, *args):
   2056         self.sr.highlight.state = uiconst.UI_DISABLED
   2057 
   2058     def OnMouseExit(self, *args):
   2059         self.sr.highlight.state = uiconst.UI_HIDDEN
   2060 
   2061     def OnDragEnter(self, dragObj, drag, *args):
   2062         if drag and drag[0].__guid__ in ('xtriui.InvItem', 'xtriui.FittingSlot', 'listentry.InvItem') and drag[0].rec.categoryID == const.categoryReaction and drag[0].rec.itemID != self.itemID:
   2063             self.sr.highlight.state = uiconst.UI_DISABLED
   2064 
   2065     def OnDragExit(self, *args):
   2066         self.sr.highlight.state = uiconst.UI_HIDDEN
   2067 
   2068     def GetDragData(self, *args):
   2069         if self.itemID is None:
   2070             return []
   2071         rec = utillib.KeyVal()
   2072         rec.itemID = self.itemID
   2073         rec.typeID = self.typeID
   2074         rec.ownerID = None
   2075         rec.groupID = evetypes.GetGroupID(self.typeID)
   2076         rec.categoryID = evetypes.GetCategoryID(self.typeID)
   2077         rec.quantity = rec.stacksize = 1
   2078         rec.locationID = self.locationID
   2079         rec.singleton = True
   2080         fakeNode = utillib.KeyVal()
   2081         fakeNode.__guid__ = 'xtriui.InvItem'
   2082         fakeNode.item = rec
   2083         fakeNode.rec = rec
   2084         fakeNode.itemID = rec.itemID
   2085         fakeNode.ownerID = None
   2086         fakeNode.invtype = self.typeID
   2087         fakeNode.container = None
   2088         fakeNode.label = uix.GetItemName(rec, fakeNode)
   2089         return [fakeNode]
   2090 
   2091 
   2092 class BaseTextStructure(Generic):
   2093     __guid__ = 'listentry.BaseTextStructure'
   2094     __notifyevents__ = ['OnStateChange']
   2095 
   2096     def Startup(self, *args):
   2097         Generic.Startup(self, *args)
   2098         sm.RegisterNotify(self)
   2099 
   2100     def _OnClose(self, *args):
   2101         Generic._OnClose(self, *args)
   2102         sm.UnregisterNotify(self)
   2103 
   2104     def OnStateChange(self, itemID, flag, isActive, *args):
   2105         if GetAttrs(self, 'sr', 'node') is None:
   2106             return
   2107         if self.sr.node.rec.itemID != itemID:
   2108             return
   2109         if flag == state.mouseOver:
   2110             self.Hilite(isActive)
   2111         elif flag == state.selected:
   2112             self.SetSelection(isActive)
   2113 
   2114     def Hilite(self, isActive):
   2115         if isActive:
   2116             self.ShowHilite()
   2117         else:
   2118             self.HideHilite()
   2119 
   2120     def SetSelection(self, isActive):
   2121         if isActive:
   2122             self.Select()
   2123         else:
   2124             self.Deselect()
   2125         self.sr.node.selected = isActive
   2126 
   2127     def OnMouseEnter(self, *args):
   2128         Generic.OnMouseEnter(self, *args)
   2129         if self.sr.node:
   2130             sm.GetService('stateSvc').SetState(self.sr.node.rec.itemID, state.mouseOver, 1)
   2131 
   2132     def OnMouseExit(self, *args):
   2133         Generic.OnMouseExit(self, *args)
   2134         if self.sr.node:
   2135             sm.GetService('stateSvc').SetState(self.sr.node.rec.itemID, state.mouseOver, 0)
   2136 
   2137     def OnClick(self, *args):
   2138         if self.sr.node:
   2139             Generic.OnClick(self, *args)
   2140         if sm.GetService('target').IsTarget(self.sr.node.rec.itemID):
   2141             sm.GetService('stateSvc').SetState(self.sr.node.rec.itemID, state.activeTarget, 1)
   2142         elif uicore.uilib.Key(uiconst.VK_CONTROL):
   2143             sm.GetService('target').TryLockTarget(self.sr.node.rec.itemID)
   2144         elif uicore.uilib.Key(uiconst.VK_MENU):
   2145             GetMenuService().TryLookAt(self.sr.node.rec.itemID)
   2146 
   2147 
   2148 class Structure(BaseTextStructure):
   2149     __guid__ = 'listentry.Structure'
   2150     __params__ = ['label']
   2151 
   2152     def Startup(self, *args):
   2153         BaseTextStructure.Startup(self, *args)
   2154 
   2155     def Load(self, node):
   2156         BaseTextStructure.Load(self, node)
   2157         self.UpdateState()
   2158 
   2159     def _OnClose(self, *args):
   2160         BaseTextStructure._OnClose(self, *args)
   2161         sm.UnregisterNotify(self)
   2162 
   2163     def Unload(self):
   2164         self.loaded = 0
   2165 
   2166     def UpdateState(self):
   2167         state = sm.GetService('pwn').GetStructureState(self.sr.node.rec)
   2168         progressCont = self.FindChild('progresscontainer')
   2169         if progressCont:
   2170             progressCont.Close()
   2171         if state[0] in ('anchoring', 'onlining', 'unanchoring', 'reinforced', 'operating'):
   2172             powerUsageLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/DisplayPowerUsage', powerUsage=self.sr.node.power)
   2173             cpuUsageLabel = localization.GetByLabel('UI/Inflight/MoonMining/Structures/DisplayCPUUsage', cpuUsage=self.sr.node.cpu)
   2174             displayState = structProgressMap.get(state[0], None)
   2175             if displayState:
   2176                 stateLabel = POS_STRUCTURE_STATE[displayState]
   2177             else:
   2178                 stateLabel = localization.GetByLabel('UI/Generic/Done')
   2179             label = '%s<t>%s<t><right>%s<t><right>%s' % (uix.GetSlimItemName(self.sr.node.rec),
   2180              stateLabel,
   2181              powerUsageLabel,
   2182              cpuUsageLabel)
   2183             uthread.new(self.sr.node.StructureProgress, self, label, state[1], state[2], self.sr.label)
   2184         self.sr.label.text = [uix.GetSlimItemName(self.sr.node.rec),
   2185          '<t>',
   2186          POS_STRUCTURE_STATE[state[0]],
   2187          '<t><right>',
   2188          localization.GetByLabel('UI/Inflight/MoonMining/Structures/DisplayPowerUsage', powerUsage=self.sr.node.power),
   2189          '<t><right>',
   2190          localization.GetByLabel('UI/Inflight/MoonMining/Structures/DisplayCPUUsage', cpuUsage=self.sr.node.cpu)]
   2191 
   2192 
   2193 class StructureControl(BaseTextStructure):
   2194     __guid__ = 'listentry.StructureControl'
   2195     __params__ = ['label']
   2196 
   2197     def Startup(self, *args):
   2198         BaseTextStructure.Startup(self, *args)
   2199         self.sr.controllerID = None
   2200         self.sr.targetID = None
   2201         self.sr.shooting = 0
   2202 
   2203     def Load(self, node):
   2204         BaseTextStructure.Load(self, node)
   2205         self.UpdateState()
   2206 
   2207     def _OnClose(self, *args):
   2208         BaseTextStructure._OnClose(self, *args)
   2209         sm.UnregisterNotify(self)
   2210 
   2211     def Unload(self):
   2212         self.loaded = 0
   2213 
   2214     def UpdateState(self):
   2215         self.isupdating = 1
   2216         structureID = self.sr.node.rec.itemID
   2217         state = sm.GetService('pwn').GetStructureState(self.sr.node.rec)
   2218         progressCont = self.FindChild('progresscontainer')
   2219         if progressCont:
   2220             progressCont.Close()
   2221         controllerID, controllerName = sm.GetService('pwn').GetControllerIDName(structureID)
   2222         targetID = sm.GetService('pwn').GetCurrentTarget(structureID)
   2223         stateLabel = POS_STRUCTURE_STATE[state[0]]
   2224         self.sr.label.text = [uix.GetSlimItemName(self.sr.node.rec),
   2225          '<t>',
   2226          stateLabel,
   2227          '<t>',
   2228          controllerName]
   2229         self.isupdating = 0
   2230 
   2231 
   2232 class StructureAccess(BaseTextStructure):
   2233     __guid__ = 'listentry.StructureAccess'
   2234     __params__ = ['label']
   2235 
   2236     def Startup(self, *args):
   2237         BaseTextStructure.Startup(self, args)
   2238         options = [(localization.GetByLabel('UI/Inflight/MoonMining/Structures/RoleConfigStarbaseEquipment'), 0),
   2239          (localization.GetByLabel('UI/Inflight/MoonMining/Structures/RoleStarbaseFuelTechnician'), 3),
   2240          (localization.GetByLabel('UI/Common/Corporation'), 1),
   2241          (localization.GetByLabel('UI/Common/Alliance'), 2)]
   2242         i = 200
   2243         self.sr.configs = {}
   2244         self.configs = ['viewput', 'viewputtake', 'use']
   2245         for config in self.configs:
   2246             self.sr.configs[config] = Combo(label='', parent=self, options=options, name=config, callback=self.ComboChange, pos=(i,
   2247              2,
   2248              0,
   2249              0), width=100, align=uiconst.TOPLEFT)
   2250             i += 106
   2251 
   2252     def Load(self, node):
   2253         BaseTextStructure.Load(self, node)
   2254         for key in self.configs:
   2255             if key == 'use':
   2256                 if node.rec.groupID not in [const.groupShipMaintenanceArray, const.groupReprocessingArray, const.groupCompressionArray]:
   2257                     self.sr.configs['use'].state = uiconst.UI_HIDDEN
   2258                 else:
   2259                     self.sr.configs['use'].state = uiconst.UI_NORMAL
   2260                     self.sr.configs['use'].SelectItemByValue(node.flags[key])
   2261             else:
   2262                 self.sr.configs[key].SelectItemByValue(node.flags[key])
   2263 
   2264         if self.sr.node.scroll.sr.tabs:
   2265             self.OnColumnChanged()
   2266 
   2267     def OnColumnChanged(self, *args):
   2268         i = self.sr.node.scroll.sr.tabs[0]
   2269         self.sr.label.width = i - 6
   2270         for key in self.configs:
   2271             self.sr.configs[key].left = i + 1
   2272             i += 106
   2273 
   2274     def ComboChange(self, combo, header, value, *args):
   2275         setattr(self.sr.node.flags, combo.name, value)
   2276 
   2277     def GetHeight(self, *args):
   2278         return Combo.default_height + 6