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

missingSkillbooksWnd.py (15824B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\characterskills\client\UI\missingSkillbooksWnd.py
      2 import eveicon
      3 import evetypes
      4 import characterskills.common
      5 from carbonui import uiconst, PickState, Axis, ButtonVariant, TextColor
      6 from carbonui.button.group import ButtonGroup, ButtonSizeMode
      7 from carbonui.control.button import Button
      8 from carbonui.control.scrollContainer import ScrollContainer
      9 from carbonui.control.window import Window
     10 from carbonui.primitives.container import Container
     11 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     12 from carbonui.primitives.line import Line
     13 from carbonui.primitives.sprite import Sprite
     14 from carbonui.window.resizer import Orientation
     15 from eve.client.script.ui import eveColor
     16 from eve.client.script.ui.control.eveLabel import EveLabelLarge, EveLabelMedium
     17 from eve.client.script.ui.control.infoIcon import InfoIcon
     18 from eve.client.script.ui.skillPlan import skillPlanUtil
     19 from eve.client.script.ui.skillPlan.skillPlanConst import BUTTON_GROUP_ID_TOP_LEVEL, BUTTON_GROUP_ID_SKILL_PLANS, PANEL_SKILL_PLANS, PANEL_PERSONAL
     20 from localization import GetByLabel
     21 from skills.skillplan.skillPlanConst import MAX_PERSONAL_PLANS
     22 from skills.skillplan.skillPlanService import GetSkillPlanSvc
     23 MAIN_CONT_PADDING = 16
     24 CONTENTS_CONT_PADDING = 12
     25 WINDOW_WIDTH_DOUBLE = 360
     26 WINDOW_WIDTH_SINGLE = 360
     27 SKILL_LIST_MAX_HEIGHT = 100
     28 CONTENT_SIZE_PROP_DOUBLE = 0.48
     29 CONTENT_SIZE_PROP_SINGLE = 1.0
     30 BUTTON_HEIGHT = 40
     31 BUTTON_MIN_WIDTH = 130
     32 
     33 class MissingSkillbooksWnd(Window):
     34     default_width = WINDOW_WIDTH_DOUBLE
     35     default_height = 300
     36     default_windowID = 'missingSkillbooksWnd'
     37     default_useDefaultPos = True
     38     default_captionLabelPath = 'UI/SkillPlan/MissingSkillbooksWindow/ConfirmPurchaseTitle'
     39     default_iconNum = 'res:/UI/Texture/WindowIcons/skills.png'
     40 
     41     def ApplyAttributes(self, attributes):
     42         super(MissingSkillbooksWnd, self).ApplyAttributes(attributes)
     43         self.MakeUnResizeable()
     44         self.context = attributes.context
     45         self.CreateBaseLayout()
     46         self.CreateAvailableForPurchaseLayout()
     47         self.CreateUnavailableForPurchaseLayout()
     48         self.CreateBottomButtonsLayout()
     49         self.UpdateLayout()
     50         self.UpdateHeight()
     51 
     52     def CreateBaseLayout(self):
     53         self.mainCont = ContainerAutoSize(name='mainCont', parent=self.sr.main, align=uiconst.TOTOP)
     54         self.contentsCont = ContainerAutoSize(name='contentsCont', parent=self.mainCont, align=uiconst.TOTOP, padTop=CONTENTS_CONT_PADDING)
     55         self.availableForPurchaseCont = ContainerAutoSize(name='availableForPurchaseCont', parent=self.contentsCont, align=uiconst.TOTOP, height=CONTENT_SIZE_PROP_DOUBLE)
     56         self.bottomCont = ContainerAutoSize(name='bottomCont', parent=self.mainCont, align=uiconst.TOTOP, padTop=CONTENTS_CONT_PADDING)
     57         self.CreateSeparator()
     58         self.unavailableForPurchaseCont = ContainerAutoSize(name='unavailableForPurchaseCont', parent=self.contentsCont, align=uiconst.TOTOP, height=CONTENT_SIZE_PROP_DOUBLE)
     59 
     60     def CreateAvailableForPurchaseLayout(self):
     61         self.availableListScrollCont = None
     62         self.CreatePurchaseSectionTitle(self.availableForPurchaseCont, GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/AvailableForRemoteInjection'), on_click=lambda : self.ToggleSection(self.availableListScrollCont))
     63         self.availableListScrollCont = ScrollContainer(parent=self.availableForPurchaseCont, name='listScrollCont', align=uiconst.TOTOP, height=SKILL_LIST_MAX_HEIGHT)
     64         if len(self.context.available_for_purchase) > 0:
     65             skillNames = [ '- %s\n' % evetypes.GetName(type_id) for type_id in self.context.available_for_purchase ]
     66         else:
     67             skillNames = ''
     68         EveLabelMedium(parent=self.availableListScrollCont, name='skillListLabel', align=uiconst.TOTOP, text=skillNames)
     69         cost = sum(map(characterskills.common.get_direct_purchase_price, self.context.available_for_purchase))
     70         EveLabelMedium(parent=self.availableForPurchaseCont, name='priceLabel', align=uiconst.TOTOP, text=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/PriceLabel', cost=cost), padTop=2)
     71         self.availableButtonGroup = ButtonGroup(parent=self.availableForPurchaseCont, align=uiconst.TOTOP, padTop=4, button_size_mode=ButtonSizeMode.STRETCH, orientation=Axis.VERTICAL)
     72         self.buyAndInjectButton = Button(parent=self.availableButtonGroup, name='buyAndInjectButton', label=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/BuyAndInjectButton'), hint=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/BuyAndInjectTooltip'), align=uiconst.TOTOP, func=self._OnBuyAndInjectButton)
     73         self.availableCheckMarketButton = Button(parent=self.availableButtonGroup, name='availableCheckMarketButton', label=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/CheckMarketButton'), hint=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/CheckMarketTooltip'), align=uiconst.TOTOP, func=self._OnAvailableCheckMarketButton, texturePath=eveicon.market_details, variant=ButtonVariant.GHOST)
     74         self.availableCreateSkillPlanButton = Button(parent=self.availableButtonGroup, name='createSkillPlanBtn', label=GetByLabel('Tooltips/SkillPlanner/SkillPlanButtonTooltip'), align=uiconst.TORIGHT, func=self._OnCreateSkillPlanButton, texturePath=eveicon.skill_plan, variant=ButtonVariant.GHOST)
     75         self.availableCreateSkillPlanButton.GetHint = self._GetSkillPlanButtonHint
     76 
     77     def CreateUnavailableForPurchaseLayout(self):
     78         self.unavailableListScrollCont = None
     79         self.CreatePurchaseSectionTitle(self.unavailableForPurchaseCont, GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/UnavailableForRemoteInjection'), eveColor.HOT_RED, on_click=lambda : self.ToggleSection(self.unavailableListScrollCont))
     80         self.unavailableListScrollCont = ScrollContainer(parent=self.unavailableForPurchaseCont, name='listScrollCont', align=uiconst.TOTOP, height=SKILL_LIST_MAX_HEIGHT)
     81         if len(self.context.unavailable_for_purchase) > 0:
     82             skillNames = [ '- %s\n' % evetypes.GetName(type_id) for type_id in self.context.unavailable_for_purchase ]
     83         else:
     84             skillNames = ''
     85         EveLabelMedium(parent=self.unavailableListScrollCont, name='skillListLabel', align=uiconst.TOTOP, text=skillNames)
     86         self.unavailableButtonGroup = ButtonGroup(parent=self.unavailableForPurchaseCont, align=uiconst.TOTOP, padTop=2, button_size_mode=ButtonSizeMode.STRETCH, orientation=Axis.VERTICAL)
     87         self.unavailableCheckMarketButton = Button(parent=self.unavailableButtonGroup, name='unavailableCheckMarketButton', label=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/CheckMarketButton'), hint=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/CheckMarketTooltip'), align=uiconst.TOTOP, func=self._OnUnavailableCheckMarketButton, texturePath=eveicon.market_details)
     88         self.unavailableCreateSkillPlanButton = Button(parent=self.unavailableButtonGroup, name='createSkillPlanBtn', label=GetByLabel('Tooltips/SkillPlanner/SkillPlanButtonTooltip'), align=uiconst.TORIGHT, func=self._OnCreateSkillPlanButton, texturePath=eveicon.skill_plan, variant=ButtonVariant.GHOST)
     89         self.unavailableCreateSkillPlanButton.GetHint = self._GetSkillPlanButtonHint
     90 
     91     def CreateBottomButtonsLayout(self):
     92         self.sharedButtonCont = ButtonGroup(name='sharedButtonCont', parent=self.bottomCont, align=uiconst.TOBOTTOM, height=BUTTON_HEIGHT, button_size_mode=ButtonSizeMode.STRETCH, orientation=Axis.VERTICAL)
     93         self.sharedCheckMarketButton = Button(parent=self.sharedButtonCont, name='sharedCheckMarketButton', label=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/CheckMarketButton'), hint=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/CheckMarketTooltip'), align=uiconst.TOBOTTOM, func=self._OnSharedCheckMarketButton, texturePath=eveicon.market_details)
     94         self.createSkillPlanButton = Button(parent=self.sharedButtonCont, name='createSkillPlanBtn', label=GetByLabel('Tooltips/SkillPlanner/SkillPlanButtonTooltip'), align=uiconst.TORIGHT, func=self._OnCreateSkillPlanButton, texturePath=eveicon.skill_plan, variant=ButtonVariant.GHOST)
     95         self.createSkillPlanButton.GetHint = self._GetSkillPlanButtonHint
     96 
     97     def CreateSeparator(self):
     98         self.separatorLine = Line(parent=self.contentsCont, align=uiconst.TOTOP, color=eveColor.ICE_WHITE, weight=1, opacity=0.5, padTop=10, padBottom=10)
     99 
    100     def CreatePurchaseSectionTitle(self, parentContainer, titleLabel, titleColor = None, on_click = None):
    101         return SkillListHeadingContainer(parent=parentContainer, name='mainTitleCont', align=uiconst.TOTOP, height=22, padBottom=4, titleLabel=titleLabel, titleColor=titleColor, on_click=on_click)
    102 
    103     def ToggleSection(self, section):
    104         section.display = not section.display
    105         self.UpdateHeight()
    106 
    107     def UpdateHeight(self):
    108         height = 0
    109         contentHeight = 0
    110         if self.availableForPurchaseCont.display:
    111             self.availableButtonGroup.FlagForceUpdateAlignment()
    112             self.availableButtonGroup._AssureAlignmentUpdated()
    113             self.availableForPurchaseCont.SetSizeAutomatically()
    114             contentHeight += self.availableForPurchaseCont.height
    115         if self.unavailableForPurchaseCont.display:
    116             if not self.availableForPurchaseCont.display:
    117                 self.unavailableButtonGroup.FlagForceUpdateAlignment()
    118                 self.unavailableButtonGroup._AssureAlignmentUpdated()
    119             self.unavailableForPurchaseCont.SetSizeAutomatically()
    120             contentHeight += self.unavailableForPurchaseCont.height
    121         if self.availableForPurchaseCont.display and self.unavailableForPurchaseCont.display:
    122             self.sharedButtonCont.FlagForceUpdateAlignment()
    123             self.sharedButtonCont._AssureAlignmentUpdated()
    124         if self.separatorLine.display:
    125             contentHeight += 15
    126         height += contentHeight + CONTENTS_CONT_PADDING
    127         self.bottomCont.SetSizeAutomatically()
    128         height += self.bottomCont.height + CONTENTS_CONT_PADDING
    129         _, height = self.GetWindowSizeForContentSize(height=height)
    130         self.height = height
    131 
    132     def UpdateLayout(self):
    133         availableForPurchase = len(self.context.available_for_purchase) > 0
    134         unavailableForPurchase = len(self.context.unavailable_for_purchase) > 0
    135         self._ResizeWindow(availableForPurchase, unavailableForPurchase)
    136         self._UpdateButtonsAndContentDisplay(availableForPurchase, unavailableForPurchase)
    137 
    138     def _ShouldShowSkillPlanButton(self):
    139         return self.context.skill_plan_template is not None
    140 
    141     def _CanCreatePlan(self):
    142         numPlans = len(GetSkillPlanSvc().GetAllPersonal())
    143         return numPlans < MAX_PERSONAL_PLANS
    144 
    145     def _GetSkillPlanButtonHint(self):
    146         hint = GetByLabel('Tooltips/SkillPlanner/SkillPlanButtonTooltip')
    147         numPlans = len(GetSkillPlanSvc().GetAllPersonal())
    148         if self._CanCreatePlan():
    149             return hint
    150         else:
    151             return u'{}\n\n<color={}>{}</color>'.format(hint, TextColor.WARNING, GetByLabel('UI/SkillPlan/MaximumSkillPlanReached', numPlans=numPlans))
    152 
    153     def _UpdateButtonsAndContentDisplay(self, availableForPurchase, unavailableForPurchase):
    154         self.availableForPurchaseCont.display = availableForPurchase
    155         self.unavailableForPurchaseCont.display = unavailableForPurchase
    156         self.sharedButtonCont.display = availableForPurchase and unavailableForPurchase
    157         self.separatorLine.display = availableForPurchase and unavailableForPurchase
    158         self.availableCheckMarketButton.display = not self.sharedButtonCont.display
    159         self.unavailableCheckMarketButton.display = not self.sharedButtonCont.display
    160         self.availableCreateSkillPlanButton.display = not self.sharedButtonCont.display
    161         self.unavailableCreateSkillPlanButton.display = not self.sharedButtonCont.display
    162         self.createSkillPlanButton.display = self._ShouldShowSkillPlanButton()
    163         self.availableCreateSkillPlanButton.display = self._ShouldShowSkillPlanButton()
    164         self.unavailableCreateSkillPlanButton.display = self._ShouldShowSkillPlanButton()
    165 
    166     def _ResizeWindow(self, availableForPurchase, unavailableForPurchase):
    167         if availableForPurchase and unavailableForPurchase:
    168             self.width = WINDOW_WIDTH_DOUBLE
    169             self.availableForPurchaseCont.width = CONTENT_SIZE_PROP_DOUBLE
    170             self.unavailableForPurchaseCont.width = CONTENT_SIZE_PROP_DOUBLE
    171         else:
    172             self.width = WINDOW_WIDTH_SINGLE
    173             self.availableForPurchaseCont.width = CONTENT_SIZE_PROP_SINGLE
    174             self.unavailableForPurchaseCont.width = CONTENT_SIZE_PROP_SINGLE
    175 
    176     def _OnCancelButton(self, *args):
    177         self.SetModalResult(uiconst.ID_CLOSE)
    178         self.CloseByUser()
    179 
    180     def _OnBuyAndInjectButton(self, *args):
    181         success = self._BuyMissingSkills()
    182         if success and len(self.context.unavailable_for_purchase) == 0:
    183             self.SetModalResult(uiconst.ID_YES)
    184             self.Close()
    185         else:
    186             self.UpdateLayout()
    187             self.UpdateHeight()
    188 
    189     def _OnSharedCheckMarketButton(self, *args):
    190         self.context.multibuy_all_skills()
    191         self.SetModalResult(uiconst.ID_CLOSE)
    192         self.Close()
    193 
    194     def _OnAvailableCheckMarketButton(self, *args):
    195         self.context.multibuy_available_skills()
    196         self.SetModalResult(uiconst.ID_CLOSE)
    197         self.Close()
    198 
    199     def _OnUnavailableCheckMarketButton(self, *args):
    200         self.context.multibuy_unavailable_skills()
    201         self.SetModalResult(uiconst.ID_CLOSE)
    202         self.Close()
    203 
    204     def _BuyMissingSkills(self):
    205         return self.context.purchase_available_skills()
    206 
    207     def _OnCreateSkillPlanButton(self, *args):
    208         template = self.context.skill_plan_template
    209         if not self._CanCreatePlan():
    210             skillPlanUtil.SetPersistedPanelID(BUTTON_GROUP_ID_TOP_LEVEL, PANEL_SKILL_PLANS)
    211             skillPlanUtil.SetPersistedPanelID(BUTTON_GROUP_ID_SKILL_PLANS, PANEL_PERSONAL)
    212             template = None
    213         sm.GetService('cmd').OpenSkillsWindow(forceClose=True, skillPlanTemplate=template)
    214         self.SetModalResult(uiconst.ID_CLOSE)
    215         self.CloseByUser()
    216 
    217 
    218 class SkillListHeadingContainer(Container):
    219 
    220     def ApplyAttributes(self, attributes):
    221         self.default_state = uiconst.UI_NORMAL
    222         self.default_pickState = PickState.ON
    223         super(SkillListHeadingContainer, self).ApplyAttributes(attributes)
    224         self.titleLabel = attributes.get('titleLabel', '')
    225         self.titleColor = attributes.get('titleColor', None)
    226         self.on_click = attributes.get('on_click', None)
    227         self.background_color = (0.2, 0.2, 0.2, 0.2)
    228         self.ConstructLayout()
    229 
    230     def ConstructLayout(self):
    231         spriteCont = ContainerAutoSize(parent=self, name='iconCont', align=uiconst.TOLEFT, padRight=10)
    232         Sprite(parent=spriteCont, name='skillbookIcon', align=uiconst.CENTER, texturePath=eveicon.skill_book, height=16, width=16, left=4)
    233         titleCont = ContainerAutoSize(parent=self, name='labelCont', align=uiconst.TOLEFT, padRight=2)
    234         title = EveLabelLarge(parent=titleCont, name='titleLabel', align=uiconst.CENTERLEFT, text=self.titleLabel, maxWidth=250)
    235         if self.titleColor is not None:
    236             title.SetDefaultColor(self.titleColor)
    237         InfoIcon(parent=ContainerAutoSize(parent=self, name='showInfoCont', align=uiconst.TOLEFT, height=16), name='showInfo', align=uiconst.CENTER, hint=GetByLabel('UI/SkillPlan/MissingSkillbooksWindow/RemoteInjectionTooltip'))
    238 
    239     def OnMouseEnter(self, *args):
    240         self.background_color = (0.2, 0.2, 0.2, 0.8)
    241 
    242     def OnMouseExit(self, *args):
    243         self.background_color = (0.2, 0.2, 0.2, 0.5)
    244 
    245     def OnClick(self, *args):
    246         if self.on_click:
    247             self.on_click()