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

selectedSkillPlanContainer.py (24375B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\skillPlan\selectedPlan\selectedSkillPlanContainer.py
      2 import math
      3 import blue
      4 import eveicon
      5 import threadutils
      6 import uthread2
      7 from carbonui import uiconst
      8 from carbonui.button.group import ButtonGroup
      9 from carbonui.control.button import Button
     10 from carbonui.control.buttonIcon import ButtonIcon
     11 from carbonui.control.scrollContainer import ScrollContainer
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     14 from carbonui.primitives.frame import Frame
     15 from carbonui.uianimations import animations
     16 from eve.client.script.ui import eveColor
     17 from eve.client.script.ui.control.eveLabel import EveLabelLarge
     18 from eve.client.script.ui.shared.careerPortal import careerConst
     19 from eve.client.script.ui.skillPlan import skillPlanUISignals
     20 from eve.client.script.ui.skillPlan.contents.skillPlanContents import SkillPlanContents
     21 from eve.client.script.ui.skillPlan.controls.milestoneIndicatorHeader import MilestoneIndicatorHeader
     22 from eve.client.script.ui.skillPlan.milestone.skillPlanProgressIndicator import SkillPlanProgressIndicator
     23 from eve.client.script.ui.skillPlan.selectedPlan.skillPlanLockedCont import SkillPlanLockedCont
     24 from eve.client.script.ui.skillPlan.skillPlanConst import HINT_BY_CAREER_ID, HINT_BY_FACTION_ID, ICON_BY_FACTION_ID
     25 from eve.common.script.util.notificationconst import notificationTypeSkillsAddedFromSkillPlan
     26 from eveui import Sprite
     27 from localization import GetByLabel
     28 from notifications.common.notification import Notification
     29 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     30 from skills.skillplan import skillPlanSignals
     31 from skills.skillplan.loggers.skillPlanLogger import log_certified_skill_plan_track_plan_clicked, log_certified_skill_plan_train_all_clicked
     32 from skills.skillplan.skillPlanDragData import SkillPlanDragData
     33 from skills.skillplan.skillPlanService import GetSkillPlanSvc
     34 from uihighlighting.uniqueNameConst import GetUniqueSkillPlanBtn
     35 COLOR_FRAME = eveColor.LED_GREY
     36 PAD = 16
     37 TOP_CONT_HEIGHT = 32
     38 BUTTONS_HEIGHT = 32
     39 BUTTONS_WIDTH = 32
     40 MIDDLE_BUTTONS_WIDTH = 32
     41 MIDDLE_BUTTONS_ICON_SIZE = 20
     42 MIDDLE_BUTTONS_PAD = 4
     43 WIDTH_OVERVIEW_CONT = 0.4
     44 MINWIDTH_OVERVIEW_CONT = 350
     45 
     46 def OpenSkillPlanWindow():
     47     from eve.client.script.ui.skillPlan.skillPlanDockablePanel import SkillPlanDockablePanel
     48     skill_plans_window = SkillPlanDockablePanel.Open()
     49     if skill_plans_window and not skill_plans_window.IsFullscreen():
     50         skill_plans_window.Maximize()
     51 
     52 
     53 class PlanCompletedBanner(Container):
     54     default_height = 42
     55 
     56     def ApplyAttributes(self, attributes):
     57         super(PlanCompletedBanner, self).ApplyAttributes(attributes)
     58         leftCont = Container(name='leftcont', parent=self, align=uiconst.TOLEFT, width=42, bgColor=eveColor.COPPER_OXIDE_GREEN)
     59         Sprite(name='completedIcon', parent=leftCont, align=uiconst.CENTER, pos=(0, 0, 34, 34), texturePath='res:/UI/Texture/classes/SkillPlan/completedIcon.png')
     60         mainCont = Container(name='mainCont', parent=self, bgColor=eveColor.WHITE, padLeft=10)
     61         EveLabelLarge(parent=mainCont, align=uiconst.CENTERLEFT, text=GetByLabel('UI/SkillPlan/SkillPlanCompleted'), color=eveColor.BLACK, left=14, shadowOffset=(0, 0))
     62 
     63 
     64 class SelectedSkillPlanContainer(Container):
     65     __notifyevents__ = ['OnSubscriptionChanged',
     66      'OnSkillsAvailable',
     67      'OnSkillQueueChanged',
     68      'OnSkillsChanged']
     69 
     70     def ApplyAttributes(self, attributes):
     71         super(SelectedSkillPlanContainer, self).ApplyAttributes(attributes)
     72         sm.RegisterNotify(self)
     73         skillPlan = attributes.skillPlan
     74         self.skillPlan = None
     75         self.skillsVisible = False
     76         self.updateComponentsThrottleFunc = None
     77         skillPlanSignals.on_saved.connect(self.OnSkillPlanSaved)
     78         skillPlanSignals.on_tracked_plan_changed.connect(self.OnTrackedPlanChanged)
     79         self.mainCont = Container(name='mainCont', parent=self)
     80         self.bgCont = Container(name='bgCont', parent=self, align=uiconst.TOLEFT_PROP, width=WIDTH_OVERVIEW_CONT, minWidth=MINWIDTH_OVERVIEW_CONT)
     81         self.ConstructCloseButton()
     82         self.ConstructBackground()
     83         self.overviewCont = Container(name='overviewCont', parent=self.mainCont, align=uiconst.TOLEFT_PROP, width=WIDTH_OVERVIEW_CONT, minWidth=MINWIDTH_OVERVIEW_CONT, padding=(50, 10, 50, 50))
     84         self.contentsCont = Container(name='contentsCont', parent=self.mainCont, align=uiconst.TOALL, padding=(0, 50, 50, 50))
     85         self.ConstructOverviewCont()
     86         self.ConstructContentsCont()
     87         self.SetSkillPlan(skillPlan)
     88 
     89     def ConstructBackground(self):
     90         Frame(parent=self.bgCont, texturePath='res:/UI/Texture/Shared/DarkStyle/panel2Corner_Stroke.png', color=COLOR_FRAME, cornerSize=11)
     91         Frame(parent=self.bgCont, texturePath='res:/UI/Texture/Shared/DarkStyle/panel2Corner_Solid.png', color=(0, 0, 0, 0.92), cornerSize=11)
     92         Sprite(name='leftWing', parent=self.bgCont, align=uiconst.TOPLEFT, texturePath='res:/UI/Texture/classes/SkillPlan/skillPlanWing.png', pos=(-8, 215, 8, 86), color=COLOR_FRAME)
     93         Sprite(name='rightWing', parent=self.bgCont, align=uiconst.TOPRIGHT, texturePath='res:/UI/Texture/classes/SkillPlan/skillPlanWing.png', pos=(-8, 215, 8, 86), color=COLOR_FRAME, rotation=math.pi)
     94 
     95     def ConstructOverviewCont(self):
     96         Sprite(name='skillPlanIcon', parent=self.overviewCont, align=uiconst.TOPLEFT, pos=(-36, 6, 20, 20), state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/classes/SkillPlan/skillPlanIcon.png')
     97         self.headerCont = MilestoneIndicatorHeader(parent=self.overviewCont, align=uiconst.TOTOP, padBottom=6)
     98         self.ConstructIconCont()
     99         self.skillPlanProgressIndicator = SkillPlanProgressIndicator(parent=self.overviewCont, align=uiconst.TOTOP_PROP, height=0.48)
    100         self.ConstructMiddleButtonsCont()
    101         self.toggleContentsButton = Button(name='toggleContentsButton', parent=self.overviewCont, align=uiconst.TOTOP, texturePath='res:/UI/Texture/Shared/DarkStyle/buttonInProgressArrow.png', label=GetByLabel('UI/SkillPlan/ShowSkillPlanContents'), iconSize=12, padTop=16, func=self.OnToggleContents)
    102         self.completedBanner = PlanCompletedBanner(parent=self.overviewCont, align=uiconst.TOTOP, state=uiconst.UI_HIDDEN, padTop=16)
    103         descriptionScroll = ScrollContainer(parent=self.overviewCont, align=uiconst.TOALL, padTop=16)
    104         self.descriptionLabel = EveLabelLarge(name='descriptionLabel', parent=descriptionScroll, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, linkStyle=uiconst.LINKSTYLE_REGULAR)
    105         self.ConstructBottomButtonsCont()
    106         self.UpdateComponents()
    107 
    108     def ConstructIconCont(self):
    109         iconCont = Container(name='iconCont', parent=self.overviewCont, align=uiconst.TOTOP_NOPUSH, height=32, padTop=6)
    110         self.factionIcon = Sprite(name='factionIcon', parent=iconCont, align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL, pos=(0, 0, 32, 32), opacity=0.5)
    111         self.factionIcon.LoadTooltipPanel = self.LoadFactionTooltip
    112         self.careerPathIcon = Sprite(name='careerPathIcon', parent=iconCont, align=uiconst.TOPRIGHT, state=uiconst.UI_NORMAL, pos=(0, 0, 32, 32), opacity=0.5)
    113         self.careerPathIcon.LoadTooltipPanel = self.LoadCareerTooltip
    114 
    115     def ConstructCloseButton(self):
    116         ButtonIcon(name='closeButton', parent=self.bgCont, align=uiconst.TOPRIGHT, pos=(8, 8, 16, 16), texturePath='res:/UI/Texture/Shared/DarkStyle/windowClose.png', func=self.OnCloseButton)
    117 
    118     def OnCloseButton(self, *args):
    119         skillPlanUISignals.on_close_button()
    120 
    121     def ConstructMiddleButtonsCont(self):
    122         self.middleButtonsCont = Container(parent=self.overviewCont, name='buttonsCont', align=uiconst.TOTOP, height=MIDDLE_BUTTONS_WIDTH, padTop=16)
    123         self.controlButtonsCont = ButtonGroup(parent=self.middleButtonsCont, align=uiconst.TOLEFT)
    124         self.editButton = Button(name='editButton', parent=self.controlButtonsCont, align=uiconst.TOLEFT, texturePath='res:/UI/Texture/classes/SkillPlan/buttonIcons/editPlanIcon.png', func=self.OnEditButton, iconSize=MIDDLE_BUTTONS_ICON_SIZE)
    125         self.editButton.GetHint = self.GetEditHint
    126         self.saveButton = Button(name='saveButton', parent=self.controlButtonsCont, align=uiconst.TOLEFT, texturePath='res:/UI/Texture/classes/SkillPlan/buttonIcons/savePlanIcon.png', hint=GetByLabel('UI/SkillPlan/SavePlan'), func=self.SaveSkillPlan, iconSize=MIDDLE_BUTTONS_ICON_SIZE)
    127         self.shareButton = Button(name='shareButton', parent=self.controlButtonsCont, align=uiconst.TOLEFT, texturePath='res:/UI/Texture/classes/SkillPlan/buttonIcons/sharePlanIcon.png', hint=GetByLabel('UI/SkillPlan/SharePlan'), iconSize=MIDDLE_BUTTONS_ICON_SIZE)
    128         self.shareButton.GetDragData = self.GetShareButtonDragData
    129         self.deleteButton = Button(name='deleteButton', parent=self.controlButtonsCont, align=uiconst.TOLEFT, texturePath='res:/UI/Texture/classes/SkillPlan/buttonIcons/delete.png', func=self.OnDeleteButton, iconSize=MIDDLE_BUTTONS_ICON_SIZE)
    130         self.deleteButton.GetHint = self.GetDeleteHint
    131         self.trackButton = Button(name='trackButton', parent=self.middleButtonsCont, align=uiconst.TORIGHT, texturePath=eveicon.look_at, func=self.OnTrackButton, iconSize=MIDDLE_BUTTONS_ICON_SIZE, padLeft=MIDDLE_BUTTONS_PAD)
    132         self.trackButton.GetHint = self.GetTrackHint
    133         self.saveButton.Disable()
    134         self.shareButton.Disable()
    135         self.trackButton.Disable()
    136         self.deleteButton.Disable()
    137         self.shareButton.MakeDragObject()
    138 
    139     def GetDeleteHint(self):
    140         return GetByLabel('UI/SkillPlan/DeletePlan')
    141 
    142     def GetEditHint(self):
    143         if self.skillPlan.IsEditable():
    144             return GetByLabel('UI/SkillPlan/EditPlan')
    145         else:
    146             return GetByLabel('UI/SkillPlan/SaveAndEditPlan')
    147 
    148     def GetTrackHint(self):
    149         if not self.skillPlan.IsTrackable():
    150             return GetByLabel('UI/SkillPlan/SaveAnTrackPlan')
    151         elif GetSkillPlanSvc().IsSkillPlanTracked(self.skillPlan.GetID()):
    152             return GetByLabel('UI/SkillPlan/UntrackPlanHint')
    153         else:
    154             return GetByLabel('UI/SkillPlan/TrackPlanHint')
    155 
    156     def SaveSkillPlan(self, *args):
    157         if self.skillPlan:
    158             skillPlanUISignals.on_selected(self.GetSkillPlanCopy())
    159 
    160     def GetShareButtonDragData(self, *args):
    161         return SkillPlanDragData(self.skillPlan.GetID(), self.skillPlan.GetName(), self.skillPlan.GetOwnerID())
    162 
    163     def ConstructBottomButtonsCont(self):
    164         self.bottomButtonsCont = ContainerAutoSize(parent=self.overviewCont, name='bottomButtonsCont', align=uiconst.TOBOTTOM, padTop=6, idx=0)
    165         lockedContPar = Container(name='lockedContPar', parent=self.bottomButtonsCont, align=uiconst.TOTOP, height=60)
    166         self.lockedCont = SkillPlanLockedCont(parent=lockedContPar, align=uiconst.CENTERTOP)
    167         self.lockedCont.onMissingSkillsButtonSignal.connect(self.OnToggleContents)
    168         self.startTrainingBtn = Button(parent=self.bottomButtonsCont, name='startTrainingButton', align=uiconst.TOTOP, label=GetByLabel('UI/SkillPlan/StartTraining'), iconSize=12, func=self.TrainSkills, padTop=5, analyticID='AddAllSkillsToTrainingQueue')
    169 
    170     def ConstructContentsCont(self):
    171         self.skillPlanContents = SkillPlanContents(parent=self.contentsCont, name='skillPlanContentsPropCont', align=uiconst.TOLEFT_PROP, width=0.0, opacity=0.0, padding=(10, 18, 0, 0))
    172 
    173     def OnToggleContents(self, *args):
    174         if self.skillsVisible:
    175             self.HideSkills()
    176         else:
    177             self.ShowSkills()
    178         self.mainCont.GetAbsolutePosition()
    179         skillPlanUISignals.on_skill_collapse_changing(self.skillPlan, self.skillsVisible, self)
    180 
    181     def HideSkills(self):
    182         if self.skillsVisible:
    183             duration = 0.2
    184             animations.MorphScalar(self.skillPlanContents, 'width', startVal=self.skillPlanContents.width, endVal=0.0, duration=duration)
    185             animations.MorphScalar(self.bgCont, 'width', self.bgCont.width, WIDTH_OVERVIEW_CONT, duration=duration)
    186             animations.FadeTo(self.skillPlanContents, 0.1, 0.0, duration=duration)
    187             self.skillsVisible = False
    188             self.skillPlanContents.state = uiconst.UI_DISABLED
    189             self.UpdateToggleContentsBtn(isSkillPlanVisible=False)
    190 
    191     def ShowSkills(self, *args):
    192         if not self.skillsVisible:
    193             uthread2.start_tasklet(self.skillPlanContents.SetSkillPlan, self.skillPlan)
    194             duration = 0.2
    195             animations.MorphScalar(self.skillPlanContents, 'width', startVal=self.skillPlanContents.width, endVal=1.0, duration=duration)
    196             animations.MorphScalar(self.bgCont, 'width', self.bgCont.width, 1.0, duration=duration)
    197             animations.FadeTo(self.skillPlanContents, 0.0, 1.0, duration=0.4)
    198             self.skillsVisible = True
    199             self.skillPlanContents.state = uiconst.UI_PICKCHILDREN
    200             self.UpdateToggleContentsBtn(isSkillPlanVisible=True)
    201 
    202     def UpdateToggleContentsBtn(self, isSkillPlanVisible):
    203         if isSkillPlanVisible:
    204             self.toggleContentsButton.texturePath = 'res:/UI/Texture/Shared/DarkStyle/buttonInProgressArrowRight.png'
    205             self.toggleContentsButton.SetLabel(GetByLabel('UI/SkillPlan/HideSkillPlanContents'))
    206         else:
    207             self.toggleContentsButton.texturePath = 'res:/UI/Texture/Shared/DarkStyle/buttonInProgressArrow.png'
    208             self.toggleContentsButton.SetLabel(GetByLabel('UI/SkillPlan/ShowSkillPlanContents'))
    209 
    210     def IsCurrentSkillPlan(self, skillPlanID):
    211         return self.skillPlan and skillPlanID == self.skillPlan.GetID()
    212 
    213     def OnSkillPlanSaved(self, skillPlan):
    214         if self.IsCurrentSkillPlan(skillPlan.GetID()):
    215             self.skillPlanContents.SetSkillPlan(self.skillPlan)
    216             self.UpdateInformation()
    217 
    218     def OnTrackedPlanChanged(self, untrackedPlan, _):
    219         if untrackedPlan and self.IsCurrentSkillPlan(untrackedPlan.GetID()):
    220             self.UpdateComponents()
    221 
    222     def SetSkillPlan(self, skillPlan):
    223         if self.skillPlan:
    224             animations.FadeTo(self.overviewCont, self.overviewCont.opacity, 0.0, 0.1)
    225         else:
    226             self.overviewCont.opacity = 0.0
    227         self.skillPlan = skillPlan
    228         self.lockedCont.SetSkillPlan(self.skillPlan)
    229         self.skillPlanProgressIndicator.SetSkillPlan(self.skillPlan)
    230         self.headerCont.SetCaption(skillPlan.GetTypeName())
    231         animations.FadeTo(self.overviewCont, self.overviewCont.opacity, 1.0, 0.1)
    232         self.saveButton.Enable()
    233         self.shareButton.Enable()
    234         self.trackButton.Enable()
    235         self.deleteButton.Enable()
    236         self.UpdateInformation()
    237         self.UpdateComponents()
    238         self.UpdateUniquUiNames()
    239 
    240     def UpdateUniquUiNames(self):
    241         try:
    242             planID = self.skillPlan.GetID().int
    243             self.toggleContentsButton.uniqueUiName = GetUniqueSkillPlanBtn(planID, 0)
    244             self.startTrainingBtn.uniqueUiName = GetUniqueSkillPlanBtn(planID, 1)
    245         except Exception:
    246             pass
    247 
    248     def UpdateComponents(self):
    249         self.UpdateStartTrainingButton()
    250         self.UpdateTrackedButton()
    251         self.UpdateLockedCont()
    252         if self.skillsVisible and self.skillPlanContents:
    253             self.skillPlanContents.UpdateSkillsMissingBanner()
    254             self.skillPlanContents.UpdateOmegaBanner()
    255         if self.skillPlan and self.skillPlan.IsCompleted():
    256             self.completedBanner.Show()
    257             self.bottomButtonsCont.Hide()
    258         else:
    259             self.completedBanner.Hide()
    260             self.bottomButtonsCont.Show()
    261 
    262     def UpdateLockedCont(self):
    263         if not self.skillPlan:
    264             return
    265         self.lockedCont.Update()
    266 
    267     def UpdateStartTrainingButton(self):
    268         if not self.skillPlan or not self.skillPlan.IsTrainable():
    269             self.startTrainingBtn.Disable()
    270             self.startTrainingBtn.SetHint(GetByLabel('UI/SkillPlan/StartTrainingLockedHint'))
    271         elif self.skillPlan.IsQueuedOrTrained():
    272             self.startTrainingBtn.Disable()
    273             self.startTrainingBtn.SetHint(GetByLabel('UI/SkillPlan/StartTrainingNothingToTrainHint'))
    274         else:
    275             self.startTrainingBtn.Enable()
    276             self.startTrainingBtn.SetHint(GetByLabel('UI/SkillPlan/StartTrainingHint'))
    277 
    278     def UpdateTrackedButton(self):
    279         if not self.skillPlan:
    280             return
    281         if GetSkillPlanSvc().IsSkillPlanTracked(self.skillPlan.GetID()):
    282             texturePath = eveicon.camera_untrack
    283         else:
    284             texturePath = eveicon.look_at
    285         self.trackButton.texturePath = texturePath
    286 
    287     def UpdateInformation(self):
    288         if not self.skillPlan:
    289             return
    290         self.headerCont.SetSkillPlanName(self.skillPlan.GetName())
    291         self.descriptionLabel.text = self.skillPlan.GetDescription()
    292         self.UpdateFactionIcon()
    293         self.UpdateCareerPathIcon()
    294         if self.skillPlan.IsEditable():
    295             self.editButton.display = True
    296             self.deleteButton.display = True
    297         else:
    298             self.editButton.display = False
    299             self.deleteButton.display = False
    300 
    301     def UpdateCareerPathIcon(self):
    302         careerPathID = self.skillPlan.GetCareerPathID()
    303         if careerPathID:
    304             self.careerPathIcon.display = True
    305             self.careerPathIcon.texturePath = careerConst.CAREERS_32_SIZES[careerPathID]
    306         else:
    307             self.careerPathIcon.display = False
    308 
    309     def UpdateFactionIcon(self):
    310         factionID = self.skillPlan.GetFactionID()
    311         if factionID:
    312             self.factionIcon.Show()
    313             self.factionIcon.texturePath = ICON_BY_FACTION_ID[factionID]
    314         else:
    315             self.factionIcon.Hide()
    316 
    317     def OnTrackButton(self, *args):
    318         if not self.skillPlan:
    319             return
    320         if not self.skillPlan.IsTrackable():
    321             self._CreateCopySelectAndTrack()
    322         else:
    323             self._ToggleTracked(self.skillPlan.GetID())
    324 
    325     def _CreateCopySelectAndTrack(self):
    326         skillPlan = self.GetSkillPlanCopy()
    327         skillPlanUISignals.on_selected(skillPlan)
    328         GetSkillPlanSvc().SetTrackedSkillPlanID(skillPlan.GetID())
    329 
    330     def _ToggleTracked(self, skillPlanID):
    331         if GetSkillPlanSvc().IsSkillPlanTracked(skillPlanID):
    332             GetSkillPlanSvc().SetTrackedSkillPlanID(None)
    333         else:
    334             GetSkillPlanSvc().SetTrackedSkillPlanID(skillPlanID)
    335             if self.skillPlan.IsCertified():
    336                 log_certified_skill_plan_track_plan_clicked(skillPlanID)
    337         self.UpdateTrackedButton()
    338 
    339     def GetSkillPlanCopy(self):
    340         uthread2.start_tasklet(prompt_player_fsd_dialog, 'SkillPlanCopied')
    341         return GetSkillPlanSvc().SaveCopyOfPlanAsPersonalSkillPlan(self.skillPlan)
    342 
    343     def OnEditButton(self, *args):
    344         skillPlan = self.skillPlan if self.skillPlan.IsEditable() else self.GetSkillPlanCopy()
    345         skillPlanUISignals.on_edit_button(skillPlan)
    346 
    347     def OnDeleteButton(self, *args):
    348         self.deleteButton.Disable()
    349         try:
    350             skillPlanUISignals.on_delete_button(self.skillPlan.GetID())
    351         finally:
    352             self.deleteButton.Enable()
    353 
    354     def TrainSkills(self, *args):
    355         if self.skillPlan:
    356             numSkillsAdded = self.skillPlan.AddToTrainingQueue()
    357             self._CheckSetCurrentSkillPlanAsTracked()
    358             self.UpdateTrackedButton()
    359             if numSkillsAdded > 0:
    360                 skillPlanId = self.skillPlan.GetID()
    361                 skillPlanName = self.skillPlan.GetName()
    362                 self.TriggerSkillsAddedNotification(numSkillsAdded, skillPlanName)
    363                 if self.skillPlan.IsCertified():
    364                     log_certified_skill_plan_train_all_clicked(skillPlanId)
    365 
    366     def _CheckSetCurrentSkillPlanAsTracked(self):
    367         trackedSkillplan = GetSkillPlanSvc().GetTrackedSkillPlan()
    368         skillPlan = self.skillPlan if self.skillPlan.IsTrackable() else self.GetSkillPlanCopy()
    369         if trackedSkillplan is None:
    370             GetSkillPlanSvc().SetTrackedSkillPlanID(skillPlan.GetID())
    371         elif trackedSkillplan.GetID() != skillPlan.GetID():
    372             if prompt_player_fsd_dialog('AskTrackPlan', {}, uiconst.YESNO, suppress=uiconst.ID_YES) == uiconst.ID_YES:
    373                 GetSkillPlanSvc().SetTrackedSkillPlanID(skillPlan.GetID())
    374 
    375     def OnSubscriptionChanged(self):
    376         self.UpdateComponents()
    377 
    378     def OnSkillsAvailable(self, typeIDs):
    379         self.UpdateComponents()
    380 
    381     def OnSkillQueueChanged(self):
    382         if self.destroyed:
    383             return
    384         self.UpdateComponents_throttled()
    385 
    386     def OnSkillsChanged(self, change):
    387         self.UpdateComponents()
    388 
    389     def UpdateComponents_throttled(self):
    390         if not getattr(self, 'updateComponentsThrottleFunc', None):
    391 
    392             @threadutils.throttled(1.0)
    393             def _UpdateComponents_throttled():
    394                 self.UpdateComponents()
    395 
    396             self.updateComponentsThrottleFunc = _UpdateComponents_throttled
    397         self.updateComponentsThrottleFunc()
    398 
    399     @staticmethod
    400     def TriggerSkillsAddedNotification(numSkills, planName):
    401         notification = Notification.MakeSkillNotification(header=GetByLabel('UI/SkillPlan/SkillsAddedNotification', numSkills=numSkills, planName=planName), text='', created=blue.os.GetWallclockTime(), callBack=None, notificationType=notificationTypeSkillsAddedFromSkillPlan)
    402         sm.ScatterEvent('OnNewNotificationReceived', notification)
    403 
    404     def LoadFactionTooltip(self, tooltipPanel, *args):
    405         factionID = self.skillPlan.GetFactionID()
    406         if factionID:
    407             self._LoadTooltipForIcons(tooltipPanel, GetByLabel('UI/SkillPlan/SkillPlanFaction'), GetByLabel(HINT_BY_FACTION_ID[factionID]))
    408 
    409     def LoadCareerTooltip(self, tooltipPanel, *args):
    410         careerPath = self.skillPlan.GetCareerPathID()
    411         if careerPath:
    412             self._LoadTooltipForIcons(tooltipPanel, GetByLabel('UI/SkillPlan/SkillPlanCareerPath'), GetByLabel(HINT_BY_CAREER_ID[careerPath]))
    413 
    414     def _LoadTooltipForIcons(self, tooltipPanel, header, text):
    415         tooltipPanel.LoadStandardSpacing()
    416         tooltipPanel.columns = 1
    417         tooltipPanel.AddMediumHeader(text=header)
    418         tooltipPanel.AddLabelMedium(text=text, wrapWidth=300)
    419 
    420 
    421 class LinkedSkillPlanContainer(SelectedSkillPlanContainer):
    422 
    423     def ApplyAttributes(self, attributes):
    424         super(LinkedSkillPlanContainer, self).ApplyAttributes(attributes)
    425         self.contentsCont.padRight = 6
    426         self.bgCont.width = 1.0
    427         showSkills = attributes.showSkills
    428         if showSkills:
    429             self._ShowSkillsPanel()
    430             self.skillsVisible = True
    431         else:
    432             self._HideSkillsPanel()
    433 
    434     def ConstructBackground(self):
    435         pass
    436 
    437     def ConstructCloseButton(self):
    438         pass
    439 
    440     def UpdateInformation(self):
    441         super(LinkedSkillPlanContainer, self).UpdateInformation()
    442         self.deleteButton.display = False
    443 
    444     def HideSkills(self):
    445         if self.skillsVisible:
    446             self._HideSkillsPanel()
    447             self.skillsVisible = False
    448 
    449     def _HideSkillsPanel(self):
    450         self.skillPlanContents.width = 0.0
    451         self.skillPlanContents.opacity = 0.0
    452         self.skillPlanContents.state = uiconst.UI_DISABLED
    453         self.overviewCont.width = 1.0
    454         self.UpdateToggleContentsBtn(isSkillPlanVisible=False)
    455 
    456     def ShowSkills(self, *args):
    457         if not self.skillsVisible:
    458             self._ShowSkillsPanel()
    459             self.skillsVisible = True
    460 
    461     def _ShowSkillsPanel(self):
    462         uthread2.start_tasklet(self.skillPlanContents.SetSkillPlan, self.skillPlan)
    463         self.skillPlanContents.width = 1.0
    464         self.skillPlanContents.opacity = 1.0
    465         self.skillPlanContents.state = uiconst.UI_PICKCHILDREN
    466         self.overviewCont.width = WIDTH_OVERVIEW_CONT
    467         self.UpdateToggleContentsBtn(isSkillPlanVisible=True)
    468 
    469     def OnTrackButton(self, *args):
    470         super(LinkedSkillPlanContainer, self).OnTrackButton(*args)
    471         if not self.skillPlan:
    472             return
    473         OpenSkillPlanWindow()
    474 
    475     def OnEditButton(self, *args):
    476         OpenSkillPlanWindow()
    477         super(LinkedSkillPlanContainer, self).OnEditButton(*args)
    478 
    479     def TrainSkills(self, *args):
    480         if self.skillPlan:
    481             OpenSkillPlanWindow()
    482         super(LinkedSkillPlanContainer, self).TrainSkills(*args)