Ejemplo n.º 1
0
class SellItemContainer(BuySellItemContainerBase):
    __guid__ = 'uicls.SellItemContainer'
    belowColor = '<color=0xffff5050>'
    aboveColor = '<color=0xff00ff00>'
    totaLabelPath = 'UI/Market/MarketQuote/AskTotal'

    def ApplyAttributes(self, attributes):
        self.item = attributes.item
        self.typeID = self.item.typeID
        BuySellItemContainerBase.ApplyAttributes(self, attributes)
        self.adjustQtyAndPriceTimer = None
        self.isUpdating = False
        self.singleton = self.item.singleton
        self.itemID = self.item.itemID
        self.itemName = evetypes.GetName(self.typeID)
        self.brokersFee = 0.0
        self.salesTax = 0.0
        self.totalSum = 0.0
        self.stationID = attributes.stationID
        self.limits = self.quoteSvc.GetSkillLimits(self.stationID)
        self.solarSystemID = attributes.solarSystemID
        self.regionID = self.GetRegionID()
        self.locationID = self.item.locationID
        self.bestBid = attributes.bestBid
        self.bestPrice = attributes.bestPrice
        self.totalStrikethroughLine = None
        self.priceAmountWarning = None
        self.deltaCont = Container(parent=self,
                                   align=uiconst.TORIGHT,
                                   width=30)
        theRestCont = Container(name='theRestCont',
                                parent=self,
                                align=uiconst.TOALL)
        self.totalCont = Container(name='totalCont',
                                   parent=theRestCont,
                                   align=uiconst.TORIGHT_PROP,
                                   width=0.3)
        self.priceCont = Container(name='priceCont',
                                   parent=theRestCont,
                                   align=uiconst.TORIGHT_PROP,
                                   width=0.22)
        self.qtyCont = Container(name='qtyCont',
                                 parent=theRestCont,
                                 align=uiconst.TORIGHT_PROP,
                                 width=0.15)
        self.itemCont = Container(name='itemCont',
                                  parent=theRestCont,
                                  align=uiconst.TORIGHT_PROP,
                                  width=0.33)
        self.deleteCont = Container(name='deleteCont',
                                    parent=self.itemCont,
                                    align=uiconst.TORIGHT,
                                    width=24)
        self.deleteButton = ButtonIcon(
            texturePath='res:/UI/Texture/Icons/73_16_210.png',
            pos=(0, 0, 16, 16),
            align=uiconst.CENTERRIGHT,
            parent=self.deleteCont,
            hint=GetByLabel('UI/Generic/RemoveItem'),
            idx=0,
            func=self.RemoveItem)
        self.deleteCont.display = False
        self.textCont = Container(name='textCont',
                                  parent=self.itemCont,
                                  align=uiconst.TOALL)
        self.errorBg = ErrorFrame(bgParent=self)
        self.DrawItem()
        self.DrawQty()
        self.DrawPrice()
        self.DrawTotal()
        self.DrawDelta()
        self.estimatedSellCount = self.GetSellCountEstimate()
        self.SetTotalSumAndLabel()
        self.brokersFeePerc = self.limits.GetBrokersFeeForLocation(
            self.stationID)
        self.UpdateBrokersFee()
        self.GetSalesTax()
        self.ShowNoSellOrders()
        self.UpdateOrderStateInUI()

    def GetRegionID(self):
        return cfg.mapSystemCache.Get(session.solarsystemid2).regionID

    def OnDurationChanged(self, duration):
        self.OnChange()

    def ShowNoSellOrders(self, force=False):
        if self.IsImmediateOrder() and (self.bestBid is None or force):
            uicore.animations.FadeIn(self.errorBg, 0.35, duration=0.3)

    def GetDuration(self):
        from eve.client.script.ui.shared.market.sellMulti import SellItems
        wnd = SellItems.GetIfOpen()
        if not wnd:
            return
        return wnd.durationCombo.GetValue()

    def DrawQty(self):
        qty = self.item.stacksize
        self.qtyEdit = SinglelineEdit(name='qtyEdit',
                                      parent=self.qtyCont,
                                      align=uiconst.TOTOP,
                                      top=11,
                                      padLeft=4)
        self.qtyEdit.IntMode(*(1, long(qty)))
        self.qtyEdit.SetValue(qty)
        self.qtyEdit.OnChange = self.OnChange
        self.qtyEdit.hint = GetByLabel('UI/Common/Quantity')

    def DrawPrice(self):
        self.priceEdit = SinglelineEdit(name='priceEdit',
                                        parent=self.priceCont,
                                        align=uiconst.TOTOP,
                                        top=11,
                                        padLeft=8)
        self.priceEdit.FloatMode(*(0.01, 9223372036854.0, 2))
        self.priceEdit.SetValue(self.bestPrice)
        self.priceEdit.OnChange = self.OnChange
        self.priceEdit.hint = GetByLabel('UI/Market/MarketQuote/AskPrice')

    def DrawDelta(self):
        self.deltaContainer = SellDeltaContainer(parent=self.deltaCont,
                                                 delta=self.GetDelta(),
                                                 func=self.OpenMarket,
                                                 align=uiconst.CENTERRIGHT)
        self.deltaContainer.LoadTooltipPanel = self.LoadDeltaTooltip
        self.UpdateDelta()

    def GetTradeWndClass(self):
        from eve.client.script.ui.shared.market.sellMulti import SellItems
        return SellItems

    def LoadDeltaTooltip(self, tooltipPanel, *args):
        tooltipPanel.LoadGeneric2ColumnTemplate()
        tooltipPanel.cellPadding = (4, 1, 4, 1)
        tooltipPanel.AddLabelLarge(
            text=GetByLabel('UI/Market/MarketQuote/AskPrice'))
        tooltipPanel.AddLabelLarge(text=FmtISK(self.priceEdit.GetValue()),
                                   align=uiconst.CENTERRIGHT)
        tooltipPanel.AddSpacer(1, 8, colSpan=tooltipPanel.columns)
        tooltipPanel.AddLabelMedium(
            text='%s %s' %
            (GetByLabel('UI/Market/MarketQuote/RegionalAdverage'),
             self.GetDeltaText()))
        tooltipPanel.AddLabelMedium(text=FmtISK(self.averagePrice),
                                    align=uiconst.CENTERRIGHT)
        tooltipPanel.AddLabelMedium(
            text=GetByLabel('UI/Market/MarketQuote/BestRegional'))
        bestMatch = tooltipPanel.AddLabelMedium(text='',
                                                align=uiconst.CENTERRIGHT)
        bestMatchDetails = tooltipPanel.AddLabelSmall(
            text='', align=uiconst.CENTERRIGHT, colSpan=tooltipPanel.columns)
        if not self.bestBid:
            bestMatch.text = GetByLabel('UI/Contracts/ContractEntry/NoBids')
            bestMatchDetails.text = GetByLabel(
                'UI/Market/MarketQuote/ImmediateWillFail')
            bestMatch.color = (1.0, 0.275, 0.0, 1.0)
            bestMatchDetails.color = (1.0, 0.275, 0.0, 1.0)
        else:
            bestMatch.text = FmtISK(self.bestBid.price)
            bestMatchText, volRemaining = self.GetBestMatchText()
            bestMatchDetails.text = bestMatchText
            bestMatchDetails.SetAlpha(0.6)
            if volRemaining:
                vol = tooltipPanel.AddLabelSmall(text=volRemaining,
                                                 align=uiconst.CENTERRIGHT,
                                                 colSpan=tooltipPanel.columns)
                vol.SetAlpha(0.6)

    def GetBestMatchText(self):
        jumps = max(self.bestBid.jumps - max(0, self.bestBid.range), 0)
        minVolumeText = None
        if jumps == 0 and self.stationID == self.bestBid.stationID:
            jumpText = GetByLabel('UI/Market/MarketQuote/ItemsInSameStation')
        else:
            jumpText = GetByLabel('UI/Market/MarketQuote/JumpsFromThisSystem',
                                  jumps=jumps)
        if self.bestBid.minVolume > 1 and self.bestBid.volRemaining >= self.bestBid.minVolume:
            minVolumeText = GetByLabel(
                'UI/Market/MarketQuote/SimpleMinimumVolume',
                min=self.bestBid.minVolume)
        return (GetByLabel('UI/Market/MarketQuote/SellQuantity',
                           volRemaining=long(self.bestBid.volRemaining),
                           jumpText=jumpText), minVolumeText)

    def DrawItem(self):
        iconCont = Container(parent=self.textCont,
                             align=uiconst.TOLEFT,
                             width=32,
                             padding=4)
        self.iconInnerCont = Container(name='iconInnerCont',
                                       parent=iconCont,
                                       align=uiconst.CENTERLEFT,
                                       pos=(0, 0, 32, 32))
        self.wheel = LoadingWheel(parent=self.iconInnerCont,
                                  pos=(0, 0, 48, 48),
                                  align=uiconst.CENTER,
                                  idx=0)
        self.wheel.display = False
        self.techIcon = Sprite(parent=self.iconInnerCont,
                               pos=(0, 0, 16, 16),
                               align=uiconst.TOPLEFT,
                               state=uiconst.UI_NORMAL)
        self.icon = Icon(parent=self.iconInnerCont,
                         typeID=self.typeID,
                         state=uiconst.UI_DISABLED,
                         ignoreSize=True,
                         pos=(0, 0, 32, 32))
        GetTechLevelIcon(self.techIcon, 1, self.typeID)
        itemName = GetByLabel('UI/Contracts/ContractsWindow/ShowInfoLink',
                              showInfoName=self.itemName,
                              info=('showinfo', self.typeID, self.item.itemID))
        self.itemNameLabel = Label(text=itemName,
                                   parent=self.textCont,
                                   left=40,
                                   align=uiconst.CENTERLEFT,
                                   state=uiconst.UI_NORMAL,
                                   autoFadeSides=35,
                                   fontsize=12)

    def UpdateBrokersFee(self):
        fee = self.quoteSvc.BrokersFee(self.stationID, self.totalSum,
                                       self.brokersFeePerc)
        feeAmount = fee.amt
        self.brokersFee = feeAmount

    def GetSalesTax(self):
        tax = self.totalSum * self.limits['acc']
        self.salesTax = tax

    def GetTotalSum(self):
        self.GetTotalSumAndDisplaySum()
        return self.totalSum

    def GetTotalSumAndDisplaySum(self):
        price = self.GetPrice()
        qty = self.GetQty()
        sumToDisplay = price * qty
        totalSum = sumToDisplay
        if self.IsImmediateOrder():
            if self.estimatedSellCount == 0:
                totalSum = 0
            elif self.estimatedSellCount < qty:
                sumToDisplay = self.estimatedSellCount * price
                totalSum = sumToDisplay
        self.totalSum = totalSum
        return (totalSum, sumToDisplay)

    def UpdateTotalSumLabel(self, totalSum, sumToDisplay):
        self.totalLabel.text = FmtISK(sumToDisplay)
        if sumToDisplay != totalSum:
            self.ConstructTotalStrikethroughLine()
            self.totalStrikethroughLine.width = self.totalLabel.textwidth
        else:
            self.ChangeTotalStrikethroughDisplay(display=False)

    def OnChange(self, *args):
        if self.adjustQtyAndPriceTimer:
            self.adjustQtyAndPriceTimer.KillTimer()
        self.adjustQtyAndPriceTimer = AutoTimer(200,
                                                self.AdjustQtyAndPrice_thread,
                                                *args)
        self.SetItemLoading()

    def AdjustQtyAndPrice_thread(self, *args):
        self.adjustQtyTimer = None
        if self.destroyed:
            return
        self.estimatedSellCount = self.GetSellCountEstimate()
        self.SetTotalSumAndLabel()
        self.UpdateBrokersFee()
        self.GetSalesTax()
        self.deltaContainer.display = True
        self.UpdateDelta()
        self.wheel.display = False
        self.isUpdating = False
        if self.parentEditFunc:
            self.parentEditFunc(args)
        self.UpdateOrderStateInUI()

    def SetItemLoading(self):
        self.totalLabel.text = NA_CHAR
        self.deltaContainer.display = False
        self.wheel.display = True
        self.isUpdating = True

    def SetTotalSumAndLabel(self):
        totalSum, displaySum = self.GetTotalSumAndDisplaySum()
        self.UpdateTotalSumLabel(totalSum, displaySum)

    def UpdateOrderStateInUI(self):
        duration = self.GetDuration()
        if duration != 0:
            self.ChangePriceAmountWarningDisplay(display=False)
            self.HideNoSellOrders()
            return
        qty = self.GetQty()
        if self.estimatedSellCount == 0:
            self.ShowNoSellOrders(force=True)
            self.ChangePriceAmountWarningDisplay(display=False)
        elif self.estimatedSellCount < qty:
            self.HideNoSellOrders()
            self.PrepareWarningInfo(self.estimatedSellCount, qty)
        else:
            self.HideNoSellOrders()
            self.ChangePriceAmountWarningDisplay(display=False)

    def PrepareWarningInfo(self, estimatedSellCount, qtyToSell):
        self.ConstructPriceAmountWarning()
        self.ConstructQtyBg()
        self.ChangePriceAmountWarningDisplay(display=True)
        self.priceAmountWarning.info = (estimatedSellCount, qtyToSell)

    def GetPrice(self):
        price = self.priceEdit.GetValue()
        return price

    def GetQty(self):
        qty = self.qtyEdit.GetValue()
        return qty

    def GetQtyToSell(self):
        qty = self.GetQty()
        if self.IsImmediateOrder():
            return min(self.estimatedSellCount, qty)
        else:
            return qty

    def IsImmediateOrder(self):
        isImmediate = self.GetDuration() == 0
        return isImmediate

    def SetQtyAndPrice(self, newQty, newPrice):
        self.qtyEdit.SetValue(newQty)
        self.priceEdit.SetValue(newPrice)
        self.OnChange()

    def GetSellCountEstimate(self):
        return self.quoteSvc.GetSellCountEstimate(self.typeID, self.stationID,
                                                  self.GetPrice(),
                                                  self.GetQty())

    def MakeSingle(self):
        self.height = 80
        self.qtyCont.width = 0
        self.itemCont.width = 0.42
        self.totalCont.width = 0.36
        self.itemNameLabel.fontsize = 14
        self.totalLabel.fontsize = 14
        self.itemNameLabel.left = 72
        self.icon.SetSize(64, 64)
        self.wheel.SetSize(64, 64)
        self.iconInnerCont.SetSize(64, 64)
        self.priceEdit.padLeft = 4
        self.priceEdit.align = uiconst.TOBOTTOM
        self.qtyEdit.top = 20
        self.priceEdit.top = 20
        self.qtyEdit.SetParent(self.priceCont)
        if self.priceAmountWarning:
            self.priceAmountWarning.top = -10

    def RemoveSingle(self):
        self.height = 40
        self.qtyCont.width = 0.15
        self.itemCont.width = 0.33
        self.totalCont.width = 0.3
        self.itemNameLabel.fontsize = 12
        self.totalLabel.fontsize = 12
        self.itemNameLabel.left = 40
        self.icon.SetSize(32, 32)
        self.wheel.SetSize(48, 48)
        self.iconInnerCont.SetSize(32, 32)
        self.priceEdit.align = uiconst.TOTOP
        self.qtyEdit.top = 11
        self.priceEdit.top = 11
        self.priceEdit.padLeft = 8
        self.qtyEdit.SetParent(self.qtyCont)
        if self.priceAmountWarning:
            self.priceAmountWarning.top = 0

    def ConstructPriceAmountWarning(self):
        if self.priceAmountWarning:
            return None
        cont = Container(name='priceAmountWarning',
                         parent=self.itemCont,
                         align=uiconst.TORIGHT,
                         left=-4,
                         width=16,
                         idx=0)
        self.priceAmountWarning = Sprite(
            parent=cont,
            pos=(0, 0, 16, 16),
            align=uiconst.CENTER,
            texturePath='res:/ui/texture/icons/44_32_7.png')
        self.priceAmountWarning.SetRGB(1.0, 0.3, 0.3, 0.8)
        self.priceAmountWarning.info = (None, None)
        self.priceAmountWarning.GetHint = self.GetWarningHint

    def ConstructQtyBg(self):
        if getattr(self.qtyEdit, 'warningBg', None):
            return
        warningBg = Fill(bgParent=self.qtyEdit, color=(1, 0, 0, 0.3))
        self.qtyEdit.warningBg = warningBg

    def ConstructTotalStrikethroughLine(self):
        if self.totalStrikethroughLine:
            return
        self.totalStrikethroughLine = Line(parent=self.totalCont,
                                           align=uiconst.CENTERRIGHT,
                                           pos=(2, 0, 0, 1),
                                           idx=0,
                                           color=(1, 1, 1, 0.8))

    def ChangeTotalStrikethroughDisplay(self, display=False):
        if self.totalStrikethroughLine:
            self.totalStrikethroughLine.display = display

    def ChangePriceAmountWarningDisplay(self, display=False):
        if self.priceAmountWarning:
            self.priceAmountWarning.display = display
        if getattr(self.qtyEdit, 'warningBg', None):
            self.qtyEdit.warningBg.display = display

    def GetWarningHint(self):
        estimatedSellCount, qtyToSell = self.priceAmountWarning.info
        if estimatedSellCount is None or qtyToSell is None:
            return
        txt = GetByLabel('UI/Market/MarketQuote/QtyPriceWarning',
                         estimatedSellNum=int(estimatedSellCount),
                         tryingToSellNum=qtyToSell)
        return txt
Ejemplo n.º 2
0
class ImpactVisualizer():
    def __init__(self):
        self.name = 'Impact Visualizer'
        self.windowID = 'ImpactVisualizer_ ' + self.name
        self.damageLocatorID = 0
        self.impactVelocity = [0.0, -1000.0, 0.0]
        self.impactObjectMass = 100000
        self.shipId = None
        self.shipInput = None
        self.impactArrow = None
        self.arrowModel = None
        self.impactArrowBoundingRadius = 0.0
        self.impactRotation = geo2.QuaternionRotationSetYawPitchRoll(
            0.0, math.pi, 0.0)
        self.damageLocatorPos = (0.0, 0.0, 0.0)
        self.arrowPositionUpdater = None
        self.lockVelocity = True
        self.randomize = False
        self.arrowModel = trinity.Load('res:/Model/global/impactDirection.red')

    def SetupImpactArrow(self):
        self.impactArrow = trinity.EveRootTransform()
        self.impactArrow.name = 'DebugImpactArrow'
        self.impactArrow.children.append(self.arrowModel)
        self.arrowPositionUpdater = ArrowPositionUpdater(self.impactArrow)

    def GetImpactArrowBoundingRadius(self):
        geometry = self.arrowModel.mesh.geometry
        geometry.RecalculateBoundingSphere()
        self.impactArrowBoundingRadius = geometry.GetBoundingSphere(0)[1]

    def _OnClose(self):
        self.RemoveImpactArrowFromScene()
        self.arrowPositionUpdater.Stop()

    def GetBall(self, ballID=None):
        if ballID is None:
            ballID = self.shipId
        return sm.GetService('michelle').GetBall(ballID)

    def ShowUI(self):
        self.SetupImpactArrow()
        uicontrols.Window.CloseIfOpen(windowID=self.windowID)
        wnd = uicontrols.Window.Open(windowID=self.windowID)
        wnd.SetTopparentHeight(0)
        wnd.SetMinSize([500, 100])
        wnd.SetCaption(self.name)
        wnd._OnClose = self._OnClose
        main = wnd.GetMainArea()
        headerCont = Container(name='headerCont',
                               parent=main,
                               align=uiconst.TOTOP,
                               height=30,
                               padBottom=10)
        bottomCont = Container(name='bottomCont',
                               parent=main,
                               align=uiconst.TOBOTTOM,
                               height=30)
        self.shipIdLabel = EveLabelSmall(name='shipIDLabel',
                                         align=uiconst.CENTER,
                                         parent=headerCont,
                                         text='Ship ID: %s' % self.shipId)
        Button(name='apply_button',
               align=uiconst.CENTER,
               parent=bottomCont,
               label='Apply Physical Impact',
               func=self._OnApplyPhysicalImpact)
        mainContainer = GridContainer(name='mainCont',
                                      parent=main,
                                      align=uiconst.TOALL,
                                      columns=4,
                                      rows=3)
        container = Container(name='impactVelocityLockAndLabel',
                              align=uiconst.TOALL,
                              parent=mainContainer,
                              padRight=10)
        self.lockVelocityButton = ButtonIcon(
            name='MyButtonIcon',
            parent=container,
            align=uiconst.TOPLEFT,
            width=16,
            height=16,
            iconSize=16,
            padLeft=10,
            texturePath='res:/UI/Texture/Icons/bookmark.png',
            func=self.OnLockVelocity)
        EveLabelSmall(name='impactVelocity',
                      align=uiconst.TORIGHT,
                      parent=container,
                      padRight=10,
                      text='Impact Velocity')
        self.impactVelocityXInput = SinglelineEdit(
            name='xVelocity',
            align=uiconst.TOTOP,
            label='X',
            parent=mainContainer,
            padRight=10,
            setvalue=str(self.impactVelocity[0]),
            OnFocusLost=self.OnSetImpactVelocityX,
            OnReturn=self.OnSetImpactVelocityX)
        self.impactVelocityYInput = SinglelineEdit(
            name='yVelocity',
            align=uiconst.TOTOP,
            label='Y',
            parent=mainContainer,
            padRight=10,
            setvalue=str(self.impactVelocity[1]),
            OnFocusLost=self.OnSetImpactVelocityY,
            OnReturn=self.OnSetImpactVelocityY)
        self.impactVelocityZInput = SinglelineEdit(
            name='zVelocity',
            align=uiconst.TOTOP,
            label='Z',
            parent=mainContainer,
            padRight=10,
            setvalue=str(self.impactVelocity[2]),
            OnFocusLost=self.OnSetImpactVelocityZ,
            OnReturn=self.OnSetImpactVelocityZ)
        EveLabelSmall(name='shipIDInputLabel',
                      parent=mainContainer,
                      align=uiconst.TORIGHT,
                      padRight=10,
                      text='Ship ID')
        self.shipInput = SinglelineEdit(name='shipIdInput',
                                        parent=mainContainer,
                                        align=uiconst.TOTOP,
                                        padRight=10,
                                        setvalue=str(session.shipid),
                                        OnFocusLost=self.OnSetShipId,
                                        OnReturn=self.OnSetShipId)
        EveLabelSmall(name='damageLocatorLabel',
                      align=uiconst.TORIGHT,
                      padRight=10,
                      parent=mainContainer,
                      text='Damage Locator')
        self.damageLocatorInput = SinglelineEdit(
            name='damageLocator',
            align=uiconst.TOTOP,
            label='',
            parent=mainContainer,
            padRight=10,
            setvalue=str(self.damageLocatorID),
            ints=(0, 0),
            OnChange=self.OnSetDamageLocator)
        EveLabelSmall(name='impactMassLabel',
                      align=uiconst.TORIGHT,
                      padRight=10,
                      parent=mainContainer,
                      text='Impact Mass')
        self.impactMassInput = SinglelineEdit(name='impactMass',
                                              align=uiconst.TOTOP,
                                              label='',
                                              parent=mainContainer,
                                              padRight=10,
                                              setvalue=str(
                                                  self.impactObjectMass),
                                              OnChange=self.OnSetImpactMass)
        self.randomizeDL = Checkbox(name='myCheckbox',
                                    parent=mainContainer,
                                    text='Randomize Damage Locators',
                                    checked=self.randomize,
                                    callback=self.OnRandomize)
        self.AddImpactArrowToScene()
        self.OnSetShipId()

    def OnSetShipId(self, *args):
        try:
            shipId = long(self.shipInput.GetValue())
        except ValueError:
            print "Could not set shipId to '%s'" % self.shipInput.GetValue()
            return

        if self.shipId == shipId:
            return
        if sm.GetService('michelle').GetBall(shipId) is None:
            print "No ball with id '%d' found in ballpark" % shipId
            return
        print 'Setting ship ID to %d' % shipId
        self.shipId = shipId
        self.shipIdLabel.SetText('Ship ID: %s' % self.shipId)
        self.arrowPositionUpdater.SetBall(self.GetBall())
        self.damageLocatorInput.IntMode(
            minint=0, maxint=len(self.GetBall().model.damageLocators))
        if len(self.GetBall().model.damageLocators) >= self.damageLocatorID:
            self.damageLocatorInput.SetValue(str(self.damageLocatorID))
        else:
            self.damageLocatorInput.SetValue(str(0))
        self.OnSetDamageLocator()

    def OnSetImpactVelocityX(self, *args):
        self.impactVelocity = (float(self.impactVelocityXInput.GetValue()),
                               self.impactVelocity[1], self.impactVelocity[2])
        self.arrowPositionUpdater.SetArrowDirection(self.impactVelocity)

    def OnSetImpactVelocityY(self, *args):
        self.impactVelocity = (self.impactVelocity[0],
                               float(self.impactVelocityYInput.GetValue()),
                               self.impactVelocity[2])
        self.arrowPositionUpdater.SetArrowDirection(self.impactVelocity)

    def OnSetImpactVelocityZ(self, *args):
        self.impactVelocity = (self.impactVelocity[0], self.impactVelocity[1],
                               float(self.impactVelocityZInput.GetValue()))
        self.arrowPositionUpdater.SetArrowDirection(self.impactVelocity)

    def OnLockVelocity(self, *args):
        self.lockVelocity = not self.lockVelocity
        if self.lockVelocity:
            self.lockVelocityButton.SetRotation(0)
        else:
            self.lockVelocityButton.SetRotation(-20)

    def OnSetDamageLocator(self, *args):
        self.damageLocatorID = int(self.damageLocatorInput.GetValue())
        self.arrowPositionUpdater.SetDamageLocator(self.damageLocatorID)
        if not self.lockVelocity:
            _, rotation = self.GetBall().model.damageLocators[
                self.damageLocatorID]
            self.impactVelocity = geo2.QuaternionTransformVector(
                rotation, (0.0, geo2.Vec3Length(self.impactVelocity), 0.0))
            self.impactVelocity = (-self.impactVelocity[0],
                                   -self.impactVelocity[1],
                                   -self.impactVelocity[2])
            self.impactVelocityXInput.SetValue(str(self.impactVelocity[0]))
            self.impactVelocityYInput.SetValue(str(self.impactVelocity[1]))
            self.impactVelocityZInput.SetValue(str(self.impactVelocity[2]))
            self.arrowPositionUpdater.SetArrowDirection(self.impactVelocity)

    def OnSetImpactMass(self, *args):
        self.impactObjectMass = float(self.impactMassInput.GetValue())

    def OnRandomize(self, *args):
        self.randomize = not self.randomize
        if self.randomize and self.lockVelocity:
            self.OnLockVelocity()

    def RemoveImpactArrowFromScene(self):
        scene = sm.GetService('sceneManager').GetActiveScene()
        objectsToRemove = []
        for o in scene.objects:
            if o.name == 'DebugImpactArrow':
                objectsToRemove.append(o)

        for o in objectsToRemove:
            scene.objects.remove(o)

    def AddImpactArrowToScene(self):
        scene = sm.GetService('sceneManager').GetActiveScene()
        scene.objects.append(self.impactArrow)

    def _OnApplyPhysicalImpact(self, *args):
        if self.randomize:
            newDamageLocatorID = random.randint(
                0,
                len(self.GetBall().model.damageLocators) - 1)
            while newDamageLocatorID == self.damageLocatorID:
                newDamageLocatorID = random.randint(
                    0,
                    len(self.GetBall().model.damageLocators) - 1)

            self.damageLocatorID = newDamageLocatorID
            self.damageLocatorInput.SetValue(str(self.damageLocatorID))
            self.OnSetDamageLocator()
        sm.GetService('michelle').GetBall(
            self.shipId).ApplyTorqueAtDamageLocator(self.damageLocatorID,
                                                    self.impactVelocity,
                                                    self.impactObjectMass)
Ejemplo n.º 3
0
class PurchaseDetailsPanel(BasePurchasePanel):
    default_name = 'purchaseDetailsPanel'

    def ApplyAttributes(self, attributes):
        super(PurchaseDetailsPanel, self).ApplyAttributes(attributes)
        self.button = None
        self.offer = attributes.offer
        self.aurumBalance = attributes.aurumBalance
        self.buyOfferCallback = attributes.buyOfferCallback
        self.previewCallback = attributes.previewCallback
        self.CreateProductLayout(self.offer)
        self.CreateBuyLayout(self.offer, self.aurumBalance)

    def CreateProductLayout(self, offer):
        productContainer = Container(name='productContainer',
                                     parent=self,
                                     align=uiconst.TOTOP,
                                     height=PRODUCTSCROLL_PANEL_HEIGHT)
        productScroll = ScrollContainer(parent=productContainer,
                                        align=uiconst.TOALL,
                                        padTop=16)
        productQuantities = GetSortedTokens(offer.productQuantities)
        for typeID, quantity in productQuantities:
            VgsDetailProduct(parent=productScroll,
                             typeID=typeID,
                             quantity=quantity,
                             onClick=self.previewCallback)

    def CreateBuyLayout(self, offer, aurumBalance):
        self.buyContainer = Container(name='buyContainer',
                                      parent=self,
                                      align=uiconst.TOTOP,
                                      height=BUY_PANEL_HEIGHT)
        self.priceLabel = AurLabelLarge(parent=self.buyContainer,
                                        align=uiconst.TOLEFT,
                                        amount=offer.price,
                                        baseAmount=offer.basePrice,
                                        padding=(10, 7, 0, 6))
        self.button = DetailButton(parent=self.buyContainer,
                                   align=uiconst.TORIGHT,
                                   left=TEXT_PADDING,
                                   padTop=8,
                                   padBottom=8)
        self.UpdateButton(offer.price)
        self.quantityEdit = SinglelineEdit(
            parent=self.buyContainer,
            integermode=True,
            width=40,
            fontsize=VGS_FONTSIZE_MEDIUM,
            align=uiconst.TORIGHT,
            left=TEXT_PADDING,
            padTop=6,
            padBottom=10,
            bgColor=TAG_COLOR,
            OnChange=self.OnQuantityChange,
            maxLength=2,
            hint=localization.GetByLabel('UI/Common/Quantity'))
        self.quantityEdit.IntMode(minint=QUANTITY_MIN, maxint=QUANTITY_MAX)
        self.quantityEdit.sr.background.Hide()

    def UpdateButton(self, offerPrice):
        if self.aurumBalance >= offerPrice:
            buttonLabel = localization.GetByLabel(
                'UI/VirtualGoodsStore/OfferDetailBuyNowButton')
            buttonFunc = self.OnBuyClick
            color = BUY_BUTTON_COLOR
        else:
            buttonLabel = localization.GetByLabel(
                'UI/VirtualGoodsStore/BuyAurOnline')
            buttonFunc = self._BuyAurum
            color = BUY_AUR_BUTTON_COLOR
        self.button.OnClick = buttonFunc
        self.button.SetText(buttonLabel)
        self.button.color.SetRGB(*color)

    def OnQuantityChange(self, text):
        try:
            quantity = int(text)
            quantity = max(QUANTITY_MIN, min(quantity, QUANTITY_MAX))
        except ValueError:
            quantity = QUANTITY_MIN

        newOfferPrice = self.offer.price * quantity
        self.priceLabel.SetAmount(newOfferPrice,
                                  self.offer.basePrice * quantity)
        self.UpdateButton(newOfferPrice)

    def _BuyAurum(self):
        sm.GetService('audio').SendUIEvent('store_aur')
        sm.GetService('viewState').GetView(
            ViewState.VirtualGoodsStore)._LogBuyAurum('DetailButton')
        uicore.cmd.BuyAurumOnline()

    def OnBuyClick(self, *args):
        logger.debug('OnBuyClick %s' % (self.offer, ))
        sm.GetService('audio').SendUIEvent('store_buy')
        self.button.Disable()
        self.buyOfferCallback(self.offer,
                              quantity=self.quantityEdit.GetValue())
Ejemplo n.º 4
0
class SellItemContainer(Container):
    __guid__ = 'uicls.SellItemContainer'
    default_height = 40
    default_align = uiconst.TOTOP
    default_state = uiconst.UI_NORMAL

    def ApplyAttributes(self, attributes):
        Container.ApplyAttributes(self, attributes)
        self.parentFunc = attributes.parentFunc
        self.padding = (0, 2, 0, 2)
        self.item = attributes.item
        self.singleton = self.item.singleton
        self.parentEditFunc = attributes.editFunc
        self.typeID = self.item.typeID
        self.itemID = self.item.itemID
        self.invType = cfg.invtypes.Get(self.typeID)
        self.itemName = self.invType.name
        self.brokersFee = 0.0
        self.salesTax = 0.0
        self.totalSum = 0.0
        self.quote = sm.GetService('marketQuote')
        self.limits = self.quote.GetSkillLimits()
        self.stationID, officeFolderID, officeID = sm.GetService(
            'invCache').GetStationIDOfficeFolderIDOfficeIDOfItem(self.item)
        self.located = None
        if officeFolderID is not None:
            self.located = [officeFolderID, officeID]
        station = sm.GetService('ui').GetStation(self.stationID)
        self.solarSystemID = station.solarSystemID
        self.regionID = self.GetRegionID(self.stationID)
        self.averagePrice = self.quote.GetAveragePrice(self.typeID)
        self.bestBid = self.quote.GetBestBid(self.typeID,
                                             locationID=self.solarSystemID)
        self.GetBestPrice()
        self.deltaCont = Container(parent=self,
                                   align=uiconst.TORIGHT,
                                   width=30)
        theRestCont = Container(parent=self, align=uiconst.TOALL)
        self.totalCont = Container(parent=theRestCont,
                                   align=uiconst.TORIGHT_PROP,
                                   width=0.3)
        self.priceCont = Container(parent=theRestCont,
                                   align=uiconst.TORIGHT_PROP,
                                   width=0.22)
        self.qtyCont = Container(parent=theRestCont,
                                 align=uiconst.TORIGHT_PROP,
                                 width=0.15)
        self.itemCont = Container(parent=theRestCont,
                                  align=uiconst.TORIGHT_PROP,
                                  width=0.33)
        self.deleteCont = Container(parent=self.itemCont,
                                    align=uiconst.TORIGHT,
                                    width=24)
        self.deleteButton = ButtonIcon(
            texturePath='res:/UI/Texture/Icons/73_16_210.png',
            pos=(0, 0, 16, 16),
            align=uiconst.CENTERRIGHT,
            parent=self.deleteCont,
            hint=GetByLabel('UI/Generic/RemoveItem'),
            idx=0,
            func=self.RemoveItem)
        self.deleteCont.display = False
        self.textCont = Container(parent=self.itemCont, align=uiconst.TOALL)
        self.errorBg = ErrorFrame(bgParent=self)
        self.DrawItem()
        self.DrawQty()
        self.DrawPrice()
        self.DrawTotal()
        self.DrawDelta()
        self.GetTotalSum()
        self.GetBrokersFee()
        self.GetSalesTax()
        self.ShowNoSellOrders()

    def RemoveItem(self, *args):
        self.parentFunc(self, *args)

    def GetRegionID(self, stationID):
        regionID = cfg.evelocations.Get(stationID).Station().regionID
        return regionID

    def ShowNoSellOrders(self):
        wnd = SellItems.GetIfOpen()
        if not wnd:
            return
        if wnd.durationCombo.GetValue() == 0 and self.bestBid is None:
            uicore.animations.FadeIn(self.errorBg, 0.35, duration=0.3)

    def HideNoSellOrders(self):
        uicore.animations.FadeOut(self.errorBg, duration=0.3)

    def DrawQty(self):
        qty = self.item.stacksize
        self.qtyEdit = SinglelineEdit(name='qtyEdit',
                                      parent=self.qtyCont,
                                      align=uiconst.TOTOP,
                                      top=11,
                                      padLeft=4)
        self.qtyEdit.IntMode(*(1, long(qty)))
        self.qtyEdit.SetValue(qty)
        self.qtyEdit.OnChange = self.OnChange
        self.qtyEdit.hint = GetByLabel('UI/Common/Quantity')

    def DrawTotal(self):
        self.totalLabel = EveLabelMediumBold(text=self.totalSum,
                                             parent=self.totalCont,
                                             left=4,
                                             align=uiconst.CENTERRIGHT,
                                             state=uiconst.UI_NORMAL,
                                             autoFadeSides=35)
        self.totalLabel.hint = GetByLabel('UI/Market/MarketQuote/AskTotal')

    def DrawPrice(self):
        self.priceEdit = SinglelineEdit(name='priceEdit',
                                        parent=self.priceCont,
                                        align=uiconst.TOTOP,
                                        top=11,
                                        padLeft=8)
        self.priceEdit.FloatMode(*(0.01, 9223372036854.0, 2))
        self.priceEdit.SetValue(self.bestPrice)
        self.priceEdit.OnChange = self.OnChange
        self.priceEdit.hint = GetByLabel('UI/Market/MarketQuote/AskPrice')

    def DrawDelta(self):
        self.deltaContainer = DeltaContainer(parent=self.deltaCont,
                                             delta=self.GetDelta(),
                                             func=self.OpenMarket,
                                             align=uiconst.CENTERRIGHT)
        self.deltaContainer.LoadTooltipPanel = self.LoadDeltaTooltip
        self.UpdateDelta()

    def OnMouseEnter(self, *args):
        self.mouseovertimer = AutoTimer(1, self.UpdateMouseOver)
        self.deleteCont.display = True

    def UpdateMouseOver(self):
        mo = uicore.uilib.mouseOver
        if mo in (self.itemNameLabel, self, self.deleteCont, self.deleteButton,
                  self.totalLabel):
            return
        self.mouseovertimer = None
        self.deleteCont.display = False

    def Close(self, *args):
        self.mouseovertimer = None
        self.parentFunc = None
        Container.Close(self, *args)

    def OpenMarket(self, *args):
        sm.GetService('marketutils').ShowMarketDetails(self.typeID, None)
        wnd = SellItems.GetIfOpen()
        wnd.SetOrder(0)

    def LoadDeltaTooltip(self, tooltipPanel, *args):
        tooltipPanel.LoadGeneric2ColumnTemplate()
        tooltipPanel.cellPadding = (4, 1, 4, 1)
        tooltipPanel.AddLabelLarge(
            text=GetByLabel('UI/Market/MarketQuote/AskPrice'))
        tooltipPanel.AddLabelLarge(text=FmtISK(self.priceEdit.GetValue()),
                                   align=uiconst.CENTERRIGHT)
        tooltipPanel.AddSpacer(1, 8, colSpan=tooltipPanel.columns)
        tooltipPanel.AddLabelMedium(
            text='%s %s' %
            (GetByLabel('UI/Market/MarketQuote/RegionalAdverage'),
             self.GetDeltaText()))
        tooltipPanel.AddLabelMedium(text=FmtISK(self.averagePrice),
                                    align=uiconst.CENTERRIGHT)
        tooltipPanel.AddLabelMedium(
            text=GetByLabel('UI/Market/MarketQuote/BestRegional'))
        bestMatch = tooltipPanel.AddLabelMedium(text='',
                                                align=uiconst.CENTERRIGHT)
        bestMatchDetails = tooltipPanel.AddLabelSmall(
            text='', align=uiconst.CENTERRIGHT, colSpan=tooltipPanel.columns)
        if not self.bestBid:
            bestMatch.text = GetByLabel('UI/Contracts/ContractEntry/NoBids')
            bestMatchDetails.text = GetByLabel(
                'UI/Market/MarketQuote/ImmediateWillFail')
            bestMatch.color = (1.0, 0.275, 0.0, 1.0)
            bestMatchDetails.color = (1.0, 0.275, 0.0, 1.0)
        else:
            bestMatch.text = FmtISK(self.bestBid.price)
            bestMatchText, volRemaining = self.GetBestMatchText()
            bestMatchDetails.text = bestMatchText
            bestMatchDetails.SetAlpha(0.6)
            if volRemaining:
                vol = tooltipPanel.AddLabelSmall(text=volRemaining,
                                                 align=uiconst.CENTERRIGHT,
                                                 colSpan=tooltipPanel.columns)
                vol.SetAlpha(0.6)

    def GetDeltaText(self):
        price = self.GetPrice()
        percentage = (price - self.averagePrice) / self.averagePrice
        if percentage < 0:
            color = '<color=0xffff5050>'
        else:
            color = '<color=0xff00ff00>'
        percText = '%s%s</color>' % (
            color,
            GetByLabel('UI/Common/Percentage',
                       percentage=FmtAmt(percentage * 100, showFraction=1)))
        return percText

    def GetBestMatchText(self):
        jumps = max(self.bestBid.jumps - max(0, self.bestBid.range), 0)
        minVolumeText = None
        if jumps == 0 and self.stationID == self.bestBid.stationID:
            jumpText = GetByLabel('UI/Market/MarketQuote/ItemsInSameStation')
        else:
            jumpText = GetByLabel('UI/Market/MarketQuote/JumpsFromThisSystem',
                                  jumps=jumps)
        if self.bestBid.minVolume > 1 and self.bestBid.volRemaining >= self.bestBid.minVolume:
            minVolumeText = GetByLabel(
                'UI/Market/MarketQuote/SimpleMinimumVolume',
                min=self.bestBid.minVolume)
        return (GetByLabel('UI/Market/MarketQuote/SellQuantity',
                           volRemaining=long(self.bestBid.volRemaining),
                           jumpText=jumpText), minVolumeText)

    def GetDelta(self):
        price = self.GetPrice()
        percentage = (price - self.averagePrice) / self.averagePrice
        return percentage

    def UpdateDelta(self):
        delta = self.GetDelta()
        self.deltaContainer.UpdateDelta(delta)

    def DrawItem(self):
        iconCont = Container(parent=self.textCont,
                             align=uiconst.TOLEFT,
                             width=32,
                             padding=4)
        self.icon = Icon(parent=iconCont,
                         typeID=self.typeID,
                         state=uiconst.UI_DISABLED)
        self.icon.SetSize(32, 32)
        itemName = GetByLabel('UI/Contracts/ContractsWindow/ShowInfoLink',
                              showInfoName=self.itemName,
                              info=('showinfo', self.typeID, self.item.itemID))
        self.itemNameLabel = Label(text=itemName,
                                   parent=self.textCont,
                                   left=40,
                                   align=uiconst.CENTERLEFT,
                                   state=uiconst.UI_NORMAL,
                                   autoFadeSides=35,
                                   fontsize=12)

    def GetBestPrice(self):
        bestMatchableBid = self.quote.GetBestMatchableBid(
            self.typeID, self.stationID, self.item.stacksize)
        if bestMatchableBid:
            self.bestPrice = bestMatchableBid.price
        else:
            self.bestPrice = self.averagePrice

    def GetBrokersFee(self):
        fee = self.quote.BrokersFee(self.stationID, self.totalSum,
                                    self.limits['fee'])
        feeAmount = fee.amt
        self.brokersFee = feeAmount

    def GetSalesTax(self):
        tax = self.totalSum * self.limits['acc']
        self.salesTax = tax

    def GetTotalSum(self):
        price = self.GetPrice()
        qty = self.GetQty()
        self.totalSum = price * qty
        self.totalLabel.text = FmtISK(self.totalSum)
        return self.totalSum

    def OnChange(self, *args):
        self.GetTotalSum()
        self.GetBrokersFee()
        self.GetSalesTax()
        self.UpdateDelta()
        if self.parentEditFunc:
            self.parentEditFunc(args)

    def GetPrice(self):
        price = self.priceEdit.GetValue()
        return price

    def GetQty(self):
        qty = self.qtyEdit.GetValue()
        return qty

    def MakeSingle(self):
        self.height = 80
        self.qtyCont.width = 0
        self.itemCont.width = 0.42
        self.totalCont.width = 0.36
        self.itemNameLabel.fontsize = 14
        self.totalLabel.fontsize = 14
        self.itemNameLabel.left = 72
        self.icon.SetSize(64, 64)
        self.icon.top = 4
        self.priceEdit.padLeft = 4
        self.priceEdit.align = uiconst.TOBOTTOM
        self.qtyEdit.top = 20
        self.priceEdit.top = 20
        self.qtyEdit.SetParent(self.priceCont)

    def RemoveSingle(self):
        self.height = 40
        self.qtyCont.width = 0.15
        self.itemCont.width = 0.33
        self.totalCont.width = 0.3
        self.itemNameLabel.fontsize = 12
        self.totalLabel.fontsize = 12
        self.itemNameLabel.left = 40
        self.icon.SetSize(32, 32)
        self.icon.top = 0
        self.priceEdit.align = uiconst.TOTOP
        self.qtyEdit.top = 11
        self.priceEdit.top = 11
        self.priceEdit.padLeft = 8
        self.qtyEdit.SetParent(self.qtyCont)
Ejemplo n.º 5
0
class BasePinContainer(Window):
    __guid__ = 'planet.ui.BasePinContainer'
    __notifyevents__ = ['OnRefreshPins', 'ProcessColonyDataSet']
    default_height = 185
    default_width = 300
    default_minSize = (300, 185)
    default_maxSize = (450, None)
    default_state = uiconst.UI_NORMAL
    default_align = uiconst.TOPLEFT
    default_name = 'BasePinContainer'
    default_opacity = 0.0
    default_topParentHeight = 0
    default_isCollapseable = False
    default_isPinable = False
    default_isStackable = False
    default_isMinimizable = False
    default_windowID = 'PlanetPinWindow'
    INFO_CONT_HEIGHT = 70

    def GetBaseHeight(self):
        return self.main.height + 26

    def ApplyAttributes(self, attributes):
        Window.ApplyAttributes(self, attributes)
        self.main = ContainerAutoSize(parent=self.sr.main,
                                      name='main',
                                      padding=3,
                                      state=uiconst.UI_PICKCHILDREN,
                                      align=uiconst.TOTOP,
                                      alignMode=uiconst.TOTOP)
        self.planetUISvc = sm.GetService('planetUI')
        self.planetSvc = sm.GetService('planetSvc')
        self.pin = attributes.Get('pin', None)
        self.uiEffects = uicls.UIEffects()
        self.showingActionContainer = False
        self.currentRoute = None
        self.showNext = None
        self.lastCalled = None
        self.commodityToRoute = None
        self.buttonTextValue = ''
        infoCont = Container(parent=self.main,
                             name='infoCont',
                             padding=5,
                             align=uiconst.TOTOP,
                             height=self.INFO_CONT_HEIGHT)
        self.infoContLeft = Container(name='leftCol',
                                      parent=infoCont,
                                      align=uiconst.TOLEFT_PROP,
                                      width=0.5)
        self.infoContRight = Container(name='rightCol',
                                       parent=infoCont,
                                       align=uiconst.TOLEFT_PROP,
                                       width=0.5)
        self._GetInfoCont()
        self._UpdateInfoCont()
        self.buttonCont = GridContainer(parent=self.main,
                                        name='buttonCont',
                                        height=40,
                                        align=uiconst.TOTOP,
                                        padding=(-1, 0, -1, 0))
        BumpedUnderlay(bgParent=self.buttonCont)
        self.buttonCont.lines = 1
        self.buttonCont.columns = 6
        self.buttonTextCont = self._DrawAlignTopCont(22, 'buttonTextCont')
        self.buttonText = EveLabelSmall(parent=self.buttonTextCont,
                                        align=uiconst.CENTER,
                                        color=(1.0, 1.0, 1.0, 1.0),
                                        state=uiconst.UI_NORMAL)
        self.buttonTextCont.height = max(22, self.buttonText.textheight)
        self.actionCont = Container(parent=self.sr.main,
                                    name='actionCont',
                                    padding=(6, 0, 6, 6),
                                    clipChildren=True)
        self.SetCaption(self._GetPinName())
        self.main.SetSizeAutomatically()
        self.height = self.GetBaseHeight()
        self.LoadActionButtons(self._GetActionButtons())
        uicore.animations.FadeTo(self, 0.0, 1.0, duration=0.3)
        self.updateInfoContTimer = base.AutoTimer(100, self._UpdateInfoCont)
        sm.GetService('audio').SendUIEvent(
            'wise:/msg_pi_pininteraction_open_play')
        self.ResizeActionCont(None)

    def ShowDefaultPanel(self):
        if hasattr(self, 'defaultPanel'):
            self.ShowPanel(self.defaultPanel, self.defaultPanelID)

    def _GetPinName(self):
        return planetCommon.GetGenericPinName(self.pin.typeID, self.pin.id)

    def _GetInfoCont(self):
        pass

    def _GetActionButtons(self):
        btns = [
            util.KeyVal(id=planetCommonUI.PANEL_STATS,
                        panelCallback=self.PanelShowStats),
            util.KeyVal(id=planetCommonUI.PANEL_LINKS,
                        panelCallback=self.PanelShowLinks),
            util.KeyVal(id=planetCommonUI.PANEL_ROUTES,
                        panelCallback=self.PanelShowRoutes),
            util.KeyVal(id=planetCommonUI.PANEL_DECOMMISSION,
                        panelCallback=self.PanelDecommissionPin)
        ]
        return btns

    def ShowPanel(self, panelCallback, panelID, *args):
        _, label = planetCommonUI.PANELDATA[panelID]
        name = localization.GetByLabel(label)
        self.buttonText.text = name
        self.buttonTextValue = name
        if self.showingActionContainer:
            self.showNext = panelCallback
            return
        self.showNext = None
        self.showingActionContainer = True
        self.actionCont.Flush()
        if self.lastCalled != name:
            if args:
                cont = panelCallback(*args)
            else:
                cont = panelCallback()
            if cont:
                cont.state = uiconst.UI_HIDDEN
                self.lastCalled = name
                cont.opacity = 0.0
                self.ResizeActionCont(panelID)
                cont.state = uiconst.UI_PICKCHILDREN
                self.uiEffects.MorphUI(cont,
                                       'opacity',
                                       1.0,
                                       time=250.0,
                                       float=1,
                                       maxSteps=1000)
                uicore.registry.SetFocus(cont)
        else:
            self.HideCurrentPanel()
        self.showingActionContainer = False
        if self.showNext:
            self.ShowPanel(self.showNext, panelID)

    def HideCurrentPanel(self):
        self.actionCont.Flush()
        self.ResizeActionCont()
        self.lastCalled = None
        self.buttonTextValue = ''

    def _DrawAlignTopCont(self,
                          height,
                          name,
                          padding=(0, 0, 0, 0),
                          state=uiconst.UI_PICKCHILDREN):
        return Container(parent=self.main,
                         name=name,
                         pos=(0, 0, 0, height),
                         padding=padding,
                         state=state,
                         align=uiconst.TOTOP)

    def OnIconButtonMouseEnter(self, iconButton, *args):
        ButtonIcon.OnMouseEnter(iconButton, *args)
        self.buttonText.text = iconButton.name

    def OnIconButtonMouseExit(self, iconButton, *args):
        ButtonIcon.OnMouseExit(iconButton, *args)
        self.buttonText.text = self.buttonTextValue

    def LoadActionButtons(self, buttons):
        iconSize = 32
        w = self.width - 6
        maxIcons = 7.0
        n = float(len(buttons))
        pad = 5 + 1 * iconSize * (1.0 - n / maxIcons)
        w -= 2 * pad
        space = (w - n * iconSize) / n
        self.buttonCont.columns = len(buttons)
        for i, b in enumerate(buttons):
            iconPath, cerberusPath = planetCommonUI.PANELDATA[b.id]
            panelName = localization.GetByLabel(cerberusPath)
            if i == 0:
                self.defaultPanel = b.panelCallback
                self.defaultPanelID = b.id
            cont = Container(name=panelName, parent=self.buttonCont)
            ib = ButtonIcon(texturePath=iconPath,
                            parent=cont,
                            align=uiconst.CENTER,
                            name=panelName,
                            hint=b.Get('hint', ''),
                            width=iconSize,
                            height=iconSize,
                            iconSize=iconSize,
                            func=self._OnIconButtonClicked,
                            args=(b.panelCallback, b.id))
            ib.OnMouseEnter = (self.OnIconButtonMouseEnter, ib)
            ib.OnMouseExit = (self.OnIconButtonMouseExit, ib)

    def _OnIconButtonClicked(self, panelCallback, panelID, *args):
        self.ShowPanel(panelCallback, panelID)

    def CloseByUser(self, *args):
        self.planetUISvc.CloseCurrentlyOpenContainer()

    def PanelShowLinks(self):
        cont = Container(parent=self.actionCont, state=uiconst.UI_HIDDEN)
        self.linkScroll = scroll = Scroll(parent=cont,
                                          name='linksScroll',
                                          align=uiconst.TOALL)
        self.linkScroll.sr.id = 'planetBasePinLinkScroll'
        self.LoadLinkScroll()
        btns = [[
            localization.GetByLabel('UI/PI/Common/CreateNew'),
            self._CreateNewLink, None
        ],
                [
                    localization.GetByLabel('UI/PI/Common/DeleteLink'),
                    self._DeleteLink, None
                ]]
        ButtonGroup(btns=btns, idx=0, parent=cont)
        return cont

    def LoadLinkScroll(self):
        scrolllist = []
        planet = sm.GetService('planetUI').GetCurrentPlanet()
        colony = planet.GetColony(session.charid)
        links = colony.colonyData.GetLinksForPin(self.pin.id)
        for linkedPinID in links:
            link = colony.GetLink(self.pin.id, linkedPinID)
            linkedPin = colony.GetPin(linkedPinID)
            distance = link.GetDistance()
            bandwidthUsed = link.GetBandwidthUsage()
            percentageUsed = 100 * (bandwidthUsed / link.GetTotalBandwidth())
            data = util.KeyVal()
            data.label = '%s<t>%s<t>%s' % (planetCommon.GetGenericPinName(
                linkedPin.typeID, linkedPin.id), util.FmtDist(distance),
                                           localization.GetByLabel(
                                               'UI/Common/Percentage',
                                               percentage=percentageUsed))
            data.hint = ''
            data.OnMouseEnter = self.OnLinkEntryHover
            data.OnMouseExit = self.OnLinkEntryExit
            data.OnDblClick = self.OnLinkListentryDblClicked
            data.id = (link.endpoint1.id, link.endpoint2.id)
            sortBy = linkedPinID
            scrolllist.append((sortBy, listentry.Get('Generic', data=data)))

        scrolllist = uiutil.SortListOfTuples(scrolllist)
        self.linkScroll.Load(
            contentList=scrolllist,
            noContentHint=localization.GetByLabel(
                'UI/PI/Common/NoLinksPresent'),
            headers=[
                localization.GetByLabel('UI/PI/Common/Destination'),
                localization.GetByLabel('UI/Common/Distance'),
                localization.GetByLabel('UI/PI/Common/CapacityUsed')
            ])

    def OnLinkListentryDblClicked(self, entry):
        myPinManager = sm.GetService('planetUI').myPinManager
        link = myPinManager.linksByPinIDs[entry.sr.node.id]
        for node in self.linkScroll.GetNodes():
            myPinManager.RemoveHighlightLink(node.id)

        sm.GetService('planetUI').OpenContainer(link)

    def OnLinkEntryHover(self, entry):
        node = entry.sr.node
        self.planetUISvc.myPinManager.HighlightLink(self.pin.id, node.id)

    def OnLinkEntryExit(self, entry):
        node = entry.sr.node
        self.planetUISvc.myPinManager.RemoveHighlightLink(node.id)

    def _CreateNewLink(self, *args):
        self.planetUISvc.myPinManager.SetLinkParent(self.pin.id)
        self.CloseByUser()

    def _DeleteLink(self, *args):
        selected = self.linkScroll.GetSelected()
        if len(selected) > 0:
            self.planetUISvc.myPinManager.RemoveLink(selected[0].id)
            self.LoadLinkScroll()

    def _DrawEditBox(self, parent, text):
        textHeight = uix.GetTextHeight(text,
                                       width=self.width - 30,
                                       fontsize=fontConst.EVE_MEDIUM_FONTSIZE)
        edit = Edit(setvalue=text,
                    parent=parent,
                    align=uiconst.TOTOP,
                    height=textHeight + 18,
                    top=-6,
                    hideBackground=1,
                    readonly=True)
        edit.scrollEnabled = False
        return edit

    def ResizeActionCont(self, panelID=None):
        if panelID:
            minHeight, maxHeight = planetCommonUI.PANEL_MIN_MAX_HEIGHT[panelID]
            if maxHeight:
                height = (minHeight + maxHeight) / 2
            else:
                height = minHeight
        else:
            height = minHeight = maxHeight = 0
        baseHeight = self.GetBaseHeight()
        uicore.animations.MorphScalar(self,
                                      'height',
                                      self.height,
                                      height + baseHeight,
                                      duration=0.3)
        self.SetMinSize((self.default_minSize[0], baseHeight + minHeight))
        if minHeight == maxHeight:
            self.SetFixedHeight(baseHeight + minHeight)
        elif maxHeight:
            self.SetFixedHeight(None)
            self.SetMaxSize((self.default_maxSize[0], baseHeight + maxHeight))
        else:
            self.SetFixedHeight(None)
            self.SetMaxSize((self.default_maxSize[0], None))

    def _UpdateInfoCont(self):
        pass

    def PanelShowStorage(self):
        cont = Container(parent=self.actionCont, state=uiconst.UI_HIDDEN)
        self.storageContentScroll = Scroll(parent=cont,
                                           name='storageContentsScroll',
                                           id='planetStorageContentsScroll')
        self.storageContentScroll.sr.fixedColumns = {'': 28}
        self.LoadStorageContentScroll()
        btns = [[
            localization.GetByLabel('UI/PI/Common/CreateRoute'),
            self._CreateRoute, 'storageContentScroll'
        ],
                [
                    localization.GetByLabel('UI/PI/Common/ExpeditedTransfer'),
                    self._CreateTransfer, None
                ]]
        self.createRouteButton = ButtonGroup(btns=btns, parent=cont, idx=0)
        return cont

    def LoadStorageContentScroll(self):
        scrolllist = []
        for typeID, amount in self.pin.contents.iteritems():
            data = util.KeyVal()
            volume = evetypes.GetVolume(typeID) * amount
            data.label = '<t>%s<t>%s<t>%s' % (evetypes.GetName(typeID), amount,
                                              volume)
            data.amount = amount
            data.typeID = typeID
            data.itemID = None
            data.getIcon = (True, )
            data.OnDblClick = self.OnStorageEntryDblClicked
            sortBy = amount
            scrolllist.append((sortBy, listentry.Get('Item', data=data)))

        scrolllist = uiutil.SortListOfTuples(scrolllist)
        self.storageContentScroll.Load(
            contentList=scrolllist,
            noContentHint=localization.GetByLabel(
                'UI/PI/Common/NoContentsPresent'),
            headers=[
                '',
                localization.GetByLabel('UI/PI/Common/Type'),
                localization.GetByLabel('UI/Common/Amount'),
                localization.GetByLabel('UI/Common/Volume')
            ])

    def OnStorageEntryDblClicked(self, entry):
        self._CreateRoute('storageContentScroll')

    def PanelShowProducts(self):
        cont = Container(parent=self.actionCont, state=uiconst.UI_HIDDEN)
        self.productScroll = Scroll(parent=cont, name='productsScroll')
        self.productScroll.sr.id = 'planetBasePinProductScroll'
        self.LoadProductScroll()
        btns = [[
            localization.GetByLabel('UI/PI/Common/CreateRoute'),
            self._CreateRoute, 'productScroll'
        ]]
        self.createRouteButton = ButtonGroup(btns=btns, parent=cont, idx=0)
        btns = [[
            localization.GetByLabel('UI/PI/Common/DeleteRoute'),
            self._DeleteRoute, ()
        ]]
        self.deleteRouteButton = ButtonGroup(btns=btns, parent=cont, idx=0)
        self.createRouteButton.state = uiconst.UI_HIDDEN
        self.deleteRouteButton.state = uiconst.UI_HIDDEN
        return cont

    def LoadProductScroll(self):
        scrolllist = []
        colony = self.planetUISvc.planet.GetColony(session.charid)
        if colony is None or colony.colonyData is None:
            raise RuntimeError(
                'Cannot load product scroll for pin on a planet that has no colony'
            )
        sourcedRoutes = colony.colonyData.GetSourceRoutesForPin(self.pin.id)
        routesByTypeID = {}
        for route in sourcedRoutes:
            typeID = route.GetType()
            if typeID not in routesByTypeID:
                routesByTypeID[typeID] = []
            routesByTypeID[typeID].append(route)

        for typeID, amount in self.pin.GetProductMaxOutput().iteritems():
            typeName = evetypes.GetName(typeID)
            for route in routesByTypeID.get(typeID, []):
                qty = route.GetQuantity()
                amount -= qty
                data = util.KeyVal(
                    label='%s<t>%s<t>%s' %
                    (qty, typeName,
                     localization.GetByLabel('UI/PI/Common/Routed')),
                    typeID=typeID,
                    itemID=None,
                    getIcon=True,
                    routeID=route.routeID,
                    OnMouseEnter=self.OnRouteEntryHover,
                    OnMouseExit=self.OnRouteEntryExit,
                    OnClick=self.OnProductEntryClicked,
                    OnDblClick=self.OnProductEntryDblClicked)
                scrolllist.append(listentry.Get('Item', data=data))

            if amount > 0:
                data = util.KeyVal()
                data.label = '%s<t>%s<t>%s' % (amount, evetypes.GetName(
                    typeID), localization.GetByLabel('UI/PI/Common/NotRouted'))
                data.typeID = typeID
                data.amount = amount
                data.itemID = None
                data.getIcon = True
                data.OnClick = self.OnProductEntryClicked
                data.OnDblClick = self.OnProductEntryDblClicked
                scrolllist.append(listentry.Get('Item', data=data))

        self.productScroll.Load(
            contentList=scrolllist,
            noContentHint=localization.GetByLabel(
                'UI/PI/Common/NoProductsPresent'),
            headers=[
                localization.GetByLabel('UI/Common/Amount'),
                localization.GetByLabel('UI/PI/Common/Type'), ''
            ])

    def OnProductEntryClicked(self, entry):
        node = entry.sr.node
        if node.Get('routeID', None) is None:
            self.createRouteButton.state = uiconst.UI_NORMAL
            self.deleteRouteButton.state = uiconst.UI_HIDDEN
        else:
            self.createRouteButton.state = uiconst.UI_HIDDEN
            self.deleteRouteButton.state = uiconst.UI_NORMAL

    def OnProductEntryDblClicked(self, entry):
        node = entry.sr.node
        if node.Get('routeID', None) is None:
            self._CreateRoute('productScroll')

    def _CreateRoute(self, scroll):
        selected = getattr(self, scroll).GetSelected()
        if len(selected) > 0:
            entry = selected[0]
            self.planetUISvc.myPinManager.EnterRouteMode(
                self.pin.id, entry.typeID)
            self.ShowPanel(self.PanelCreateRoute,
                           planetCommonUI.PANEL_CREATEROUTE, entry.typeID,
                           entry.amount)

    def SubmitRoute(self):
        if not getattr(self, 'routeAmountEdit', None):
            return
        sm.GetService('planetUI').myPinManager.CreateRoute(
            self.routeAmountEdit.GetValue())
        self.HideCurrentPanel()
        self.commodityToRoute = None

    def _DeleteRoute(self):
        selected = self.productScroll.GetSelected()
        if len(selected) > 0:
            entry = selected[0]
            if entry.routeID:
                self.planetUISvc.myPinManager.RemoveRoute(entry.routeID)
                self.LoadProductScroll()
                self.createRouteButton.state = uiconst.UI_HIDDEN
                self.deleteRouteButton.state = uiconst.UI_HIDDEN

    def _DeleteRouteFromEntry(self):
        if not hasattr(self, 'routeScroll'):
            return
        selected = self.routeScroll.GetSelected()
        if len(selected) > 0:
            entry = selected[0]
            if entry.routeID:
                self.planetUISvc.myPinManager.RemoveRoute(entry.routeID)
                self.LoadRouteScroll()
                self.uiEffects.MorphUI(self.routeInfo,
                                       'opacity',
                                       0.0,
                                       time=125.0,
                                       float=1,
                                       newthread=0,
                                       maxSteps=1000)

    def _CreateTransfer(self, *args):
        if sm.GetService('planetUI').GetCurrentPlanet().IsInEditMode():
            raise UserError('CannotTransferInEditMode')
        self.planetUISvc.myPinManager.EnterRouteMode(self.pin.id,
                                                     None,
                                                     oneoff=True)
        self.ShowPanel(self.PanelSelectTransferDest,
                       planetCommonUI.PANEL_TRANSFER)

    def PanelDecommissionPin(self):
        typeName = evetypes.GetName(self.pin.typeID)
        if evetypes.GetGroupID(self.pin.typeID) == const.groupCommandPins:
            text = localization.GetByLabel(
                'UI/PI/Common/DecommissionCommandPin', typeName=typeName)
        else:
            text = localization.GetByLabel('UI/PI/Common/DecommissionLink',
                                           typeName=typeName)
        cont = Container(parent=self.actionCont, state=uiconst.UI_HIDDEN)
        Label(parent=cont, text=text, align=uiconst.TOTOP)
        btns = [[
            localization.GetByLabel('UI/PI/Common/Proceed'),
            self._DecommissionSelf, None
        ]]
        ButtonGroup(btns=btns, idx=0, parent=cont)
        return cont

    def _DecommissionSelf(self, *args):
        sm.GetService('audio').SendUIEvent(
            'wise:/msg_pi_build_decommission_play')
        self.planetUISvc.myPinManager.RemovePin(self.pin.id)
        self.CloseByUser()

    def OnRouteEntryHover(self, entry):
        self.planetUISvc.myPinManager.ShowRoute(entry.sr.node.routeID)

    def OnRouteEntryExit(self, entry):
        self.planetUISvc.myPinManager.StopShowingRoute(entry.sr.node.routeID)

    def OnRefreshPins(self, pinIDs):
        if hasattr(
                self,
                'lastCalled') and self.lastCalled == localization.GetByLabel(
                    'UI/PI/Common/Storage'):
            self.LoadStorageContentScroll()

    def ProcessColonyDataSet(self, planetID):
        if self.planetUISvc.planetID != planetID:
            return
        self.pin = sm.GetService('planetSvc').GetPlanet(planetID).GetPin(
            self.pin.id)

    def PanelShowStats(self, *args):
        cont = Container(parent=self.actionCont,
                         align=uiconst.TOALL,
                         state=uiconst.UI_HIDDEN)
        self.statsScroll = scroll = Scroll(parent=cont, name='StatsScroll')
        scrolllist = self.GetStatsEntries()
        scroll.Load(contentList=scrolllist,
                    headers=[
                        localization.GetByLabel('UI/PI/Common/Attribute'),
                        localization.GetByLabel('UI/Common/Value')
                    ])
        return cont

    def GetStatsEntries(self):
        scrolllist = []
        if self.pin.GetCpuUsage() > 0:
            data = util.KeyVal(
                label='%s<t>%s' %
                (localization.GetByLabel('UI/PI/Common/CpuUsage'),
                 localization.GetByLabel('UI/PI/Common/TeraFlopsAmount',
                                         amount=self.pin.GetCpuUsage())))
            scrolllist.append(listentry.Get('Generic', data=data))
        if self.pin.GetCpuOutput() > 0:
            data = util.KeyVal(
                label='%s<t>%s' %
                (localization.GetByLabel('UI/PI/Common/CpuOutput'),
                 localization.GetByLabel('UI/PI/Common/TeraFlopsAmount',
                                         amount=self.pin.GetCpuOutput())))
            scrolllist.append(listentry.Get('Generic', data=data))
        if self.pin.GetPowerUsage() > 0:
            data = util.KeyVal(
                label='%s<t>%s' %
                (localization.GetByLabel('UI/PI/Common/PowerUsage'),
                 localization.GetByLabel('UI/PI/Common/MegaWattsAmount',
                                         amount=self.pin.GetPowerUsage())))
            scrolllist.append(listentry.Get('Generic', data=data))
        if self.pin.GetPowerOutput() > 0:
            data = util.KeyVal(
                label='%s<t>%s' %
                (localization.GetByLabel('UI/PI/Common/PowerOutput'),
                 localization.GetByLabel('UI/PI/Common/MegaWattsAmount',
                                         amount=self.pin.GetPowerOutput())))
            scrolllist.append(listentry.Get('Generic', data=data))
        return scrolllist

    def OnPlanetRouteWaypointAdded(self, currentRoute):
        self.currentRoute = currentRoute
        self.UpdatePanelCreateRoute()

    def PanelCreateRoute(self, typeID, amount):
        cont = Container(parent=self.actionCont,
                         pos=(0, 0, 0, 130),
                         align=uiconst.TOTOP,
                         state=uiconst.UI_HIDDEN)
        cont._OnClose = self.OnPanelCreateRouteClosed
        w = self.width - 5
        self.sourceMaxAmount = amount
        self.routeMaxAmount = amount
        self.commodityToRoute = typeID
        self.commoditySourceMaxAmount = amount
        self.currRouteCycleTime = self.pin.GetCycleTime()
        resourceTxt = localization.GetByLabel(
            'UI/PI/Common/ItemAmount',
            itemName=evetypes.GetName(typeID),
            amount=int(self.routeMaxAmount))
        CaptionAndSubtext(
            parent=cont,
            caption=localization.GetByLabel('UI/PI/Common/CommodityToRoute'),
            subtext=resourceTxt,
            iconTypeID=typeID,
            top=0,
            width=w)
        CaptionAndSubtext(
            parent=cont,
            caption=localization.GetByLabel('UI/PI/Common/QtyAmount'),
            width=w,
            top=30,
            state=uiconst.UI_DISABLED)
        self.routeAmountEdit = SinglelineEdit(
            name='routeAmountEdit',
            parent=cont,
            setvalue=self.routeMaxAmount,
            height=14,
            width=56,
            align=uiconst.TOPLEFT,
            top=44,
            ints=(0, self.routeMaxAmount),
            OnChange=self.OnRouteAmountEditChanged)
        self.routeAmountText = EveLabelSmall(parent=cont,
                                             left=60,
                                             top=46,
                                             state=uiconst.UI_NORMAL)
        self.routeDestText = CaptionAndSubtext(
            parent=cont,
            caption=localization.GetByLabel('UI/Common/Destination'),
            top=70,
            width=w)
        btns = [[
            localization.GetByLabel('UI/PI/Common/CreateRoute'),
            self.SubmitRoute, ()
        ]]
        self.createRouteButton = ButtonGroup(btns=btns,
                                             parent=cont,
                                             line=False,
                                             alwaysLite=True)
        self.UpdatePanelCreateRoute()
        return cont

    def OnPanelCreateRouteClosed(self, *args):
        sm.GetService('planetUI').myPinManager.LeaveRouteMode()

    def OnRouteAmountEditChanged(self, newVal):
        try:
            routeAmount = int(newVal)
        except ValueError:
            return

        if not self.currRouteCycleTime:
            return
        routeAmount = min(routeAmount, self.routeMaxAmount)
        routeAmount = max(routeAmount, 0.0)
        volume = planetCommon.GetCommodityTotalVolume(
            {self.commodityToRoute: routeAmount})
        volumePerHour = planetCommon.GetBandwidth(volume,
                                                  self.currRouteCycleTime)
        sm.GetService('planetUI').myPinManager.OnRouteVolumeChanged(
            volumePerHour)

    def UpdatePanelCreateRoute(self):
        if not self.currentRoute or len(self.currentRoute) < 2:
            destName = localization.GetByLabel(
                'UI/PI/Common/NoDestinationSelected')
            self.routeMaxAmount = self.sourceMaxAmount
            self.currRouteCycleTime = self.pin.GetCycleTime()
        else:
            self.routeDestPin = sm.GetService(
                'planetUI').GetCurrentPlanet().GetColony(
                    session.charid).GetPin(self.currentRoute[-1])
            isValid, invalidTxt, self.currRouteCycleTime = planetCommon.GetRouteValidationInfo(
                self.pin, self.routeDestPin, self.commodityToRoute)
            destName = planetCommon.GetGenericPinName(self.routeDestPin.typeID,
                                                      self.routeDestPin.id)
            if not isValid:
                destName = localization.GetByLabel(
                    'UI/PI/Common/InvalidDestination',
                    destName=destName,
                    reason=invalidTxt)
            if not isValid:
                self.routeMaxAmount = 0
            elif self.routeDestPin.IsProcessor(
            ) and self.commodityToRoute in self.routeDestPin.GetConsumables():
                destMaxAmount = self.routeDestPin.GetConsumables().get(
                    self.commodityToRoute)
                if self.pin.IsStorage():
                    self.routeMaxAmount = destMaxAmount
                else:
                    self.routeMaxAmount = min(destMaxAmount,
                                              self.commoditySourceMaxAmount)
            else:
                self.routeMaxAmount = self.commoditySourceMaxAmount
        self.routeAmountEdit.SetText(self.routeMaxAmount)
        self.routeAmountEdit.IntMode(0, self.routeMaxAmount)
        self.routeAmountText.text = localization.GetByLabel(
            'UI/PI/Common/RoutedPortion', maxAmount=self.routeMaxAmount)
        self.OnRouteAmountEditChanged(self.routeMaxAmount)
        self.routeDestText.SetSubtext(destName)

    def PanelSelectTransferDest(self, *args):
        cont = Container(parent=self.actionCont,
                         pos=(0, 0, 0, 15),
                         align=uiconst.TOTOP,
                         state=uiconst.UI_HIDDEN)
        cont._OnClose = self.OnPanelSelectTransferDestClosed
        Label(parent=cont,
              text=localization.GetByLabel(
                  'UI/PI/Common/SelectTransferDestination'),
              align=uiconst.TOTOP)
        return cont

    def OnPanelSelectTransferDestClosed(self, *args):
        sm.GetService('planetUI').myPinManager.LeaveRouteMode()

    def SetPin(self, pin):
        self.pin = pin

    def PanelShowRoutes(self, *args):
        self.showRoutesCont = cont = Container(parent=self.actionCont,
                                               state=uiconst.UI_HIDDEN)
        self.routeScroll = Scroll(parent=cont, name='routeScroll')
        self.routeScroll.multiSelect = False
        self.routeScroll.sr.id = 'planetBaseShowRoutesScroll'
        self.routeInfo = Container(parent=cont,
                                   pos=(0, 0, 0, 100),
                                   align=uiconst.TOBOTTOM,
                                   state=uiconst.UI_HIDDEN,
                                   idx=0,
                                   padTop=4)
        w = self.width / 2 - 10
        self.routeInfoSource = CaptionAndSubtext(
            parent=self.routeInfo,
            caption=localization.GetByLabel('UI/PI/Common/Origin'),
            width=w)
        self.routeInfoDest = CaptionAndSubtext(
            parent=self.routeInfo,
            caption=localization.GetByLabel('UI/PI/Common/Destination'),
            width=w,
            top=38)
        self.routeInfoType = CaptionAndSubtext(
            parent=self.routeInfo,
            caption=localization.GetByLabel('UI/Common/Commodity'),
            width=w,
            left=w)
        self.routeInfoBandwidth = CaptionAndSubtext(
            parent=self.routeInfo,
            caption=localization.GetByLabel('UI/PI/Common/CapacityUsed'),
            width=w,
            left=w,
            top=38)
        btns = []
        if self.pin.IsStorage() and hasattr(self, '_CreateRoute'):
            btns.append([
                localization.GetByLabel('UI/PI/Common/CreateRoute'),
                self._CreateRoute, 'routeScroll'
            ])
        btns.append([
            localization.GetByLabel('UI/PI/Common/DeleteRoute'),
            self._DeleteRouteFromEntry, ()
        ])
        self.routeInfoBtns = ButtonGroup(btns=btns,
                                         parent=self.routeInfo,
                                         idx=0)
        self.LoadRouteScroll()
        return cont

    def GetRouteTypeLabel(self, route, pin):
        if not route or not pin:
            return localization.GetByLabel('UI/Common/Unknown')
        elif route.GetSourcePinID() == pin.id:
            return localization.GetByLabel('UI/PI/Common/Outgoing')
        elif route.GetDestinationPinID() == pin.id:
            return localization.GetByLabel('UI/PI/Common/Incoming')
        else:
            return localization.GetByLabel('UI/PI/Common/Transiting')

    def LoadRouteScroll(self):
        scrolllist = []
        routesShown = []
        colony = self.planetUISvc.GetCurrentPlanet().GetColony(
            self.pin.ownerID)
        if colony is None or colony.colonyData is None:
            raise RuntimeError(
                'Unable to load route scroll without active colony on planet')
        links = colony.colonyData.GetLinksForPin(self.pin.id)
        for linkedPinID in links:
            link = colony.GetLink(self.pin.id, linkedPinID)
            for routeID in link.routesTransiting:
                if routeID in routesShown:
                    continue
                route = colony.GetRoute(routeID)
                typeID = route.GetType()
                qty = route.GetQuantity()
                typeName = evetypes.GetName(typeID)
                data = util.KeyVal(
                    label='<t>%s<t>%s<t>%s' %
                    (typeName, qty, self.GetRouteTypeLabel(route, self.pin)),
                    typeID=typeID,
                    itemID=None,
                    getIcon=True,
                    OnMouseEnter=self.OnRouteEntryHover,
                    OnMouseExit=self.OnRouteEntryExit,
                    routeID=route.routeID,
                    OnClick=self.OnRouteEntryClick,
                    amount=qty)
                scrolllist.append(listentry.Get('Item', data=data))
                routesShown.append(route.routeID)

        self.routeScroll.Load(
            contentList=scrolllist,
            noContentHint=localization.GetByLabel(
                'UI/PI/Common/NoIncomingOrOutgoingRoutes'),
            headers=[
                '',
                localization.GetByLabel('UI/Common/Commodity'),
                localization.GetByLabel('UI/Common/Quantity'),
                localization.GetByLabel('UI/PI/Common/Type')
            ])

    def OnRouteEntryClick(self, *args):
        selectedRoutes = self.routeScroll.GetSelected()
        if len(selectedRoutes) < 1:
            self.routeInfo.state = uiconst.UI_HIDDEN
            return
        selectedRouteData = selectedRoutes[0]
        selectedRoute = None
        colony = self.planetUISvc.GetCurrentPlanet().GetColony(session.charid)
        links = colony.colonyData.GetLinksForPin(self.pin.id)
        for linkedPinID in links:
            link = colony.GetLink(self.pin.id, linkedPinID)
            for routeID in link.routesTransiting:
                if routeID == selectedRouteData.routeID:
                    selectedRoute = route = colony.GetRoute(routeID)
                    break

        if selectedRoute is None or not evetypes.Exists(
                selectedRoute.GetType()):
            return
        if selectedRoute.GetSourcePinID() == self.pin.id:
            self.routeInfoSource.SetSubtext(
                localization.GetByLabel('UI/PI/Common/ThisStructure'))
        else:
            sourcePin = sm.GetService('planetUI').planet.GetPin(
                selectedRoute.GetSourcePinID())
            self.routeInfoSource.SetSubtext(
                planetCommon.GetGenericPinName(sourcePin.typeID, sourcePin.id))
        if selectedRoute.GetDestinationPinID() == self.pin.id:
            self.routeInfoDest.SetSubtext(
                localization.GetByLabel('UI/PI/Common/ThisStructure'))
        else:
            destPin = sm.GetService('planetUI').planet.GetPin(
                selectedRoute.GetDestinationPinID())
            self.routeInfoDest.SetSubtext(
                planetCommon.GetGenericPinName(destPin.typeID, destPin.id))
        routeTypeID = route.GetType()
        routeQty = route.GetQuantity()
        self.routeInfoType.SetSubtext(
            localization.GetByLabel('UI/PI/Common/ItemAmount',
                                    itemName=evetypes.GetName(routeTypeID),
                                    amount=int(routeQty)))
        bandwidthAttr = cfg.dgmattribs.Get(const.attributeLogisticalCapacity)
        self.routeInfoBandwidth.SetSubtext(
            GetFormatAndValue(bandwidthAttr,
                              selectedRoute.GetBandwidthUsage()))
        createRouteBtn = self.routeInfoBtns.GetBtnByLabel(
            localization.GetByLabel('UI/PI/Common/CreateRoute'))
        if createRouteBtn:
            if selectedRoute.GetDestinationPinID() == self.pin.id:
                createRouteBtn.state = uiconst.UI_NORMAL
            else:
                createRouteBtn.state = uiconst.UI_HIDDEN
        self.routeInfo.opacity = 0.0
        self.routeInfo.state = uiconst.UI_PICKCHILDREN
        self.uiEffects.MorphUI(self.routeInfo,
                               'opacity',
                               1.0,
                               time=125.0,
                               float=1,
                               newthread=0,
                               maxSteps=1000)