Wed, 10 Apr 2013 00:46:32 +0300
Added undo/redo foundations. Capable of undoing and redoing delete operations
gui.cpp | file | annotate | diff | comparison | revisions | |
gui_editactions.cpp | file | annotate | diff | comparison | revisions | |
history.cpp | file | annotate | diff | comparison | revisions | |
history.h | file | annotate | diff | comparison | revisions | |
ldforge.pro | file | annotate | diff | comparison | revisions | |
misc.h | file | annotate | diff | comparison | revisions |
--- a/gui.cpp Tue Apr 09 21:59:56 2013 +0300 +++ b/gui.cpp Wed Apr 10 00:46:32 2013 +0300 @@ -55,6 +55,8 @@ EXTERN_ACTION (help) EXTERN_ACTION (about) EXTERN_ACTION (aboutQt) +EXTERN_ACTION (undo) +EXTERN_ACTION (redo) vector<actionmeta> g_ActionMeta; cfg (bool, lv_colorize, true); @@ -151,6 +153,9 @@ // Edit menu qEditMenu = menuBar ()->addMenu (tr ("&Edit")); + ADD_MENU_ITEM (Edit, undo) // Undo + ADD_MENU_ITEM (Edit, redo) // Redo + qEditMenu->addSeparator (); // ----- ADD_MENU_ITEM (Edit, cut) // Cut ADD_MENU_ITEM (Edit, copy) // Copy ADD_MENU_ITEM (Edit, paste) // Paste @@ -199,6 +204,8 @@ addToolBar (qInsertToolBar); qEditToolBar = new QToolBar ("Edit"); + ADD_TOOLBAR_ITEM (Edit, undo) + ADD_TOOLBAR_ITEM (Edit, redo) ADD_TOOLBAR_ITEM (Edit, cut) ADD_TOOLBAR_ITEM (Edit, copy) ADD_TOOLBAR_ITEM (Edit, paste)
--- a/gui_editactions.cpp Tue Apr 09 21:59:56 2013 +0300 +++ b/gui_editactions.cpp Wed Apr 10 00:46:32 2013 +0300 @@ -21,6 +21,7 @@ #include "zz_setContentsDialog.h" #include "file.h" #include "zz_colorSelectDialog.h" +#include "history.h" vector<LDObject*> g_Clipboard; @@ -80,7 +81,24 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= ACTION (del, "Delete", "delete", "Delete the selection", KEY (Delete)) { - g_ForgeWindow->deleteSelection (); + vector<LDObject*> sel = g_ForgeWindow->getSelectedObjects (); + + if (sel.size() == 0) + return; + + vector<ulong> ulaIndices; + vector<LDObject*> copies; + + for (LDObject* obj : sel) { + copies.insert (copies.begin(), obj->clone ()); + ulaIndices.insert (ulaIndices.begin(), obj->getIndex (g_CurrentFile)); + + g_CurrentFile->forgetObject (obj); + delete obj; + } + + History::addEntry (new DeleteHistory (ulaIndices, copies)); + g_ForgeWindow->refresh (); } // ============================================================================= @@ -291,4 +309,12 @@ ACTION (moveDown, "Move Down", "arrow-down", "Move the current selection down.", CTRL (Down)) { doMoveSelection (false); +} + +ACTION (undo, "Undo", "undo", "Undo a step.", CTRL (Z)) { + History::undo (); +} + +ACTION (redo, "Redo", "redo", "Redo a step.", CTRL_SHIFT (Z)) { + History::redo (); } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/history.cpp Wed Apr 10 00:46:32 2013 +0300 @@ -0,0 +1,89 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 Santeri `arezey` Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "history.h" +#include "ldtypes.h" +#include "file.h" +#include "misc.h" +#include "gui.h" + +// ============================================================================= +void DeleteHistory::undo () { + for (ulong i = 0; i < cache.size(); ++i) { + LDObject* obj = cache[i]->clone (); + g_CurrentFile->objects.insert (g_CurrentFile->objects.begin() + indices[i], obj); + } + + g_ForgeWindow->refresh (); +} + +// ============================================================================= +void DeleteHistory::redo () { + for (ulong i = 0; i < cache.size(); ++i) { + LDObject* obj = g_CurrentFile->objects[indices[i]]; + + g_CurrentFile->forgetObject (obj); + delete obj; + } + + g_ForgeWindow->refresh (); +} + +// ============================================================================= +DeleteHistory::~DeleteHistory () { + for (LDObject* obj : cache) + delete obj; +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +namespace History { + std::vector<HistoryEntry*> entries; + + static long lPos = -1; + + // ========================================================================= + void addEntry (HistoryEntry* entry) { + // If there's any entries after our current position, we need to remove them now + for (ulong i = lPos + 1; i < entries.size(); ++i) { + + delete entries[i]; + entries.erase (entries.begin() + i); + } + + entries.push_back (entry); + lPos++; + } + + // ========================================================================= + void undo () { + if (lPos == -1) + return; // nothing to undo + + entries[lPos--]->undo (); + } + + // ========================================================================= + void redo () { + if (lPos == (long) entries.size () - 1) + return; // nothing to redo; + + entries[++lPos]->redo (); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/history.h Wed Apr 10 00:46:32 2013 +0300 @@ -0,0 +1,66 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 Santeri `arezey` Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HISTORY_H +#define HISTORY_H + +#include "common.h" + +#define IMPLEMENT_HISTORY_TYPE(N) \ + virtual HistoryType_e getType () const { \ + return HISTORY_##N; \ + } \ + +enum HistoryType_e { + HISTORY_Delete, +}; + +class HistoryEntry { +public: + virtual void undo () {} + virtual void redo () {} + virtual ~HistoryEntry () {} + + virtual HistoryType_e getType () const { + return (HistoryType_e)(0); + }; +}; + +class DeleteHistory : public HistoryEntry { +public: + IMPLEMENT_HISTORY_TYPE (Delete) + + vector<ulong> indices; + vector<LDObject*> cache; + + DeleteHistory (vector<ulong> indices, vector<LDObject*> cache) : + indices (indices), cache (cache) {} + virtual ~DeleteHistory (); + virtual void undo (); + virtual void redo (); +}; + +namespace History { + extern std::vector<HistoryEntry*> entries; + + void addEntry (HistoryEntry* entry); + void undo (); + void redo (); +}; + +#endif // HISTORY_H \ No newline at end of file
--- a/ldforge.pro Tue Apr 09 21:59:56 2013 +0300 +++ b/ldforge.pro Wed Apr 10 00:46:32 2013 +0300 @@ -11,15 +11,16 @@ # Input HEADERS += bbox.h \ + colors.h \ common.h \ + config.h \ + file.h \ gldraw.h \ gui.h \ - file.h \ + history.h \ ldtypes.h \ misc.h \ str.h \ - config.h \ - colors.h \ types.h \ zz_addObjectDialog.h \ zz_colorSelectDialog.h \ @@ -34,6 +35,7 @@ gui.cpp \ gui_actions.cpp \ gui_editactions.cpp \ + history.cpp \ file.cpp \ ldtypes.cpp \ main.cpp \
--- a/misc.h Tue Apr 09 21:59:56 2013 +0300 +++ b/misc.h Wed Apr 10 00:46:32 2013 +0300 @@ -45,6 +45,15 @@ return false; } +template<class T> std::vector<T> reverseVector (std::vector<T> in) { + std::vector<T> out; + + for (T stuff : in) + out.insert (out.begin(), in); + + return out; +} + // ============================================================================= // stringparser //