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()