Added undo/redo foundations. Capable of undoing and redoing delete operations

Wed, 10 Apr 2013 00:46:32 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Wed, 10 Apr 2013 00:46:32 +0300
changeset 85
b1541b547c8c
parent 84
c9438ea54ed9
child 86
d7e02a4315a7

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
 //

mercurial