Laid down the foundations of the new history system

Mon, 10 Jun 2013 15:15:23 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Mon, 10 Jun 2013 15:15:23 +0300
changeset 271
d5ec224c1879
parent 270
f5f2353af0d9
child 272
2074672a6554

Laid down the foundations of the new history system

changelog.txt file | annotate | diff | comparison | revisions
src/file.cpp file | annotate | diff | comparison | revisions
src/file.h file | annotate | diff | comparison | revisions
src/gldraw.cpp file | annotate | diff | comparison | revisions
src/gui.cpp file | annotate | diff | comparison | revisions
src/gui_editactions.cpp file | annotate | diff | comparison | revisions
src/history.cpp file | annotate | diff | comparison | revisions
src/history.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
src/types.h file | annotate | diff | comparison | revisions
--- a/changelog.txt	Sat Jun 01 22:42:52 2013 +0300
+++ b/changelog.txt	Mon Jun 10 15:15:23 2013 +0300
@@ -1,5 +1,5 @@
 =================================================
-== Changes in version 1.1
+== Changes since version 1.0
 =================================================
 
 - Added a progress dialog for file loading to respond to desktops while loading files. With large files
--- a/src/file.cpp	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/file.cpp	Mon Jun 10 15:15:23 2013 +0300
@@ -91,6 +91,7 @@
 LDOpenFile::LDOpenFile () {
 	setImplicit (true);
 	setSavePos (-1);
+	history ().setFile (this);
 }
 
 // =============================================================================
@@ -429,6 +430,7 @@
 	g_win->R ()->setFile (f);
 	g_win->fullRefresh ();
 	g_win->updateTitle ();
+	f->history ().updateActions ();
 }
 
 // =============================================================================
@@ -819,7 +821,11 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 ulong LDOpenFile::addObject (LDObject* obj) {
-	m_objs << obj;
+	PROP_NAME (history).add (new AddHistory (PROP_NAME (objs).size (), obj));
+	PROP_NAME (objs) << obj;
+	
+	if (obj->getType () == LDObject::Vertex)
+		PROP_NAME (vertices) << obj;
 	
 	if (this == g_curfile)
 		g_BBox.calcObject (obj);
@@ -831,6 +837,7 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void LDOpenFile::insertObj (const ulong pos, LDObject* obj) {
+	m_history.add (new AddHistory (pos, obj));
 	m_objs.insert (pos, obj);
 	
 	if (this == g_curfile)
@@ -841,16 +848,8 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void LDOpenFile::forgetObject (LDObject* obj) {
-	// Find the index for the given object
-	ulong idx;
-	for (idx = 0; idx < (ulong)m_objs.size(); ++idx)
-		if (m_objs[idx] == obj)
-			break; // found it
-	
-	if (idx >= m_objs.size ())
-		return; // was not found
-	
-	// Erase it from memory
+	ulong idx = obj->getIndex (this);
+	m_history.add (new DelHistory (idx, obj));
 	m_objs.erase (idx);
 	
 	// Update the bounding box
--- a/src/file.h	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/file.h	Mon Jun 10 15:15:23 2013 +0300
@@ -52,6 +52,7 @@
 	PROPERTY (vector<LDObject*>, cache, setCache)
 	PROPERTY (long, savePos, setSavePos)
 	MUTABLE_READ_PROPERTY (History, history)
+	READ_PROPERTY (vector<LDObject*>, vertices, setVertices)
 	
 public:
 	typedef vector<LDObject*>::it it;
--- a/src/gldraw.cpp	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/gldraw.cpp	Mon Jun 10 15:15:23 2013 +0300
@@ -1268,9 +1268,11 @@
 	}
 	
 	if (obj) {
+		file ()->history ().open ();
 		file ()->addObject (obj);
 		compileObject (obj);
 		g_win->fullRefresh ();
+		file ()->history ().close ();
 	}
 	
 	m_drawedVerts.clear ();
--- a/src/gui.cpp	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/gui.cpp	Mon Jun 10 15:15:23 2013 +0300
@@ -133,8 +133,6 @@
 	
 	// things not implemented yet
 	findAction ("help")->setEnabled (false);
-	
-	g_curfile->history ().updateActions ();
 }
 
 // =============================================================================
@@ -528,8 +526,11 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
+EXTERN_ACTION (undo);
+EXTERN_ACTION (redo);
 void ForgeWindow::slot_action () {
-	g_curfile->history ().open ();
+	if (sender () != ACTION (undo) && sender () != ACTION (redo))
+		g_curfile->history ().open ();
 	
 	// Get the action that triggered this slot.
 	QAction* qAct = static_cast<QAction*> (sender ());
--- a/src/gui_editactions.cpp	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/gui_editactions.cpp	Mon Jun 10 15:15:23 2013 +0300
@@ -366,11 +366,11 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 MAKE_ACTION (undo, "Undo", "undo", "Undo a step.", CTRL (Z)) {
-	
+	g_curfile->history ().undo ();
 }
 
 MAKE_ACTION (redo, "Redo", "redo", "Redo a step.", CTRL_SHIFT (Z)) {
-	
+	g_curfile->history ().redo ();
 }
 
 MAKE_ACTION (showHistory, "Edit History", "history", "Show the history dialog.", (0)) {
--- a/src/history.cpp	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/history.cpp	Mon Jun 10 15:15:23 2013 +0300
@@ -21,6 +21,7 @@
 #include "file.h"
 #include "misc.h"
 #include "gui.h"
+#include "gldraw.h"
 
 EXTERN_ACTION (undo)
 EXTERN_ACTION (redo)
@@ -30,11 +31,33 @@
 }
 
 void History::undo () {
+	if (m_changesets.size () == 0 || pos () == -1)
+		return;
 	
+	const list& set = changeset (pos ());
+	
+	// Iterate the list in reverse and undo all actions
+	for (const AbstractHistoryEntry* change : c_rev<AbstractHistoryEntry*> (set))
+		change->undo ();
+	
+	setPos (pos () - 1);
+	g_win->refresh ();
+	updateActions ();
 }
 
 void History::redo () {
+	if (pos () == (long) m_changesets.size ())
+		return;
 	
+	const list& set = changeset (pos () + 1);
+	
+	// Redo things - in the order as they were done in the first place
+	for (const AbstractHistoryEntry* change : set)
+		change->redo ();
+	
+	setPos (pos () + 1);
+	g_win->refresh ();
+	updateActions ();
 }
 
 void History::clear () {
@@ -42,8 +65,8 @@
 }
 
 void History::updateActions () {
-	ACTION (undo)->setEnabled (false);
-	ACTION (redo)->setEnabled (false);
+	ACTION (undo)->setEnabled (pos () != -1);
+	ACTION (redo)->setEnabled (pos () < (long) m_changesets.size () - 1);
 }
 
 void History::open () {
@@ -58,19 +81,60 @@
 		return;
 	
 	setOpened (false);
+	
 	if (m_currentArchive.size () == 0)
 		return;
 	
 	while (pos () < size () - 1)
-		m_entries.erase (size () - 1);
+		m_changesets.erase (size () - 1);
 	
-	m_entries << m_currentArchive;
+	m_changesets << m_currentArchive;
 	m_currentArchive.clear ();
 	setPos (pos () + 1);
 	updateActions ();
 }
 
 void History::add (AbstractHistoryEntry* entry) {
-	assert (opened ());
+	if (!opened ()) {
+		delete entry;
+		return;
+	}
+	
+	entry->setParent (this);
 	m_currentArchive << entry;
-}
\ No newline at end of file
+}
+
+// =============================================================================
+void AddHistory::undo () const {
+	LDOpenFile* f = parent ()->file ();
+	LDObject* obj = f->object (index ());
+	f->forgetObject (obj);
+	delete obj;
+}
+
+void AddHistory::redo () const {
+	LDOpenFile* f = parent ()->file ();
+	LDObject* obj = parseLine (code ());
+	f->insertObj (index (), obj);
+	g_win->R ()->compileObject (obj);
+}
+
+AddHistory::~AddHistory () {}
+
+// =============================================================================
+// heh
+void DelHistory::undo () const {
+	LDOpenFile* f = parent ()->file ();
+	LDObject* obj = parseLine (code ());
+	f->insertObj (index (), obj);
+	g_win->R ()->compileObject (obj);
+}
+
+void DelHistory::redo () const {
+	LDOpenFile* f = parent ()->file ();
+	LDObject* obj = f->object (index ());
+	f->forgetObject (obj);
+	delete obj;
+}
+
+DelHistory::~DelHistory () {}
\ No newline at end of file
--- a/src/history.h	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/history.h	Mon Jun 10 15:15:23 2013 +0300
@@ -24,32 +24,29 @@
 
 #define IMPLEMENT_HISTORY_TYPE(N) \
 	virtual ~N##History (); \
-	virtual void undo (); \
-	virtual void redo (); \
-	virtual HistoryType type () { return HISTORY_##N; }
+	virtual void undo () const; \
+	virtual void redo () const; \
+	virtual History::Type type () { return History::N; }
 
 class AbstractHistoryEntry;
 
 // =============================================================================
-enum HistoryType {
-	HISTORY_Del,
-	HISTORY_SetColor,
-	HISTORY_Edit,
-	HISTORY_ListMove,
-	HISTORY_Add,
-	HISTORY_QuadSplit,
-	HISTORY_Inline,
-	HISTORY_Move,
-	HISTORY_Combo,
-};
-
 class History {
 	PROPERTY (long, pos, setPos)
+	PROPERTY (LDOpenFile*, file, setFile)
 	READ_PROPERTY (bool, opened, setOpened)
 	
 public:
 	typedef vector<AbstractHistoryEntry*> list;
 	
+	enum Type {
+		Del,
+		Edit,
+		ListMove,
+		Add,
+		Move,
+	};
+	
 	History ();
 	void undo ();
 	void redo ();
@@ -59,27 +56,33 @@
 	void open ();
 	void close ();
 	void add (AbstractHistoryEntry* entry);
-	long size () const { return m_entries.size (); }
+	long size () const { return m_changesets.size (); }
 	
 	History& operator<< (AbstractHistoryEntry* entry) {
 		add (entry);
 		return *this;
 	}
 	
+	const list& changeset (long pos) const {
+		return m_changesets[pos];
+	}
+	
 private:
 	list m_currentArchive;
-	vector<list> m_entries;
+	vector<list> m_changesets;
 };
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 class AbstractHistoryEntry {
+	PROPERTY (History*, parent, setParent)
+	
 public:
-	virtual void undo () {}
-	virtual void redo () {}
+	virtual void undo () const {}
+	virtual void redo () const {}
 	virtual ~AbstractHistoryEntry () {}
-	virtual HistoryType type () { return (HistoryType)(0); }
+	virtual History::Type type () { return (History::Type) 0; }
 };
 
 // =============================================================================
@@ -93,14 +96,14 @@
 	};
 	
 	PROPERTY (ulong, index, setIndex)
-	PROPERTY (LDObject*, copy, setCopy)
+	PROPERTY (str, code, setCode)
 	PROPERTY (DelHistory::Type, type, setType)
 	
 public:
 	IMPLEMENT_HISTORY_TYPE (Del)
 	
-	DelHistory (ulong idx, LDObject* copy, Type type) :
-		m_index (idx), m_copy (copy), m_type (type) {}
+	DelHistory (ulong idx, LDObject* obj, Type type = Other) :
+		m_index (idx), m_code (obj->raw ()), m_type (type) {}
 };
 
 // =============================================================================
@@ -108,14 +111,14 @@
 // =============================================================================
 class EditHistory : public AbstractHistoryEntry {
 	PROPERTY (ulong, index, setIndex)
-	PROPERTY (LDObject*, oldCopy, setOldCopy)
-	PROPERTY (LDObject*, newCopy, setNewCopy)
+	PROPERTY (str, oldCode, setOldCode)
+	PROPERTY (str, newCode, setNewCode)
 	
 public:
 	IMPLEMENT_HISTORY_TYPE (Edit)
 	
-	EditHistory (ulong idx, LDObject* oldcopy, LDObject* newcopy) :
-		m_index (idx), m_oldCopy (oldcopy), m_newCopy (newcopy) {}
+	EditHistory (ulong idx, str oldCode, str newCode) :
+		m_index (idx), m_oldCode (oldCode), m_newCode (newCode) {}
 };
 
 // =============================================================================
@@ -143,14 +146,14 @@
 	};
 	
 	PROPERTY (ulong, index, setIndex)
-	PROPERTY (LDObject*, copy, setCopy)
+	PROPERTY (str, code, setCode)
 	PROPERTY (AddHistory::Type, type, setType)
 	
 public:
 	IMPLEMENT_HISTORY_TYPE (Add)
 	
-	AddHistory (ulong idx, LDObject* copy, Type type = Other) :
-		m_index (idx), m_copy (copy), m_type (type) {}
+	AddHistory (ulong idx, LDObject* obj, Type type = Other) :
+		m_index (idx), m_code (obj->raw ()), m_type (type) {}
 };
 
 // =============================================================================
--- a/src/main.cpp	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/main.cpp	Mon Jun 10 15:15:23 2013 +0300
@@ -41,6 +41,8 @@
 // =============================================================================
 int main (int argc, char* argv[]) {
 	const QApplication app (argc, argv);
+	g_app = &app;
+	g_curfile = NULL;
 	
 	// Load or create the configuration
 	if (!config::load ()) {
@@ -57,9 +59,6 @@
 	initPartList ();
 	
 	ForgeWindow* win = new ForgeWindow;
-	
-	g_app = &app;
-	
 	newFile ();
 	
 	win->show ();
--- a/src/types.h	Sat Jun 01 22:42:52 2013 +0300
+++ b/src/types.h	Mon Jun 10 15:15:23 2013 +0300
@@ -24,6 +24,9 @@
 
 class String;
 typedef String str;
+template<class T> class ConstVectorReverser;
+template<class T> using c_rev = ConstVectorReverser<T>;
+
 typedef unsigned int uint;
 typedef unsigned short ushort;
 typedef unsigned long ulong;
@@ -129,6 +132,8 @@
 public:
 	typedef typename std::vector<T>::iterator it;
 	typedef typename std::vector<T>::const_iterator c_it;
+	typedef typename std::vector<T>::reverse_iterator r_it;
+	typedef typename std::vector<T>::const_reverse_iterator cr_it;
 	
 	vector () {}
 	vector (initlist<T> vals) {
@@ -151,6 +156,22 @@
 		return m_vect.cend ();
 	}
 	
+	r_it rbegin () {
+		return m_vect.rbegin ();
+	}
+	
+	cr_it crbegin () const {
+		return m_vect.crbegin ();
+	}
+	
+	r_it rend () {
+		return m_vect.rend ();
+	}
+	
+	cr_it crend () const {
+		return m_vect.crend ();
+	}
+	
 	void erase (ulong pos) {
 		assert (pos < size ());
 		m_vect.erase (m_vect.begin () + pos);
@@ -191,7 +212,7 @@
 	vector<T> reverse () const {
 		vector<T> rev;
 		
-		for (const T& val : m_vect)
+		for (const T& val : c_rev<T> (*this))
 			rev << val;
 		
 		return rev;
@@ -239,4 +260,47 @@
 	std::vector<T> m_vect;
 };
 
+template<class T> class VectorReverser {
+public:
+	typedef typename vector<T>::r_it it;
+	
+	VectorReverser (vector<T>& vect) {
+		m_vect = &vect;
+	}
+	
+	it begin () {
+		return m_vect->rbegin ();
+	}
+	
+	it end () {
+		return m_vect->rend ();
+	}
+	
+private:
+	vector<T>* m_vect;
+};
+
+template<class T> class ConstVectorReverser {
+public:
+	typedef typename vector<T>::cr_it it;
+	
+	ConstVectorReverser (const vector<T>& vect) {
+		m_vect = &vect;
+	}
+	
+	it begin () const {
+		return m_vect->crbegin ();
+	}
+	
+	it end () const {
+		return m_vect->crend ();
+	}
+	
+private:
+	const vector<T>* m_vect;
+};
+
+template<class T> using rev = VectorReverser<T>;
+template<class T> using c_rev = ConstVectorReverser<T>;
+
 #endif // TYPES_H
\ No newline at end of file

mercurial