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

oldRedeemPanel.py (27783B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\redeem\oldRedeemPanel.py
      2 import logging
      3 import math
      4 from carbon.client.script.environment.AudioUtil import PlaySound
      5 from carbonui.control.scrollContainer import ScrollContainer
      6 from carbonui.primitives.containerAutoSize import ContainerAutoSize
      7 from carbonui.primitives.fill import Fill
      8 from carbonui.primitives.gradientSprite import GradientSprite
      9 from carbonui.primitives.line import Line
     10 from carbonui.primitives.sprite import Sprite
     11 from carbonui.util.bunch import Bunch
     12 from eve.client.script.ui.control import eveIcon, eveLabel
     13 from eveexceptions.exceptionEater import ExceptionEater
     14 from eve.client.script.ui.tooltips.tooltipsWrappers import TooltipHeaderDescriptionWrapper
     15 import uthread
     16 from carbonui.primitives.transform import Transform
     17 import eve.client.script.ui.shared.redeem.redeemUiConst as redeemColors
     18 from eve.client.script.ui.view.aurumstore.vgsUiPrimitives import LazyUrlSprite
     19 from carbonui.primitives.container import Container
     20 import carbonui.const as uiconst
     21 import localization
     22 import blue
     23 from eve.client.script.ui.util.uiComponents import Component, ButtonEffect
     24 import trinity
     25 from localization.formatters import FormatTimeIntervalShortWritten, TIME_CATEGORY_DAY, TIME_CATEGORY_MINUTE
     26 import evetypes
     27 from carbonui.uicore import uicore
     28 REDEEM_BUTTON_HEIGHT = 30
     29 DRAG_TEXT_CONTAINER_HEIGHT = 28
     30 LABEL_CONTAINER_HEIGHT = 45
     31 DEFAULT_TOKEN_SIZE = 64
     32 REDEEM_TOKEN_TOP_PADDING = 4
     33 REDEEM_ITEM_POP_IN_TIME = 0.2
     34 REDEEM_ITEM_HOVER_EFFECT_TIME = 0.1
     35 log = logging.getLogger(__name__)
     36 
     37 class RedeemPanel(ContainerAutoSize):
     38     default_align = uiconst.TOBOTTOM_NOPUSH
     39     default_state = uiconst.UI_NORMAL
     40     default_tokenSize = DEFAULT_TOKEN_SIZE
     41     default_dragEnabled = True
     42     default_instructionText = None
     43     default_name = 'RedeemPanel'
     44     isDropLocation = False
     45 
     46     def ApplyAttributes(self, attributes):
     47         ContainerAutoSize.ApplyAttributes(self, attributes)
     48         account = sm.GetService('vgsService').GetStore().GetAccount()
     49         account.SubscribeToRedeemingTokensUpdatedEvent(self.OnRedeemingTokensUpdated)
     50         self.expandCallback = attributes.get('expandCallback', None)
     51         self.collapseCallback = attributes.get('collapseCallback', None)
     52         self.dragEnabled = attributes.get('dragEnabled', self.default_dragEnabled)
     53         self.instructionText = attributes.get('instructionText', self.default_instructionText)
     54         self.buttonOnClick = attributes.get('buttonClick', self.ChangeCollapsedState)
     55         self.listenToRedeemQueueUpdatedEvents = True
     56         self.allTokens = {}
     57         self._isCollapsed = True
     58         self.redeemButton = RedeemButton(parent=self, name='redeemButton', align=uiconst.TOTOP, height=REDEEM_BUTTON_HEIGHT, state=uiconst.UI_NORMAL, OnClick=self.buttonOnClick, borderColor=attributes.get('redeemButtonBorderColor', redeemColors.REDEEM_BUTTON_BORDER_COLOR), backgroundColor=attributes.get('redeemButtonBackgroundColor', redeemColors.REDEEM_BUTTON_BACKGROUND_COLOR), fillColor=attributes.get('redeemButtonFillColor', redeemColors.REDEEM_BUTTON_FILL_COLOR), textColor=attributes.get('textColor', redeemColors.TEXT_COLOR))
     59         self.redeemContainer = RedeemContainer(parent=self, name='panelContent', align=uiconst.TOTOP, tokenSize=attributes.get('tokenSize', self.default_tokenSize), dragEnabled=self.dragEnabled, instructionText=self.instructionText)
     60         Fill(bgParent=self, color=attributes.get('redeemPanelBackgroundColor', redeemColors.REDEEM_PANEL_BACKGROUND_COLOR))
     61         self.height = self.redeemButton.height
     62         self.top = -self.height
     63         self.display = False
     64         self.CollapsePanel(False)
     65 
     66     def Close(self):
     67         with ExceptionEater('Could not unsubscribe from RedeemingQueueUpdated event'):
     68             account = sm.GetService('vgsService').GetStore().GetAccount()
     69             account.UnsubscribeFromRedeemingTokensUpdatedEvent(self.OnRedeemingTokensUpdated)
     70         ContainerAutoSize.Close(self)
     71 
     72     def SetListenToRedeemQueueUpdatedEvents(self, listenToRedeemQueueUpdatedEvents):
     73         self.listenToRedeemQueueUpdatedEvents = listenToRedeemQueueUpdatedEvents
     74 
     75     def GetHeight(self):
     76         if not self.display:
     77             return 0
     78         elif self.isCollapsed:
     79             return self.GetButtonHeight()
     80         else:
     81             return self.GetButtonHeight() + self.GetPanelHeight()
     82 
     83     def GetPanelHeight(self):
     84         return self.redeemContainer.expandedHeight
     85 
     86     def GetButtonHeight(self):
     87         return self.redeemButton.height
     88 
     89     def ChangeCollapsedState(self):
     90         if self.isCollapsed:
     91             if self.expandCallback:
     92                 self.expandCallback()
     93             else:
     94                 self.ExpandPanel()
     95         elif self.collapseCallback:
     96             self.collapseCallback()
     97         else:
     98             self.CollapsePanel()
     99 
    100     def ExpandPanel(self, animate = True, showNewItems = True, duration = REDEEM_ITEM_POP_IN_TIME, timeOffset = 0.0):
    101         self.UpdateDisplay(timeOffset=0.0)
    102         self.redeemButton.Expand(animate, duration=duration, timeOffset=timeOffset)
    103         self.redeemContainer.Expand(animate, showNewItems=showNewItems, duration=duration, timeOffset=timeOffset)
    104         self._isCollapsed = False
    105 
    106     def CollapsePanel(self, animate = True, duration = REDEEM_ITEM_POP_IN_TIME, timeOffset = 0.0, callback = None):
    107         self.redeemButton.Collapse(animate, duration=duration, timeOffset=timeOffset)
    108         self.redeemContainer.Collapse(animate, duration=duration, timeOffset=timeOffset, callback=callback)
    109         self._isCollapsed = True
    110 
    111     def IsCollapsed(self):
    112         return self.isCollapsed
    113 
    114     def OnRedeemingTokensUpdated(self):
    115         if self.listenToRedeemQueueUpdatedEvents:
    116             self.redeemContainer.OnRedeemingTokensUpdated()
    117             if self.redeemContainer.HasRedeemItems():
    118                 self.ShowPanel()
    119             else:
    120                 self.HidePanel()
    121 
    122     def RedeemItems(self, redeemedItems):
    123         self.redeemContainer.TokensRedeemed(redeemedItems)
    124 
    125     def ShowPanel(self, animate = True, duration = 0.3, timeOffset = 0.0):
    126         if self.IsHidden() and animate:
    127             self.CollapsePanel(animate=False)
    128             self.Show()
    129             uicore.animations.MorphScalar(self, 'top', startVal=self.top, endVal=0, duration=duration, timeOffset=timeOffset)
    130         if not animate:
    131             self.top = 0
    132             self.Show()
    133 
    134     def HidePanel(self, animate = True, duration = 0.3, timeOffset = 0.0):
    135         if not self.IsHidden() and animate:
    136             if not self.isCollapsed:
    137                 self.redeemContainer.Collapse(animate)
    138                 timeOffset = max(timeOffset, REDEEM_ITEM_POP_IN_TIME)
    139             uicore.animations.MorphScalar(self, 'top', startVal=self.top, endVal=-self.height, duration=duration, timeOffset=timeOffset, callback=self.Hide)
    140         if not animate:
    141             self.top = -self.height
    142             self.Hide()
    143 
    144     def UpdateDisplay(self, animate = True, duration = 0.3, timeOffset = 0.0):
    145         self.redeemContainer.UpdateTokens()
    146         if self.redeemContainer.HasRedeemItems() and self.IsHidden():
    147             self.ShowPanel(animate=animate, duration=duration, timeOffset=timeOffset)
    148         elif not self.redeemContainer.HasRedeemItems() and not self.IsHidden():
    149             self.HidePanel(animate=animate, duration=duration, timeOffset=timeOffset)
    150 
    151     def HasRedeemItems(self):
    152         return self.redeemContainer.HasRedeemItems()
    153 
    154     def AddRedeemContainerContent(self, redeemContainer):
    155         newTokens = {key:token for key, token in self.redeemContainer.allTokens.iteritems() if token.IsNew()}
    156         oldTokens = {key:token for key, token in self.redeemContainer.allTokens.iteritems() if not token.IsNew()}
    157         self.redeemContainer.ScrollToEnd()
    158         partialOpacity = 0.35
    159         fullOpacity = 1.0
    160         for tokenKey, token in oldTokens.iteritems():
    161             uicore.animations.FadeTo(token, startVal=fullOpacity, endVal=partialOpacity, duration=0.5)
    162 
    163         for tokenKey, destinationToken in newTokens.iteritems():
    164             sourceToken = redeemContainer.PopToken(destinationToken.redeemTokenData)
    165             if sourceToken:
    166                 sourceToken.AnimateOut(callback=destinationToken.Blink, timeOffset=0.6)
    167 
    168         for tokenKey, token in oldTokens.iteritems():
    169             uicore.animations.FadeTo(token, startVal=partialOpacity, endVal=fullOpacity, duration=0.5, timeOffset=1.0 + 4 * REDEEM_ITEM_POP_IN_TIME)
    170 
    171 
    172 class RedeemButton(Transform):
    173     default_name = 'RedeemButton'
    174 
    175     def ApplyAttributes(self, attributes):
    176         Transform.ApplyAttributes(self, attributes)
    177         borderColor = attributes.get('borderColor', redeemColors.REDEEM_BUTTON_BORDER_COLOR)
    178         backgroundColor = attributes.get('backgroundColor', redeemColors.REDEEM_BUTTON_BACKGROUND_COLOR)
    179         fillColor = attributes.get('fillColor', redeemColors.REDEEM_BUTTON_FILL_COLOR)
    180         textColor = attributes.get('textColor', redeemColors.TEXT_COLOR)
    181         Line(parent=self, color=borderColor, align=uiconst.TOTOP, weight=1)
    182         Fill(bgParent=self, color=backgroundColor)
    183         borderFillColor = fillColor[:3]
    184         self.borderFill = GradientSprite(bgParent=self, rgbData=[(0, borderFillColor), (0.5, borderFillColor), (1.0, borderFillColor)], alphaData=[(0.3, 0.1), (0.5, 0.4), (0.7, 0.1)], idx=0, state=uiconst.UI_DISABLED)
    185         self.onClick = attributes.get('OnClick', None)
    186         self.captionCont = Container(parent=self, name='captionCont', align=uiconst.CENTERTOP)
    187         self.expanderIcon = Sprite(parent=self.captionCont, texturePath='res:/UI/Texture/Icons/105_32_5.png', align=uiconst.CENTERRIGHT, pos=(0, 0, 32, 32), state=uiconst.UI_DISABLED, color=textColor)
    188         self.availableLabel = eveLabel.EveCaptionMedium(parent=self.captionCont, align=uiconst.CENTERLEFT, text=localization.GetByLabel('UI/RedeemWindow/RedeemableItems'), state=uiconst.UI_DISABLED, color=textColor, bold=False)
    189         self.availableLabel.letterspace = 1
    190         self.captionCont.width = self.availableLabel.textwidth + 10 + self.expanderIcon.width
    191         self.captionCont.height = max(self.availableLabel.textheight + 10, self.expanderIcon.height)
    192         self.height = self.captionCont.height
    193         push = sm.GetService('window').GetCameraLeftOffset(self.captionCont.width, align=uiconst.CENTERTOP, left=0)
    194         self.captionCont.left = push
    195 
    196     def Expand(self, animate = True, duration = REDEEM_ITEM_POP_IN_TIME, timeOffset = 0.0):
    197         self.Animate(0, animate, duration, timeOffset)
    198 
    199     def Collapse(self, animate = True, duration = REDEEM_ITEM_POP_IN_TIME, timeOffset = 0.0):
    200         self.Animate(math.pi, animate, duration, timeOffset)
    201 
    202     def Animate(self, endVal, animate, duration, timeOffset = 0.0):
    203         if animate:
    204             uicore.animations.MorphScalar(self.expanderIcon, 'rotation', startVal=self.expanderIcon.rotation, endVal=endVal, duration=duration, timeOffset=timeOffset)
    205         else:
    206             self.expanderIcon.rotation = endVal
    207 
    208     def DefaultOnClick(self):
    209         pass
    210 
    211     def OnClick(self, *args):
    212         PlaySound(uiconst.SOUND_BUTTON_CLICK)
    213         if self.onClick:
    214             self.onClick()
    215 
    216     def OnMouseEnter(self, *args):
    217         PlaySound(uiconst.SOUND_BUTTON_HOVER)
    218 
    219 
    220 class RedeemContainer(Container):
    221     default_name = 'RedeemContainer'
    222     default_dragEnabled = True
    223     default_instructionText = None
    224     default_tokenSize = DEFAULT_TOKEN_SIZE
    225     default_minimizeTokens = False
    226 
    227     def ApplyAttributes(self, attributes):
    228         self.tokens = {}
    229         self.allTokens = {}
    230         Container.ApplyAttributes(self, attributes)
    231         self.clipChildren = True
    232         self.redeemSvc = sm.GetService('redeem')
    233         self.tokenSize = attributes.get('tokenSize', self.default_tokenSize)
    234         self.dragEnabled = attributes.get('dragEnabled', self.default_dragEnabled)
    235         self.instructionText = attributes.get('instructionText', self.default_instructionText)
    236         self.containerWidth = attributes.get('containerWidth', 0)
    237         self.textColor = attributes.get('textColor', redeemColors.TEXT_COLOR)
    238         self.minimizeTokens = attributes.get('minimizeTokens', self.default_minimizeTokens)
    239         self.expandedHeight = self.GetTokenHeight() + self.GetInstructionHeight()
    240         c = Container(parent=self, name='tokenContainerParent', height=self.expandedHeight, align=uiconst.TOTOP)
    241         self.tokenContainer = ScrollContainer(parent=c, name='tokenScrollContainer', height=self.GetTokenHeight(), align=uiconst.CENTERTOP)
    242         if self.instructionText:
    243             self.bottomContent = Container(parent=c, name='bottomBorder', align=uiconst.TOBOTTOM, height=DRAG_TEXT_CONTAINER_HEIGHT)
    244             self.instructionLabel = eveLabel.EveLabelMedium(parent=self.bottomContent, name='instructionLabel', align=uiconst.CENTER, padLeft=4, padTop=3, text=self.instructionText, color=self.textColor, opacity=0.8, state=uiconst.UI_NORMAL)
    245             push = sm.GetService('window').GetCameraLeftOffset(self.instructionLabel.width, align=uiconst.CENTER, left=0)
    246             self.instructionLabel.left = push
    247 
    248     def ScrollToEnd(self):
    249         self.tokenContainer.ScrollToHorizontal(1.0)
    250 
    251     def _OnResize(self, *args):
    252         self.SetTokenContainerWidth()
    253 
    254     def GetTokenHeight(self):
    255         tokenHeight = self.tokenSize + REDEEM_TOKEN_TOP_PADDING
    256         if not self.minimizeTokens:
    257             tokenHeight += LABEL_CONTAINER_HEIGHT
    258         return tokenHeight
    259 
    260     def GetInstructionHeight(self):
    261         if self.instructionText:
    262             return DRAG_TEXT_CONTAINER_HEIGHT
    263         return 0
    264 
    265     def UpdateTokens(self):
    266         self.tokens = self.GetTokens()
    267         self.LoadTokens()
    268 
    269     def CreateRedeemToken(self, token):
    270         desc = self.redeemSvc.GetTokenDescription(token) or self.redeemSvc.GetTokenLabel(token)
    271         redeemTokenData = RedeemTokenObject(typeID=token.typeID, quantity=token.quantity, expireDateTime=token.expireDateTime, stationID=token.stationID, tokenID=token.tokenID, massTokenID=token.massTokenID, blueprintRuns=token.blueprintRuns)
    272         t = RedeemableToken(parent=self.tokenContainer, redeemTokenData=redeemTokenData, desc=desc, dragEnabled=self.dragEnabled, tokenSize=self.tokenSize, closeCallback=self.SetTokenContainerWidth, minimized=self.minimizeTokens)
    273         return t
    274 
    275     def GetSortedRedeemTokens(self):
    276         expiringTokens = [ (tokenKey, token) for tokenKey, token in self.tokens.iteritems() if token.expireDateTime ]
    277         expiringTokens = sorted(expiringTokens, key=lambda x: x[1].expireDateTime)
    278         nonExpiringTokens = [ (tokenKey, token) for tokenKey, token in self.tokens.iteritems() if not token.expireDateTime ]
    279         nonExpiringTokens = sorted(nonExpiringTokens, key=lambda x: x[1].tokenID)
    280         sortedTokens = expiringTokens + nonExpiringTokens
    281         return sortedTokens
    282 
    283     def LoadTokens(self):
    284         updatedTokens = self.GetSortedRedeemTokens()
    285         tokensToRemove = [ tokenKey for tokenKey in self.allTokens.keys() if tokenKey not in self.tokens ]
    286         for tokenKey in tokensToRemove:
    287             token = self.allTokens.pop(tokenKey, None)
    288             if token:
    289                 token.Close()
    290 
    291         for tokenKey, token in updatedTokens:
    292             if tokenKey not in self.allTokens:
    293                 self.allTokens[tokenKey] = self.CreateRedeemToken(token)
    294 
    295         self.SetTokenContainerWidth()
    296 
    297     def TokensRedeemed(self, redeemedItems):
    298         for tokenKey in redeemedItems:
    299             t = self.allTokens.pop(tokenKey, None)
    300             if t:
    301                 t.AnimateOut(callback=t.Close)
    302             self.tokens.pop(tokenKey)
    303 
    304     def PopToken(self, token):
    305         return self.allTokens.pop(self.ExtractTokenKey(token), None)
    306 
    307     def ExtractTokenKey(self, token):
    308         return (token.tokenID, token.massTokenID)
    309 
    310     def GetTokens(self):
    311         return {self.ExtractTokenKey(token):token for token in self.redeemSvc.GetRedeemTokens()}
    312 
    313     def HasRedeemItems(self):
    314         return len(self.tokens) > 0
    315 
    316     def OnRedeemingTokensUpdated(self):
    317         oldTokenKeys = self.tokens.keys()
    318         self.UpdateTokens()
    319         for tokenKey in self.tokens.keys():
    320             if tokenKey not in oldTokenKeys:
    321                 self.allTokens[tokenKey].SetIsNew(True)
    322 
    323     def SetTokenContainerWidth(self):
    324         width = sum((t.width + t.padLeft + t.padRight for t in self.allTokens.itervalues()))
    325         parentWidth = self.parent.GetAbsoluteRight() - self.parent.GetAbsoluteLeft()
    326         minWidth = parentWidth if self.containerWidth == 0 else self.containerWidth
    327         self.tokenContainer.width = min(minWidth, width)
    328         if self.tokenContainer.width != minWidth:
    329             push = sm.GetService('window').GetCameraLeftOffset(self.tokenContainer.width, align=uiconst.CENTER, left=0)
    330             self.tokenContainer.left = push
    331 
    332     def Expand(self, animate, showNewItems = True, duration = REDEEM_ITEM_POP_IN_TIME, timeOffset = 0.0):
    333         heightValue = self.expandedHeight
    334         if animate:
    335             uicore.animations.MorphScalar(self, 'height', startVal=self.height, endVal=heightValue, duration=duration, timeOffset=timeOffset)
    336             for token in self.allTokens.itervalues():
    337                 if showNewItems or not token.IsNew():
    338                     token.AnimateIn(animate=False)
    339 
    340             if self.instructionText:
    341                 uicore.animations.FadeIn(self.instructionLabel, duration=duration, timeOffset=timeOffset + duration)
    342         else:
    343             self.height = heightValue
    344             if self.instructionText:
    345                 self.instructionLabel.opacity = 1.0
    346 
    347     def Collapse(self, animate, duration = REDEEM_ITEM_POP_IN_TIME, timeOffset = 0.0, callback = None):
    348         heightValue = 0
    349         if animate:
    350             uicore.animations.MorphScalar(self, 'height', startVal=self.height, endVal=heightValue, duration=duration, callback=callback)
    351             for token in self.allTokens.itervalues():
    352                 token.AnimateOut(animate=True, timeOffset=timeOffset + duration)
    353 
    354         else:
    355             self.height = heightValue
    356         if self.instructionText:
    357             self.instructionLabel.opacity = 0
    358 
    359 
    360 class StaticRedeemContainer(RedeemContainer):
    361 
    362     def ApplyAttributes(self, attributes):
    363         RedeemContainer.ApplyAttributes(self, attributes)
    364         offerQuantity = attributes.offerQuantity
    365         tokenObjects = [ RedeemTokenObject(typeID=token.typeId, quantity=token.quantity * offerQuantity, imageUrl=token.imageUrl, name=token.name) for token in attributes.redeemTokens ]
    366         self.staticRedeemTokens = {self.ExtractTokenKey(token):token for token in tokenObjects}
    367         self.UpdateTokens()
    368         self.Expand(animate=False)
    369 
    370     def CreateRedeemToken(self, token):
    371         t = RedeemableToken(parent=self.tokenContainer, redeemTokenData=token, desc='', dragEnabled=self.dragEnabled, tokenSize=self.tokenSize, minimized=True)
    372         t.AnimateIn(animate=False)
    373         return t
    374 
    375     def ExtractTokenKey(self, token):
    376         return (token.typeID, token.quantity)
    377 
    378     def GetTokens(self):
    379         return self.staticRedeemTokens
    380 
    381 
    382 class RedeemTokenObject(object):
    383 
    384     def __init__(self, typeID = -1, quantity = 0, expireDateTime = 0, stationID = 0, tokenID = 0, massTokenID = 0, blueprintRuns = 0, imageUrl = None, name = None):
    385         self.typeID = typeID
    386         self.quantity = quantity
    387         self.expireDateTime = expireDateTime
    388         self.stationID = stationID
    389         self.tokenID = tokenID
    390         self.massTokenID = massTokenID
    391         self.blueprintRuns = blueprintRuns
    392         self.typeName = name
    393         self.portionSize = 1
    394         self.imageUrl = imageUrl
    395         if typeID > 0 and evetypes.Exists(typeID):
    396             self.typeName = evetypes.GetName(typeID)
    397             self.portionSize = evetypes.GetPortionSize(typeID)
    398 
    399     def __repr__(self):
    400         return 'RedeemToken %s' % [self.typeID,
    401          self.quantity,
    402          self.expireDateTime,
    403          self.stationID,
    404          self.tokenID,
    405          self.massTokenID,
    406          self.typeName,
    407          self.portionSize,
    408          self.imageUrl]
    409 
    410 
    411 def GetRedeemableTokenBorder(parent, _):
    412     return parent.highlightOverlay
    413 
    414 
    415 @Component(ButtonEffect(opacityIdle=0.0, opacityHover=1.0, bgElementFunc=GetRedeemableTokenBorder, audioOnEntry=uiconst.SOUND_ENTRY_HOVER))
    416 
    417 class RedeemableToken(Transform):
    418     default_tokenSize = DEFAULT_TOKEN_SIZE
    419     default_align = uiconst.TOLEFT
    420     default_state = uiconst.UI_NORMAL
    421     default_itemPadding = 6
    422     default_scalingCenter = (0.5, 0.5)
    423     default_name = 'RedeemableToken'
    424     isDragObject = True
    425     isDropLocation = False
    426 
    427     def ApplyAttributes(self, attributes):
    428         Transform.ApplyAttributes(self, attributes)
    429         self.tokenSize = attributes.get('tokenSize', self.default_tokenSize)
    430         self.closeCallback = attributes.get('closeCallback', None)
    431         self.textColor = attributes.get('textColor', redeemColors.TEXT_COLOR)
    432         self.padLeft = attributes.get('itemPadding', self.default_itemPadding)
    433         self.padRight = attributes.get('itemPadding', self.default_itemPadding)
    434         self.minimized = attributes.get('minimized', False)
    435         self.redeemTokenData = attributes.redeemTokenData
    436         self.isDragObject = attributes.dragEnabled
    437         self.typeID = self.redeemTokenData.typeID
    438         self.imageUrl = self.redeemTokenData.imageUrl
    439         self.blueprintRuns = self.redeemTokenData.blueprintRuns
    440         quantity = self.redeemTokenData.quantity
    441         portionSize = self.redeemTokenData.portionSize
    442         totalQuantity = quantity * portionSize
    443         isBpCopy = False
    444         if self.blueprintRuns:
    445             isBpCopy = True
    446         self.desc = attributes.desc
    447         self.expireDateTime = self.redeemTokenData.expireDateTime
    448         self.width = self.tokenSize
    449         self.height = self.GetTokenHeight()
    450         self.itemCont = Container(parent=self, name='itemCont', align=uiconst.TOTOP, state=uiconst.UI_PICKCHILDREN, height=self.tokenSize, width=self.tokenSize, padTop=REDEEM_TOKEN_TOP_PADDING)
    451         self.iconCont = Container(parent=self.itemCont, name='iconCont', align=uiconst.TOTOP, state=uiconst.UI_DISABLED, width=self.tokenSize, height=self.tokenSize)
    452         if not self.minimized:
    453             self.CreateAdditionalInformation()
    454         self.highlightOverlay = Sprite(name='hilite', align=uiconst.TOALL, state=uiconst.UI_DISABLED, parent=self.iconCont, texturePath='res:/UI/Texture/classes/InvItem/bgHover.png', blendMode=trinity.TR2_SBM_ADD, opacity=0.0, idx=0)
    455         Sprite(bgParent=self.iconCont, name='background', texturePath='res:/UI/Texture/classes/InvItem/bgNormal.png')
    456         if self.typeID:
    457             self.icon = eveIcon.Icon(parent=self.iconCont, name='icon', align=uiconst.CENTER, state=uiconst.UI_DISABLED, typeID=self.typeID, size=self.tokenSize, isCopy=isBpCopy)
    458         elif self.imageUrl:
    459             self.icon = LazyUrlSprite(name='image', parent=self.iconCont, align=uiconst.CENTER, imageUrl=self.imageUrl, state=uiconst.UI_DISABLED, height=64, width=64)
    460         self.quantityContainer = Container(parent=self.iconCont, name='quantityContainer', idx=0, pos=(0, 53, 32, 11), align=uiconst.TOPRIGHT, state=uiconst.UI_DISABLED, bgColor=(0, 0, 0, 0.95))
    461         self.quantityLabel = eveLabel.Label(parent=self.quantityContainer, left=2, maxLines=1, fontsize=9, color=self.textColor, text=totalQuantity)
    462         self.isNew = False
    463         self.tooltipPanelClassInfo = TooltipHeaderDescriptionWrapper(header=self.redeemTokenData.typeName, description=self.GenerateHintText())
    464         self.scale = (0.0, 0.0)
    465 
    466     def GetTokenHeight(self):
    467         tokenHeight = self.tokenSize
    468         if not self.minimized:
    469             tokenHeight += LABEL_CONTAINER_HEIGHT
    470         return tokenHeight
    471 
    472     def GenerateHintText(self):
    473         texts = [ t for t in [self.desc, self.GetStationLocationName(), self.GetDetailedExpiryText()] if t != '' ]
    474         hintText = '<br>'.join(texts)
    475         return hintText
    476 
    477     def GetStationLocationName(self):
    478         if not self.redeemTokenData.stationID:
    479             return ''
    480         return localization.GetByLabel('UI/RedeemWindow/RedeemableTo', desc='', station=self.redeemTokenData.stationID)
    481 
    482     def GetExpiryText(self):
    483         if not self.expireDateTime:
    484             return ''
    485         now = blue.os.GetWallclockTime()
    486         timeLeft = self.expireDateTime - now
    487         if timeLeft < 0:
    488             return localization.GetByLabel('UI/Generic/Expired')
    489         return FormatTimeIntervalShortWritten(timeLeft, showFrom=TIME_CATEGORY_DAY, showTo=TIME_CATEGORY_MINUTE)
    490 
    491     def GetDetailedExpiryText(self):
    492         expireText = ''
    493         if self.expireDateTime:
    494             expireText = localization.GetByLabel('UI/ActivatePlex/Expires', expiryDate=self.expireDateTime)
    495         return expireText
    496 
    497     def CreateAdditionalInformation(self):
    498         labelContainer = Container(parent=self, name='labelContainer', align=uiconst.TOTOP, height=LABEL_CONTAINER_HEIGHT)
    499         self.itemLabel = eveLabel.EveLabelSmall(parent=labelContainer, name='itemLabel', align=uiconst.TOTOP, text='<center>' + self.redeemTokenData.typeName + '</center>', color=self.textColor, maxLines=2)
    500         if self.expireDateTime:
    501             self.expiryTimeLabel = eveLabel.EveLabelSmall(parent=labelContainer, name='expiryTimeLabel', align=uiconst.TOTOP, text='<center>' + self.GetExpiryText() + '</center>', color=self.textColor, opacity=0.5)
    502         if self.redeemTokenData.stationID:
    503             padding = 4
    504             self.lockedToStationIcon = Sprite(name='lockedToStationIcon', parent=self.iconCont, align=uiconst.BOTTOMLEFT, texturePath='res:/UI/Texture/Classes/RedeemPanel/pin-location.png', padLeft=padding, padBottom=padding, width=18 + padding, height=24 + padding)
    505 
    506     def GetDragData(self, *args):
    507         fakeNode = Bunch(typeID=self.typeID, tokenInfo=(self.redeemTokenData.tokenID, self.redeemTokenData.massTokenID))
    508         return [fakeNode]
    509 
    510     def PrepareDrag(self, dragContainer, dragSource):
    511         t = RedeemableToken(parent=dragContainer, redeemTokenData=self.redeemTokenData, desc=self.desc, tokenSize=self.tokenSize, align=uiconst.TOPLEFT, minimized=True)
    512         t.AnimateIn()
    513         return (0, 0)
    514 
    515     def KillDragContainer(self, dragContainer):
    516         uthread.new(self.KillDragContainer_thread, dragContainer)
    517 
    518     def KillDragContainer_thread(self, dragContainer):
    519         try:
    520             child = dragContainer.children[0]
    521             child.AnimateOut()
    522         finally:
    523             uicore.layer.dragging.Flush()
    524 
    525     def SetScale(self, scale):
    526         self.scale = scale
    527 
    528     def AnimateIn(self, animate = True, timeOffset = 0.0, callback = None):
    529         endScale = (1.0, 1.0)
    530         if animate:
    531             uicore.animations.Tr2DScaleTo(self, startScale=self.scale, endScale=endScale, duration=REDEEM_ITEM_POP_IN_TIME, timeOffset=timeOffset, callback=callback)
    532         else:
    533             self.scale = endScale
    534 
    535     def AnimateOut(self, animate = True, timeOffset = 0.0, callback = None):
    536         endScale = (0.0, 0.0)
    537         if animate:
    538             uicore.animations.Tr2DScaleTo(self, startScale=self.scale, endScale=endScale, duration=REDEEM_ITEM_POP_IN_TIME, timeOffset=timeOffset, callback=callback)
    539         else:
    540             self.scale = endScale
    541         self.isNew = False
    542 
    543     def Blink(self):
    544         self.AnimateIn(animate=True)
    545         uicore.animations.BlinkIn(self.icon, duration=REDEEM_ITEM_POP_IN_TIME, timeOffset=REDEEM_ITEM_POP_IN_TIME)
    546 
    547     def IsNew(self):
    548         return self.isNew
    549 
    550     def SetIsNew(self, isNew):
    551         self.isNew = isNew
    552 
    553     def Close(self):
    554         Transform.Close(self)
    555         if self.closeCallback is not None:
    556             self.closeCallback()