From 926e0a903526a20effca0164729e5dccf169e78b Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sat, 21 Jul 2018 00:12:28 -0400 Subject: [PATCH] Start working on some undo / redo functionality. this is just the start, only module state changes and fit rename is implemented, and probably not very well x_x --- gui/builtinShipBrowser/fitItem.py | 23 ++++++++++++++--- gui/builtinViews/fittingView.py | 7 +++-- gui/fitCommands/__init__.py | 1 + gui/fitCommands/moduleStateChange.py | 38 ++++++++++++++++++++++++++++ gui/mainFrame.py | 6 +++++ gui/mainMenuBar.py | 4 +-- service/fit.py | 3 +++ 7 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 gui/fitCommands/__init__.py create mode 100644 gui/fitCommands/moduleStateChange.py diff --git a/gui/builtinShipBrowser/fitItem.py b/gui/builtinShipBrowser/fitItem.py index 2f05229d0..99cb9e0bb 100644 --- a/gui/builtinShipBrowser/fitItem.py +++ b/gui/builtinShipBrowser/fitItem.py @@ -21,6 +21,25 @@ from service.fit import Fit pyfalog = Logger(__name__) +class FitRenameCommand(wx.Command): + def __init__(self, fitID, newName): + wx.Command.__init__(self, True, "FitRename") + self.fitID = fitID + self.newName = newName + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.oldName = None + self.sFit = Fit.getInstance() + + def Do(self): + self.oldName, _ = self.sFit.renameFit(self.fitID, self.newName) + wx.PostEvent(self.mainFrame, FitRenamed(fitID=self.fitID)) + return True + + def Undo(self): + self.sFit.renameFit(self.fitID, self.oldName) + wx.PostEvent(self.mainFrame, FitRenamed(fitID=self.fitID)) + return True + class FitItem(SFItem.SFBrowserItem): def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0, None), shipID=None, itemData=None, graphicID=None, @@ -325,14 +344,12 @@ class FitItem(SFItem.SFBrowserItem): self.Refresh() def renameFit(self, event=None): - sFit = Fit.getInstance() self.tcFitName.Show(False) self.editWasShown = 0 fitName = self.tcFitName.GetValue() if fitName: self.fitName = fitName - sFit.renameFit(self.fitID, self.fitName) - wx.PostEvent(self.mainFrame, FitRenamed(fitID=self.fitID)) + self.mainFrame.command.Submit(FitRenameCommand(self.fitID, self.fitName)) else: self.tcFitName.SetValue(self.fitName) diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index d6bf4ae0c..6ccc00c33 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -34,6 +34,7 @@ from gui.bitmap_loader import BitmapLoader import gui.builtinViews.emptyView from logbook import Logger from gui.chrome_tabs import EVT_NOTEBOOK_PAGE_CHANGED +import gui.fitCommands as cmd from service.fit import Fit from service.market import Market @@ -127,6 +128,8 @@ class FittingViewDrop(wx.DropTarget): return t + + class FittingView(d.Display): DEFAULT_COLS = ["State", "Ammo Icon", @@ -642,14 +645,14 @@ class FittingView(d.Display): fitID = self.mainFrame.getActiveFit() ctrl = event.cmdDown or event.middleIsDown click = "ctrl" if ctrl is True else "right" if event.GetButton() == 3 else "left" - sFit.toggleModulesState(fitID, self.mods[self.GetItemData(row)], mods, click) + + self.mainFrame.command.Submit(cmd.FitModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)], mods, click)) # update state tooltip tooltip = self.activeColumns[col].getToolTip(self.mods[self.GetItemData(row)]) if tooltip: self.SetToolTip(tooltip) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) else: event.Skip() diff --git a/gui/fitCommands/__init__.py b/gui/fitCommands/__init__.py new file mode 100644 index 000000000..19100381e --- /dev/null +++ b/gui/fitCommands/__init__.py @@ -0,0 +1 @@ +from .moduleStateChange import FitModuleStateChangeCommand \ No newline at end of file diff --git a/gui/fitCommands/moduleStateChange.py b/gui/fitCommands/moduleStateChange.py new file mode 100644 index 000000000..c490115e2 --- /dev/null +++ b/gui/fitCommands/moduleStateChange.py @@ -0,0 +1,38 @@ +import wx +from service.fit import Fit + +import gui.mainFrame +from gui import globalEvents as GE + + +class FitModuleStateChangeCommand(wx.Command): + def __init__(self, fitID, baseMod, modules, click): + # todo: instead of modules, needs to be positions. Dead objects are a thing + wx.Command.__init__(self, True, "Module State Change") + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.sFit = Fit.getInstance() + self.fitID = fitID + self.baseMod = baseMod + self.modules = modules + self.click = click + + self.old_states = {} + for mod in modules: + # we don't use the actual module as the key, because it may have been deleted in subsequent calls (even if + # we undo a deletion, wouldn't be the same obj). So, we store the position + self.old_states[mod.modPosition] = mod.state + + def Do(self): + # todo: determine if we've changed state (recalc). If not, store that so we don't attempt to recalc on undo + self.sFit.toggleModulesState(self.fitID, self.baseMod, self.modules, self.click) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + + def Undo(self): + # todo: some sanity checking to make sure that we are applying state back to the same modules? + fit = self.sFit.getFit(self.fitID) + for k, v in self.old_states.items(): + fit.modules[k].state = v + self.sFit.recalc(fit) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 9b237663c..2a94f1b2c 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -170,6 +170,8 @@ class MainFrame(wx.Frame): i = wx.Icon(BitmapLoader.getBitmap("pyfa", "gui")) self.SetIcon(i) + self.command = wx.CommandProcessor() + # Create the layout and windows mainSizer = wx.BoxSizer(wx.HORIZONTAL) @@ -514,6 +516,10 @@ class MainFrame(wx.Frame): self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id=wx.ID_PREFERENCES) # User guide self.Bind(wx.EVT_MENU, self.goWiki, id=menuBar.wikiId) + + self.Bind(wx.EVT_MENU, lambda evt: MainFrame.getInstance().command.Undo(), id=wx.ID_UNDO) + + self.Bind(wx.EVT_MENU, lambda evt: MainFrame.getInstance().command.Redo(), id=wx.ID_REDO) # EVE Forums self.Bind(wx.EVT_MENU, self.goForums, id=menuBar.forumId) # Save current character diff --git a/gui/mainMenuBar.py b/gui/mainMenuBar.py index 9c421f779..c0a28f1dc 100644 --- a/gui/mainMenuBar.py +++ b/gui/mainMenuBar.py @@ -90,8 +90,8 @@ class MainMenuBar(wx.MenuBar): editMenu = wx.Menu() self.Append(editMenu, "&Edit") - # editMenu.Append(wx.ID_UNDO) - # editMenu.Append(wx.ID_REDO) + editMenu.Append(wx.ID_UNDO) + editMenu.Append(wx.ID_REDO) editMenu.Append(wx.ID_COPY, "To Clipboard\tCTRL+C", "Export a fit to the clipboard") editMenu.Append(wx.ID_PASTE, "From Clipboard\tCTRL+V", "Import a fit from the clipboard") diff --git a/service/fit.py b/service/fit.py index 122de2fa6..3a4d044eb 100644 --- a/service/fit.py +++ b/service/fit.py @@ -170,8 +170,11 @@ class Fit(object): def renameFit(fitID, newName): pyfalog.debug("Renaming fit ({0}) to: {1}", fitID, newName) fit = eos.db.getFit(fitID) + old_name = fit.name fit.name = newName eos.db.commit() + return old_name, newName + @staticmethod def deleteFit(fitID):