1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.xmlhammer.gui;
22
23 import java.util.ArrayList;
24
25 import javax.swing.event.ChangeEvent;
26 import javax.swing.event.ChangeListener;
27 import javax.swing.event.EventListenerList;
28 import javax.swing.undo.CompoundEdit;
29 import javax.swing.undo.UndoManager;
30 import javax.swing.undo.UndoableEdit;
31
32 import org.apache.log4j.Logger;
33
34 public class ProjectUndoManager extends UndoManager {
35 private static final long serialVersionUID = -4923400585127602904L;
36 private EventListenerList listeners = null;
37
38 private UndoableEdit mark = null;
39 private UndoManager discardableUndoManager = null;
40 private ArrayList<CompoundEdit> compounds = null;
41
42 private boolean undoing = false;
43 private boolean redoing = false;
44
45 public ProjectUndoManager() {
46 listeners = new EventListenerList();
47 compounds = new ArrayList<CompoundEdit>();
48
49 discardableUndoManager = new UndoManager();
50 }
51
52 @Override
53 public boolean addEdit(UndoableEdit edit) {
54 boolean result = false;
55
56 if (!undoing && !redoing) {
57 if (compounds.size() == 0) {
58 Logger.getLogger(getClass()).debug("addEdit("+edit+")");
59
60 discardableUndoManager.discardAllEdits();
61
62 result = super.addEdit(edit);
63
64 fireStateChanged();
65 } else {
66 result = compounds.get(compounds.size()-1).addEdit( edit);
67 }
68 }
69
70 return result;
71 }
72
73 public boolean addDiscardableEdit(UndoableEdit edit) {
74 boolean result = false;
75
76 if (!undoing && !redoing) {
77 result = discardableUndoManager.addEdit(edit);
78 fireStateChanged();
79 }
80
81 return result;
82 }
83
84 @Override
85 public void undo() {
86 undoing = true;
87
88 if (discardableUndoManager.canUndo()) {
89 discardableUndoManager.undo();
90 } else {
91 super.undo();
92 }
93
94 fireStateChanged();
95 undoing = false;
96 }
97
98 public void startCompound() {
99 if (!undoing && !redoing) {
100 compounds.add(new CompoundEdit());
101 }
102 }
103
104 public void endCompound() {
105 if (compounds.size() > 0) {
106 CompoundEdit edit = compounds.remove(compounds.size()-1);
107 edit.end();
108
109 if (compounds.size() > 0) {
110 compounds.get(compounds.size()-1).addEdit(edit);
111 } else {
112 addEdit(edit);
113 }
114 }
115 }
116
117 public void discardCompound() {
118 if (compounds.size() > 0) {
119 compounds.remove(compounds.size()-1);
120 }
121 }
122
123 public boolean isCompound() {
124 return compounds.size() > 0;
125 }
126
127 @Override
128 public void redo() {
129 redoing = true;
130
131 if (discardableUndoManager.canRedo()) {
132 discardableUndoManager.redo();
133 } else {
134 super.redo();
135 }
136
137 fireStateChanged();
138 redoing = false;
139 }
140
141 public void mark() {
142 mark = editToBeUndone();
143 }
144
145 public boolean isMark() {
146 if (!discardableUndoManager.canUndo()) {
147 return mark == editToBeUndone();
148 }
149
150 return false;
151 }
152
153 public void addChangeListener(ChangeListener listener) {
154 listeners.add( ChangeListener.class, listener);
155 }
156
157 public void removeChangeListener(ChangeListener listener) {
158 listeners.remove( ChangeListener.class, listener);
159 }
160
161 public synchronized boolean canUndo() {
162 return discardableUndoManager.canUndo() || super.canUndo();
163 }
164
165 public synchronized boolean canRedo() {
166 return discardableUndoManager.canRedo() || super.canRedo();
167 }
168
169 public synchronized void discardDiscardableEdits() {
170 discardableUndoManager.discardAllEdits();
171
172 fireStateChanged();
173 }
174
175 public synchronized void discardAllEdits() {
176 discardableUndoManager.discardAllEdits();
177 super.discardAllEdits();
178 compounds.clear();
179
180 fireStateChanged();
181 }
182
183 protected void fireStateChanged() {
184
185 Object[] list = listeners.getListenerList();
186
187
188
189 for ( int i = list.length-2; i >= 0; i -= 2) {
190 if ( list[i] == ChangeListener.class) {
191 ((ChangeListener)list[i+1]).stateChanged( new ChangeEvent( this));
192 }
193 }
194 }
195 }