1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing.undo;
27
28import java.io.Serializable;
29import javax.swing.UIManager;
30
31/**
32 * An abstract implementation of <code>UndoableEdit</code>,
33 * implementing simple responses to all boolean methods in
34 * that interface.
35 *
36 * @author Ray Ryan
37 */
38@SuppressWarnings("serial") // Same-version serialization only
39public class AbstractUndoableEdit implements UndoableEdit, Serializable {
40
41    /**
42     * String returned by <code>getUndoPresentationName</code>;
43     * as of Java 2 platform v1.3.1 this field is no longer used. This value
44     * is now localized and comes from the defaults table with key
45     * <code>AbstractUndoableEdit.undoText</code>.
46     *
47     * @see javax.swing.UIDefaults
48     */
49    protected static final String UndoName = "Undo";
50
51    /**
52     * String returned by <code>getRedoPresentationName</code>;
53     * as of Java 2 platform v1.3.1 this field is no longer used. This value
54     * is now localized and comes from the defaults table with key
55     * <code>AbstractUndoableEdit.redoText</code>.
56     *
57     * @see javax.swing.UIDefaults
58     */
59    protected static final String RedoName = "Redo";
60
61    /**
62     * Defaults to true; becomes false if this edit is undone, true
63     * again if it is redone.
64     */
65    boolean hasBeenDone;
66
67    /**
68     * True if this edit has not received <code>die</code>; defaults
69     * to <code>true</code>.
70     */
71    boolean alive;
72
73    /**
74     * Creates an <code>AbstractUndoableEdit</code> which defaults
75     * <code>hasBeenDone</code> and <code>alive</code> to <code>true</code>.
76     */
77    public AbstractUndoableEdit() {
78        super();
79
80        hasBeenDone = true;
81        alive = true;
82    }
83
84    /**
85     * Sets <code>alive</code> to false. Note that this
86     * is a one way operation; dead edits cannot be resurrected.
87     * Sending <code>undo</code> or <code>redo</code> to
88     * a dead edit results in an exception being thrown.
89     *
90     * <p>Typically an edit is killed when it is consolidated by
91     * another edit's <code>addEdit</code> or <code>replaceEdit</code>
92     * method, or when it is dequeued from an <code>UndoManager</code>.
93     */
94    public void die() {
95        alive = false;
96    }
97
98    /**
99     * Throws <code>CannotUndoException</code> if <code>canUndo</code>
100     * returns <code>false</code>. Sets <code>hasBeenDone</code>
101     * to <code>false</code>. Subclasses should override to undo the
102     * operation represented by this edit. Override should begin with
103     * a call to super.
104     *
105     * @exception CannotUndoException if <code>canUndo</code>
106     *    returns <code>false</code>
107     * @see     #canUndo
108     */
109    public void undo() throws CannotUndoException {
110        if (!canUndo()) {
111            throw new CannotUndoException();
112        }
113        hasBeenDone = false;
114    }
115
116    /**
117     * Returns true if this edit is <code>alive</code>
118     * and <code>hasBeenDone</code> is <code>true</code>.
119     *
120     * @return true if this edit is <code>alive</code>
121     *    and <code>hasBeenDone</code> is <code>true</code>
122     *
123     * @see     #die
124     * @see     #undo
125     * @see     #redo
126     */
127    public boolean canUndo() {
128        return alive && hasBeenDone;
129    }
130
131    /**
132     * Throws <code>CannotRedoException</code> if <code>canRedo</code>
133     * returns false. Sets <code>hasBeenDone</code> to <code>true</code>.
134     * Subclasses should override to redo the operation represented by
135     * this edit. Override should begin with a call to super.
136     *
137     * @exception CannotRedoException if <code>canRedo</code>
138     *     returns <code>false</code>
139     * @see     #canRedo
140     */
141    public void redo() throws CannotRedoException {
142        if (!canRedo()) {
143            throw new CannotRedoException();
144        }
145        hasBeenDone = true;
146    }
147
148    /**
149     * Returns <code>true</code> if this edit is <code>alive</code>
150     * and <code>hasBeenDone</code> is <code>false</code>.
151     *
152     * @return <code>true</code> if this edit is <code>alive</code>
153     *   and <code>hasBeenDone</code> is <code>false</code>
154     * @see     #die
155     * @see     #undo
156     * @see     #redo
157     */
158    public boolean canRedo() {
159        return alive && !hasBeenDone;
160    }
161
162    /**
163     * This default implementation returns false.
164     *
165     * @param anEdit the edit to be added
166     * @return false
167     *
168     * @see UndoableEdit#addEdit
169     */
170    public boolean addEdit(UndoableEdit anEdit) {
171        return false;
172    }
173
174    /**
175     * This default implementation returns false.
176     *
177     * @param anEdit the edit to replace
178     * @return false
179     *
180     * @see UndoableEdit#replaceEdit
181     */
182    public boolean replaceEdit(UndoableEdit anEdit) {
183        return false;
184    }
185
186    /**
187     * This default implementation returns true.
188     *
189     * @return true
190     * @see UndoableEdit#isSignificant
191     */
192    public boolean isSignificant() {
193        return true;
194    }
195
196    /**
197     * This default implementation returns "". Used by
198     * <code>getUndoPresentationName</code> and
199     * <code>getRedoPresentationName</code> to
200     * construct the strings they return. Subclasses should override to
201     * return an appropriate description of the operation this edit
202     * represents.
203     *
204     * @return the empty string ""
205     *
206     * @see     #getUndoPresentationName
207     * @see     #getRedoPresentationName
208     */
209    public String getPresentationName() {
210        return "";
211    }
212
213    /**
214     * Retreives the value from the defaults table with key
215     * <code>AbstractUndoableEdit.undoText</code> and returns
216     * that value followed by a space, followed by
217     * <code>getPresentationName</code>.
218     * If <code>getPresentationName</code> returns "",
219     * then the defaults value is returned alone.
220     *
221     * @return the value from the defaults table with key
222     *    <code>AbstractUndoableEdit.undoText</code>, followed
223     *    by a space, followed by <code>getPresentationName</code>
224     *    unless <code>getPresentationName</code> is "" in which
225     *    case, the defaults value is returned alone.
226     * @see #getPresentationName
227     */
228    public String getUndoPresentationName() {
229        String name = getPresentationName();
230        if (!"".equals(name)) {
231            name = UIManager.getString("AbstractUndoableEdit.undoText") +
232                " " + name;
233        } else {
234            name = UIManager.getString("AbstractUndoableEdit.undoText");
235        }
236
237        return name;
238    }
239
240    /**
241     * Retreives the value from the defaults table with key
242     * <code>AbstractUndoableEdit.redoText</code> and returns
243     * that value followed by a space, followed by
244     * <code>getPresentationName</code>.
245     * If <code>getPresentationName</code> returns "",
246     * then the defaults value is returned alone.
247     *
248     * @return the value from the defaults table with key
249     *    <code>AbstractUndoableEdit.redoText</code>, followed
250     *    by a space, followed by <code>getPresentationName</code>
251     *    unless <code>getPresentationName</code> is "" in which
252     *    case, the defaults value is returned alone.
253     * @see #getPresentationName
254     */
255    public String getRedoPresentationName() {
256        String name = getPresentationName();
257        if (!"".equals(name)) {
258            name = UIManager.getString("AbstractUndoableEdit.redoText") +
259                " " + name;
260        } else {
261            name = UIManager.getString("AbstractUndoableEdit.redoText");
262        }
263
264        return name;
265    }
266
267    /**
268     * Returns a string that displays and identifies this
269     * object's properties.
270     *
271     * @return a String representation of this object
272     */
273    public String toString()
274    {
275        return super.toString()
276            + " hasBeenDone: " + hasBeenDone
277            + " alive: " + alive;
278    }
279}
280