diff --git a/graphs/data/base/graph.py b/graphs/data/base/graph.py index 7e812eec1..7f1f8dd04 100644 --- a/graphs/data/base/graph.py +++ b/graphs/data/base/graph.py @@ -125,6 +125,12 @@ class FitGraph(metaclass=ABCMeta): cacheFitID, cacheTgtType, cacheTgtID = cacheKey if cacheTgtType == 'profile' and extraData == cacheTgtID: plotKeysToClear.add(cacheKey) + # Target fit resist mode changed + elif reason == GraphCacheCleanupReason.resistModeChanged: + for cacheKey in self._plotCache: + cacheFitID, cacheTgtType, cacheTgtID = cacheKey + if cacheTgtType == 'fit' and extraData == cacheTgtID: + plotKeysToClear.add(cacheKey) # Wipe out whole plot cache otherwise else: for cacheKey in self._plotCache: diff --git a/graphs/events.py b/graphs/events.py new file mode 100644 index 000000000..d9989725c --- /dev/null +++ b/graphs/events.py @@ -0,0 +1,4 @@ +# noinspection PyPackageRequirements +import wx.lib.newevent + +ResistModeChanged, RESIST_MODE_CHANGED = wx.lib.newevent.NewEvent() diff --git a/graphs/gui/frame.py b/graphs/gui/frame.py index 3ef624139..5d70dc50d 100644 --- a/graphs/gui/frame.py +++ b/graphs/gui/frame.py @@ -29,9 +29,8 @@ from logbook import Logger import gui.display import gui.globalEvents as GE import gui.mainFrame -from eos.saveddata.fit import Fit -from eos.saveddata.targetProfile import TargetProfile from graphs.data.base import FitGraph +from graphs.events import RESIST_MODE_CHANGED from gui.bitmap_loader import BitmapLoader from service.const import GraphCacheCleanupReason from service.settings import GraphSettings @@ -131,6 +130,7 @@ class GraphFrame(wx.Frame): self.mainFrame.Bind(GE.TARGET_PROFILE_RENAMED, self.OnProfileRenamed) self.mainFrame.Bind(GE.TARGET_PROFILE_CHANGED, self.OnProfileChanged) self.mainFrame.Bind(GE.TARGET_PROFILE_REMOVED, self.OnProfileRemoved) + self.mainFrame.Bind(RESIST_MODE_CHANGED, self.OnResistModeChanged) self.mainFrame.Bind(GE.GRAPH_OPTION_CHANGED, self.OnGraphOptionChanged) self.Layout() @@ -196,6 +196,13 @@ class GraphFrame(wx.Frame): self.ctrlPanel.OnProfileRemoved(event) self.draw() + def OnResistModeChanged(self, event): + event.Skip() + for fitID in event.fitIDs: + self.clearCache(reason=GraphCacheCleanupReason.resistModeChanged, extraData=fitID) + self.ctrlPanel.OnResistModeChanged(event) + self.draw() + def OnGraphOptionChanged(self, event): event.Skip() self.clearCache(reason=GraphCacheCleanupReason.optionChanged) @@ -216,6 +223,7 @@ class GraphFrame(wx.Frame): self.mainFrame.Unbind(GE.TARGET_PROFILE_RENAMED, handler=self.OnProfileRenamed) self.mainFrame.Unbind(GE.TARGET_PROFILE_CHANGED, handler=self.OnProfileChanged) self.mainFrame.Unbind(GE.TARGET_PROFILE_REMOVED, handler=self.OnProfileRemoved) + self.mainFrame.Unbind(RESIST_MODE_CHANGED, handler=self.OnResistModeChanged) self.mainFrame.Unbind(GE.GRAPH_OPTION_CHANGED, handler=self.OnGraphOptionChanged) self.Destroy() diff --git a/graphs/gui/lists.py b/graphs/gui/lists.py index d4c48e907..39f31e417 100644 --- a/graphs/gui/lists.py +++ b/graphs/gui/lists.py @@ -38,7 +38,7 @@ class BaseWrapperList(gui.display.Display): def __init__(self, graphFrame, parent): super().__init__(parent) self.graphFrame = graphFrame - self.__wrappers = [] + self._wrappers = [] self.hoveredRow = None self.hoveredColumn = None @@ -51,7 +51,7 @@ class BaseWrapperList(gui.display.Display): @property def wrappers(self): # Sort fits first, then target profiles - return sorted(self.__wrappers, key=lambda w: not w.isFit) + return sorted(self._wrappers, key=lambda w: not w.isFit) # UI-related stuff @property @@ -146,11 +146,11 @@ class BaseWrapperList(gui.display.Display): return None def removeWrappers(self, wrappers): - wrappers = set(wrappers).intersection(self.__wrappers) + wrappers = set(wrappers).intersection(self._wrappers) if not wrappers: return for wrapper in wrappers: - self.__wrappers.remove(wrapper) + self._wrappers.remove(wrapper) self.updateView() for wrapper in wrappers: if wrapper.isFit: @@ -169,16 +169,16 @@ class BaseWrapperList(gui.display.Display): return wrappers def appendItem(self, item): - self.__wrappers.append(self.wrapperClass(item)) + self._wrappers.append(self.wrapperClass(item)) def containsFitID(self, fitID): - for wrapper in self.__wrappers: + for wrapper in self._wrappers: if wrapper.isFit and wrapper.item.ID == fitID: return True return False def containsProfileID(self, profileID): - for wrapper in self.__wrappers: + for wrapper in self._wrappers: if wrapper.isProfile and wrapper.item.ID == profileID: return True return False @@ -189,13 +189,13 @@ class BaseWrapperList(gui.display.Display): self.updateView() def OnFitChanged(self, event): - if set(event.fitIDs).intersection(w.item.ID for w in self.__wrappers if w.isFit): + if set(event.fitIDs).intersection(w.item.ID for w in self._wrappers if w.isFit): self.updateView() def OnFitRemoved(self, event): - wrapper = next((w for w in self.__wrappers if w.isFit and w.item.ID == event.fitID), None) + wrapper = next((w for w in self._wrappers if w.isFit and w.item.ID == event.fitID), None) if wrapper is not None: - self.__wrappers.remove(wrapper) + self._wrappers.remove(wrapper) self.updateView() def OnProfileRenamed(self, event): @@ -207,9 +207,9 @@ class BaseWrapperList(gui.display.Display): self.updateView() def OnProfileRemoved(self, event): - wrapper = next((w for w in self.__wrappers if w.isProfile and w.item.ID == event.profileID), None) + wrapper = next((w for w in self._wrappers if w.isProfile and w.item.ID == event.profileID), None) if wrapper is not None: - self.__wrappers.remove(wrapper) + self._wrappers.remove(wrapper) self.updateView() # Context menu handlers @@ -223,7 +223,7 @@ class BaseWrapperList(gui.display.Display): self.graphFrame.draw() def getExistingFitIDs(self): - return [w.item.ID for w in self.__wrappers if w.isFit] + return [w.item.ID for w in self._wrappers if w.isFit] def addFitsByIDs(self, fitIDs): sFit = Fit.getInstance() @@ -290,6 +290,10 @@ class TargetWrapperList(BaseWrapperList): if menu: self.PopupMenu(menu) + def OnResistModeChanged(self, event): + if set(event.fitIDs).intersection(w.item.ID for w in self._wrappers if w.isFit): + self.updateView() + @property def defaultTTText(self): return 'Drag a fit into this list to have your fits graphed against it' diff --git a/graphs/gui/panel.py b/graphs/gui/panel.py index 484d608b6..b72dc8131 100644 --- a/graphs/gui/panel.py +++ b/graphs/gui/panel.py @@ -366,6 +366,9 @@ class GraphControlPanel(wx.Panel): self.sourceList.OnProfileRemoved(event) self.targetList.OnProfileRemoved(event) + def OnResistModeChanged(self, event): + self.targetList.OnResistModeChanged(event) + def formatLabel(self, axisDef): if axisDef.unit is None: return axisDef.label diff --git a/gui/builtinContextMenus/__init__.py b/gui/builtinContextMenus/__init__.py index 39b19107c..ac5cdd8ab 100644 --- a/gui/builtinContextMenus/__init__.py +++ b/gui/builtinContextMenus/__init__.py @@ -12,6 +12,7 @@ from gui.builtinContextMenus import moduleAmmoChange from gui.builtinContextMenus import moduleSpool from gui.builtinContextMenus import boosterSideEffects from gui.builtinContextMenus import fighterAbilities +from gui.builtinContextMenus import resistMode # Item info from gui.builtinContextMenus import itemStats from gui.builtinContextMenus import itemMarketJump diff --git a/gui/builtinContextMenus/resistMode.py b/gui/builtinContextMenus/resistMode.py new file mode 100644 index 000000000..1401298eb --- /dev/null +++ b/gui/builtinContextMenus/resistMode.py @@ -0,0 +1,66 @@ +from collections import OrderedDict + +# noinspection PyPackageRequirements +import wx + +import gui.mainFrame +from graphs.events import ResistModeChanged +from graphs.wrapper import TargetWrapper +from gui.contextMenu import ContextMenuCombined +from service.const import TargetResistMode + + +optionMap = OrderedDict(( + ('Auto', TargetResistMode.auto), + ('Shield', TargetResistMode.shield), + ('Armor', TargetResistMode.armor), + ('Hull', TargetResistMode.hull), + ('Weighed Average', TargetResistMode.weighedAverage))) + + +class TargetWrapperResists(ContextMenuCombined): + + def __init__(self): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + + def display(self, callingWindow, srcContext, mainItem, selection): + if srcContext != 'graphTgtList': + return False + if not isinstance(mainItem, TargetWrapper) or not mainItem.isFit: + return False + self.callingWindow = callingWindow + self.selection = selection + return True + + def getText(self, callingWindow, itmContext, mainItem, selection): + return 'Resist Mode' + + def addOption(self, menu, optionLabel): + id = ContextMenuCombined.nextID() + self.optionIds[id] = optionLabel + menuItem = wx.MenuItem(menu, id, optionLabel, kind=wx.ITEM_CHECK) + menu.Bind(wx.EVT_MENU, self.handleMode, menuItem) + return menuItem + + def getSubMenu(self, callingWindow, context, mainItem, selection, rootMenu, i, pitem): + msw = True if "wxMSW" in wx.PlatformInfo else False + self.optionIds = {} + sub = wx.Menu() + for optionLabel, optionValue in optionMap.items(): + menuItem = self.addOption(rootMenu if msw else sub, optionLabel) + sub.Append(menuItem) + menuItem.Check(mainItem.resistMode == optionValue) + return sub + + def handleMode(self, event): + optionLabel = self.optionIds[event.Id] + optionValue = optionMap[optionLabel] + changedFitIDs = set() + for wrapper in self.selection: + if wrapper.isFit and wrapper.resistMode != optionValue: + wrapper.resistMode = optionValue + changedFitIDs.add(wrapper.item.ID) + wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), ResistModeChanged(fitIDs=changedFitIDs)) + + +TargetWrapperResists.register() diff --git a/service/const.py b/service/const.py index 056975543..4ffab0db4 100644 --- a/service/const.py +++ b/service/const.py @@ -128,6 +128,7 @@ class GraphCacheCleanupReason(IntEnum): graphSwitched = autoId() inputChanged = autoId() optionChanged = autoId() + resistModeChanged = autoId() @unique