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

reprocessingWnd.py (40292B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\reprocessing\ui\reprocessingWnd.py
      2 from math import pi
      3 import carbonui.const as uiconst
      4 import evetypes
      5 from carbonui.control.combo import Combo
      6 from carbonui.primitives.flowcontainer import FlowContainer
      7 import uthread
      8 from menu import MenuLabel, MenuList
      9 from carbon.common.script.util.format import FmtAmt
     10 from carbonui.const import CENTER
     11 from carbonui.control.scrollContainer import ScrollContainer
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     14 from carbonui.primitives.fill import Fill
     15 from carbonui.primitives.frame import Frame
     16 from carbonui.primitives.gradientSprite import GradientSprite
     17 from carbonui.primitives.layoutGrid import LayoutGrid
     18 from carbonui.primitives.sprite import Sprite
     19 from carbonui.uicore import uicore
     20 from carbonui.util.color import Color
     21 from dogma.const import attributeRefiningYieldMutator
     22 from carbonui.control.button import Button
     23 from eve.client.script.ui.control.eveIcon import Icon
     24 from eve.client.script.ui.control.eveLabel import EveCaptionMedium, EveLabelMedium, EveLabelMediumBold, EveLabelSmallBold
     25 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel
     26 from carbonui.control.window import Window
     27 from eve.client.script.ui.control.themeColored import GradientThemeColored
     28 import eve.client.script.ui.shared.pointerTool.pointerToolConst as pConst
     29 from eve.common.script.sys.eveCfg import GetActiveShip
     30 from eve.common.script.util.eveFormat import FmtISKAndRound, FmtISK
     31 from eveservices.menu import GetMenuService
     32 from inventorycommon.const import flagCorpSAGsExcludingProjects, flagHangar, corpDivisionsByFlag
     33 from localization import GetByLabel
     34 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     35 from reprocessing.ui.const import STATE_REPROCESS, STATE_RESTRICTED, STATE_SUSPICIOUS, STATE_RANDOMIZED, TILE_SIZE, COL_YELLOW, COL_RED, COL_GREEN, COL_BLUE, COL_LIGHTBLUE
     36 from reprocessing.ui.containerCreator import ContainerCreator, Containers
     37 from reprocessing.ui.controller import Controller, NodesToItems
     38 from reprocessing.ui.grouper import GetCategoryGrouper, GetGroupGrouper
     39 from reprocessing.ui.inputGroups import InputGroups
     40 from reprocessing.ui.inputItemAdder import InputItemAdder
     41 from reprocessing.ui.itemContainers import InputItemContainerInterface, ItemContainerInterface
     42 from reprocessing.ui.itemReprocessor import ItemReprocessor
     43 from reprocessing.ui.outputItemAdder import OutputItemAdder, MaterialFetcher
     44 from reprocessing.ui.quotes import Quotes
     45 from reprocessing.ui.randomizedOutputContainer import RandomisedOutputContainer
     46 from reprocessing.ui.reprocessingItemContainer import ReprocessingItemContainer
     47 from reprocessing.ui.resultsContainer import ReprocessResultsContainer
     48 from reprocessing.ui.states import States
     49 from reprocessing.ui.tileplacer import TilePlacer
     50 from reprocessing.ui.util import GetTypeSkillBonuses, GetAttributeSkillBonusFromTypeID, GetSpecialReprocessingSkillBonuses, GetScrapMetalReprocessingSkillBonuses
     51 from reprocessing.ui.animation import FadeElementsInSequence
     52 from reprocessing.util import TypeHasSpecialReprocessingSkillBonuses, CategoryHasSpecialReprocessingSkillBonuses
     53 from uthread2 import start_tasklet
     54 from utillib import KeyVal
     55 
     56 class ReprocessingWnd(Window):
     57     __guid__ = 'form.ReprocessingWnd'
     58     default_width = 600
     59     default_height = 400
     60     default_minSize = (default_width, default_height)
     61     default_windowID = 'reprocessingWindow'
     62     default_descriptionLabelPath = 'Tooltips/StationServices/ReprocessingPlant_description'
     63     default_captionLabelPath = 'UI/Station/ReprocessingPlant'
     64     default_iconNum = 'res:/UI/Texture/WindowIcons/Reprocess.png'
     65 
     66     def ApplyAttributes(self, attributes):
     67         Window.ApplyAttributes(self, attributes)
     68         self.preSelectedItems = attributes.selectedItems
     69         self.outputPrice = 0
     70         self.outputItemsCount = 0
     71         mainCont = Container(name='mainCont', parent=self.sr.main, padding=uiconst.defaultPadding)
     72         self.bottomContainer = bottomCont = Container(name='bottomCont', parent=mainCont, align=uiconst.TOBOTTOM, height=36)
     73         reprocessingCont = Container(name='reprocessingCont', parent=mainCont, align=uiconst.TOALL)
     74         inputCont = Container(name='inputCont', parent=reprocessingCont, align=uiconst.TOLEFT_PROP, width=0.48)
     75         outputCont = Container(name='outputCont', parent=reprocessingCont, align=uiconst.TORIGHT_PROP, width=0.48)
     76         self.inputInfoCont = ReprocessInputContainer(name='inputInfo', parent=inputCont, dropFunc=self.AddItemByDrag, removeFunc=self.RemoveItem)
     77         self.outputInfoCont = ReprocessOutputContainer(name='outputInfo', parent=outputCont)
     78         self.resultsInfoCont = ReprocessResultsContainer(name='resultsInfo', parent=outputCont)
     79         self.loadingOverlay = Container(parent=self.inputInfoCont, idx=0)
     80         Fill(bgParent=self.loadingOverlay, color=(0.0, 0.0, 0.0, 0.3))
     81         LoadingWheel(name='loadingWheel', parent=self.loadingOverlay, align=uiconst.CENTER, width=80, height=80, state=uiconst.UI_DISABLED)
     82         self.loadingOverlay.opacity = 0.0
     83         self.controller = CreateReprocessingWindowController(self, self.inputInfoCont, self.outputInfoCont, sm.GetService('invCache'), sm.GetService('reprocessing'), GetActiveShip)
     84         self.inputInfoCont.captionLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/InputMaterials')
     85         self.outputInfoCont.captionLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/PredictedOutputResults')
     86         self.resultsInfoCont.captionLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/ActualOutputResults')
     87         btnCont = Container(name='buttonCont', parent=bottomCont, align=uiconst.TOBOTTOM, height=36, idx=0, padding=(-4, 3, -4, -2))
     88         GradientThemeColored(bgParent=btnCont)
     89         self.reprocessButton = Button(parent=btnCont, name='reprocessButton', uniqueUiName=pConst.UNIQUE_NAME_REPROCESS_BUTTON, label=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessButton'), func=self.ReprocessItems, align=uiconst.CENTERRIGHT, fixedheight=28, left=8)
     90         left = self.reprocessButton.left + self.reprocessButton.width
     91         self.totalIskCostLabel = EveLabelMedium(parent=btnCont, text='', align=uiconst.CENTERRIGHT, left=left + 8, color=COL_RED)
     92         self.cancelButton = Button(parent=btnCont, label=GetByLabel('UI/Common/Buttons/Cancel'), func=self.Cancel, align=uiconst.CENTERLEFT, fixedheight=28, left=8)
     93         self.DisableReprocessButton(disable=True)
     94         self.ShowPredictedOutputsPanel()
     95         if self.preSelectedItems:
     96             start_tasklet(self.AddPreselectedItems, self.preSelectedItems)
     97 
     98     def ShowInputLoading(self):
     99         self.inputInfoCont.overlayCont.display = False
    100         uicore.animations.FadeIn(self.loadingOverlay, endVal=1.0, duration=0.2)
    101 
    102     def HideInputLoading(self):
    103         uicore.animations.FadeOut(self.loadingOverlay, duration=0.2)
    104 
    105     def DisableReprocessButton(self, disable):
    106         if disable:
    107             self.reprocessButton.Disable()
    108             self.reprocessButton.hint = GetByLabel('UI/Reprocessing/ReprocessingWindow/NoReprocessableItems')
    109         else:
    110             self.reprocessButton.Enable()
    111             self.reprocessButton.hint = ''
    112 
    113     def AddPreselectedItems(self, items):
    114         self.controller.AddItems(items)
    115         if self.reprocessButton.disabled and self.controller.HasReprocessableOutput():
    116             self.DisableReprocessButton(disable=False)
    117 
    118     def RemoveItem(self, itemID):
    119         self.controller.RemoveItem(itemID)
    120         if not self.controller.HasReprocessableOutput():
    121             self.DisableReprocessButton(True)
    122 
    123     def AddItemByDrag(self, dragObj, nodes):
    124         self.controller.AddItems(NodesToItems(nodes))
    125         if self.reprocessButton.disabled and self.controller.HasReprocessableOutput():
    126             self.DisableReprocessButton(disable=False)
    127         self.cancelButton.SetLabel(GetByLabel('UI/Common/Buttons/Cancel'))
    128         self.ShowPredictedOutputsPanel()
    129 
    130     def Cancel(self, *args):
    131         self.CloseByUser()
    132 
    133     def GetOutputItems(self):
    134         return []
    135 
    136     def ReprocessItems(self, *args):
    137         reprocessed, remaining, outputByTypeID = self.controller.Reprocess(*self.outputInfoCont.outputCombo.GetValue())
    138         self.DisableReprocessButton(disable=True)
    139         self.cancelButton.SetLabel(GetByLabel('UI/Common/Buttons/Cancel'))
    140         for item in remaining:
    141             self.RemoveItem(item.itemID)
    142 
    143         self.inputInfoCont.FadeOutGroups()
    144         self.outputInfoCont.FadeOutGroups()
    145         self.controller.RemoveAllInputItems()
    146         self.outputInfoCont.RemoveRandomizedOutputs()
    147         if reprocessed:
    148             self.outputInfoCont.overlayCont.display = True
    149         self.ShowActualResultsPanel(outputByTypeID)
    150         self.inputInfoCont.ShowDropHereHint()
    151 
    152     def UpdateTotalIskCost(self, iskCost):
    153         self.totalIskCostLabel.SetText(FmtISK(-iskCost))
    154 
    155     def Close(self, *args, **kwargs):
    156         super(ReprocessingWnd, self).Close(*args, **kwargs)
    157         if self.controller:
    158             self.controller.Close()
    159 
    160     def ShowPredictedOutputsPanel(self):
    161         self.outputInfoCont.display = True
    162         self.resultsInfoCont.display = False
    163 
    164     def ShowActualResultsPanel(self, outputByTypeID):
    165         self.outputInfoCont.display = False
    166         self.resultsInfoCont.display = True
    167         self.resultsInfoCont.SetResults(outputByTypeID)
    168 
    169 
    170 class ReprocessingContainer(Container):
    171 
    172     def ApplyAttributes(self, attributes):
    173         Container.ApplyAttributes(self, attributes)
    174         nameCont = Container(name='nameCont', parent=self, align=uiconst.TOTOP, height=18)
    175         self.infoCont = Container(name='infoCont', parent=self, align=uiconst.TOBOTTOM, height=54, clipChildren=True)
    176         self.groupContainers = {}
    177         self.overlayCont = Container(name='overlayCont', parent=self, align=uiconst.TOALL)
    178         self.CreateScrollContainer()
    179         self.captionLabel = EveLabelMediumBold(parent=nameCont, left=6)
    180         self.volumeLabel = EveLabelMedium(name='volumeLabel', parent=self.infoCont, align=uiconst.BOTTOMRIGHT, left=5, top=4)
    181         self.totalPriceLabel = EveLabelMedium(name='totalPriceLabel', parent=self.infoCont, align=uiconst.BOTTOMRIGHT, left=5, top=20)
    182         self.numItemsLabel = EveLabelMedium(name='numItemsLabel', parent=self.infoCont, align=uiconst.BOTTOMRIGHT, left=5, top=36)
    183 
    184     def CreateScrollContainer(self):
    185         self.scrollCont = ScrollContainer(parent=self, align=uiconst.TOALL, showUnderlay=True)
    186 
    187     def UpdateSummaryLabels(self, outputPrice, numberOfItems, volume = None):
    188         self.totalPriceLabel.text = GetByLabel('UI/Inventory/EstIskPrice', iskString=FmtISKAndRound(outputPrice, False))
    189         self.numItemsLabel.text = GetByLabel('UI/Inventory/NumItems', numItems=numberOfItems, numFilteredTxt='')
    190         if volume is not None:
    191             self.volumeLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/TotalVolume', volume=FmtAmt(volume, showFraction=2))
    192         self.totalPriceLabel.display = True
    193         self.numItemsLabel.display = True
    194         self.volumeLabel.display = True
    195 
    196     def HideSummaryLabels(self):
    197         self.totalPriceLabel.display = False
    198         self.numItemsLabel.display = False
    199         self.volumeLabel.display = False
    200 
    201     def RemoveGroup(self, groupID):
    202         group = self.groupContainers.pop(groupID)
    203         group.Close()
    204 
    205     def AddItem(self, groupID, ctrlID_item):
    206         ctrlID, item = ctrlID_item
    207         self.groupContainers[groupID].tilePlacer.AddItem(ctrlID, item)
    208         self.overlayCont.display = False
    209 
    210 
    211 class ReprocessInputContainer(ReprocessingContainer):
    212 
    213     def ApplyAttributes(self, attributes):
    214         ReprocessingContainer.ApplyAttributes(self, attributes)
    215         self.removeFunc = attributes.removeFunc
    216         self.scrollCont.name = 'inputScroll'
    217         self.scrollCont.Copy = self.CopyInput
    218         self.scrollCont.OnDropData = self.OnDroppingItems
    219         self.parentDropFunc = attributes.dropFunc
    220         self.volumeLabel.display = False
    221         self.UpdateSummaryLabels(0, 0)
    222         self.overlayCont.GetAbsoluteSize()
    223         self.ShowDropHereHint()
    224 
    225     def AddGroup(self, groupID, groupName):
    226         self.groupContainers[groupID] = ReprocessingInputGroupContainer(parent=self.scrollCont, align=uiconst.TOTOP, percentage=0.5, groupID=groupID, groupName=groupName)
    227 
    228     def AddItem(self, groupID, ctrlID_item):
    229         ctrlID, item = ctrlID_item
    230         self.scrollCont.HideNoContentHint()
    231         ReprocessingContainer.AddItem(self, groupID, (ctrlID, item))
    232         item.OnDropData = self.OnDroppingItems
    233         item.GetMenu = lambda *args: self.GetItemMenu(ctrlID, item.typeID)
    234         self.groupContainers[groupID].tilePlacer.mainContainer.OnDropData = self.OnDroppingItems
    235 
    236     def OnDroppingItems(self, dragObj, nodes):
    237         if self.parentDropFunc:
    238             self.parentDropFunc(dragObj, nodes)
    239 
    240     def GetItemMenu(self, itemID, typeID):
    241         menu = MenuList()
    242         menu += GetMenuService().GetMenuFromItemIDTypeID(itemID, typeID, includeMarketDetails=True)
    243         menu.append((GetByLabel('UI/Generic/RemoveItem'), self.removeFunc, (itemID,)))
    244         return menu
    245 
    246     def AnimateItems(self):
    247         for group in self.groupContainers.itervalues():
    248             inputItems = group.tilePlacer.GetItems()
    249             timeOffset = 0.2 / len(inputItems)
    250             funcs = [ (self.GrayOutItem, (item,)) for item in inputItems ]
    251             uthread.parallel(funcs)
    252             for item in inputItems:
    253                 uicore.animations.FadeOut(item, duration=timeOffset, sleep=True)
    254 
    255         for groupID, group in self.groupContainers.items():
    256             group.Close()
    257 
    258         self.groupContainers = {}
    259 
    260     def GrayOutItem(self, item):
    261         animateCall = lambda cont: uicore.animations.MorphScalar(cont, attrName='saturation', startVal=1.0, endVal=0.0, duration=0.3, sleep=True)
    262         uthread.parallel([(animateCall, (item.icon,)), (animateCall, (item.techIcon,))])
    263 
    264     def SetEfficiency(self, group, efficiency, typeIDs):
    265         self.groupContainers[group].SetEfficiency(efficiency, typeIDs)
    266 
    267     def SetTaxAndStationEfficiency(self, group, efficiency, tax):
    268         self.groupContainers[group].SetTaxAndStationEfficiency(efficiency, tax)
    269 
    270     def CopyInput(self):
    271         allItems = []
    272         groupConts = self.groupContainers.values()
    273         groupConts.sort(key=lambda x: x.GetOrder())
    274         for group in groupConts:
    275             inputItems = group.tilePlacer.GetItems()
    276             allItems += inputItems
    277 
    278         CopyItemsToClipboard(allItems)
    279 
    280     def FadeOutGroups(self):
    281         FadeElementsInSequence(self.groupContainers.values(), 0.5, 1.0, 0.0, True)
    282 
    283     def ShowDropHereHint(self):
    284         self.scrollCont.ShowNoContentHint(GetByLabel('UI/Reprocessing/ReprocessingWindow/DropHereToReprocess'))
    285 
    286 
    287 class ReprocessOutputContainer(ReprocessingContainer):
    288 
    289     def ApplyAttributes(self, attributes):
    290         ReprocessingContainer.ApplyAttributes(self, attributes)
    291         self.scrollCont.name = 'outputScroll'
    292         self.scrollCont.Copy = self.CopyOutput
    293         self.volumeLabel.display = True
    294         self.UpdateSummaryLabels(0, 0, 0)
    295         self.overlayCont.display = False
    296         w, h = self.overlayCont.GetAbsoluteSize()
    297         overlayLabel = EveCaptionMedium(name='overlayLabel', parent=self.overlayCont, align=uiconst.CENTER)
    298         overlayLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/OutputTransferredTo')
    299         self.overlayLabel2 = EveLabelMediumBold(name='overlayLabel2', parent=self.overlayCont, align=uiconst.CENTER, top=20, state=uiconst.UI_NORMAL)
    300         self.overlayLabel2.text = GetByLabel('UI/Inventory/ItemHangar')
    301         self.overlayLabel2.OnClick = uicore.cmd.OpenInventory
    302         self._CreateOutputCombo()
    303         self.randomizedOutputContainers = {}
    304 
    305     def _CreateOutputCombo(self):
    306         hangarValue = (session.stationid or session.structureid, flagHangar)
    307         sameLocationValue = (None, None)
    308         comboOptions = [(GetByLabel('UI/Reprocessing/ReprocessingWindow/InputLocationComboBoxLabel'),
    309           sameLocationValue,
    310           None,
    311           None,
    312           0), (GetByLabel('UI/Inventory/ItemHangar'),
    313           hangarValue,
    314           None,
    315           'res:/ui/Texture/WindowIcons/itemHangar.png',
    316           0)]
    317         office = sm.GetService('officeManager').GetCorpOfficeAtLocation()
    318         if office:
    319             officeLabel = GetByLabel('UI/Inventory/CorporationHangars')
    320             officeIcon = 'res:/UI/Texture/WindowIcons/corporation.png'
    321             comboOptions.append((officeLabel,
    322              None,
    323              None,
    324              officeIcon,
    325              0))
    326             divisions = sm.GetService('corp').GetDivisionNames()
    327             for flagID in flagCorpSAGsExcludingProjects:
    328                 divID = corpDivisionsByFlag[flagID]
    329                 comboOptions.append((divisions[divID + 1],
    330                  (office.officeID, flagID),
    331                  None,
    332                  officeIcon,
    333                  1))
    334 
    335         outputLabel = EveLabelSmallBold(name='overlayLabel', parent=self.infoCont, align=uiconst.CENTERLEFT, top=-5)
    336         outputLabel.text = GetByLabel('UI/Industry/OutputLocation')
    337         self.outputCombo = Combo(parent=self.infoCont, align=uiconst.BOTTOMLEFT, callback=self.OnCombo, height=22, width=120)
    338         self.outputCombo.LoadOptions(comboOptions, hangarValue)
    339         self.outputCombo.last_selected = hangarValue
    340 
    341     def OnCombo(self, comboBox, key, value):
    342         if value is None:
    343             comboBox.SelectItemByValue(comboBox.last_selected)
    344             return
    345         comboBox.last_selected = value
    346         flag = value[1]
    347         if not self.overlayCont.display:
    348             if flag in corpDivisionsByFlag:
    349                 division = corpDivisionsByFlag[flag] + 1
    350                 self.overlayLabel2.text = '%s - %s' % (GetByLabel('UI/Inventory/CorporationHangars'), sm.GetService('corp').GetDivisionNames()[division])
    351             else:
    352                 self.overlayLabel2.text = key
    353 
    354     def AddGroup(self, groupID, groupName):
    355         self.groupContainers[groupID] = ReprocessingOutputGroupContainer(parent=self.scrollCont, align=uiconst.TOTOP, percentage=0.5, groupID=groupID, groupName=groupName)
    356 
    357     def AddRandomizedOutput(self, quote):
    358         if quote.typeID in self.randomizedOutputContainers:
    359             c = self.randomizedOutputContainers[quote.typeID]
    360         else:
    361             c = RandomisedOutputContainer(parent=self.scrollCont, align=uiconst.TOTOP, percentage=0.5, inputTypeID=quote.typeID)
    362             self.randomizedOutputContainers[quote.typeID] = c
    363         c.AddOutputsFromQuote(quote)
    364 
    365     def RemoveRandomizedOutputs(self):
    366         for c in self.randomizedOutputContainers.itervalues():
    367             c.Close()
    368 
    369         self.randomizedOutputContainers.clear()
    370 
    371     def AddItem(self, groupID, ctrlID_item):
    372         ctrlID, item = ctrlID_item
    373         ReprocessingContainer.AddItem(self, groupID, (ctrlID, item))
    374         item.GetMenu = (self.GetItemMenu, ctrlID)
    375 
    376     @staticmethod
    377     def GetItemMenu(typeID):
    378         m = [(MenuLabel('UI/Commands/ShowInfo'), sm.GetService('info').ShowInfo, (typeID,))]
    379         if evetypes.GetMarketGroupID(typeID) is not None:
    380             sm.GetService('marketutils').AddMarketDetailsMenuOption(m, typeID)
    381             m.append((MenuLabel('UI/Inventory/ItemActions/AddTypeToMarketQuickbar'), sm.GetService('marketutils').AddTypeToQuickBar, (typeID,)))
    382         return m
    383 
    384     def GetItems(self):
    385         items = []
    386         for group in self.groupContainers.itervalues():
    387             items.extend(group.tilePlacer.GetItems())
    388 
    389         return items
    390 
    391     def FadeOutGroups(self):
    392         allGroups = []
    393         allGroups.extend(self.groupContainers.itervalues())
    394         allGroups.extend(self.randomizedOutputContainers.itervalues())
    395         FadeElementsInSequence(allGroups, 0.5, 1.0, 0.0, True)
    396 
    397     def ShowItems(self):
    398         self.overlayCont.display = False
    399 
    400     def CopyOutput(self):
    401         CopyItemsToClipboard(self.GetItems())
    402 
    403 
    404 class ReprocessingInputItemContainer(ReprocessingItemContainer):
    405     isDragObject = True
    406 
    407     def ApplyAttributes(self, attributes):
    408         ReprocessingItemContainer.ApplyAttributes(self, attributes)
    409         self.getTypeAttribute = sm.GetService('clientDogmaStaticSvc').GetTypeAttribute
    410         self.getSkillLevel = sm.GetService('skills').MySkillLevel
    411         self.itemID = attributes.itemID
    412         self.quantity = attributes.quantity
    413         self.outputMaterials = attributes.outputMaterials
    414         self.hintInfo = attributes.hintInfo
    415         self.onMouseEnter = None
    416         self.onMouseExit = None
    417         bgSprite = Sprite(bgParent=self.spriteCont, name='background', texturePath='res:/UI/Texture/classes/InvItem/bgNormal.png')
    418 
    419     def AddItem(self):
    420         pass
    421 
    422     def OnMouseEnter(self, *args):
    423         if uicore.uilib.leftbtn:
    424             return
    425         if self.onMouseEnter is not None:
    426             self.onMouseEnter()
    427 
    428     def OnMouseExit(self, *args):
    429         if self.onMouseExit is not None:
    430             self.onMouseExit()
    431 
    432     def RegisterForHoverEvents(self, itemID, onMouseEnter, onMouseExit):
    433         self.onMouseEnter = lambda : onMouseEnter(itemID)
    434         self.onMouseExit = lambda : onMouseExit(itemID)
    435 
    436     def GetDragData(self):
    437         return [KeyVal(itemID=self.itemID, __guid__='xtriui.TypeIcon', typeID=self.typeID, isReprocessingItem=True)]
    438 
    439     def LoadTooltipPanel(self, tooltipPanel, *args):
    440         typeID, reprocessingYield, stationTaxHint, itemYieldHint, stationEfficiency = self.hintInfo
    441         tooltipPanel.LoadGeneric1ColumnTemplate()
    442         rowSpan = 1
    443         if self.itemState:
    444             rowSpan = 2
    445         subGrid1 = LayoutGrid()
    446         icon = Icon(width=64, height=64, align=CENTER)
    447         icon.LoadIconByTypeID(typeID=self.typeID, ignoreSize=True)
    448         subGrid1.AddCell(icon, rowSpan=rowSpan)
    449         yieldText = '<color=%s>%s%%</color>' % (Color.RGBtoHex(*COL_LIGHTBLUE), FmtAmt(reprocessingYield * 100.0, showFraction=1))
    450         topLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ItemYieldHint', itemName=evetypes.GetName(self.typeID), itemYield=yieldText), width=170, autoFitToText=True, left=6, top=4, bold=True)
    451         subGrid1.AddCell(topLabel)
    452         if self.itemState:
    453             hintText = ''
    454             hintColor = None
    455             if self.itemState == STATE_REPROCESS:
    456                 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessedFurtherHint')
    457                 hintColor = COL_GREEN
    458             elif self.itemState == STATE_RESTRICTED:
    459                 portionSize = evetypes.GetPortionSize(typeID)
    460                 if portionSize > self.quantity:
    461                     noOfItems = FmtAmt(portionSize, showFraction=0)
    462                     hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/CannotReprocessHint', noOfItems=noOfItems)
    463                 else:
    464                     hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/CannotReprocessNoValueHint')
    465                 hintColor = COL_RED
    466             elif self.itemState == STATE_SUSPICIOUS:
    467                 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessingWarningHint')
    468                 hintColor = COL_YELLOW
    469             elif self.itemState == STATE_RANDOMIZED:
    470                 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/RandomizedOutputHint')
    471                 hintColor = COL_BLUE
    472             stateHint = EveLabelMedium(text=hintText, width=170, autoFitToText=True, left=6, top=4, color=hintColor)
    473             subGrid1.AddCell(stateHint)
    474         tooltipPanel.AddCell(subGrid1)
    475         subGrid = LayoutGrid()
    476         subGrid.AddCell(cellPadding=6, colSpan=2)
    477         subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/DetailedYieldHint'), color=COL_BLUE, bold=True), colSpan=2)
    478         for label in GetTypeReprocessingModifiersAsLabels(typeID, stationEfficiency, self.getTypeAttribute, self.getSkillLevel):
    479             subGrid.AddCell(label)
    480 
    481         if itemYieldHint:
    482             subGrid.AddCell(cellPadding=6, colSpan=2)
    483             subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YouWillReceiveHint'), color=COL_BLUE, bold=True), colSpan=2)
    484             for typeID, qty in itemYieldHint:
    485                 subGrid.AddCell(EveLabelMedium(text=FmtAmt(qty, showFraction=False), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_LIGHTBLUE, bold=True))
    486                 subGrid.AddCell(EveLabelMedium(text='%s' % evetypes.GetName(typeID), colSpan=1, padLeft=3))
    487 
    488         tooltipPanel.AddCell(subGrid)
    489 
    490 
    491 class ReprocessingOutputItemContainer(ReprocessingItemContainer):
    492 
    493     def ApplyAttributes(self, attributes):
    494         ReprocessingItemContainer.ApplyAttributes(self, attributes)
    495         self.outputFrame = Frame(name='outputFrame', bgParent=self.spriteCont, texturePath='res:/UI/Texture/Reprocessing/Dash_Frame_48.png')
    496         self.outputFrame.SetRGB(*COL_YELLOW)
    497         qtyInfo = attributes.qtyInfo
    498         typeInfo = attributes.fromTypeInfo
    499         self._SetInfo(qtyInfo, typeInfo)
    500 
    501     def LoadTooltipPanel(self, tooltipPanel, *args):
    502         tooltipPanel.LoadGeneric1ColumnTemplate()
    503         subGrid1 = LayoutGrid()
    504         icon = Icon(width=64, height=64, align=CENTER)
    505         icon.LoadIconByTypeID(typeID=self.typeID, ignoreSize=True)
    506         subGrid1.AddCell(cellObject=icon)
    507         subGrid1.AddCell(EveLabelMedium(text=evetypes.GetName(self.typeID), width=170, autoFitToText=True, left=6, top=4, bold=True))
    508         tooltipPanel.AddCell(subGrid1)
    509         subGrid = LayoutGrid()
    510         subGrid.columns = 2
    511         l1 = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessedFrom'), color=COL_BLUE, bold=True)
    512         subGrid.AddCell(l1, colSpan=2)
    513         for typeID, quantity in self.typeInfo.iteritems():
    514             subGrid.AddCell(EveLabelMedium(text=FmtAmt(quantity, showFraction=0), align=uiconst.TORIGHT, padRight=3, color=COL_LIGHTBLUE, bold=True))
    515             subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessedFromType', typeName=evetypes.GetName(typeID)), padLeft=3))
    516 
    517         subGrid.AddCell(EveLabelMedium(text=FmtAmt(self.unrecoverableQty, showFraction=0), colSpan=1, align=uiconst.TORIGHT, padRight=2, color=COL_RED, bold=True))
    518         subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/NotRecoverableHint'), colSpan=1, padLeft=2))
    519         subGrid.AddCell(EveLabelMedium(text=FmtAmt(self.quantity, showFraction=0), colSpan=1, align=uiconst.TORIGHT, padRight=2, color=COL_GREEN, bold=True))
    520         subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/TotalOutputHint'), colSpan=1, padLeft=2))
    521         if self.iskCost:
    522             subGrid.AddCell(EveLabelMedium(text=FmtAmt(self.iskCost, showFraction=0), colSpan=1, align=uiconst.TORIGHT, padRight=2, bold=True))
    523             subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/IskPaidPerItem'), colSpan=1, padLeft=2))
    524         tooltipPanel.AddCell(subGrid)
    525 
    526     def Update(self, qtyInfo, fromItemIDs, fromTypeInfo):
    527         self._SetInfo(qtyInfo, fromTypeInfo)
    528 
    529     def _SetInfo(self, qtyInfo, typeInfo):
    530         self.quantity, self.iskCost, self.unrecoverableQty = qtyInfo
    531         self.typeInfo = typeInfo
    532         self._SetQtyText()
    533 
    534 
    535 def AskToContinue(error):
    536     buttons = uiconst.YESNO
    537     default = uiconst.ID_YES
    538     msg = cfg.GetMessage(error.msg, error.dict, onNotFound='return')
    539     if msg.type not in ('warning', 'question'):
    540         buttons = None
    541         default = None
    542     ret = prompt_player_fsd_dialog(error.msg, error.dict, buttons=buttons, default=default)
    543     return ret == uiconst.ID_YES
    544 
    545 
    546 def CreateOutputItemContainer(typeID, fromItemIDs, fromTypeInfo, qtyInfo, canBeReprocessed):
    547     if canBeReprocessed:
    548         itemState = STATE_REPROCESS
    549     else:
    550         itemState = None
    551     return ReprocessingOutputItemContainer(align=uiconst.TOPLEFT, width=TILE_SIZE, height=TILE_SIZE, typeID=typeID, qtyInfo=qtyInfo, itemID=0, fromTypeInfo=fromTypeInfo, itemState=itemState)
    552 
    553 
    554 def CreateInputItemContainer(item, hintInfo, itemState):
    555     return ReprocessingInputItemContainer(align=uiconst.TOPLEFT, width=TILE_SIZE, height=TILE_SIZE, typeID=item.typeID, quantity=item.quantity, itemID=item.itemID, categoryID=item.categoryID, hintInfo=hintInfo, itemState=itemState, singleton=item.singleton, stacksize=item.stacksize)
    556 
    557 
    558 class ReprocessingInputGroupContainer(ContainerAutoSize):
    559 
    560     def ApplyAttributes(self, attributes):
    561         Container.ApplyAttributes(self, attributes)
    562         self.header = ReprocessingInputHeaderContainer(parent=self, align=uiconst.TOTOP, height=24, percentage=0.0, groupID=attributes.groupID, groupName=attributes.groupName)
    563         tileContainer = FlowContainer(parent=self, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, contentSpacing=(8, 8), padding=8)
    564         self.tilePlacer = TilePlacer(tileContainer)
    565 
    566     def SetEfficiency(self, efficiency, typeIDs):
    567         self.header.UpdateGauge(efficiency)
    568         self.header.UpdateSkills(typeIDs)
    569 
    570     def SetTaxAndStationEfficiency(self, efficiency, tax):
    571         self.header.stationEfficiency = efficiency
    572         self.header.stationTax = tax
    573 
    574 
    575 class ReprocessingOutputGroupContainer(ContainerAutoSize):
    576 
    577     def ApplyAttributes(self, attributes):
    578         Container.ApplyAttributes(self, attributes)
    579         self.header = ReprocessingHeaderContainer(parent=self, align=uiconst.TOTOP, height=24, percentage=0.0, groupID=attributes.groupID, groupName=attributes.groupName)
    580         tileContainer = FlowContainer(parent=self, align=uiconst.TOTOP, contentSpacing=(8, 8), padding=8)
    581         self.tilePlacer = TilePlacer(tileContainer)
    582 
    583     def UpdateInfo(self, typeID, qtyInfo, fromItemIDs, fromTypeInfo):
    584         tile = self.tilePlacer.GetItem(typeID)
    585         tile.Update(qtyInfo, fromItemIDs, fromTypeInfo)
    586 
    587 
    588 class ReprocessingHeaderContainer(Container):
    589     default_align = uiconst.TOTOP
    590     default_height = 24
    591 
    592     def ApplyAttributes(self, attributes):
    593         Container.ApplyAttributes(self, attributes)
    594         self.groupID = attributes.groupID
    595         self.groupName = attributes.groupName
    596         Fill(bgParent=self, color=(0.0, 0.0, 0.0, 0.5))
    597         leftCont = Container(parent=self, align=uiconst.TOALL)
    598         self.headerText = EveLabelMedium(text=self.groupName, parent=leftCont, left=2, maxLines=1, align=uiconst.CENTERLEFT, padLeft=4)
    599 
    600 
    601 class ReprocessingInputHeaderContainer(ReprocessingHeaderContainer):
    602 
    603     def ApplyAttributes(self, attributes):
    604         ReprocessingHeaderContainer.ApplyAttributes(self, attributes)
    605         self.percentage = attributes.percentage
    606         self.avgBonus = 0
    607         self.state = uiconst.UI_NORMAL
    608         self.groupHilite = Fill(bgParent=self, color=(0.4, 0.4, 0.4, 0.1), opacity=0.0)
    609         self.getTypeAttribute = sm.GetService('clientDogmaStaticSvc').GetTypeAttribute
    610         self.getSkillLevel = sm.GetService('skills').MySkillLevel
    611         self.stationTax = attributes.tax
    612         self.stationEfficiency = attributes.efficiency
    613         if self._ShouldShowEfficiencyGauge():
    614             rightCont = Container(parent=self, align=uiconst.TORIGHT, width=100)
    615             Sprite(parent=rightCont, width=24, height=24, ignoreSize=True, align=uiconst.TOLEFT, texturePath='res:/UI/Texture/Reprocessing/Reprocess.png')
    616             self.gaugeParent = Container(name='gaugeParent', parent=rightCont, align=uiconst.TOALL, padding=(0, 5, 2, 4), state=uiconst.UI_NORMAL)
    617             self.gaugeParent.LoadTooltipPanel = self.LoadGaugeTooltipPanel
    618             self.gaugeLabel = EveLabelSmallBold(parent=self.gaugeParent, align=uiconst.CENTER)
    619             Frame(parent=self.gaugeParent, color=(0.5, 0.5, 0.5, 0.05))
    620             Fill(bgParent=self.gaugeParent, color=(0.0, 0.0, 0.0, 0.8))
    621             self.reprocessingGauge = GradientSprite(parent=self.gaugeParent, align=uiconst.TOLEFT_PROP, rotation=-pi / 2, rgbData=[(0, COL_YELLOW)], alphaData=[(0, 0.6), (0.5, 0.4), (1.0, 0.6)], state=uiconst.UI_DISABLED)
    622             self.UpdateGauge(self.percentage)
    623 
    624     def _ShouldShowEfficiencyGauge(self):
    625         return CategoryHasSpecialReprocessingSkillBonuses(self.groupID)
    626 
    627     def UpdateGauge(self, percentage):
    628         if not self._ShouldShowEfficiencyGauge():
    629             return
    630         self.reprocessingGauge.width = percentage
    631         self.percentage = percentage
    632         self.gaugeLabel.text = GetByLabel('UI/Common/Formatting/PercentageDecimal', percentage=percentage * 100.0)
    633 
    634     def UpdateSkills(self, typeIDs):
    635         skillBonuses = []
    636         for groupID, typeIDs in typeIDs.iteritems():
    637             for typeID in typeIDs:
    638                 _, bonus = GetAttributeSkillBonusFromTypeID(typeID, self.getTypeAttribute, self.getSkillLevel)
    639                 skillBonuses.append(bonus)
    640 
    641         bonusAmt = sum(skillBonuses)
    642         self.avgBonus = bonusAmt / len(typeIDs)
    643 
    644     def LoadGaugeTooltipPanel(self, tooltipPanel, *args):
    645         tooltipPanel.LoadGeneric1ColumnTemplate()
    646         subGrid1 = LayoutGrid()
    647         icon = Sprite(width=64, height=64, ignoreSize=True, align=CENTER, texturePath='res:/UI/Texture/Reprocessing/Reprocess.png')
    648         subGrid1.AddCell(icon)
    649         itemName = self.groupName
    650         yieldText = '<color=%s>%s%%</color>' % (Color.RGBtoHex(*COL_LIGHTBLUE), FmtAmt(self.percentage * 100.0, showFraction=1))
    651         topLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ItemYieldHint', itemName=itemName, itemYield=yieldText), width=170, autoFitToText=True, left=6, top=4, bold=True)
    652         subGrid1.AddCell(topLabel)
    653         tooltipPanel.AddCell(subGrid1)
    654         subGrid = LayoutGrid()
    655         l1 = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessingCalculations'), color=COL_BLUE, bold=True)
    656         subGrid.AddCell(l1, colSpan=2)
    657         for label in GetCategoryReprocessingModifiersAsLabels(self.groupID, self.stationEfficiency, self.getTypeAttribute, self.getSkillLevel, self.avgBonus):
    658             subGrid.AddCell(label)
    659 
    660         tooltipPanel.AddCell(subGrid)
    661 
    662     def OnMouseEnter(self, *args):
    663         uicore.animations.FadeIn(self.groupHilite, duration=0.4, endVal=0.25)
    664 
    665     def OnMouseExit(self, *args):
    666         uicore.animations.FadeOut(self.groupHilite, duration=0.4)
    667 
    668 
    669 def CreateReprocessingWindowController(wnd, inputInfoCont, outputInfoCont, invCache, reprocessing, GetActiveShip):
    670     quotes = Quotes(reprocessing)
    671     materialFetcher = MaterialFetcher(quotes)
    672     inputItemContainer = inputInfoCont
    673     inputItemContainer = InputItemContainerInterface(inputItemContainer)
    674     outputItemContainer = outputInfoCont
    675     outputItemContainer = ItemContainerInterface(outputItemContainer)
    676     inputGrouper = GetCategoryGrouper()
    677     inputGroups = InputGroups(inputItemContainer, inputGrouper)
    678     containerCreator = ContainerCreator(Containers(CreateInputItemContainer), Containers(CreateOutputItemContainer), quotes)
    679     inputItemAdder = InputItemAdder(inputItemContainer, containerCreator, quotes, States(quotes), inputGrouper, GetActiveShip)
    680     outputItemAdder = OutputItemAdder(materialFetcher, outputItemContainer, containerCreator, GetGroupGrouper(), quotes)
    681     reprocessor = ItemReprocessor(reprocessing, invCache, AskToContinue)
    682     controller = Controller(wnd, inputItemAdder, inputGroups, quotes, outputItemAdder, reprocessor, GetActiveShip)
    683     sm.RegisterNotify(controller)
    684     return controller
    685 
    686 
    687 def GetTypeReprocessingModifiersAsLabels(typeID, stationEfficiency, getTypeAttribute, getSkillLevel):
    688     labelList = []
    689     labelList.extend(GetStationEfficiencyAsLabel(stationEfficiency))
    690     labelList.extend(GetTypeSkillBonusesAsLabels(typeID, getTypeAttribute, getSkillLevel))
    691     if TypeHasSpecialReprocessingSkillBonuses(typeID):
    692         labelList.extend(GetImplantModifiersAsLabels(getTypeAttribute))
    693     return labelList
    694 
    695 
    696 def GetCategoryReprocessingModifiersAsLabels(categoryID, stationEfficiency, getTypeAttribute, getSkillLevel, avgBonus):
    697     labelList = []
    698     labelList.extend(GetStationEfficiencyAsLabel(stationEfficiency))
    699     if CategoryHasSpecialReprocessingSkillBonuses(categoryID):
    700         labelList.extend(GetOreAvgBonusAsLabel(avgBonus))
    701         skillBonuses = GetSpecialReprocessingSkillBonuses(getTypeAttribute, getSkillLevel)
    702         labelList.extend(_CreateSkillBonusLabelsFromSkillBonuses(skillBonuses))
    703         labelList.extend(GetImplantModifiersAsLabels(getTypeAttribute))
    704     else:
    705         skillBonuses = GetScrapMetalReprocessingSkillBonuses(getTypeAttribute, getSkillLevel)
    706         labelList.extend(_CreateSkillBonusLabelsFromSkillBonuses(skillBonuses))
    707     return labelList
    708 
    709 
    710 def GetStationEfficiencyAsLabel(stationEfficiency):
    711     stationBonusLabel = EveLabelMedium(text=GetByLabel('UI/Common/Formatting/Percentage', percentage=stationEfficiency * 100), colSpan=1, align=uiconst.TORIGHT, padRight=2, color=COL_LIGHTBLUE, bold=True)
    712     stationTextLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/BaseYield'), colSpan=1, padLeft=2)
    713     return (stationBonusLabel, stationTextLabel)
    714 
    715 
    716 def GetOreAvgBonusAsLabel(avgBonus):
    717     labelOpacity = 0.35
    718     if avgBonus > 0:
    719         labelOpacity = 1.0
    720     oreAvgBonusLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 + avgBonus / 100), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_GREEN, bold=True, opacity=labelOpacity)
    721     oreAvgTextLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/OreProcessingHint'), colSpan=1, padLeft=3, opacity=labelOpacity)
    722     return (oreAvgBonusLabel, oreAvgTextLabel)
    723 
    724 
    725 def GetTypeSkillBonusesAsLabels(typeID, getTypeAttribute, getSkillLevel):
    726     skillBonuses = GetTypeSkillBonuses(typeID, getTypeAttribute, getSkillLevel)
    727     skillLabels = _CreateSkillBonusLabelsFromSkillBonuses(skillBonuses)
    728     return skillLabels
    729 
    730 
    731 def _CreateSkillBonusLabelsFromSkillBonuses(skillBonuses):
    732     skillLabels = []
    733     for skillType, bonus in skillBonuses:
    734         skillName = evetypes.GetName(skillType)
    735         labelOpacity = 0.35
    736         if bonus > 0:
    737             labelOpacity = 1.0
    738         skillLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 + bonus / 100), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_GREEN, bold=True, opacity=labelOpacity))
    739         skillLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/BonusFromSkill', skillName=skillName), colSpan=1, padLeft=3, opacity=labelOpacity))
    740 
    741     return skillLabels
    742 
    743 
    744 def GetImplantModifiersAsLabels(getTypeAttribute):
    745     implantLabels = []
    746     implants = sm.GetService('godma').GetItem(session.charid).implants
    747     for implant in implants:
    748         implantBonus = getTypeAttribute(implant.typeID, attributeRefiningYieldMutator)
    749         if implantBonus > 0.0:
    750             implantLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 + implantBonus / 100), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_GREEN, bold=True))
    751             implantLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/BonusFromSkill', skillName=evetypes.GetName(implant.typeID)), colSpan=1, padLeft=3))
    752 
    753     return implantLabels
    754 
    755 
    756 def GetStationTaxAsLabel(stationTax):
    757     taxBonusLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 - stationTax), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_RED, bold=True)
    758     taxTextLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/StationTaxHint'), colSpan=1, padLeft=3)
    759     return (taxBonusLabel, taxTextLabel)
    760 
    761 
    762 def CopyItemsToClipboard(items):
    763     textLine = []
    764     for item in items:
    765         t = '%s\t%s' % (evetypes.GetName(item.typeID), abs(item.quantity))
    766         textLine.append(t)
    767 
    768     text = '\n'.join(textLine)
    769     from carbon.common.script.util.commonutils import StripTags
    770     strippedText = StripTags(text)
    771     if strippedText:
    772         import blue
    773         blue.pyos.SetClipboardData(strippedText)