1 |
/* StateEdit.java -- |
/* StateEdit.java -- UndoableEdit for StateEditable implementations. |
2 |
Copyright (C) 2002, 2003 Free Software Foundation, Inc. |
Copyright (C) 2002, 2003 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
42 |
import java.util.Iterator; |
import java.util.Iterator; |
43 |
|
|
44 |
/** |
/** |
45 |
* StateEdit |
* A helper class, making it easy to support undo and redo. |
46 |
* @author Andrew Selkirk |
* |
47 |
|
* <p>The following example shows how to use this class. |
48 |
|
* |
49 |
|
* <pre> Foo foo; // class Foo implements {@link StateEditable} |
50 |
|
* StateEdit edit; |
51 |
|
* |
52 |
|
* edit = new StateEdit(foo, "Name Change"); |
53 |
|
* foo.setName("Jane Doe"); |
54 |
|
* edit.end(); |
55 |
|
* undoManager.addEdit(edit);</pre> |
56 |
|
* |
57 |
|
* <p>If <code>Foo</code>’s implementation of {@link |
58 |
|
* StateEditable} considers the name as part of the editable state, |
59 |
|
* the user can now choose “Undo Name Change” or |
60 |
|
* “Redo Name Change” from the respective menu. No |
61 |
|
* further undo support is needed from the application. |
62 |
|
* |
63 |
|
* <p>The following explains what happens in the example. |
64 |
|
* |
65 |
|
* <p><ol><li>When a <code>StateEdit</code> is created, the associated |
66 |
|
* {@link StateEditable} gets asked to store its state into a hash |
67 |
|
* table, {@link #preState}.</li> |
68 |
|
* |
69 |
|
* <li>The application will now perform some changes to the edited |
70 |
|
* object. This typically happens by invoking methods on the edited |
71 |
|
* object.</li> |
72 |
|
* |
73 |
|
* <li>The editing phase is terminated by invoking the {@link #end()} |
74 |
|
* method of the <code>StateEdit</code>. The <code>end()</code> method |
75 |
|
* does two things. |
76 |
|
* |
77 |
|
* <ul><li>The edited object receives a second request for storing |
78 |
|
* its state. This time, it will use a different hash table, {@link |
79 |
|
* #postState}.</li> |
80 |
|
* |
81 |
|
* <li>To increase efficiency, the <code>StateEdit</code> now removes |
82 |
|
* any entries from {@link #preState} and {@link #postState} that have |
83 |
|
* the same key, and whose values are equal. Equality is determined |
84 |
|
* by invoking the <code>equals</code> method inherited from |
85 |
|
* {@link java.lang.Object}.</li></ul></li> |
86 |
|
* |
87 |
|
* <li>When the user later chooses to undo the <code>StateEdit</code>, |
88 |
|
* the edited object is asked to {@linkplain StateEditable#restoreState |
89 |
|
* restore its state} from the {@link #preState} table. Similarly, |
90 |
|
* when the user chooses to <i>redo</i> the <code>StateEdit</code>, |
91 |
|
* the edited object gets asked to restore its state from the {@link |
92 |
|
* #postState}.</li></ol> |
93 |
|
* |
94 |
|
* @author Andrew Selkirk (aselkirk@sympatico.ca) |
95 |
|
* @author Sascha Brawer (brawer@dandelis.ch) |
96 |
*/ |
*/ |
97 |
public class StateEdit extends AbstractUndoableEdit |
public class StateEdit |
98 |
|
extends AbstractUndoableEdit |
99 |
{ |
{ |
|
|
|
|
//------------------------------------------------------------- |
|
|
// Variables -------------------------------------------------- |
|
|
//------------------------------------------------------------- |
|
|
|
|
100 |
/** |
/** |
101 |
* RCSID |
* The ID of the Java source file in Sun’s Revision Control |
102 |
|
* System (RCS). This certainly should not be part of the API |
103 |
|
* specification. But in order to be API-compatible with |
104 |
|
* Sun’s reference implementation, GNU Classpath also has to |
105 |
|
* provide this field. However, we do not try to match its value. |
106 |
*/ |
*/ |
107 |
protected static final String RCSID = ""; // TODO |
protected static final String RCSID = ""; |
108 |
|
|
109 |
|
|
110 |
/** |
/** |
111 |
* object |
* The object which is being edited by this <code>StateEdit</code>. |
112 |
*/ |
*/ |
113 |
protected StateEditable object; |
protected StateEditable object; |
114 |
|
|
115 |
|
|
116 |
/** |
/** |
117 |
* preState |
* The state of <code>object</code> at the time of constructing |
118 |
|
* this <code>StateEdit</code>. |
119 |
*/ |
*/ |
120 |
protected Hashtable preState; |
protected Hashtable preState; |
121 |
|
|
122 |
|
|
123 |
/** |
/** |
124 |
* postState |
* The state of <code>object</code> at the time when {@link #end()} |
125 |
|
* was called. |
126 |
*/ |
*/ |
127 |
protected Hashtable postState; |
protected Hashtable postState; |
128 |
|
|
129 |
|
|
130 |
/** |
/** |
131 |
* undoRedoName |
* A human-readable name for this edit action. |
132 |
*/ |
*/ |
133 |
protected String undoRedoName; |
protected String undoRedoName; |
134 |
|
|
135 |
|
|
|
//------------------------------------------------------------- |
|
|
// Initialization --------------------------------------------- |
|
|
//------------------------------------------------------------- |
|
|
|
|
136 |
/** |
/** |
137 |
* Constructor StateEdit |
* Constructs a <code>StateEdit</code>, specifying the object whose |
138 |
* @param obj Object to edit |
* state is being edited. |
139 |
|
* |
140 |
|
* @param obj the object whose state is being edited by this |
141 |
|
* <code>StateEdit</code>. |
142 |
*/ |
*/ |
143 |
public StateEdit(StateEditable obj) |
public StateEdit(StateEditable obj) |
144 |
{ |
{ |
145 |
init(obj, null); |
init(obj, null); |
146 |
} |
} |
147 |
|
|
148 |
|
|
149 |
/** |
/** |
150 |
* Constructor StateEdit |
* Constructs a <code>StateEdit</code>, specifying the object whose |
151 |
* @param obj Object to edit |
* state is being edited. |
152 |
* @param name Presentation name |
* |
153 |
|
* @param obj the object whose state is being edited by this |
154 |
|
* <code>StateEdit</code>. |
155 |
|
* |
156 |
|
* @param name the human-readable name of the editing action. |
157 |
*/ |
*/ |
158 |
public StateEdit(StateEditable obj, String name) |
public StateEdit(StateEditable obj, String name) |
159 |
{ |
{ |
161 |
} |
} |
162 |
|
|
163 |
|
|
|
//------------------------------------------------------------- |
|
|
// Methods ---------------------------------------------------- |
|
|
//------------------------------------------------------------- |
|
|
|
|
164 |
/** |
/** |
165 |
* Initialize this object. |
* Initializes this <code>StateEdit</code>. The edited object will |
166 |
* @param obj Object to edit |
* be asked to store its current state into {@link #preState}. |
167 |
* @param name Presentation name |
* |
168 |
|
* @param obj the object being edited. |
169 |
|
* |
170 |
|
* @param name the human-readable name of the editing action. |
171 |
*/ |
*/ |
172 |
protected void init(StateEditable obj, String name) |
protected void init(StateEditable obj, String name) |
173 |
{ |
{ |
178 |
obj.storeState(preState); |
obj.storeState(preState); |
179 |
} |
} |
180 |
|
|
181 |
|
|
182 |
/** |
/** |
183 |
* Indicate that all edits are finished, and update this object |
* Informs this <code>StateEdit</code> that all edits are finished. |
184 |
* with final state. |
* The edited object will be asked to store its state into {@link |
185 |
|
* #postState}, and any redundant entries will get removed from |
186 |
|
* {@link #preState} and {@link #postState}. |
187 |
*/ |
*/ |
188 |
public void end() |
public void end() |
189 |
{ |
{ |
191 |
removeRedundantState(); |
removeRedundantState(); |
192 |
} |
} |
193 |
|
|
194 |
|
|
195 |
/** |
/** |
196 |
* Undo this edit by applying the initial state to the edited object. |
* Undoes this edit operation. The edited object will be asked to |
197 |
|
* {@linkplain StateEditable#restoreState restore its state} from |
198 |
|
* {@link #preState}. |
199 |
|
* |
200 |
|
* @throws CannotUndoException if {@link #canUndo()} returns |
201 |
|
* <code>false</code>, for example because this action has already |
202 |
|
* been undone. |
203 |
*/ |
*/ |
204 |
public void undo() |
public void undo() |
205 |
{ |
{ |
206 |
|
super.undo(); |
207 |
object.restoreState(preState); |
object.restoreState(preState); |
208 |
} |
} |
209 |
|
|
210 |
|
|
211 |
/** |
/** |
212 |
* Undo this edit by applying the final state to the edited object. |
* Redoes this edit operation. The edited object will be asked to |
213 |
|
* {@linkplain StateEditable#restoreState restore its state} from |
214 |
|
* {@link #postState}. |
215 |
|
* |
216 |
|
* @throws CannotRedoException if {@link #canRedo()} returns |
217 |
|
* <code>false</code>, for example because this action has not yet |
218 |
|
* been undone. |
219 |
*/ |
*/ |
220 |
public void redo() |
public void redo() |
221 |
{ |
{ |
222 |
|
super.redo(); |
223 |
object.restoreState(postState); |
object.restoreState(postState); |
224 |
} |
} |
225 |
|
|
226 |
|
|
227 |
/** |
/** |
228 |
* Return the presentation name of this object. |
* Returns a human-readable, localized name that describes this |
229 |
* @returns The name, or null if not set |
* editing action and can be displayed to the user. |
230 |
|
* |
231 |
|
* @returns the name, or <code>null</code> if no presentation |
232 |
|
* name is available. |
233 |
*/ |
*/ |
234 |
public String getPresentationName() |
public String getPresentationName() |
235 |
{ |
{ |
236 |
return undoRedoName; |
return undoRedoName; |
237 |
} |
} |
238 |
|
|
239 |
|
|
240 |
/** |
/** |
241 |
* removeRedundantState |
* Removes all redundant entries from the pre- and post-edit state |
242 |
|
* hash tables. An entry is considered redundant if it is present |
243 |
|
* both before and after the edit, and if the two values are equal. |
244 |
*/ |
*/ |
245 |
protected void removeRedundantState() |
protected void removeRedundantState() |
246 |
{ |
{ |