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

item.py (51984B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\item.py
      2 import eveicon
      3 import telemetry
      4 import dogma.data
      5 import eve.client.script.environment.invControllers as invCtrl
      6 import inventorycommon.typeHelpers
      7 import localization
      8 import log
      9 import weakref
     10 from carbon.common.script.util.format import FmtAmt
     11 from carbonui.control.contextMenu.menuDataFactory import CreateMenuDataFromRawTuples
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.fill import Fill
     14 from carbonui.primitives.frame import Frame
     15 from carbonui.primitives.line import Line
     16 from carbonui.primitives.sprite import Sprite
     17 from carbonui.uianimations import animations
     18 from carbonui.util.various_unsorted import GetAttrs, GetWindowAbove
     19 from carbonui import fontconst, TextColor, uiconst
     20 from carbonui.control.scrollentries import SE_BaseClassCore
     21 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     22 from carbonui.uicore import uicore
     23 from dogma import units
     24 from eve.client.script.ui.control import eveIcon
     25 from eve.client.script.ui.control.eveLabel import EveLabelMedium, Label, EveLabelSmall
     26 from eve.client.script.ui.control.themeColored import FrameThemeColored
     27 from eve.client.script.ui.shared.neocom.neocom.highlightState import GetIndicatorGlowBrightness, HighlightState, GetIndicatorColor
     28 from eve.client.script.ui.util import uix
     29 from eve.client.script.ui.control.eveWindowUnderlay import ListEntryUnderlay
     30 from eve.client.script.ui.services.menuSvcExtras.invItemFunctions import GetContainerContents
     31 from eve.client.script.ui.services.menuSvcExtras.menuFunctions import ActivateCharacterReSculpt, ActivateSkillExtractor, ActivateSkillInjector, OpenCrate, ActivateAbyssalKey, CraftDynamicItem, ActivateRandomJumpKey, ActivatePVPfilamentKey, ActivateVoidSpaceKey, ActivateWarpVector, DecryptItem
     32 from eve.client.script.ui.shared.cloneGrade import ORIGIN_INVENTORY
     33 from eve.client.script.ui.shared.cloneGrade.omegaCloneOverlayIcon import OmegaCloneOverlayIcon
     34 from eve.client.script.ui.shared.fitting.ghostFittingHelpers import TryPreviewFitItemOnMouseAction
     35 from eve.client.script.ui.shared.market.sellMulti import SellItems
     36 from eve.client.script.ui.shared.tooltip.item import InventoryItemTooltip
     37 from eve.client.script.ui.shared.activateMultiTraining import ActivateMultiTraining
     38 from eve.client.script.ui.skilltrading.banner import AlphaInjectorBanner, SkillInjectorBanner, NonDiminishingInjectionBoosterBanner
     39 from eve.common.lib import appConst as const
     40 from eve.common.script.sys import eveCfg
     41 from eve.common.script.util import industryCommon
     42 from eveexceptions import UserError
     43 from eveservices.menu import GetMenuService
     44 from evetypes import TypeNotFoundException
     45 from fighters.client import GetSquadronClassResPath, GetSquadronClassTooltip
     46 from inventorycommon.const import VIEWMODE_LIST, VIEWMODE_DETAILS, VIEWMODE_ICONS, VIEWMODE_ASSETS, VIEWMODE_CARDS
     47 from inventorycommon.util import GetItemVolume, IsShipFittingFlag
     48 from menucheckers.itemCheckers import ItemChecker
     49 from omega.client.clone_grade_svc import get_clone_grade_svc
     50 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     51 from uthread2 import StartTasklet
     52 _CONTAINER_GROUPS = {const.groupWreck,
     53  const.groupCargoContainer,
     54  const.groupSecureCargoContainer,
     55  const.groupAuditLogSecureContainer,
     56  const.groupFreightContainer}
     57 OPACITY_BG = 0.9
     58 COLOR_ACTIVESHIP = (0.0,
     59  0.6,
     60  0.0,
     61  1.0)
     62 SLOT_TEXTURES = {const.effectRigSlot: 'res:/UI/Texture/classes/InvItem/slotSizeIIII.png',
     63  const.effectHiPower: 'res:/UI/Texture/classes/InvItem/slotSizeIII.png',
     64  const.effectMedPower: 'res:/UI/Texture/classes/InvItem/slotSizeII.png',
     65  const.effectLoPower: 'res:/UI/Texture/classes/InvItem/slotSizeI.png'}
     66 AMMOSIZE_TEXTURES = {0: None,
     67  1: 'res:/UI/Texture/classes/InvItem/ammoSizeS.png',
     68  2: 'res:/UI/Texture/classes/InvItem/ammoSizeM.png',
     69  3: 'res:/UI/Texture/classes/InvItem/ammoSizeL.png',
     70  4: 'res:/UI/Texture/classes/InvItem/ammoSizeXL.png'}
     71 TAG_SIZE = 8
     72 TAG_COLOR = (0.97, 0.09, 0.13)
     73 TAG_TEXTURE_PATH = 'res:/UI/Texture/Shared/smallDot.png'
     74 TAG_PADDING = 2
     75 
     76 class InvItemIconContainer(Container):
     77     default_state = uiconst.UI_NORMAL
     78     isDragObject = True
     79 
     80     def __init__(self, parent, height, entry):
     81         self._entry_ref = weakref.ref(entry)
     82         super(InvItemIconContainer, self).__init__(name='IconContainer', parent=parent, align=uiconst.TOTOP, height=height)
     83 
     84     @property
     85     def typeID(self):
     86         entry = self._entry_ref()
     87         if entry is not None:
     88             return getattr(entry, 'typeID', None)
     89 
     90     def GetMenu(self):
     91         entry = self._entry_ref()
     92         if entry is not None:
     93             return entry.GetMenu()
     94 
     95     def GetDragData(self, *args):
     96         entry = self._entry_ref()
     97         if entry is not None:
     98             return entry.GetDragData()
     99 
    100     def OnEndDrag(self, dragSource, dropLocation, dragData):
    101         entry = self._entry_ref()
    102         if entry is not None:
    103             return entry.OnEndDrag(dragSource, dropLocation, dragData)
    104 
    105     def OnClick(self, *args):
    106         entry = self._entry_ref()
    107         if entry is not None:
    108             return entry.OnClick(*args)
    109 
    110     def OnDblClick(self, *args):
    111         entry = self._entry_ref()
    112         if entry is not None:
    113             return entry.OnDblClick(*args)
    114 
    115     def OnMouseDown(self, *args):
    116         entry = self._entry_ref()
    117         if entry is not None:
    118             return entry.OnMouseDown(*args)
    119 
    120     def OnMouseUp(self, *args):
    121         entry = self._entry_ref()
    122         if entry is not None:
    123             return entry.OnMouseUp(*args)
    124 
    125     def OnDragEnter(self, dragObj, nodes):
    126         entry = self._entry_ref()
    127         if entry is not None:
    128             return entry.OnDragEnter(dragObj, nodes)
    129 
    130     def OnDragExit(self, dragObj, nodes):
    131         entry = self._entry_ref()
    132         if entry is not None:
    133             return entry.OnDragExit(dragObj, nodes)
    134 
    135     def OnDropData(self, dragObj, nodes):
    136         entry = self._entry_ref()
    137         if entry is not None:
    138             return entry.OnDropData(dragObj, nodes)
    139 
    140     def LoadTooltipPanel(self, panel, owner):
    141         entry = self._entry_ref()
    142         if entry is not None:
    143             return entry.LoadTooltipPanel(panel, owner)
    144 
    145 
    146 class InvItem(SE_BaseClassCore):
    147     __guid__ = 'xtriui.InvItem'
    148     __groups__ = []
    149     __categories__ = []
    150     __notifyevents__ = ['ProcessActiveShipChanged',
    151      'OnLockedItemChangeUI',
    152      'OnInvClipboardChanged',
    153      'OnInventoryBadgingCreated',
    154      'OnInventoryBadgingDestroyed',
    155      'OnInventoryItemUnseen',
    156      'OnInventoryItemSeen']
    157     default_name = 'InvItem'
    158     default_width = 64
    159     default_height = 64
    160     default_align = uiconst.TOPLEFT
    161     default_state = uiconst.UI_PICKCHILDREN
    162     isDragObject = True
    163     highlightable = True
    164     OMEGAICON_OPACITY = 0.8
    165     ICON_SIZE = 64
    166     _selection_frame = None
    167     _icon_frame = None
    168 
    169     def __init__(self, **kwargs):
    170         self.typeID = None
    171         self.subTypeID = None
    172         self.id = None
    173         self.powerType = None
    174         self.sr.node = None
    175         self.sr.tlicon = None
    176         self.rec = None
    177         self.activeShipHighlite = None
    178         self.blinkBG = None
    179         self.lockedIcon = None
    180         self.omegaIcon = None
    181         self.mainContainer = None
    182         self.iconCont = None
    183         self.tagContainer = None
    184         self.opacity = None
    185         self.viewOnly = None
    186         self.shouldShowTag = False
    187         self.isHovered = None
    188         super(InvItem, self).__init__(**kwargs)
    189 
    190     @telemetry.ZONE_METHOD
    191     def ApplyAttributes(self, attributes):
    192         super(InvItem, self).ApplyAttributes(attributes)
    193         sm.RegisterNotify(self)
    194         self.ConstructLayout()
    195 
    196     @classmethod
    197     def GetEntryHeight(cls):
    198         return cls.ICON_SIZE + fontconst.fontSizeFactor * 30 + 6
    199 
    200     @classmethod
    201     def GetEntryWidth(cls):
    202         return 64
    203 
    204     @classmethod
    205     def GetEntryColMargin(cls):
    206         return 16
    207 
    208     @classmethod
    209     def IsFixedWidth(cls):
    210         return True
    211 
    212     def ConstructLayout(self):
    213         self.mainContainer = Container(name='MainContainer', parent=self)
    214         self.AddIconContainer()
    215         self.AddTextContainer()
    216 
    217     def AddIconContainer(self):
    218         self.iconCont = InvItemIconContainer(parent=self.mainContainer, height=self.ICON_SIZE, entry=self)
    219         self.AddTag(parent=self.iconCont, tagAlign=uiconst.TOBOTTOM)
    220 
    221     def AddTextContainer(self):
    222         self.sr.label = Label(name='itemNameLabel', parent=self.mainContainer, align=uiconst.TOTOP, state=uiconst.UI_DISABLED, padding=(-3, 2, -3, 0), maxLines=2)
    223 
    224     def AddTag(self, parent, tagAlign):
    225         if not self.tagContainer:
    226             self.tagContainer = Line(name='newItemTagLine', parent=parent, weight=2, state=uiconst.UI_HIDDEN, align=uiconst.TOTOP_NOPUSH, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=GetIndicatorGlowBrightness(HighlightState.important), color=GetIndicatorColor(HighlightState.important))
    227 
    228     def MarkAsSeen(self):
    229         if self.shouldShowTag and self.rec:
    230             sm.GetService('neocom').MarkInventoryItemSeen(itemID=self.id, typeID=self.rec.typeID, flagID=self.rec.flagID, locationID=self.rec.locationID)
    231             self.HideTag()
    232 
    233     def IsTagged(self):
    234         return self.shouldShowTag
    235 
    236     def HideTag(self):
    237         if self.shouldShowTag:
    238             self.shouldShowTag = False
    239             self.UpdateTag()
    240 
    241     def UpdateShouldShowTag(self):
    242         if self.rec:
    243             self.shouldShowTag = sm.GetService('neocom').IsInventoryItemUnseen(itemID=self.id, typeID=self.rec.typeID, flagID=self.rec.flagID, locationID=self.rec.locationID)
    244 
    245     def UpdateTag(self):
    246         if not self.tagContainer:
    247             return
    248         self.tagContainer.state = uiconst.UI_DISABLED if self.shouldShowTag else uiconst.UI_HIDDEN
    249 
    250     def Select(self, animate = True):
    251         super(InvItem, self).Select(animate)
    252         if self._selection_frame:
    253             self._selection_frame.set_active(True, animate)
    254         self._update_icon_frame_padding()
    255         self._update_icon_opacity()
    256         self.MarkAsSeen()
    257 
    258     def Deselect(self, animate = True):
    259         super(InvItem, self).Deselect(animate)
    260         if self._selection_frame:
    261             self._selection_frame.set_active(False, animate)
    262         self._update_icon_frame_padding()
    263         self._update_icon_opacity()
    264 
    265     def OnInventoryBadgingCreated(self):
    266         self.UpdateShouldShowTag()
    267         self.UpdateTag()
    268 
    269     def OnInventoryBadgingDestroyed(self):
    270         self.shouldShowTag = False
    271         self.UpdateTag()
    272 
    273     def OnInventoryItemUnseen(self, item_ids):
    274         if self.id in item_ids:
    275             self.shouldShowTag = True
    276             self.UpdateTag()
    277 
    278     def OnInventoryItemSeen(self, item_ids):
    279         if self.id in item_ids:
    280             self.shouldShowTag = False
    281             self.UpdateTag()
    282 
    283     def OnInvClipboardChanged(self):
    284         if self.sr.node and sm.GetService('inv').IsOnClipboard(self.sr.node.item.itemID):
    285             self.opacity = 0.2
    286         else:
    287             self.opacity = 1.0
    288 
    289     def ProcessActiveShipChanged(self, shipID, oldShipID):
    290         if self.destroyed or not self.sr.node:
    291             return
    292         if self.id is not None and self.id in (shipID, oldShipID):
    293             self.Load(self.sr.node)
    294 
    295     def OnLockedItemChangeUI(self, itemID, ownerID, locationID):
    296         if not self.destroyed and self.sr.node:
    297             if itemID == self.id:
    298                 item = None
    299                 if self.rec:
    300                     item = self.rec
    301                 elif self.sr.node.item:
    302                     item = self.sr.node.item
    303                 if item is None:
    304                     log.LogInfo('Lock issue item is None')
    305                 else:
    306                     locked = item.flagID == const.flagLocked or sm.GetService('lockedItems').IsItemLocked(item)
    307                     log.LogInfo('Locked:', locked, 'item:', item)
    308                     self.SetLockState(locked)
    309 
    310     def SetViewOnly(self, isViewOnly):
    311         self.viewOnly = isViewOnly
    312         if self.sr.node:
    313             self.sr.node.viewOnly = isViewOnly
    314 
    315     def SetLockState(self, locked):
    316         self.SetViewOnly(min(1, locked))
    317         if not self.sr.icon:
    318             return
    319         if self.viewOnly:
    320             self.ConstructLockedIcon()
    321             self.lockedIcon.Show()
    322         elif self.lockedIcon:
    323             self.lockedIcon.Hide()
    324         self._update_icon_opacity()
    325 
    326     def ConstructLockedIcon(self):
    327         if not self.lockedIcon:
    328             self.lockedIcon = Sprite(name='lockedIcon', parent=self.iconCont, align=uiconst.CENTER, width=16, height=16, texturePath=eveicon.locked, hint=localization.GetByLabel('UI/Inventory/ItemLocked'), color=TextColor.SECONDARY, idx=0)
    329 
    330     def Reset(self):
    331         self.viewOnly = 0
    332         self.subTypeID = None
    333 
    334     def PreLoad(node):
    335         if node.viewMode in (VIEWMODE_LIST, VIEWMODE_DETAILS):
    336             labelFunc = node.labelFunc or uix.GetItemLabel
    337             label = labelFunc(node.item, node)
    338 
    339     def LoadMainIcon(self):
    340         if self.GetViewMode() == VIEWMODE_LIST:
    341             return
    342         if not self.sr.icon:
    343             Fill(name='background', bgParent=self.iconCont, color=(1.0, 1.0, 1.0, 0.05))
    344             self._icon_frame = Container(parent=self.iconCont, align=uiconst.TOALL, padding=self._get_icon_frame_padding(), clipChildren=True)
    345             self.sr.icon = eveIcon.Icon(name='icon', parent=self._icon_frame, align=uiconst.CENTER, width=self.ICON_SIZE, height=self.ICON_SIZE, state=uiconst.UI_DISABLED, opacity=self._get_icon_opacity())
    346         try:
    347             self.sr.icon.LoadIconByTypeID(typeID=self.rec.typeID, ignoreSize=True, isCopy=self.sr.node.isBlueprint and self.sr.node.isCopy)
    348         except TypeNotFoundException:
    349             log.LogWarn('Failed to load icon for type', self.rec.typeID, '. Type does not exist.')
    350 
    351     def _SetItemContainerInternalName(self, name, isList):
    352         self.name = name
    353         if isList:
    354             self.sr.node.panelName = name
    355 
    356     def Load(self, node):
    357         self.sr.node = node
    358         self.sr.node.__guid__ = self.__guid__
    359         self.sr.node.itemID = node.item.itemID
    360         self.id = node.item.itemID
    361         self.rec = node.item
    362         self.typeID = node.item.typeID
    363         if not self.rec:
    364             return
    365         item = ItemChecker(self.rec)
    366         self.isContainer = self.rec.groupID in _CONTAINER_GROUPS and item.IsSingleton()
    367         self.isUnassembledContainer = self.rec.groupID in _CONTAINER_GROUPS and not item.IsSingleton()
    368         if item.IsBlueprint():
    369             self.sr.node.isBlueprint = True
    370             self.sr.node.isCopy = item.IsBlueprintCopy()
    371         if self.sr.node is None:
    372             return
    373         self.Reset()
    374         self.quantity = self.rec.stacksize
    375         viewMode = self.GetViewMode()
    376         listFlag = viewMode in (VIEWMODE_LIST, VIEWMODE_DETAILS)
    377         self._SetItemContainerInternalName(name='ItemEntry_%d' % self.typeID, isList=listFlag)
    378         if viewMode != VIEWMODE_CARDS:
    379             if eveCfg.GetActiveShip() == self.sr.node.item.itemID:
    380                 if self.activeShipHighlite is None:
    381                     if listFlag:
    382                         padding = (0, 0, 0, 1)
    383                     else:
    384                         padding = (-5, -3, -5, -3)
    385                     self.activeShipHighlite = Container(name='activeShipHighlite', parent=self, idx=-1)
    386                     Frame(texturePath='res:/UI/Texture/Classes/InvItem/bgSelected.png', color=COLOR_ACTIVESHIP, parent=self.activeShipHighlite, padding=padding)
    387                     Frame(parent=self.activeShipHighlite, color=COLOR_ACTIVESHIP, padding=padding, opacity=0.4)
    388             elif self.activeShipHighlite:
    389                 self.activeShipHighlite.Close()
    390                 self.activeShipHighlite = None
    391         attribs = node.Get('godmaattribs', {})
    392         self.powerType = None
    393         for icon in (self.sr.ammosize_icon, self.sr.slotsize_icon, self.sr.contraband_icon):
    394             if icon:
    395                 icon.Hide()
    396 
    397         if item.IsHardware():
    398             if viewMode != VIEWMODE_LIST:
    399                 texturePath = None
    400                 if const.attributeChargeSize in attribs:
    401                     texturePath = AMMOSIZE_TEXTURES[attribs[const.attributeChargeSize]]
    402                 elif const.attributeRigSize in attribs:
    403                     texturePath = AMMOSIZE_TEXTURES[attribs[const.attributeRigSize]]
    404                 if texturePath:
    405                     self.ConstructAmmoSizeIcon()
    406                     self.sr.ammosize_icon.texturePath = texturePath
    407             for effect in dogma.data.get_type_effects(self.rec.typeID):
    408                 if effect.effectID in (const.effectRigSlot,
    409                  const.effectHiPower,
    410                  const.effectMedPower,
    411                  const.effectLoPower):
    412                     if viewMode != VIEWMODE_LIST:
    413                         self.ConstructSlotSizeIcon()
    414                         self.sr.slotsize_icon.LoadIcon(SLOT_TEXTURES[effect.effectID], ignoreSize=True)
    415                     self.powerType = effect.effectID
    416                     continue
    417                 if viewMode != VIEWMODE_LIST and effect.effectID == const.effectSubSystem and const.attributeSubSystemSlot in attribs:
    418                     self.ConstructSlotSizeIcon()
    419                     self.sr.slotsize_icon.LoadIcon('res:/UI/Texture/classes/InvItem/slotSubsystem.png', ignoreSize=True)
    420 
    421         elif self.rec.groupID == const.groupVoucher and self.sr.node.voucher is not None:
    422             if self.rec.typeID != const.typeBookmark:
    423                 self.subTypeID = self.sr.node.voucher.GetTypeInfo()[1]
    424         elif self.rec.categoryID == const.categoryCharge and const.attributeChargeSize in attribs:
    425             self.ConstructAmmoSizeIcon()
    426             self.sr.ammosize_icon.texturePath = AMMOSIZE_TEXTURES[attribs[const.attributeChargeSize]]
    427         factionID = sm.GetService('map').GetItem(session.solarsystemid2).factionID
    428         if inventorycommon.typeHelpers.GetIllegalityInFaction(self.sr.node.invtype, factionID) is not None:
    429             self.ConstructContrabandIcon()
    430         if listFlag:
    431             self.sr.label.width = uicore.desktop.width
    432         if viewMode == VIEWMODE_ICONS or viewMode == VIEWMODE_CARDS:
    433             self.LoadMainIcon()
    434         if self.sr.node.Get('selected', 0):
    435             self.Select(animate=False)
    436         else:
    437             self.Deselect(animate=False)
    438         self.UpdateShouldShowTag()
    439         self.UpdateTag()
    440         self.UpdateLabel()
    441         self.CheckLoadOmegaIcon()
    442         self.LoadTechLevelIcon(node.item.typeID)
    443         locked = node.Get('locked', 0)
    444         viewOnly = node.Get('viewOnly', 0)
    445         if viewMode != VIEWMODE_LIST:
    446             if item.IsFighter():
    447                 self.ConstructFighterClassIcon()
    448             elif self.sr.fighterClass:
    449                 self.sr.fighterClass.display = False
    450         self.SetLockState(locked)
    451         if not locked:
    452             self.SetViewOnly(viewOnly)
    453         if item.IsStation():
    454             self.DisableDrag()
    455         self.OnInvClipboardChanged()
    456 
    457     def GetViewMode(self):
    458         if self.sr.node:
    459             return self.sr.node.viewMode
    460 
    461     def CheckLoadOmegaIcon(self):
    462         if self.GetViewMode() not in (VIEWMODE_ICONS, VIEWMODE_DETAILS, VIEWMODE_CARDS):
    463             return
    464         if get_clone_grade_svc().is_restricted_for_alpha(self.typeID):
    465             self.ConstructOmegaIcon()
    466             self.omegaIcon.Show()
    467         elif self.omegaIcon:
    468             self.omegaIcon.Hide()
    469 
    470     def ConstructOmegaIcon(self):
    471         if not self.omegaIcon:
    472             if self._selection_frame is not None:
    473                 index = self._selection_frame.GetOrder() + 1
    474             elif self.sr.icon is not None:
    475                 index = self.sr.icon.GetOrder()
    476             else:
    477                 index = 0
    478             self.omegaIcon = OmegaCloneOverlayIcon(parent=self.iconCont, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, width=self.ICON_SIZE, height=self.ICON_SIZE, opacity=self.OMEGAICON_OPACITY, origin=ORIGIN_INVENTORY, reason=self.typeID, idx=index)
    479 
    480     def ConstructFlagsCont(self):
    481         if self.sr.flags is None:
    482             if self.GetViewMode() == VIEWMODE_DETAILS:
    483                 self.sr.flags = Container(parent=self, idx=0, name='flags', pos=(4, 21, 32, 15), align=uiconst.TOPLEFT, state=uiconst.UI_PICKCHILDREN, opacity=OPACITY_BG)
    484             elif self.GetViewMode() == VIEWMODE_ICONS:
    485                 self.sr.flags = Container(parent=self, idx=0, name='flags', pos=(2, 33, 32, 15), align=uiconst.TOPRIGHT, state=uiconst.UI_PICKCHILDREN, opacity=OPACITY_BG)
    486 
    487     def ConstructFighterClassCont(self):
    488         if self.sr.fighterClass is None:
    489             if self.sr.node.viewMode == VIEWMODE_DETAILS:
    490                 self.sr.fighterClass = Container(parent=self, idx=0, name='fighterClass', pos=(26, 0, 16, 16), align=uiconst.TOPLEFT, state=uiconst.UI_PICKCHILDREN, bgColor=(0,
    491                  0,
    492                  0,
    493                  OPACITY_BG))
    494             elif self.sr.node.viewMode == VIEWMODE_ICONS:
    495                 self.sr.fighterClass = Container(parent=self, idx=0, name='fighterClass', pos=(2, 2, 15, 15), align=uiconst.TOPRIGHT, state=uiconst.UI_PICKCHILDREN, bgColor=(0,
    496                  0,
    497                  0,
    498                  OPACITY_BG))
    499         self.sr.fighterClass.display = False
    500 
    501     def ConstructSlotSizeIcon(self):
    502         self.ConstructFlagsCont()
    503         if not self.sr.slotsize_icon:
    504             self.sr.slotsize_icon = eveIcon.Icon(parent=self.sr.flags, name='slotSize', pos=(0, 0, 15, 0), align=uiconst.TORIGHT, hint=localization.GetByLabel('UI/Inventory/FittingConstraint'))
    505         self.sr.slotsize_icon.state = uiconst.UI_DISABLED
    506 
    507     def ConstructFighterClassIcon(self):
    508         self.ConstructFighterClassCont()
    509         if not self.sr.fighterClassIcon:
    510             self.sr.fighterClassIcon = Sprite(parent=self.sr.fighterClass, name='fighterClass', pos=(0, 0, 16, 16))
    511         texturePath = GetSquadronClassResPath(self.typeID)
    512         self.sr.fighterClassIcon.LoadTexture(texturePath)
    513         self.sr.fighterClassIcon.hint = localization.GetByLabel(GetSquadronClassTooltip(self.typeID))
    514         self.sr.fighterClass.display = True
    515 
    516     def ConstructAmmoSizeIcon(self):
    517         self.ConstructFlagsCont()
    518         if not self.sr.ammosize_icon:
    519             self.sr.ammosize_icon = Sprite(parent=self.sr.flags, name='ammoSize', pos=(0, 0, 15, 0), align=uiconst.TORIGHT, hint=localization.GetByLabel('UI/Inventory/AmmoSizeConstraint'))
    520         self.sr.ammosize_icon.state = uiconst.UI_DISABLED
    521 
    522     def ConstructContrabandIcon(self):
    523         self.ConstructFlagsCont()
    524         if not self.sr.contraband_icon:
    525             self.sr.contraband_icon = Sprite(parent=self.sr.flags, name='contrabandIcon', pos=(0, 0, 15, 0), align=uiconst.TORIGHT, texturePath='res:/UI/Texture/classes/InvItem/contrabandIcon.png', hint=localization.GetByLabel('UI/Inventory/ItemIsContraband'))
    526         self.sr.contraband_icon.state = uiconst.UI_DISABLED
    527 
    528     def LoadTechLevelIcon(self, typeID = None):
    529         tlicon = uix.GetTechLevelIcon(self.sr.tlicon, 0, typeID)
    530         if tlicon is not None and GetAttrs(tlicon, 'parent') is None:
    531             self.sr.tlicon = tlicon
    532             if self.sr.node.viewMode == VIEWMODE_CARDS:
    533                 tlicon.SetParent(self.iconCont, 0)
    534             else:
    535                 tlicon.SetParent(self, 0)
    536 
    537     def UpdateLabel(self, new = 0):
    538         labelFunc = self.sr.node.labelFunc or uix.GetItemLabel
    539         label = labelFunc(self.rec, self.sr.node, new)
    540         if self.sr.node.viewMode != VIEWMODE_CARDS:
    541             self.ExpandContainerIfFirstWordExceedsWidth(label)
    542         self.sr.label.SetText(label)
    543         if self.sr.node.viewMode in (VIEWMODE_LIST, VIEWMODE_DETAILS, VIEWMODE_CARDS):
    544             return
    545         quantity = uix.GetItemQty(self.sr.node, 'ss')
    546         if self.rec.singleton or self.rec.typeID in (const.typeBookmark,):
    547             if self.sr.qtypar:
    548                 self.sr.qtypar.Close()
    549                 self.sr.qtypar = None
    550             return
    551         if not self.sr.qtypar:
    552             self.sr.qtypar = ContainerAutoSize(name='qtypar', parent=self.iconCont, align=uiconst.BOTTOMRIGHT, pos=(2, 2, 0, 0), state=uiconst.UI_DISABLED, bgColor=(0,
    553              0,
    554              0,
    555              OPACITY_BG), idx=0)
    556             self.sr.quantity_label = EveLabelSmall(parent=self.sr.qtypar, maxLines=1, opacity=1.0, padding=(4, 1, 4, 0))
    557         self.sr.quantity_label.text = quantity
    558 
    559     def _isUnlockedWithExpertSystems(self):
    560         return sm.GetService('skills').IsUnlockedWithExpertSystem(self.typeID)
    561 
    562     def ExpandContainerIfFirstWordExceedsWidth(self, label):
    563         if self.sr.node.viewMode != VIEWMODE_ICONS:
    564             return
    565         words = label[8:].split(' ')
    566         if len(words[0]) > 11:
    567             self.sr.label.padLeft = -3
    568             self.sr.label.left = 2
    569 
    570     def GetMenu(self):
    571         if self.sr.node:
    572             containerMenu = []
    573             if hasattr(self.sr.node.scroll.sr.content, 'GetMenu'):
    574                 containerMenu = self.sr.node.scroll.sr.content.GetMenu()
    575             selected = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    576             items = []
    577             for node in selected:
    578                 if node.item:
    579                     items.append((node.item, node.Get('viewOnly', 0), None))
    580 
    581             menu = CreateMenuDataFromRawTuples(GetMenuService().InvItemMenu(items))
    582             menu.AddSeparator()
    583             menu += containerMenu
    584             return menu
    585         else:
    586             return GetMenuService().InvItemMenu(self.rec, self.viewOnly)
    587 
    588     def GetHeight(self, *args):
    589         node, width = args
    590         if node.viewMode in (VIEWMODE_DETAILS, VIEWMODE_ASSETS):
    591             node.height = 42
    592         else:
    593             node.height = 21
    594         return node.height
    595 
    596     def OnClick(self, *args):
    597         if self.sr.node:
    598             if self.sr.node.Get('OnClick', None):
    599                 self.sr.node.OnClick(self)
    600             else:
    601                 self.sr.node.scroll.SelectNode(self.sr.node)
    602                 prompt_player_fsd_dialog('ListEntryClick')
    603 
    604     def OnMouseEnter(self, *args):
    605         if uicore.uilib.leftbtn:
    606             return
    607         SE_BaseClassCore.OnMouseEnter(self, *args)
    608         self.sr.hint = ''
    609         if self._hiliteFill:
    610             self._hiliteFill.hovered = True
    611         if getattr(self, 'rec', None):
    612             TryPreviewFitItemOnMouseAction(self.rec)
    613         if self.sr.node and self.sr.node.viewMode == VIEWMODE_ICONS:
    614             StartTasklet(self.SetIconHint)
    615         if self.omegaIcon and not self._isUnlockedWithExpertSystems():
    616             self.omegaIcon.OnMouseEnter()
    617         if self.rec:
    618             typeID = self.rec.typeID
    619             if typeID:
    620                 if ItemChecker(self.rec).IsSkillInjector():
    621                     sm.ScatterEvent('OnSkillInjectorMouseEnter', typeID)
    622                 if not self.isHovered:
    623                     self.isHovered = True
    624                     sm.ScatterEvent('OnInventoryItemMouseEntered', typeID, self.rec.itemID)
    625         self._update_icon_frame_padding()
    626         self.MarkAsSeen()
    627 
    628     def SetIconHint(self):
    629         if self.sr.node:
    630             quantity = uix.GetItemQty(self.sr.node, 'ln')
    631             isSingleton = bool(self.rec.singleton)
    632             itemName = uix.GetItemName(self.sr.node.item, self.sr.node)
    633             self.sr.hint = itemName if isSingleton else '%s - %s' % (quantity, itemName)
    634 
    635     def LoadTooltipPanel(self, tooltipPanel, *args):
    636         if uicore.IsDragging():
    637             return
    638         if self.rec is None:
    639             return
    640         itemChecker = ItemChecker(self.rec)
    641         if itemChecker.IsAlphaSkillInjector():
    642             tooltipPanel.LoadGeneric1ColumnTemplate()
    643             tooltipPanel.state = uiconst.UI_NORMAL
    644             injectorBanner = AlphaInjectorBanner(align=uiconst.TOPLEFT, width=280, typeID=self.rec.typeID)
    645             tooltipPanel.AddCell(injectorBanner)
    646         elif itemChecker.IsSkillInjector():
    647             tooltipPanel.LoadGeneric1ColumnTemplate()
    648             tooltipPanel.state = uiconst.UI_NORMAL
    649             injectorBanner = SkillInjectorBanner(align=uiconst.TOPLEFT, width=280, typeID=self.rec.typeID)
    650             tooltipPanel.AddCell(injectorBanner)
    651         elif itemChecker.IsNonDiminishingInjectionBooster():
    652             tooltipPanel.margin = (12, 8, 12, 8)
    653             banner = NonDiminishingInjectionBoosterBanner(align=uiconst.TOPLEFT, typeID=self.rec.typeID, quantity=self.rec.stacksize)
    654             tooltipPanel.AddCell(banner)
    655         else:
    656             InventoryItemTooltip(tooltipPanel=tooltipPanel, item=self.rec)
    657 
    658     def GetTooltipPointer(self):
    659         return uiconst.POINT_BOTTOM_2
    660 
    661     def ConstructHiliteFill(self):
    662         if not self._hiliteFill:
    663             self._hiliteFill = ListEntryUnderlay(bgParent=self.iconCont)
    664         if self._selection_frame is None:
    665             self.ConstructSelectionFrame()
    666 
    667     def ConstructSelectionFrame(self):
    668         self._selection_frame = ItemSelectionFrame(parent=self.iconCont, align=uiconst.TOALL, idx=0, active=self._isSelected and self._showHilite)
    669 
    670     def ShowHilite(self, animate = True):
    671         super(InvItem, self).ShowHilite(animate)
    672         if self._isSelected or not self._showHilite:
    673             return
    674         if self._selection_frame:
    675             self._selection_frame.set_active(True, animate)
    676         self._update_icon_frame_padding()
    677 
    678     def HideHilite(self, animate = True):
    679         super(InvItem, self).HideHilite(animate)
    680         if self._isSelected or not self._showHilite:
    681             return
    682         if self._selection_frame:
    683             self._selection_frame.set_active(False, animate)
    684         self._update_icon_frame_padding()
    685 
    686     def OnMouseExit(self, *args):
    687         SE_BaseClassCore.OnMouseExit(self, *args)
    688         if self._hiliteFill:
    689             self._hiliteFill.hovered = False
    690         if getattr(self, 'Draggable_dragging', 0):
    691             return
    692         TryPreviewFitItemOnMouseAction(None)
    693         if self.omegaIcon:
    694             self.omegaIcon.OnMouseExit()
    695         if self.rec and ItemChecker(self.rec).IsSkillInjector():
    696             sm.ScatterEvent('OnSkillInjectorMouseExit')
    697         if self.isHovered:
    698             self.isHovered = False
    699             sm.ScatterEvent('OnInventoryItemMouseExited', self.rec.typeID, self.rec.itemID)
    700         self._update_icon_frame_padding()
    701 
    702     def OnDblClick(self, *args):
    703         if self.rec is None:
    704             return
    705         itemChecker = ItemChecker(self.rec)
    706         if self.sr.node and self.sr.node.Get('OnDblClick', None):
    707             self.sr.node.OnDblClick(self)
    708         elif self.isContainer and self.rec.flagID not in (const.flagCorpDeliveries, const.flagCapsuleerDeliveries):
    709             self.OpenContainer()
    710         elif not self.viewOnly:
    711             if industryCommon.IsBlueprintCategory(self.rec.categoryID):
    712                 from eve.client.script.ui.shared.industry.industryWnd import Industry
    713                 Industry.OpenOrShowBlueprint(blueprintID=self.sr.node.itemID)
    714             elif itemChecker.OfferActivateCharacterReSculptToken():
    715                 ActivateCharacterReSculpt(self.rec.itemID)
    716             elif itemChecker.OfferActivateMultiTraining():
    717                 ActivateMultiTraining(self.rec.itemID)
    718             elif itemChecker.OfferActivateSkillInjector():
    719                 if self.typeID == const.typeAlphaTrainingInjector:
    720                     quantity = 1
    721                 else:
    722                     quantity = self.rec.stacksize
    723                 ActivateSkillInjector(self.rec, quantity)
    724             else:
    725                 if not itemChecker.IsInPilotLocation():
    726                     return
    727                 if itemChecker.IsAssembledShip():
    728                     if itemChecker.IsActiveShip():
    729                         uicore.cmd.OpenFitting()
    730                     elif session.stationid:
    731                         sm.StartService('station').TryActivateShip(self.rec)
    732                     elif session.structureid:
    733                         sm.StartService('structureDocking').ActivateShip(self.rec.itemID)
    734                 elif itemChecker.IsShip():
    735                     GetMenuService().AssembleAndBoardShip(self.rec)
    736                 elif self.isUnassembledContainer:
    737                     GetMenuService().AssembleContainer([self.rec])
    738                 elif itemChecker.OfferActivateSkillExtractor():
    739                     ActivateSkillExtractor(self.rec)
    740                 elif itemChecker.IsStructure():
    741                     sm.GetService('structureDeployment').Deploy(self.rec)
    742                 elif itemChecker.OfferOpenCrate():
    743                     OpenCrate(self.typeID, self.rec.itemID, self.rec.stacksize)
    744                 elif itemChecker.OfferRandomJumpKey():
    745                     ActivateRandomJumpKey(self.rec)
    746                 elif itemChecker.OfferPVPFilamentKey():
    747                     ActivatePVPfilamentKey(self.rec)
    748                 elif itemChecker.OfferActivateAbyssalKey():
    749                     ActivateAbyssalKey(self.rec)
    750                 elif itemChecker.OfferActivateVoidSpaceKey():
    751                     ActivateVoidSpaceKey(self.rec)
    752                 elif itemChecker.OfferWarpVector():
    753                     ActivateWarpVector(self.rec)
    754                 elif itemChecker.OfferCraftDynamicItem():
    755                     CraftDynamicItem(self.rec)
    756                 elif itemChecker.IsDecodable():
    757                     DecryptItem(self.rec.itemID, self.rec.typeID)
    758                 else:
    759                     sm.GetService('info').ShowInfo(self.rec.typeID, self.rec.itemID)
    760 
    761     def OnMouseDown(self, *args):
    762         if getattr(self, 'powerType', None):
    763             TryPreviewFitItemOnMouseAction(self.rec)
    764         uicore.uilib.tooltipHandler.CloseTooltip()
    765         SE_BaseClassCore.OnMouseDown(self, *args)
    766 
    767     def GetDragData(self, *args):
    768         if not self.sr.node:
    769             return None
    770         nodes = self.sr.node.scroll.GetSelectedNodes(self.sr.node)
    771         for node in nodes:
    772             if not getattr(node, 'viewOnly', False):
    773                 return nodes
    774 
    775     def OnEndDrag(self, dragSource, dropLocation, dragData):
    776         if dragSource.IsUnder(self):
    777             wnd = SellItems.GetIfOpen()
    778             if dropLocation.IsUnder(wnd) or dropLocation is wnd:
    779                 wnd.DropItems(None, dragData)
    780         sm.ScatterEvent('OnInvItemDropEnded', self.name)
    781 
    782     def OnMouseUp(self, btn, *args):
    783         if uicore.uilib.mouseOver != self:
    784             if getattr(self, 'powerType', None):
    785                 main = sm.GetService('station').GetSvc('fitting')
    786                 if main is not None:
    787                     main.Hilite(None)
    788         SE_BaseClassCore.OnMouseUp(self, btn, *args)
    789 
    790     def OpenContainer(self):
    791         from eve.client.script.ui.shared.inventory.invWindow import Inventory as InventoryWindow
    792         if self.rec.ownerID not in (session.charid, session.corpid):
    793             prompt_player_fsd_dialog('CantDoThatWithSomeoneElsesStuff')
    794             return
    795         wnd = GetWindowAbove(self)
    796         item = ItemChecker(self.rec)
    797         if item.IsInPilotLocation():
    798             invID = ('StationContainer', self.rec.itemID)
    799             if self.sr.node.openContainerFunc is not None:
    800                 return self.sr.node.openContainerFunc(invID)
    801             InventoryWindow.OpenOrShow(invID=invID, openFromWnd=wnd)
    802         elif item.OfferViewContents():
    803             if item.IsOwnedByMyCorp():
    804                 return GetContainerContents(self.rec, sm.GetService('invCache'), item.GetLocationIDOfItemInCorpOffice())
    805             if item.IsOwnedByMe():
    806                 if item.IsDirectlyInPersonalHangar():
    807                     return GetContainerContents(self.rec, sm.GetService('invCache'), self.rec.locationID)
    808                 inventory = sm.GetService('invCache').GetInventoryFromId(self.rec.locationID)
    809                 item = inventory.GetItem() if inventory else None
    810                 if not item:
    811                     return
    812                 category = getattr(item, 'categoryID', None)
    813                 if category == const.categoryShip and item.locationID == session.stationid:
    814                     return InventoryWindow.OpenOrShow(invID=('StationContainer', self.rec.itemID), openFromWnd=wnd)
    815 
    816     def OnDragEnter(self, dragObj, nodes):
    817         if self.sr.node.container:
    818             self.sr.node.container.OnDragEnter(dragObj, nodes)
    819         if not nodes or not getattr(nodes[0], 'rec', None):
    820             return
    821 
    822         def isStackable():
    823             for node in nodes:
    824                 if not getattr(node.rec, 'singleton', False) and node.rec.typeID == self.rec.typeID and node.rec.itemID != self.rec.itemID:
    825                     return True
    826 
    827             return False
    828 
    829         if not self.rec:
    830             return
    831         item = ItemChecker(self.rec)
    832         if self.isContainer or item.IsAssembledShip() or isStackable():
    833             self.ConstructBlinkBG()
    834             animations.FadeIn(self.blinkBG, 0.3, duration=0.2)
    835 
    836     def OnDragExit(self, dragObj, nodes):
    837         if self.sr.node.container:
    838             self.sr.node.container.OnDragExit(dragObj, nodes)
    839         if self.blinkBG:
    840             animations.FadeOut(self.blinkBG, duration=0.2)
    841         TryPreviewFitItemOnMouseAction(None)
    842 
    843     def OnDropData(self, dragObj, nodes):
    844         if self.blinkBG:
    845             animations.FadeOut(self.blinkBG, duration=0.2)
    846         if len(nodes) and getattr(nodes[0], 'scroll', None):
    847             nodes[0].scroll.ClearSelection()
    848             if not nodes[0].rec:
    849                 return
    850             if not hasattr(nodes[0].rec, 'locationID'):
    851                 return
    852             locationID = nodes[0].rec.locationID
    853             if locationID != self.rec.locationID:
    854                 if not sm.GetService('crimewatchSvc').CheckCanTakeItems(locationID):
    855                     sm.GetService('crimewatchSvc').SafetyActivated(const.shipSafetyLevelPartial)
    856                     return
    857         item = ItemChecker(self.rec)
    858         if item.IsAssembledShip():
    859             if invCtrl.ShipCargo(self.rec.itemID).OnDropData(nodes):
    860                 self.Blink()
    861             return
    862         if self.isContainer:
    863             if invCtrl.StationContainer(self.rec.itemID).OnDropData(nodes):
    864                 self.Blink()
    865             return
    866         mergeToMe = []
    867         notUsed = []
    868         fighters = []
    869         sourceID = None
    870         for node in nodes:
    871             if hasattr(node, 'WithdrawPlex') and callable(node.WithdrawPlex):
    872                 node.WithdrawPlex(self.sr.node.container.invController)
    873                 continue
    874             if getattr(node, '__guid__', None) == 'uicls.FightersHealthGauge':
    875                 fighters.append(node)
    876                 continue
    877             if getattr(node, '__guid__', None) not in ('xtriui.ShipUIModule', 'xtriui.InvItem', 'listentry.InvItem'):
    878                 notUsed.append(node)
    879                 continue
    880             if node.item.itemID == self.sr.node.item.itemID:
    881                 notUsed.append(node)
    882                 continue
    883             if node.item.typeID == self.sr.node.item.typeID and not isinstance(self.sr.node.item.itemID, tuple) and not getattr(node.item, 'singleton', False) and not self.sr.node.item.singleton:
    884                 mergeToMe.append(node.item)
    885             else:
    886                 notUsed.append(node)
    887             if sourceID is None:
    888                 sourceID = node.rec.locationID
    889 
    890         if fighters:
    891             invCtrl.ShipFighterBay(self.rec.itemID).AddFightersFromTube(fighters)
    892             return
    893         if sourceID is None:
    894             log.LogInfo('OnDropData: Moot operation with ', nodes)
    895             return
    896         if mergeToMe:
    897             mergeAllowed = self._IsMergeAllowed(mergeToMe)
    898             if not mergeAllowed:
    899                 return
    900         shift = uicore.uilib.Key(uiconst.VK_SHIFT)
    901         mergeData = []
    902         stateMgr = sm.StartService('godma').GetStateManager()
    903         dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation()
    904         singletons = []
    905         if len(mergeToMe) > 1 and shift:
    906             raise UserError('CannotPerformOnMultipleItems')
    907         for invItem in mergeToMe:
    908             if invItem.stacksize == 1:
    909                 quantity = 1
    910             elif shift:
    911                 ret = uix.QtyPopup(invItem.stacksize, 1, 1, None, localization.GetByLabel('UI/Inventory/ItemActions/StackItems'))
    912                 if ret is not None:
    913                     quantity = ret['qty']
    914                 else:
    915                     quantity = None
    916             else:
    917                 quantity = invItem.stacksize
    918             if not quantity:
    919                 continue
    920             if invItem.categoryID == const.categoryCharge and IsShipFittingFlag(invItem.flagID):
    921                 if type(invItem.itemID) is tuple:
    922                     flag = invItem.itemID[1]
    923                     chargeIDs = dogmaLocation.GetSubLocationsInBank(invItem.locationID, invItem.itemID)
    924                     if chargeIDs:
    925                         for chargeID in chargeIDs:
    926                             charge = dogmaLocation.dogmaItems[chargeID]
    927                             mergeData.append((charge.itemID,
    928                              self.rec.itemID,
    929                              dogmaLocation.GetAttributeValue(chargeID, const.attributeQuantity),
    930                              charge))
    931 
    932                     else:
    933                         mergeData.append((invItem.itemID,
    934                          self.rec.itemID,
    935                          quantity,
    936                          invItem))
    937                 else:
    938                     crystalIDs = dogmaLocation.GetCrystalsInBank(invItem.locationID, invItem.itemID)
    939                     if crystalIDs:
    940                         for crystalID in crystalIDs:
    941                             crystal = dogmaLocation.GetItem(crystalID)
    942                             if crystal.singleton:
    943                                 singletons.append(crystalID)
    944                             else:
    945                                 mergeData.append((crystal.itemID,
    946                                  self.rec.itemID,
    947                                  crystal.stacksize,
    948                                  crystal))
    949 
    950                     else:
    951                         mergeData.append((invItem.itemID,
    952                          self.rec.itemID,
    953                          quantity,
    954                          invItem))
    955             else:
    956                 mergeData.append((invItem.itemID,
    957                  self.rec.itemID,
    958                  quantity,
    959                  invItem))
    960 
    961         if singletons and GetAttrs(self, 'sr', 'node', 'rec', 'flagID'):
    962             flag = self.sr.node.rec.flagID
    963             inv = sm.GetService('invCache').GetInventoryFromId(self.rec.locationID)
    964             if inv:
    965                 inv.MultiAdd(singletons, sourceID, flag=flag, fromManyFlags=True)
    966         if mergeData and GetAttrs(self, 'sr', 'node', 'container', 'invController', 'MultiMerge'):
    967             invController = self.sr.node.container.invController
    968             sm.ScatterEvent('OnInvContDragExit', invController.GetInvID(), [])
    969             if invController.MultiMerge(mergeData, sourceID):
    970                 sm.GetService('audio').SendUIEvent('ui_state_stack')
    971                 self.Blink()
    972         if notUsed and GetAttrs(self, 'sr', 'node', 'container', 'OnDropData'):
    973             self.sr.node.container.OnDropData(dragObj, notUsed)
    974 
    975     def _IsMergeAllowed(self, mergeToMe):
    976         if session.stationid or session.structureid:
    977             return True
    978         containerItem = sm.GetService('invCache').GetInventoryFromId(self.rec.locationID).GetItem()
    979         mergeNotAllowed = containerItem.itemID == mergeToMe[0].locationID and containerItem.ownerID not in (session.charid, session.corpid, session.allianceid)
    980         return not mergeNotAllowed
    981 
    982     def Blink(self):
    983         self.ConstructBlinkBG()
    984         animations.FadeTo(self.blinkBG, 0.0, 1.0, duration=0.25, curveType=uiconst.ANIM_WAVE, loops=2)
    985 
    986     def ConstructBlinkBG(self):
    987         if self.blinkBG is None:
    988             self.blinkBG = Sprite(name='blinkBg', parent=self.iconCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/classes/InvItem/bgSelected.png', opacity=0.0, idx=0)
    989 
    990     @classmethod
    991     def GetCopyData(cls, node):
    992         if node.__guid__ == 'xtriui.InvItem':
    993             sortName = 'sort_%s' % localization.GetByLabel('UI/Common/Quantity')
    994             qty = node.get(sortName) or ''
    995             return '%s<t>%s' % (node.name, qty)
    996         return node.label
    997 
    998     def _get_icon_opacity(self):
    999         if not self.sr.node:
   1000             return 0.0
   1001         else:
   1002             view_mode = self.GetViewMode()
   1003             if self.viewOnly and view_mode == VIEWMODE_ICONS:
   1004                 return 0.25
   1005             return 1.0
   1006 
   1007     def _update_icon_opacity(self):
   1008         if self.sr.icon:
   1009             self.sr.icon.opacity = self._get_icon_opacity()
   1010 
   1011     def _get_icon_frame_padding(self):
   1012         view_mode = self.GetViewMode()
   1013         if view_mode == VIEWMODE_ICONS and (self._isSelected or self.isHovered) and self._showHilite:
   1014             return (4, 4, 4, 4)
   1015         else:
   1016             return (0, 0, 0, 0)
   1017 
   1018     def _update_icon_frame_padding(self):
   1019         if self._icon_frame:
   1020             self._icon_frame.padding = self._get_icon_frame_padding()
   1021 
   1022 
   1023 class Item(InvItem):
   1024     __guid__ = 'listentry.InvItem'
   1025     OMEGAICON_OPACITY = 1.0
   1026     ICON_SIZE = 32
   1027 
   1028     def ConstructLayout(self):
   1029         self.sr.label = EveLabelMedium(name='InventoryItemLOL', parent=self, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, idx=3, lineSpacing=-0.2, maxLines=1, autoFadeSides=16)
   1030         self.iconCont = Container(parent=self, align=uiconst.CENTERLEFT, pos=(5,
   1031          0,
   1032          self.ICON_SIZE,
   1033          self.ICON_SIZE))
   1034         self.tagContainer = None
   1035 
   1036     def Load(self, node):
   1037         InvItem.Load(self, node)
   1038         viewMode = self.GetViewMode()
   1039         if viewMode in [VIEWMODE_ICONS, VIEWMODE_DETAILS]:
   1040             self.AddTag(parent=self.iconCont, tagAlign=uiconst.TOBOTTOM)
   1041         elif viewMode == VIEWMODE_LIST:
   1042             self.AddTag(parent=self, tagAlign=uiconst.CENTER)
   1043         if viewMode == VIEWMODE_DETAILS:
   1044             self.sr.label.left = 46
   1045             self.LoadMainIcon()
   1046         else:
   1047             self.sr.label.left = 12
   1048         self.UpdateShouldShowTag()
   1049         self.UpdateTag()
   1050 
   1051     def CheckLoadOmegaIcon(self):
   1052         if self.GetViewMode() not in (VIEWMODE_ICONS, VIEWMODE_DETAILS) and not self._isUnlockedWithExpertSystems():
   1053             return
   1054         if get_clone_grade_svc().is_restricted_for_alpha(self.typeID):
   1055             self.ConstructOmegaIcon()
   1056             self.omegaIcon.Show()
   1057         elif self.omegaIcon:
   1058             self.omegaIcon.Hide()
   1059 
   1060     def ConstructOmegaIcon(self):
   1061         if not self.omegaIcon:
   1062             self.omegaIcon = OmegaCloneOverlayIcon(parent=self, align=uiconst.CENTERLEFT, state=uiconst.UI_DISABLED, pos=(5,
   1063              0,
   1064              self.ICON_SIZE,
   1065              self.ICON_SIZE), iconSize=20, opacity=self.OMEGAICON_OPACITY, idx=0, origin=ORIGIN_INVENTORY, reason=self.typeID)
   1066 
   1067     def ConstructHiliteFill(self):
   1068         SE_BaseClassCore.ConstructHiliteFill(self)
   1069 
   1070     def SetLockState(self, locked):
   1071         self.SetViewOnly(min(1, locked))
   1072         if self.viewOnly:
   1073             self.sr.label.SetRGBA(0.5, 0.5, 0.5, 1.0)
   1074             self.iconCont.opacity = 0.25
   1075             if self.sr.node.viewMode == VIEWMODE_DETAILS:
   1076                 self.ConstructLockedIcon()
   1077                 self.lockedIcon.Show()
   1078         else:
   1079             self.sr.label.SetRGBA(*TextColor.NORMAL)
   1080             self.iconCont.opacity = 1.0
   1081             if self.lockedIcon:
   1082                 self.lockedIcon.Hide()
   1083 
   1084     def ConstructLockedIcon(self):
   1085         if not self.lockedIcon:
   1086             self.lockedIcon = Sprite(name='lockedIcon', parent=self.iconCont, align=uiconst.CENTER, width=16, height=16, texturePath=eveicon.locked, hint=localization.GetByLabel('UI/Inventory/ItemLocked'), idx=0)
   1087 
   1088 
   1089 class ItemWithVolume(Item):
   1090     __guid__ = 'listentry.InvItemWithVolume'
   1091 
   1092     def UpdateLabel(self, new = 0):
   1093         InvItem.UpdateLabel(self, new)
   1094         if GetAttrs(self, 'sr', 'node', 'remote'):
   1095             return
   1096         volume = GetItemVolume(self.rec)
   1097         self.sr.node.Set('sort_%s' % localization.GetByLabel('UI/Inventory/ItemVolume'), volume)
   1098         unit = units.get_display_name(const.unitVolume)
   1099         label = '<t>%s %s' % (FmtAmt(volume), unit)
   1100         if self.sr.node.viewMode in (VIEWMODE_LIST, VIEWMODE_DETAILS):
   1101             self.sr.label.text += label
   1102             label = self.sr.label.text
   1103         else:
   1104             self.sr.label.text += label
   1105             label = self.sr.label.text
   1106         self.sr.node.label = label
   1107 
   1108 
   1109 class InvAssetItem(Item):
   1110     __guid__ = 'listentry.InvAssetItem'
   1111 
   1112     def Load(self, node):
   1113         Item.Load(self, node)
   1114         if node.Get('sublevel', 0):
   1115             padding = 16 * node.Get('sublevel', 0)
   1116             iconPadding = 5 + padding
   1117             self.sr.label.left = 46 + padding
   1118             self.iconCont.left = iconPadding
   1119             if self.omegaIcon:
   1120                 self.omegaIcon.left = iconPadding
   1121             if self.sr.flags:
   1122                 self.sr.flags.left = iconPadding
   1123             if self.sr.tlicon:
   1124                 self.sr.tlicon.left = iconPadding
   1125 
   1126     def OnDropData(self, dragObj, nodes):
   1127         pass
   1128 
   1129 
   1130 class InvAssetItemBySelection(InvAssetItem):
   1131     __guid__ = 'listentry.InvAssetItemBySelection'
   1132 
   1133     def OnMouseEnter(self, *args):
   1134         pass
   1135 
   1136     def LoadTooltipPanel(self, tooltipPanel, *args):
   1137         pass
   1138 
   1139     def Load(self, node):
   1140         node.selected = 0
   1141         InvAssetItem.Load(self, node)
   1142         if node.isSelected:
   1143             self.SelectHighlight()
   1144         else:
   1145             self.UnSelectHighlight()
   1146 
   1147     def SelectHighlight(self):
   1148         self.sr.node.isSelected = True
   1149         self.background_color = (150, 0, 0, 0.5)
   1150 
   1151     def UnSelectHighlight(self):
   1152         self.sr.node.isSelected = False
   1153         self.background_color = (0, 0, 0, 0.0)
   1154 
   1155 
   1156 class ItemSelectionFrame(Container):
   1157     _outer_frame = None
   1158 
   1159     def __init__(self, active = False, **kwargs):
   1160         self._active = active
   1161         super(ItemSelectionFrame, self).__init__(**kwargs)
   1162         self._update_active(animate=False)
   1163 
   1164     @property
   1165     def active(self):
   1166         return self._active
   1167 
   1168     @active.setter
   1169     def active(self, value):
   1170         self.set_active(value)
   1171 
   1172     def set_active(self, value, animate = True):
   1173         if self._active != value:
   1174             self._active = value
   1175             self._update_active(animate)
   1176 
   1177     def _get_frame_opacity(self):
   1178         if self._active:
   1179             return 1.0
   1180         else:
   1181             return 0.0
   1182 
   1183     def _get_outer_frame_glow_brightness(self):
   1184         if self._active:
   1185             return 0.5
   1186         else:
   1187             return 0.0
   1188 
   1189     def _update_active(self, animate = True):
   1190         if self._active:
   1191             self._create_frames_if_missing()
   1192         if not self._outer_frame:
   1193             return
   1194         opacity = self._get_frame_opacity()
   1195         if animate:
   1196             duration = uiconst.TIME_ENTRY if self._active else uiconst.TIME_EXIT
   1197             animations.MorphScalar(self._outer_frame, 'glowBrightness', startVal=self._outer_frame.glowBrightness, endVal=self._get_outer_frame_glow_brightness(), duration=duration)
   1198             animations.FadeTo(self._outer_frame, startVal=self._outer_frame.opacity, endVal=opacity, duration=duration)
   1199         else:
   1200             animations.StopAnimation(self._outer_frame, 'glowBrightness')
   1201             self._outer_frame.glowBrightness = self._get_outer_frame_glow_brightness()
   1202             animations.StopAnimation(self._outer_frame, 'opacity')
   1203             self._outer_frame.opacity = opacity
   1204 
   1205     def _create_frames_if_missing(self):
   1206         if self._outer_frame is None:
   1207             self._outer_frame = FrameThemeColored(parent=self, align=uiconst.TOALL, frameConst=uiconst.FRAME_BORDER2_CORNER0, colorType=uiconst.COLORTYPE_UIHILIGHT, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=self._get_outer_frame_glow_brightness(), opacity=self._get_frame_opacity())