KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > xam > ui > undo > QuietUndoManager


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.xam.ui.undo;
21
22 import java.io.IOException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.List JavaDoc;
25 import javax.swing.event.UndoableEditListener JavaDoc;
26 import javax.swing.text.AbstractDocument JavaDoc;
27 import javax.swing.undo.CannotRedoException JavaDoc;
28 import javax.swing.undo.CannotUndoException JavaDoc;
29 import org.netbeans.modules.xml.xam.Model;
30 import org.openide.awt.UndoRedo;
31
32 /**
33  * A proxy for another UndoRedo.Manager instance which removes and then
34  * adds the undoable edit listeners from a Swing document, each time the
35  * undo and redo operations are invoked. Essentially, this allows the
36  * client to avoid firing undo events to the listeners when doing nothing
37  * more than undoing or redoing a change to the document.
38  *
39  * <p>To use this undo manager proxy with <code>CloneableEditorSupport</code>,
40  * it is necessary to subclass <code>CloneableEditorSupport</code> and override
41  * the <code>createUndoRedoManager()</code> method to return an instance of
42  * this class, providing the return value of
43  * <code>super.createUndoRedoManager()</code> to the
44  * <code>QuietUndoManager</code> constructor. In this way, this proxy can
45  * then intercept all new edits and properly manage its state. Note that
46  * setting the document in <code>createUndoRedoManager()</code> will not be
47  * possible since the document will not have been initialized yet. It will
48  * have to happen at a later time.</p>
49  *
50  * @author Nathan Fiedler
51  */

52 public class QuietUndoManager extends CompoundUndoManager {
53     /** silence compiler warnings */
54     private static final long serialVersionUID = 1L;
55     /** Undoable edit listeners are managed for this document; may be null. */
56     private AbstractDocument JavaDoc document;
57     /** If not null, the Model is sync'd after undo/redo. */
58     private Model model;
59     private List JavaDoc<Model> otherModels = new ArrayList JavaDoc<Model>();
60
61     /**
62      * Creates a new instance of QuietUndoManager.
63      *
64      * @param original UndoRedo.Manager to be proxied.
65      */

66     public QuietUndoManager(UndoRedo.Manager original) {
67         super(original);
68     }
69
70     /**
71      * Wrap up after performing an undo/redo operation.
72      *
73      * @param listeners undoable edit listeners to be added to document.
74      */

75     private void finish(UndoableEditListener JavaDoc[] listeners) {
76         if (model != null) {
77             // When model is non-null, add ourselves as a listener since
78
// we removed us in the preparation step.
79
model.addUndoableEditListener(this);
80         }
81         if (listeners != null && listeners.length > 0) {
82             for (UndoableEditListener JavaDoc uel : listeners) {
83                 document.addUndoableEditListener(uel);
84             }
85         }
86     }
87
88     /**
89      * Prepare to perform an undo/redo operation.
90      *
91      * @return the set of undoable edit listeners removed from document.
92      */

93     private UndoableEditListener JavaDoc[] prepare() {
94         if (model != null) {
95             // If the model is set, that means we are to sync the model
96
// after performing the undo/redo operation. That, however,
97
// means we cannot be listening to the model lest we receive
98
// additional undoable edits, which would be bad.
99
model.removeUndoableEditListener(this);
100         }
101         if (document == null) {
102             return null;
103         }
104         UndoableEditListener JavaDoc[] listeners = document.getUndoableEditListeners();
105         if (listeners != null && listeners.length > 0) {
106             for (UndoableEditListener JavaDoc uel : listeners) {
107                 document.removeUndoableEditListener(uel);
108             }
109         }
110         return listeners;
111     }
112
113     /**
114      * Set the document for which the undoable edit listeners will be
115      * removed and then added back for each undo/redo operation.
116      *
117      * @param document the document whose listeners will be managed.
118      */

119     public void setDocument(AbstractDocument JavaDoc document) {
120         this.document = document;
121     }
122
123     /**
124      * Set the Model to be managed when the undo and redo operations
125      * are performed. This should only be set when the model view is
126      * being shown. Call this method with a value of <code>null</code>
127      * when the model view is being hidden.
128      *
129      * @param model Model to be managed; if null, disables management.
130      */

131     public void setModel(Model model) {
132         this.model = model;
133     }
134
135     /**
136      * Sync the Model so it does not perform the auto-sync at some
137      * later time, causing additional undoable edits from appearing
138      * on the undo queue. That would be pointless anyway, since we
139      * are simply undoing or redoing edits anyway.
140      */

141     private void syncModel() {
142         if (model != null) {
143             try {
144                 // Fortunately this method is efficient in that it knows
145
// if the change that occurred was done by the model or
146
// if the change is coming from the document (the model
147
// has a document listener on the Swing document).
148
model.sync();
149                 for(Model m: otherModels)
150                     m.sync();
151             } catch (IOException JavaDoc ioe) {
152                 // Ignore, nothing we can do about it.
153
}
154         }
155     }
156
157     public void redo() throws CannotRedoException JavaDoc {
158         UndoableEditListener JavaDoc[] listeners = prepare();
159         super.redo();
160         syncModel();
161         finish(listeners);
162     }
163
164     public void undo() throws CannotUndoException JavaDoc {
165         UndoableEditListener JavaDoc[] listeners = prepare();
166         super.undo();
167         syncModel();
168         finish(listeners);
169     }
170     
171     /**
172      * Allows other models to be synced after undo or redo.
173      */

174     public void addWrapperModel(Model model) {
175         if(!otherModels.contains(model))
176             otherModels.add(model);
177     }
178     
179     /**
180      * Removes other models that were added for sync.
181      */

182     public void removeWrapperModel(Model model) {
183         otherModels.remove(model);
184     }
185 }
186
Popular Tags