KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > swingwtx > swing > undo > UndoManager


1 /*
2    SwingWT
3    Copyright(c)2003-2004 Daniel Naab
4
5    For more information on distributing and using this program, please
6    see the accompanying "COPYING" file.
7
8    Contact me by electronic mail: dannaab@users.sourceforge.net
9
10    $Log: UndoManager.java,v $
11    Revision 1.2 2004/04/16 22:45:50 dannaab
12    Add copyright msg
13
14 */

15
16 package swingwtx.swing.undo;
17
18 import swingwtx.swing.event.UndoableEditEvent;
19 import swingwtx.swing.event.UndoableEditListener;
20
21 import java.util.Iterator JavaDoc;
22
23 /**
24  * UndoManager
25  *
26  * @author Naab
27  * @version %I%, %G%
28  */

29 public class UndoManager extends CompoundEdit
30         implements UndoableEditListener
31 {
32     int limit = 100;
33     int indexOfNextAdd = 0;
34
35     public UndoManager()
36     {
37         super();
38     }
39
40     public synchronized void setLimit(int limit) { this.limit = limit; }
41     public synchronized int getLimit() { return limit; }
42
43     /** Remove all the edits tracked by this UndoManager */
44     public synchronized void discardAllEdits()
45     {
46         // Tell each edit to "die"
47
Iterator JavaDoc iterator = edits.iterator();
48         while (iterator.hasNext())
49         {
50             UndoableEdit undoableEdit = (UndoableEdit) iterator.next();
51             undoableEdit.die();
52         }
53
54         // Clear the Vector of edits
55
edits.clear();
56     }
57
58     protected void undoTo(UndoableEdit undoableEdit) throws CannotUndoException
59     {
60         do
61         {
62             // Decrement counter
63
indexOfNextAdd--;
64
65             // If we reached the end, throw an exception.
66
if (indexOfNextAdd < 0)
67             {
68                 indexOfNextAdd = 0;
69                 throw new CannotUndoException();
70             }
71
72             // Get the edit and undo it.
73
UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(indexOfNextAdd);
74             curUndoableEdit.undo();
75
76             // If this is the last to undo, exit out of loop.
77
if (curUndoableEdit == undoableEdit)
78                 break;
79
80         } while (true);
81     }
82
83     public synchronized void undo() throws CannotUndoException
84     {
85         if (isInProgress())
86         {
87             UndoableEdit edit = editToBeUndone();
88             if (edit == null) throw new CannotUndoException();
89             undoTo(edit);
90         }
91         else
92         {
93             super.undo();
94         }
95     }
96
97     protected void redoTo(UndoableEdit undoableEdit) throws CannotRedoException
98     {
99         int size = edits.size();
100
101         do
102         {
103             // Get the edit and redo it.
104
UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(indexOfNextAdd);
105             curUndoableEdit.redo();
106
107             // If this is the last to redo, exit out of loop.
108
if (curUndoableEdit == undoableEdit)
109                 break;
110
111             // Increment counter
112
indexOfNextAdd++;
113
114             // If we reached the top, throw an exception.
115
if (indexOfNextAdd >= size)
116             {
117                 indexOfNextAdd = 0;
118                 throw new CannotRedoException();
119             }
120
121         } while (true);
122     }
123
124     public synchronized void redo() throws CannotRedoException
125     {
126         if (isInProgress())
127         {
128             UndoableEdit edit = editToBeRedone();
129             if (edit == null) throw new CannotRedoException();
130             redoTo(edit);
131         }
132         else
133         {
134             super.redo();
135         }
136     }
137
138     protected void trimEdits(int from, int to)
139     {
140         if (from <= to)
141         {
142             // Remove edits >= from, <= to
143
int itemsToRemove = to - from + 1;
144             while (itemsToRemove > 0)
145             {
146                 // Kill current edit
147
((UndoableEdit)edits.get(from)).die();
148                 edits.remove(from);
149
150                 // Decrement counter
151
itemsToRemove--;
152             }
153
154             // Update next index based on what we removed
155
if (indexOfNextAdd > to)
156                 indexOfNextAdd = indexOfNextAdd - to + from - 1;
157             else if (indexOfNextAdd >= from)
158                 indexOfNextAdd = from;
159         }
160     }
161
162     protected void trimForLimit()
163     {
164         int size = edits.size();
165
166         if (limit > 0 && size > limit)
167         {
168             // Get indices to bound on
169
int middle = limit / 2;
170             int high = Math.min(indexOfNextAdd+middle-1, size-1);
171
172             trimEdits(high+1, size-1);
173             trimEdits(0, high-limit);
174         }
175     }
176
177     public synchronized void undoOrRedo() throws CannotRedoException, CannotUndoException
178     {
179         if (indexOfNextAdd == edits.size()) undo();
180         else redo();
181     }
182
183     public synchronized boolean canUndoOrRedo()
184     {
185         return false;
186     }
187
188     public synchronized boolean canUndo()
189     {
190         boolean canUndo = false;
191
192         // If edit is active, see if it's undoable.
193
if (isInProgress())
194         {
195             UndoableEdit undoableEdit = editToBeUndone();
196             if (undoableEdit != null) canUndo = undoableEdit.canUndo();
197         }
198         // Otherwise, get CompoundEdit's default value
199
else
200         {
201             canUndo = super.canUndo();
202         }
203
204         return canUndo;
205     }
206
207     public synchronized boolean canRedo()
208     {
209         boolean canRedo = false;
210
211         // If edit is active, see if it's redoable.
212
if (isInProgress())
213         {
214             UndoableEdit undoableEdit = editToBeRedone();
215             if (undoableEdit != null) canRedo = undoableEdit.canRedo();
216         }
217         // Otherwise, get CompoundEdit's default value
218
else
219         {
220             canRedo = super.canRedo();
221         }
222
223         return canRedo;
224     }
225
226     public synchronized boolean addEdit(UndoableEdit undoableEdit)
227     {
228         boolean success;
229
230         // Make room for this UndoableEdit, if necessary
231
trimEdits(indexOfNextAdd, edits.size()-1);
232
233         // Add this edit to the list and update next index counter
234
success = super.addEdit(undoableEdit);
235         indexOfNextAdd = edits.size();
236
237         // Trim out first item if necessary
238
trimForLimit();
239
240         return success;
241     }
242
243     public synchronized void end()
244     {
245         super.end();
246         trimEdits(indexOfNextAdd, edits.size()-1);
247     }
248
249     public synchronized String JavaDoc getUndoOrRedoPresentationName()
250     {
251         if (indexOfNextAdd == edits.size()) return getUndoPresentationName();
252         else return getRedoPresentationName();
253     }
254
255     // TODO: presentation names aren't localized
256
public synchronized String JavaDoc getUndoPresentationName()
257     {
258         String JavaDoc presentationName;
259
260         // If we have an edit, get it
261
if (isInProgress())
262         {
263             UndoableEdit undoableEdit = editToBeUndone();
264             if (undoableEdit != null)
265                 presentationName = undoableEdit.getUndoPresentationName();
266             else presentationName = "Undo";
267         }
268         else
269             presentationName = super.getUndoPresentationName();
270
271         return presentationName;
272     }
273
274     // TODO: presentation names aren't localized
275
public synchronized String JavaDoc getRedoPresentationName()
276     {
277         String JavaDoc presentationName;
278
279         // If we have an edit, get it
280
if (isInProgress())
281         {
282             UndoableEdit undoableEdit = editToBeUndone();
283             if (undoableEdit != null)
284                 presentationName = undoableEdit.getRedoPresentationName();
285             else
286                 presentationName = "Redo";
287         }
288         else
289             presentationName = super.getRedoPresentationName();
290
291         return presentationName;
292     }
293
294     public void undoableEditHappened(UndoableEditEvent undoableEditEvent)
295     {
296         addEdit(undoableEditEvent.getEdit());
297     }
298
299     /** Returns the most recent significant UndoableEdit that can be undone */
300     protected UndoableEdit editToBeUndone()
301     {
302         UndoableEdit undoableEdit = null;
303
304         // Start at current location, going backwards.
305
for (int i = indexOfNextAdd-1; i >= 0; i--)
306         {
307             UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(i);
308
309             // If edit is "significant", we can undo it.
310
if (curUndoableEdit.isSignificant())
311             {
312                 undoableEdit = curUndoableEdit;
313                 break;
314             }
315         }
316
317         return undoableEdit;
318     }
319
320     /** Returns the most recent significant UndoableEdit that can be redone */
321     protected UndoableEdit editToBeRedone()
322     {
323         UndoableEdit undoableEdit = null;
324
325         // Start at current location, going forward.
326
for (int i = indexOfNextAdd; i<edits.size(); i++)
327         {
328             UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(i);
329
330             // If edit is "significant", we can redo it.
331
if (curUndoableEdit.isSignificant())
332             {
333                 undoableEdit = curUndoableEdit;
334                 break;
335             }
336         }
337
338         return undoableEdit;
339     }
340 }
341
Popular Tags