1 /*
   2  * Copyright (c) 1997, 2006, 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 
  26 package javax.swing.undo;
  27 
  28 import java.io.Serializable;
  29 import 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 public class AbstractUndoableEdit implements UndoableEdit, Serializable {
  39 
  40     /**
  41      * String returned by <code>getUndoPresentationName</code>;
  42      * as of Java 2 platform v1.3.1 this field is no longer used. This value
  43      * is now localized and comes from the defaults table with key
  44      * <code>AbstractUndoableEdit.undoText</code>.
  45      *
  46      * @see javax.swing.UIDefaults
  47      */
  48     protected static final String UndoName = "Undo";
  49 
  50     /**
  51      * String returned by <code>getRedoPresentationName</code>;
  52      * as of Java 2 platform v1.3.1 this field is no longer used. This value
  53      * is now localized and comes from the defaults table with key
  54      * <code>AbstractUndoableEdit.redoText</code>.
  55      *
  56      * @see javax.swing.UIDefaults
  57      */
  58     protected static final String RedoName = "Redo";
  59 
  60     /**
  61      * Defaults to true; becomes false if this edit is undone, true
  62      * again if it is redone.
  63      */
  64     boolean hasBeenDone;
  65 
  66     /**
  67      * True if this edit has not received <code>die</code>; defaults
  68      * to <code>true</code>.
  69      */
  70     boolean alive;
  71 
  72     /**
  73      * Creates an <code>AbstractUndoableEdit</code> which defaults
  74      * <code>hasBeenDone</code> and <code>alive</code> to <code>true</code>.
  75      */
  76     public AbstractUndoableEdit() {
  77         super();
  78 
  79         hasBeenDone = true;
  80         alive = true;
  81     }
  82 
  83     /**
  84      * Sets <code>alive</code> to false. Note that this
  85      * is a one way operation; dead edits cannot be resurrected.
  86      * Sending <code>undo</code> or <code>redo</code> to
  87      * a dead edit results in an exception being thrown.
  88      *
  89      * <p>Typically an edit is killed when it is consolidated by
  90      * another edit's <code>addEdit</code> or <code>replaceEdit</code>
  91      * method, or when it is dequeued from an <code>UndoManager</code>.
  92      */
  93     public void die() {
  94         alive = false;
  95     }
  96 
  97     /**
  98      * Throws <code>CannotUndoException</code> if <code>canUndo</code>
  99      * returns <code>false</code>. Sets <code>hasBeenDone</code>
 100      * to <code>false</code>. Subclasses should override to undo the
 101      * operation represented by this edit. Override should begin with
 102      * a call to super.
 103      *
 104      * @exception CannotUndoException if <code>canUndo</code>
 105      *    returns <code>false</code>
 106      * @see     #canUndo
 107      */
 108     public void undo() throws CannotUndoException {
 109         if (!canUndo()) {
 110             throw new CannotUndoException();
 111         }
 112         hasBeenDone = false;
 113     }
 114 
 115     /**
 116      * Returns true if this edit is <code>alive</code>
 117      * and <code>hasBeenDone</code> is <code>true</code>.
 118      *
 119      * @return true if this edit is <code>alive</code>
 120      *    and <code>hasBeenDone</code> is <code>true</code>
 121      *
 122      * @see     #die
 123      * @see     #undo
 124      * @see     #redo
 125      */
 126     public boolean canUndo() {
 127         return alive && hasBeenDone;
 128     }
 129 
 130     /**
 131      * Throws <code>CannotRedoException</code> if <code>canRedo</code>
 132      * returns false. Sets <code>hasBeenDone</code> to <code>true</code>.
 133      * Subclasses should override to redo the operation represented by
 134      * this edit. Override should begin with a call to super.
 135      *
 136      * @exception CannotRedoException if <code>canRedo</code>
 137      *     returns <code>false</code>
 138      * @see     #canRedo
 139      */
 140     public void redo() throws CannotRedoException {
 141         if (!canRedo()) {
 142             throw new CannotRedoException();
 143         }
 144         hasBeenDone = true;
 145     }
 146 
 147     /**
 148      * Returns <code>true</code> if this edit is <code>alive</code>
 149      * and <code>hasBeenDone</code> is <code>false</code>.
 150      *
 151      * @return <code>true</code> if this edit is <code>alive</code>
 152      *   and <code>hasBeenDone</code> is <code>false</code>
 153      * @see     #die
 154      * @see     #undo
 155      * @see     #redo
 156      */
 157     public boolean canRedo() {
 158         return alive && !hasBeenDone;
 159     }
 160 
 161     /**
 162      * This default implementation returns false.
 163      *
 164      * @param anEdit the edit to be added
 165      * @return false
 166      *
 167      * @see UndoableEdit#addEdit
 168      */
 169     public boolean addEdit(UndoableEdit anEdit) {
 170         return false;
 171     }
 172 
 173     /**
 174      * This default implementation returns false.
 175      *
 176      * @param anEdit the edit to replace
 177      * @return false
 178      *
 179      * @see UndoableEdit#replaceEdit
 180      */
 181     public boolean replaceEdit(UndoableEdit anEdit) {
 182         return false;
 183     }
 184 
 185     /**
 186      * This default implementation returns true.
 187      *
 188      * @return true
 189      * @see UndoableEdit#isSignificant
 190      */
 191     public boolean isSignificant() {
 192         return true;
 193     }
 194 
 195     /**
 196      * This default implementation returns "". Used by
 197      * <code>getUndoPresentationName</code> and
 198      * <code>getRedoPresentationName</code> to
 199      * construct the strings they return. Subclasses should override to
 200      * return an appropriate description of the operation this edit
 201      * represents.
 202      *
 203      * @return the empty string ""
 204      *
 205      * @see     #getUndoPresentationName
 206      * @see     #getRedoPresentationName
 207      */
 208     public String getPresentationName() {
 209         return "";
 210     }
 211 
 212     /**
 213      * Retreives the value from the defaults table with key
 214      * <code>AbstractUndoableEdit.undoText</code> and returns
 215      * that value followed by a space, followed by
 216      * <code>getPresentationName</code>.
 217      * If <code>getPresentationName</code> returns "",
 218      * then the defaults value is returned alone.
 219      *
 220      * @return the value from the defaults table with key
 221      *    <code>AbstractUndoableEdit.undoText</code>, followed
 222      *    by a space, followed by <code>getPresentationName</code>
 223      *    unless <code>getPresentationName</code> is "" in which
 224      *    case, the defaults value is returned alone.
 225      * @see #getPresentationName
 226      */
 227     public String getUndoPresentationName() {
 228         String name = getPresentationName();
 229         if (!"".equals(name)) {
 230             name = UIManager.getString("AbstractUndoableEdit.undoText") +
 231                 " " + name;
 232         } else {
 233             name = UIManager.getString("AbstractUndoableEdit.undoText");
 234         }
 235 
 236         return name;
 237     }
 238 
 239     /**
 240      * Retreives the value from the defaults table with key
 241      * <code>AbstractUndoableEdit.redoText</code> and returns
 242      * that value followed by a space, followed by
 243      * <code>getPresentationName</code>.
 244      * If <code>getPresentationName</code> returns "",
 245      * then the defaults value is returned alone.
 246      *
 247      * @return the value from the defaults table with key
 248      *    <code>AbstractUndoableEdit.redoText</code>, followed
 249      *    by a space, followed by <code>getPresentationName</code>
 250      *    unless <code>getPresentationName</code> is "" in which
 251      *    case, the defaults value is returned alone.
 252      * @see #getPresentationName
 253      */
 254     public String getRedoPresentationName() {
 255         String name = getPresentationName();
 256         if (!"".equals(name)) {
 257             name = UIManager.getString("AbstractUndoableEdit.redoText") +
 258                 " " + name;
 259         } else {
 260             name = UIManager.getString("AbstractUndoableEdit.redoText");
 261         }
 262 
 263         return name;
 264     }
 265 
 266     /**
 267      * Returns a string that displays and identifies this
 268      * object's properties.
 269      *
 270      * @return a String representation of this object
 271      */
 272     public String toString()
 273     {
 274         return super.toString()
 275             + " hasBeenDone: " + hasBeenDone
 276             + " alive: " + alive;
 277     }
 278 }