mxUndoableEdit.js
4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxUndoableEdit
*
* Implements a composite undoable edit. Here is an example for a custom change
* which gets executed via the model:
*
* (code)
* function CustomChange(model, name)
* {
* this.model = model;
* this.name = name;
* this.previous = name;
* };
*
* CustomChange.prototype.execute = function()
* {
* var tmp = this.model.name;
* this.model.name = this.previous;
* this.previous = tmp;
* };
*
* var name = prompt('Enter name');
* graph.model.execute(new CustomChange(graph.model, name));
* (end)
*
* Event: mxEvent.EXECUTED
*
* Fires between START_EDIT and END_EDIT after an atomic change was executed.
* The <code>change</code> property contains the change that was executed.
*
* Event: mxEvent.START_EDIT
*
* Fires before a set of changes will be executed in <undo> or <redo>.
* This event contains no properties.
*
* Event: mxEvent.END_EDIT
*
* Fires after a set of changeswas executed in <undo> or <redo>.
* This event contains no properties.
*
* Constructor: mxUndoableEdit
*
* Constructs a new undoable edit for the given source.
*/
function mxUndoableEdit(source, significant)
{
this.source = source;
this.changes = [];
this.significant = (significant != null) ? significant : true;
};
/**
* Variable: source
*
* Specifies the source of the edit.
*/
mxUndoableEdit.prototype.source = null;
/**
* Variable: changes
*
* Array that contains the changes that make up this edit. The changes are
* expected to either have an undo and redo function, or an execute
* function. Default is an empty array.
*/
mxUndoableEdit.prototype.changes = null;
/**
* Variable: significant
*
* Specifies if the undoable change is significant.
* Default is true.
*/
mxUndoableEdit.prototype.significant = null;
/**
* Variable: undone
*
* Specifies if this edit has been undone. Default is false.
*/
mxUndoableEdit.prototype.undone = false;
/**
* Variable: redone
*
* Specifies if this edit has been redone. Default is false.
*/
mxUndoableEdit.prototype.redone = false;
/**
* Function: isEmpty
*
* Returns true if the this edit contains no changes.
*/
mxUndoableEdit.prototype.isEmpty = function()
{
return this.changes.length == 0;
};
/**
* Function: isSignificant
*
* Returns <significant>.
*/
mxUndoableEdit.prototype.isSignificant = function()
{
return this.significant;
};
/**
* Function: add
*
* Adds the specified change to this edit. The change is an object that is
* expected to either have an undo and redo, or an execute function.
*/
mxUndoableEdit.prototype.add = function(change)
{
this.changes.push(change);
};
/**
* Function: notify
*
* Hook to notify any listeners of the changes after an <undo> or <redo>
* has been carried out. This implementation is empty.
*/
mxUndoableEdit.prototype.notify = function() { };
/**
* Function: die
*
* Hook to free resources after the edit has been removed from the command
* history. This implementation is empty.
*/
mxUndoableEdit.prototype.die = function() { };
/**
* Function: undo
*
* Undoes all changes in this edit.
*/
mxUndoableEdit.prototype.undo = function()
{
if (!this.undone)
{
this.source.fireEvent(new mxEventObject(mxEvent.START_EDIT));
var count = this.changes.length;
for (var i = count - 1; i >= 0; i--)
{
var change = this.changes[i];
if (change.execute != null)
{
change.execute();
}
else if (change.undo != null)
{
change.undo();
}
// New global executed event
this.source.fireEvent(new mxEventObject(mxEvent.EXECUTED, 'change', change));
}
this.undone = true;
this.redone = false;
this.source.fireEvent(new mxEventObject(mxEvent.END_EDIT));
}
this.notify();
};
/**
* Function: redo
*
* Redoes all changes in this edit.
*/
mxUndoableEdit.prototype.redo = function()
{
if (!this.redone)
{
this.source.fireEvent(new mxEventObject(mxEvent.START_EDIT));
var count = this.changes.length;
for (var i = 0; i < count; i++)
{
var change = this.changes[i];
if (change.execute != null)
{
change.execute();
}
else if (change.redo != null)
{
change.redo();
}
// New global executed event
this.source.fireEvent(new mxEventObject(mxEvent.EXECUTED, 'change', change));
}
this.undone = false;
this.redone = true;
this.source.fireEvent(new mxEventObject(mxEvent.END_EDIT));
}
this.notify();
};