fittingMgmtCont.py (17070B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fitting\fittingMgmtCont.py 2 from collections import Counter 3 import blue 4 import evetypes 5 from carbon.common.script.util.linkUtil import GetShowInfoLink 6 from carbonui import ButtonStyle, uiconst 7 from carbonui.control.button import Button 8 from carbonui.control.contextMenu.menuEntryData import MenuEntryData 9 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText 10 from carbonui.primitives.container import Container 11 from carbonui.primitives.containerAutoSize import ContainerAutoSize 12 from carbonui.primitives.sprite import Sprite 13 from carbonui.uicore import uicore 14 from carbonui.button.group import ButtonGroup, ButtonSizeMode 15 from eve.client.script.ui.control.eveEditPlainText import EditPlainText 16 from eve.client.script.ui.control.eveLabel import EveLabelMedium 17 from eve.client.script.ui.control.eveScroll import Scroll 18 from eve.client.script.ui.control.infoIcon import InfoIcon 19 from eve.client.script.ui.control.itemIcon import ItemIcon 20 from carbonui.control.tabGroup import TabGroup 21 from eve.client.script.ui.control.utilMenu import UtilMenu 22 from eve.client.script.ui.shared.fittingScreen.missingItemsPopup import OpenBuyAllBox 23 from eve.common.lib.appConst import corpRoleFittingManager, maxLengthFittingDescription 24 from eveexceptions import UserError 25 from inventorycommon.const import categoryStructure, numVisibleSubsystems 26 from inventorycommon.util import IsModularShip, IsSubsystemFlag 27 from localization import GetByLabel 28 from player_messaging.client.ui_message import prompt_player_fsd_dialog 29 from shipfitting.exportFittingUtil import AreModulesTranslated 30 from utillib import KeyVal 31 32 class FittingMgmtCont(Container): 33 default_align = uiconst.TOALL 34 default_clipChildren = True 35 36 def ApplyAttributes(self, attributes): 37 Container.ApplyAttributes(self, attributes) 38 self.saveCallback = attributes.get('saveCallback', None) 39 self.fittingSvc = sm.GetService('fittingSvc') 40 self.saveDeleteButtonsCont = ButtonGroup(name='buttonParent', parent=self, align=uiconst.TOBOTTOM, padTop=8, button_size_mode=ButtonSizeMode.STRETCH) 41 self.mainPanel = Container(name='rightMainPanel', parent=self, align=uiconst.TOALL) 42 topParent = Container(name='topParent', parent=self.mainPanel, align=uiconst.TOTOP, height=64) 43 self.topLeftParent = Container(name='topLeftParent', parent=topParent, align=uiconst.TOLEFT, width=64, padRight=8) 44 self.topRightParent = Container(name='topRightParent', parent=topParent, align=uiconst.TOALL) 45 self.bottomParent = Container(name='bottomParent', parent=self.mainPanel) 46 self.AddTypeIcons() 47 self.AddFittingNameElements() 48 self.AddDescriptionField() 49 self.AddButtons() 50 51 def AddTypeIcons(self): 52 self.shipIcon = FittingDraggableIcon2(name='shipIcon', parent=self.topLeftParent, state=uiconst.UI_NORMAL, pos=(0, 0, 64, 64)) 53 self.shipIcon.fitting = {} 54 self.shipIcon.hint = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/FittingIconHint') 55 self.shipIcon.OnClick = self.ClickDragIcon 56 57 def AddFittingNameElements(self): 58 shipInfoCont = Container(name='shipInfoCont', parent=self.topRightParent, align=uiconst.TOTOP, height=SingleLineEditText.default_height, padTop=12) 59 iconCont = ContainerAutoSize(name='iconCont', align=uiconst.TORIGHT, parent=shipInfoCont) 60 self.infoicon = InfoIcon(parent=iconCont, state=uiconst.UI_HIDDEN, align=uiconst.CENTERRIGHT) 61 UtilMenu(menuAlign=uiconst.TOPRIGHT, parent=iconCont, align=uiconst.CENTERRIGHT, pos=(20, 0, 16, 16), GetUtilMenu=self.SettingMenu, texturePath='res:/UI/Texture/SettingsCogwheel.png', hint=GetByLabel('UI/Common/Settings'), iconSize=18) 62 self.fittingTypeIcon = Sprite(parent=ContainerAutoSize(parent=shipInfoCont, align=uiconst.TOLEFT), pos=(0, 0, 20, 20), texturePath='res:/UI/Texture/WindowIcons/member.png', align=uiconst.CENTERLEFT) 63 self.fittingName = SingleLineEditText(name='fittingName', parent=shipInfoCont, align=uiconst.TOTOP, padding=(4, 0, 4, 0), maxLength=40, label=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/FittingName'), fontsize=12, configName='edit_fittingName', maxWidth=120, OnFocusLost=self.OnEditFieldLostFocus, OnSetFocus=self.OnEditFieldSetFocus) 64 self.OnEditFieldLostFocus() 65 truncatedText = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/Truncated') 66 self.truncatedLabel = EveLabelMedium(text=truncatedText, parent=self.topRightParent, pos=(0, 3, 60, 20), state=uiconst.UI_NORMAL, align=uiconst.TOTOP) 67 self.truncatedLabel.display = True 68 69 def OnEditFieldLostFocus(self, *args): 70 self.fittingName.opacity = 0.5 71 self.fittingName.textLabel.opacity = 2.0 72 73 def OnEditFieldSetFocus(self, *args): 74 self.fittingName.opacity = 1.0 75 self.fittingName.textLabel.opacity = 1.0 76 77 def AddDescriptionField(self): 78 self.fittingDescription = EditPlainText(setvalue=None, parent=self.bottomParent, align=uiconst.TOALL, maxLength=maxLengthFittingDescription) 79 self.fittingInfo = Scroll(name='fittingInfoScroll', parent=self.bottomParent) 80 tabs = [[GetByLabel('UI/Fitting/FittingWindow/FittingManagement/Fittings'), 81 self.fittingInfo, 82 self, 83 None, 84 self.fittingInfo], [GetByLabel('UI/Common/Description'), 85 self.fittingDescription, 86 self, 87 None, 88 self.fittingDescription]] 89 self.fittingInfoTab = TabGroup(name='tabparent', parent=self.bottomParent, idx=0) 90 self.fittingInfoTab.Startup(tabs, 'fittingInfoTab') 91 self.fittingInfo.Startup() 92 93 def AddButtons(self): 94 pass 95 96 def AddFitSaveBtns(self): 97 self.fitBtn = Button(parent=self.saveDeleteButtonsCont, label=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/Fit'), func=self.Fit) 98 self.saveBtn = Button(parent=self.saveDeleteButtonsCont, label=GetByLabel('UI/Common/Buttons/Save'), func=self.Save, get_menu_entry_data_func=self._get_save_sub_menu_data) 99 self.saveBtn.LoadTooltipPanel = self.LoadSaveBtnTooltipPanel 100 101 def _get_save_sub_menu_data(self): 102 sub_menu = [] 103 if session.allianceid: 104 alliance = sm.GetService('alliance').GetAlliance(session.allianceid) 105 if alliance.executorCorpID == session.corpid: 106 sub_menu.append(MenuEntryData(text=GetByLabel('UI/Fitting/FittingWindow/SaveForAlliance'), func=lambda : self.SaveForOwner(session.allianceid))) 107 sub_menu.append(MenuEntryData(text=GetByLabel('UI/Fitting/FittingWindow/SaveForCorp'), func=lambda : self.SaveForOwner(session.corpid))) 108 sub_menu.append(MenuEntryData(text=GetByLabel('UI/Fitting/FittingWindow/SaveForCharacter', charID=session.charid), func=lambda : self.SaveForOwner(session.charid))) 109 return MenuEntryData(text=GetByLabel('UI/Common/Buttons/Save'), func=self.Save, subMenuData=sub_menu) 110 111 def AddDeleteBtn(self): 112 self.deleteBtn = Button(parent=self.saveDeleteButtonsCont, label=GetByLabel('UI/Common/Buttons/Delete'), func=self.Delete, style=ButtonStyle.DANGER) 113 114 def TryAddSimulationBtn(self): 115 self.simulateButton = Button(parent=self.saveDeleteButtonsCont, label=GetByLabel('UI/Fitting/FittingWindow/Simulate'), func=self.SimulateFitting) 116 117 def AddExportBtn(self): 118 self.exportBtn = Button(parent=self.saveDeleteButtonsCont, label=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/ExportToClipboard'), func=self.ExportFittingToClipboard, hint=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/ExportToClipboardHint')) 119 if AreModulesTranslated(session): 120 self.exportBtn.LoadTooltipPanel = self.LoadExportTooltipPanel 121 122 def AddMultiBuyBtn(self): 123 import shipfitting.multiBuyUtil as multiBuyUtil 124 multiBuyUtil.AddBuyButton(parent=self.saveDeleteButtonsCont, fittingMgmtWnd=self) 125 126 def SettingMenu(self, menuParent): 127 nameCbChecked = settings.user.ui.Get('useFittingNameForShips', 0) 128 menuParent.AddCheckBox(text=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/UseFittingNameForShip'), checked=bool(nameCbChecked), callback=(settings.user.ui.Set, 'useFittingNameForShips', not nameCbChecked)) 129 130 def LoadSaveBtnTooltipPanel(self, tooltipPanel, *args): 131 hasCorpRoles = bool(session.corprole & corpRoleFittingManager) 132 if not hasCorpRoles: 133 return 134 tooltipPanel.LoadGeneric1ColumnTemplate() 135 tooltipPanel.state = uiconst.UI_NORMAL 136 tooltipPanel.columns = 1 137 tooltipPanel.margin = (12, 12, 12, 12) 138 tooltipPanel.cellPadding = 0 139 tooltipPanel.cellSpacing = 10 140 saveAllianceBtn = None 141 if session.allianceid and sm.GetService('alliance').GetAlliance(session.allianceid).executorCorpID == session.corpid: 142 saveAllianceBtn = Button(parent=tooltipPanel, label=GetByLabel('UI/Fitting/FittingWindow/SaveForAlliance'), func=self.SaveForOwner, args=(session.allianceid,), align=uiconst.CENTER) 143 saveCorpBtn = Button(parent=tooltipPanel, label=GetByLabel('UI/Fitting/FittingWindow/SaveForCorp'), func=self.SaveForOwner, args=(session.corpid,), align=uiconst.CENTER) 144 savePersonalBtn = Button(parent=tooltipPanel, label=GetByLabel('UI/Fitting/FittingWindow/SaveForCharacter', charID=session.charid), func=self.SaveForOwner, args=(session.charid,), align=uiconst.CENTER) 145 maxWidth = max(saveCorpBtn.width, savePersonalBtn.width) 146 if saveAllianceBtn: 147 maxWidth = max(maxWidth, saveAllianceBtn.width) 148 saveCorpBtn.width = savePersonalBtn.width = maxWidth 149 if saveAllianceBtn: 150 saveAllianceBtn.width = maxWidth 151 152 def LoadExportTooltipPanel(self, tooltipPanel, *args): 153 tooltipPanel.LoadGeneric1ColumnTemplate() 154 tooltipPanel.state = uiconst.UI_NORMAL 155 tooltipPanel.columns = 1 156 tooltipPanel.margin = (12, 12, 12, 12) 157 tooltipPanel.cellPadding = 0 158 tooltipPanel.cellSpacing = 10 159 exportBtn = Button(parent=tooltipPanel, label=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/ExportToClipboardLocalized'), func=self._ExportFittingToClipboard, args=(True,), align=uiconst.CENTER) 160 exportEnglishBtn = Button(parent=tooltipPanel, label=GetByLabel('UI/Fitting/FittingWindow/FittingManagement/ExportToClipboard'), func=self._ExportFittingToClipboard, args=(False,), align=uiconst.CENTER) 161 maxWidth = max(exportEnglishBtn.width, exportBtn.width) 162 exportEnglishBtn.width = exportBtn.width = maxWidth 163 164 def SetFittingTypeIcon(self, fittingOwner): 165 if fittingOwner == session.charid: 166 texturePath = 'res:/UI/Texture/WindowIcons/member.png' 167 text = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/PersonalFitting') 168 elif fittingOwner == session.corpid: 169 texturePath = 'res:/UI/Texture/WindowIcons/corporation.png' 170 text = GetByLabel('UI/Fitting/FittingWindow/FittingManagement/CorporationFitting') 171 else: 172 self.fittingTypeIcon.display = False 173 return 174 self.fittingTypeIcon.display = True 175 self.fittingTypeIcon.hint = text 176 self.fittingTypeIcon.texturePath = texturePath 177 178 def LoadNewFitting(self, fitting, isTruncated = False): 179 self.ShowPanel() 180 self.fitting = fitting 181 self.fittingName.SetValue(fitting.name) 182 self.fittingDescription.SetText(fitting.description) 183 self.fittingDescription.SetText(fitting.description) 184 shipName = GetShowInfoLink(fitting.shipTypeID, evetypes.GetName(fitting.shipTypeID)) 185 self.shipIcon.SetTypeID(fitting.shipTypeID) 186 self.shipIcon.fitting = fitting 187 self.infoicon.Show() 188 self.infoicon.SetTypeID(fitting.shipTypeID) 189 if isTruncated: 190 self.truncatedLabel.display = True 191 else: 192 self.truncatedLabel.display = False 193 fittingOwner = fitting.ownerID 194 self.SetFittingTypeIcon(fittingOwner) 195 scrolllist = self.fittingSvc.GetFittingInfoScrollList(fitting) 196 self.fittingInfo.Load(contentList=scrolllist) 197 if evetypes.GetCategoryID(fitting.shipTypeID) == categoryStructure: 198 self.fitBtn.Disable() 199 else: 200 self.fitBtn.Enable() 201 202 def HidePanel(self): 203 self.display = False 204 self.fitting = None 205 206 def ShowPanel(self): 207 self.display = True 208 209 def GetSelectedFitting(self): 210 return self.fitting 211 212 def ClickDragIcon(self, *args): 213 subsystems = {} 214 if IsModularShip(self.fitting.shipTypeID): 215 for typeID, flag, qty in self.fitting.fitData: 216 if IsSubsystemFlag(flag): 217 subsystems[evetypes.GetGroupID(typeID)] = typeID 218 219 if len(subsystems) != numVisibleSubsystems: 220 raise UserError('NotEnoughSubSystemsNotify', {}) 221 sm.GetService('preview').PreviewType(self.fitting.shipTypeID, subsystems) 222 223 def ShowInfo(self, *args): 224 if self.fitting is not None: 225 sm.GetService('info').ShowInfo(self.fitting.shipTypeID, None) 226 227 def Fit(self, *args): 228 fitting = self.fitting 229 failedToLoad = self.fittingSvc.LoadFitting(fitting, getFailedDict=True) 230 failedToLoadCounter = Counter({x[0]:x[1] for x in failedToLoad}) 231 if failedToLoadCounter: 232 OpenBuyAllBox(failedToLoadCounter, fitting) 233 else: 234 from eve.client.script.ui.shared.fittingScreen.fittingWnd import FittingWindow 235 wnd = FittingWindow.GetIfOpen() 236 if wnd: 237 sm.GetService('ghostFittingSvc').TryExitSimulation(askQuestion=True) 238 239 def Save(self, *args): 240 if self.fitting.ownerID == session.corpid and bool(session.corprole & corpRoleFittingManager): 241 return self.SaveForOwner(session.corpid) 242 else: 243 return self.SaveForOwner(session.charid) 244 245 def SaveForOwner(self, ownerID): 246 if self.fitting.ownerID: 247 self.SaveExistingFitting(ownerID) 248 else: 249 self.SaveNewFitting(ownerID) 250 251 def Delete(self, *args): 252 pass 253 254 def SimulateFitting(self, *args): 255 SimulateFitting(self.fitting) 256 257 def ExportFittingToClipboard(self, *args): 258 self._ExportFittingToClipboard() 259 260 def _ExportFittingToClipboard(self, isLocalized = False): 261 sm.GetService('fittingSvc').ExportFittingToClipboard(self.fitting, isLocalized) 262 263 def SaveExistingFitting(self, newOwnerID): 264 if self.fitting is None: 265 return 266 newFitting = None 267 if newOwnerID != self.fitting.ownerID: 268 return self.SaveNewFitting(newOwnerID) 269 if newFitting is not None: 270 fitting = newFitting 271 else: 272 fitting = self.fitting 273 newName = self.fittingName.GetValue() 274 newDescription = self.fittingDescription.GetValue() 275 blue.synchro.Yield() 276 self.fittingSvc.ChangeNameAndDescription(fitting.fittingID, fitting.ownerID, newName, newDescription) 277 sm.ScatterEvent('OnRedrawFittingMgmt') 278 sm.ScatterEvent('OnFittingsUpdated', self.fitting) 279 if self.saveCallback: 280 self.saveCallback() 281 282 def SaveNewFitting(self, ownerID): 283 name = self.fittingName.GetValue() 284 description = self.fittingDescription.GetValue() 285 fittingID = self.fittingSvc.PersistFitting(ownerID, name, description, fit=(self.fitting.shipTypeID, self.fitting.fitData)) 286 if fittingID > 0 and self.saveCallback: 287 self.saveCallback() 288 289 290 class FittingMgmtContInWnd(FittingMgmtCont): 291 292 def Delete(self, *args): 293 if prompt_player_fsd_dialog('DeleteFitting', {}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES: 294 return 295 if not self.fitting: 296 return 297 ownerID = self.fitting.ownerID 298 fittingID = self.fitting.fittingID 299 self.fittingSvc.DeleteFitting(ownerID, fittingID) 300 self.HidePanel() 301 302 def AddButtons(self): 303 self.AddFitSaveBtns() 304 self.AddMultiBuyBtn() 305 self.TryAddSimulationBtn() 306 self.AddExportBtn() 307 self.AddDeleteBtn() 308 309 310 class FittingMgmtContInStandalone(FittingMgmtCont): 311 312 def AddButtons(self): 313 self.AddFitSaveBtns() 314 self.AddMultiBuyBtn() 315 self.TryAddSimulationBtn() 316 317 318 class FittingDraggableIcon2(ItemIcon): 319 __guid__ = 'xtriui.FittingDraggableIcon2' 320 isDragObject = True 321 322 def Startup(self, fitting): 323 self.fitting = fitting 324 325 def GetDragData(self, *args): 326 entry = KeyVal() 327 entry.fitting = self.fitting 328 entry.__guid__ = 'listentry.FittingEntry' 329 return [entry] 330 331 332 def SimulateFitting(fitting): 333 from eve.client.script.ui.shared.fittingScreen.fittingWnd import FittingWindow 334 wnd = FittingWindow.GetIfOpen() 335 if wnd: 336 wnd.Maximize() 337 else: 338 uicore.cmd.OpenFitting() 339 sm.GetService('ghostFittingSvc').SimulateFitting(fitting)