summaryrefslogtreecommitdiff
path: root/src/js/util/mxUndoManager.js
diff options
context:
space:
mode:
authorAdhitya Kamakshidasan2016-04-04 20:02:27 +0530
committerAdhitya Kamakshidasan2016-04-04 20:02:27 +0530
commit5d474b6e265806c9df3fc80e06f8b4dd7fe16aea (patch)
treef64a5027d57f49b9833a8eea48acbd0905a1ceb3 /src/js/util/mxUndoManager.js
downloadxcos-on-web-5d474b6e265806c9df3fc80e06f8b4dd7fe16aea.tar.gz
xcos-on-web-5d474b6e265806c9df3fc80e06f8b4dd7fe16aea.tar.bz2
xcos-on-web-5d474b6e265806c9df3fc80e06f8b4dd7fe16aea.zip
Initial Commit
Diffstat (limited to 'src/js/util/mxUndoManager.js')
-rw-r--r--src/js/util/mxUndoManager.js229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/js/util/mxUndoManager.js b/src/js/util/mxUndoManager.js
new file mode 100644
index 0000000..2cb93cb
--- /dev/null
+++ b/src/js/util/mxUndoManager.js
@@ -0,0 +1,229 @@
+/**
+ * $Id: mxUndoManager.js,v 1.30 2011-10-05 06:39:19 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxUndoManager
+ *
+ * Implements a command history. When changing the graph model, an
+ * <mxUndoableChange> object is created at the start of the transaction (when
+ * model.beginUpdate is called). All atomic changes are then added to this
+ * object until the last model.endUpdate call, at which point the
+ * <mxUndoableEdit> is dispatched in an event, and added to the history inside
+ * <mxUndoManager>. This is done by an event listener in
+ * <mxEditor.installUndoHandler>.
+ *
+ * Each atomic change of the model is represented by an object (eg.
+ * <mxRootChange>, <mxChildChange>, <mxTerminalChange> etc) which contains the
+ * complete undo information. The <mxUndoManager> also listens to the
+ * <mxGraphView> and stores it's changes to the current root as insignificant
+ * undoable changes, so that drilling (step into, step up) is undone.
+ *
+ * This means when you execute an atomic change on the model, then change the
+ * current root on the view and click undo, the change of the root will be
+ * undone together with the change of the model so that the display represents
+ * the state at which the model was changed. However, these changes are not
+ * transmitted for sharing as they do not represent a state change.
+ *
+ * Example:
+ *
+ * When adding an undo manager to a graph, make sure to add it
+ * to the model and the view as well to maintain a consistent
+ * display across multiple undo/redo steps.
+ *
+ * (code)
+ * var undoManager = new mxUndoManager();
+ * var listener = function(sender, evt)
+ * {
+ * undoManager.undoableEditHappened(evt.getProperty('edit'));
+ * };
+ * graph.getModel().addListener(mxEvent.UNDO, listener);
+ * graph.getView().addListener(mxEvent.UNDO, listener);
+ * (end)
+ *
+ * The code creates a function that informs the undoManager
+ * of an undoable edit and binds it to the undo event of
+ * <mxGraphModel> and <mxGraphView> using
+ * <mxEventSource.addListener>.
+ *
+ * Event: mxEvent.CLEAR
+ *
+ * Fires after <clear> was invoked. This event has no properties.
+ *
+ * Event: mxEvent.UNDO
+ *
+ * Fires afer a significant edit was undone in <undo>. The <code>edit</code>
+ * property contains the <mxUndoableEdit> that was undone.
+ *
+ * Event: mxEvent.REDO
+ *
+ * Fires afer a significant edit was redone in <redo>. The <code>edit</code>
+ * property contains the <mxUndoableEdit> that was redone.
+ *
+ * Event: mxEvent.ADD
+ *
+ * Fires after an undoable edit was added to the history. The <code>edit</code>
+ * property contains the <mxUndoableEdit> that was added.
+ *
+ * Constructor: mxUndoManager
+ *
+ * Constructs a new undo manager with the given history size. If no history
+ * size is given, then a default size of 100 steps is used.
+ */
+function mxUndoManager(size)
+{
+ this.size = (size != null) ? size : 100;
+ this.clear();
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxUndoManager.prototype = new mxEventSource();
+mxUndoManager.prototype.constructor = mxUndoManager;
+
+/**
+ * Variable: size
+ *
+ * Maximum command history size. 0 means unlimited history. Default is
+ * 100.
+ */
+mxUndoManager.prototype.size = null;
+
+/**
+ * Variable: history
+ *
+ * Array that contains the steps of the command history.
+ */
+mxUndoManager.prototype.history = null;
+
+/**
+ * Variable: indexOfNextAdd
+ *
+ * Index of the element to be added next.
+ */
+mxUndoManager.prototype.indexOfNextAdd = 0;
+
+/**
+ * Function: isEmpty
+ *
+ * Returns true if the history is empty.
+ */
+mxUndoManager.prototype.isEmpty = function()
+{
+ return this.history.length == 0;
+};
+
+/**
+ * Function: clear
+ *
+ * Clears the command history.
+ */
+mxUndoManager.prototype.clear = function()
+{
+ this.history = [];
+ this.indexOfNextAdd = 0;
+ this.fireEvent(new mxEventObject(mxEvent.CLEAR));
+};
+
+/**
+ * Function: canUndo
+ *
+ * Returns true if an undo is possible.
+ */
+mxUndoManager.prototype.canUndo = function()
+{
+ return this.indexOfNextAdd > 0;
+};
+
+/**
+ * Function: undo
+ *
+ * Undoes the last change.
+ */
+mxUndoManager.prototype.undo = function()
+{
+ while (this.indexOfNextAdd > 0)
+ {
+ var edit = this.history[--this.indexOfNextAdd];
+ edit.undo();
+
+ if (edit.isSignificant())
+ {
+ this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
+ break;
+ }
+ }
+};
+
+/**
+ * Function: canRedo
+ *
+ * Returns true if a redo is possible.
+ */
+mxUndoManager.prototype.canRedo = function()
+{
+ return this.indexOfNextAdd < this.history.length;
+};
+
+/**
+ * Function: redo
+ *
+ * Redoes the last change.
+ */
+mxUndoManager.prototype.redo = function()
+{
+ var n = this.history.length;
+
+ while (this.indexOfNextAdd < n)
+ {
+ var edit = this.history[this.indexOfNextAdd++];
+ edit.redo();
+
+ if (edit.isSignificant())
+ {
+ this.fireEvent(new mxEventObject(mxEvent.REDO, 'edit', edit));
+ break;
+ }
+ }
+};
+
+/**
+ * Function: undoableEditHappened
+ *
+ * Method to be called to add new undoable edits to the <history>.
+ */
+mxUndoManager.prototype.undoableEditHappened = function(undoableEdit)
+{
+ this.trim();
+
+ if (this.size > 0 &&
+ this.size == this.history.length)
+ {
+ this.history.shift();
+ }
+
+ this.history.push(undoableEdit);
+ this.indexOfNextAdd = this.history.length;
+ this.fireEvent(new mxEventObject(mxEvent.ADD, 'edit', undoableEdit));
+};
+
+/**
+ * Function: trim
+ *
+ * Removes all pending steps after <indexOfNextAdd> from the history,
+ * invoking die on each edit. This is called from <undoableEditHappened>.
+ */
+mxUndoManager.prototype.trim = function()
+{
+ if (this.history.length > this.indexOfNextAdd)
+ {
+ var edits = this.history.splice(this.indexOfNextAdd,
+ this.history.length - this.indexOfNextAdd);
+
+ for (var i = 0; i < edits.length; i++)
+ {
+ edits[i].die();
+ }
+ }
+};