aboutsummaryrefslogtreecommitdiff
path: root/libjava/javax
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/javax')
-rw-r--r--libjava/javax/swing/undo/AbstractUndoableEdit.java323
-rw-r--r--libjava/javax/swing/undo/CannotRedoException.java32
-rw-r--r--libjava/javax/swing/undo/CannotUndoException.java33
-rw-r--r--libjava/javax/swing/undo/CompoundEdit.java590
-rw-r--r--libjava/javax/swing/undo/StateEdit.java160
-rw-r--r--libjava/javax/swing/undo/StateEditable.java73
6 files changed, 781 insertions, 430 deletions
diff --git a/libjava/javax/swing/undo/AbstractUndoableEdit.java b/libjava/javax/swing/undo/AbstractUndoableEdit.java
index d845e43..e694c0a 100644
--- a/libjava/javax/swing/undo/AbstractUndoableEdit.java
+++ b/libjava/javax/swing/undo/AbstractUndoableEdit.java
@@ -1,4 +1,4 @@
-/* AbstractTableModel.java --
+/* AbstractUndoableEdit.java
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,180 +39,285 @@ exception statement from your version. */
package javax.swing.undo;
import java.io.Serializable;
+import javax.swing.UIManager;
+
/**
- * AbstractUndoableEdit
- * @author Andrew Selkirk
+ * A default implementation of <code>UndoableEdit</code> that can be
+ * used as a base for implementing editing operations.
+ *
+ * @author Andrew Selkirk (aselkirk@sympatico.ca)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class AbstractUndoableEdit implements UndoableEdit, Serializable
+public class AbstractUndoableEdit
+ implements UndoableEdit, Serializable
{
+ /**
+ * The serialization ID. Verified using the <code>serialver</code>
+ * tool of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5, and Sun JDK
+ * 1.4.1_01 on GNU/Linux.
+ */
static final long serialVersionUID = 580150227676302096L;
- //-------------------------------------------------------------
- // Constants --------------------------------------------------
- //-------------------------------------------------------------
/**
- * String returned by getRedoPresentationName()
+ * The constant string &#x201c;Undo&#x201d;, which was returned by
+ * {@link #getUndoPresentationName()} on early versions of the
+ * platform. However, this field has become obsolete with version
+ * 1.3.1. That method now retrieves a localized string from the
+ * {@link javax.swing.UIManager}, using the key
+ * <code>&#x201c;AbstractUndoableEdit.undoText&#x201d;</code>.
*/
- protected static final String RedoName = "Redo";
+ protected static final String UndoName = "Undo";
+
/**
- * String returned by getUndoPresentationName()
+ * The constant string &#x201c;Redo&#x201d;, which was returned by
+ * {@link #getRedoPresentationName()} on early versions of the
+ * platform. However, this field has become obsolete with version
+ * 1.3.1. That method now retrieves a localized string from the
+ * {@link javax.swing.UIManager}, using the key
+ * <code>&#x201c;AbstractUndoableEdit.redoText&#x201d;</code>.
*/
- protected static final String UndoName = "Undo";
-
+ protected static final String RedoName = "Redo";
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
/**
- * TODO
+ * Indicates whether this editing action has been executed. A value
+ * of <code>true</code> means that the action was performed, or that
+ * a redo operation was successful. A value of <code>false</code>
+ * means that the action has not yet performed, or that an undo
+ * operation was successful.
*/
- private boolean hasBeenDone = false;
+ private boolean hasBeenDone;
+
/**
- * The edit is alive
+ * Indicates whether this editing action is still alive. The value
+ * is set to <code>true</code> by the constructor, and to
+ * <code>false</code> by the {@link #die()} method.
*/
- private boolean alive = true;
+ private boolean alive;
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
/**
- * Create new AbstractUndoableEdit
+ * Constructs a new <code>AbstractUndoableEdit</code>. The initial
+ * state is that the editing action is alive, and
+ * <code>hasBeenDone</code> is <code>true</code>.
*/
public AbstractUndoableEdit()
{
- } // AbstractUndoableEdit()
-
+ // The API specification is not clear, but Mauve test code has
+ // determined that hasBeenDone is initially set to true.
+ alive = hasBeenDone = true;
+ }
- //-------------------------------------------------------------
- // Interface: UndoableEdit ------------------------------------
- //-------------------------------------------------------------
/**
- * addEdit
- * @param anEdit TODO
- * @returns TODO
+ * Undoes this editing action.
+ *
+ * @throws CannotUndoException if {@link #canUndo()} returns
+ * <code>false</code>, for example because this action has already
+ * been undone.
+ *
+ * @see #canUndo()
+ * @see #redo()
*/
- public boolean addEdit(UndoableEdit anEdit)
+ public void undo()
+ throws CannotUndoException
{
- return false;
- } // addEdit()
-
+ if (!canUndo())
+ throw new CannotUndoException();
+ hasBeenDone = false;
+ }
+
+
/**
- * canRedo()
- * @returns true if redoable, false otherwise
+ * Determines whether it would be possible to undo this editing
+ * action.
+ *
+ * @return <code>true</code> to indicate that this action can be
+ * undone, <code>false</code> otherwise.
+ *
+ * @see #undo()
+ * @see #canRedo()
*/
- public boolean canRedo()
+ public boolean canUndo()
{
- if (alive == true && hasBeenDone == false)
- return true;
- return false;
- } // canRedo()
-
+ return alive && hasBeenDone;
+ }
+
+
/**
- * canUndo()
- * @returns true if undoable, false otherwise
+ * Redoes this editing action.
+ *
+ * @throws CannotRedoException if {@link #canRedo()} returns
+ * <code>false</code>, for example because this action has not
+ * yet been undone.
+ *
+ * @see #canRedo()
+ * @see #undo()
*/
- public boolean canUndo()
+ public void redo()
+ throws CannotRedoException
{
- if (alive == true && hasBeenDone == true)
- return true;
- return false;
- } // canUndo()
-
+ if (!canRedo())
+ throw new CannotRedoException();
+ hasBeenDone = true;
+ }
+
+
/**
- * die
+ * Determines whether it would be possible to redo this editing
+ * action.
+ *
+ * @return <code>true</code> to indicate that this action can be
+ * redone, <code>false</code> otherwise.
+ *
+ * @see #redo()
+ * @see #canUndo()
*/
- public void die()
+ public boolean canRedo()
{
- alive = false;
- } // die()
+ return alive && !hasBeenDone;
+ }
+
/**
- * getPresentation
- * @returns TODO
+ * Informs this edit action that it will no longer be used. Some
+ * actions might use this information to release resources, for
+ * example open files. Called by {@link UndoManager} before this
+ * action is removed from the edit queue.
*/
- public String getPresentationName()
+ public void die()
{
- return "";
- } // getPresentationName()
+ alive = false;
+ }
+
/**
- * getRedoPresentationName
- * @returns TODO
+ * Incorporates another editing action into this one, thus forming a
+ * combined action.
+ *
+ * <p>The default implementation always returns <code>false</code>,
+ * indicating that the editing action could not be incorporated.
+ *
+ * @param edit the editing action to be incorporated.
*/
- public String getRedoPresentationName()
+ public boolean addEdit(UndoableEdit edit)
{
- if (getPresentationName().equals(""))
- return RedoName;
- return RedoName + " " + getPresentationName();
- } // getRedoPresentationName()
-
+ return false;
+ }
+
+
/**
- * getUndoPresentationName
- * @returns TODO
+ * Incorporates another editing action into this one, thus forming a
+ * combined action that replaces the argument action.
+ *
+ * <p>The default implementation always returns <code>false</code>,
+ * indicating that the argument action should not be replaced.
+ *
+ * @param edit the editing action to be replaced.
*/
- public String getUndoPresentationName()
+ public boolean replaceEdit(UndoableEdit edit)
{
- if (getPresentationName().equals(""))
- return UndoName;
- return UndoName + " " + getPresentationName();
- } // getUndoPresentationName()
-
+ return false;
+ }
+
+
/**
- * isSignificant
- * @returns true
+ * Determines whether this editing action is significant enough for
+ * being seperately undoable by the user. A typical significant
+ * action would be the resizing of an object. However, changing the
+ * selection in a text document would usually not be considered
+ * significant.
+ *
+ * <p>The default implementation returns <code>true</code>.
+ *
+ * @return <code>true</code> to indicate that the action is
+ * significant enough for being separately undoable, or
+ * <code>false</code> otherwise.
*/
public boolean isSignificant()
{
return true;
- } // isSignificant()
-
+ }
+
+
/**
- * redo
- * @throws CannotRedoException TODO
+ * Returns a human-readable, localized name that describes this
+ * editing action and can be displayed to the user.
+ *
+ * <p>The default implementation returns an empty string.
*/
- public void redo() throws CannotRedoException
+ public String getPresentationName()
{
- if (! canRedo())
- throw new CannotRedoException();
- hasBeenDone = true;
- } // redo()
+ return "";
+ }
+
/**
- * replaceEdit
- * @param anEdit TODO
- * @returns TODO
+ * Calculates a localized name for presenting the undo action to the
+ * user.
+ *
+ * <p>The default implementation returns the concatenation of the
+ * string &#x201c;Undo&#x201d; and the action name, which is
+ * determined by calling {@link #getPresentationName()}.
+ *
+ * <p>The string &#x201c;Undo&#x201d; is retrieved from the {@link
+ * javax.swing.UIManager}, using the key
+ * <code>&#x201c;AbstractUndoableEdit.undoText&#x201d;</code>. This
+ * allows the text to be localized.
*/
- public boolean replaceEdit(UndoableEdit anEdit)
+ public String getUndoPresentationName()
{
- return false;
- } // replaceEdit()
+ String msg, pres;
+
+ msg = UIManager.getString("AbstractUndoableEdit.undoText");
+ if (msg == null)
+ msg = UndoName;
+
+ pres = getPresentationName();
+ if ((pres == null) || (pres.length() == 0))
+ return msg;
+ else
+ return msg + ' ' + pres;
+ }
+
/**
- * String representation
- * @returns String representation
+ * Calculates a localized name for presenting the redo action to the
+ * user.
+ *
+ * <p>The default implementation returns the concatenation of the
+ * string &#x201c;Redo&#x201d; and the action name, which is
+ * determined by calling {@link #getPresentationName()}.
+ *
+ * <p>The string &#x201c;Redo&#x201d; is retrieved from the {@link
+ * javax.swing.UIManager}, using the key
+ * <code>&#x201c;AbstractUndoableEdit.redoText&#x201d;</code>. This
+ * allows the text to be localized.
*/
- public String toString()
+ public String getRedoPresentationName()
{
- return (super.toString() + " hasBeenDone: " + hasBeenDone
- + " alive: " + alive);
+ String msg, pres;
+
+ msg = UIManager.getString("AbstractUndoableEdit.redoText");
+ if (msg == null)
+ msg = RedoName;
+
+ pres = getPresentationName();
+ if ((pres == null) || (pres.length() == 0))
+ return msg;
+ else
+ return msg + ' ' + pres;
}
- /**
- * undo
- * @throws CannotUndoException TODO
- */
- public void undo() throws CannotUndoException
+
+ public String toString()
{
- if (! canUndo())
- throw new CannotUndoException();
- hasBeenDone = false;
- } // undo()
-} // AbstractUndoableEdit
+ return super.toString()
+ + " hasBeenDone: " + hasBeenDone
+ + " alive: " + alive;
+ }
+}
diff --git a/libjava/javax/swing/undo/CannotRedoException.java b/libjava/javax/swing/undo/CannotRedoException.java
index 030975d..f482b75 100644
--- a/libjava/javax/swing/undo/CannotRedoException.java
+++ b/libjava/javax/swing/undo/CannotRedoException.java
@@ -1,5 +1,5 @@
-/* AbstractTableModel.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+/* CannotRedoException.java
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,17 +38,19 @@ exception statement from your version. */
package javax.swing.undo;
/**
- * CannotRedoException
- * @author Andrew Selkirk
+ * An exception which indicates that an editing action cannot be
+ * redone.
+ *
+ * @author Andrew Selkirk (aselkirk@sympatico.ca)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class CannotRedoException extends RuntimeException {
-
- /**
- * Create exception
- */
- public CannotRedoException() {
- super();
- } // CannotRedoException()
-
-
-} // CannotRedoException
+public class CannotRedoException
+ extends RuntimeException
+{
+ /**
+ * Constructs a new instance of a <code>CannotRedoException</code>.
+ */
+ public CannotRedoException()
+ {
+ }
+}
diff --git a/libjava/javax/swing/undo/CannotUndoException.java b/libjava/javax/swing/undo/CannotUndoException.java
index c039d1b..0193921 100644
--- a/libjava/javax/swing/undo/CannotUndoException.java
+++ b/libjava/javax/swing/undo/CannotUndoException.java
@@ -1,5 +1,5 @@
-/* AbstractTableModel.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+/* CannotUndoException.java
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,18 +37,21 @@ exception statement from your version. */
package javax.swing.undo;
+
/**
- * CannotUndoException
- * @author Andrew Selkirk
+ * An exception which indicates that an editing action cannot be
+ * undone.
+ *
+ * @author Andrew Selkirk (aselkirk@sympatico.ca)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class CannotUndoException extends RuntimeException {
-
- /**
- * Create exception
- */
- public CannotUndoException() {
- super();
- } // CannotUndoException()
-
-
-} // CannotUndoException
+public class CannotUndoException
+ extends RuntimeException
+{
+ /**
+ * Constructs a new instance of a <code>CannotUndoException</code>.
+ */
+ public CannotUndoException()
+ {
+ }
+}
diff --git a/libjava/javax/swing/undo/CompoundEdit.java b/libjava/javax/swing/undo/CompoundEdit.java
index be612da..12ff2bd 100644
--- a/libjava/javax/swing/undo/CompoundEdit.java
+++ b/libjava/javax/swing/undo/CompoundEdit.java
@@ -1,5 +1,5 @@
-/* AbstractTableModel.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+/* CompoundEdit.java -- Combines multiple UndoableEdits.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,242 +41,352 @@ package javax.swing.undo;
import java.util.Vector;
/**
- * CompoundEdit
- * @author Andrew Selkirk
+ * An editing action that consists of multiple
+ * <code>UndoableEdits</code>.
+ *
+ * <p>The use of a <code>CompoundEdit</code> is divided in two separate
+ * phases.
+ *
+ * <ol><li>In the first phase, the <code>CompoundEdit</code> is
+ * initialized. After a new instance of <code>CompoundEdit</code> has
+ * been created, {@link #addEdit(UndoableEdit)} is called for each
+ * element of the compound. To terminate the initialization phase,
+ * call {@link #end()}.</li>
+ *
+ * <li>In the second phase, the the <code>CompoundEdit</code> can be
+ * used, typically by invoking {@link #undo()} and {@link
+ * #redo()}.</li></ol>
+ *
+ * @author Andrew Selkirk (aselkirk@sympatico.ca)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class CompoundEdit extends AbstractUndoableEdit {
-
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * The collection of UndoableEdits undone/redone en
- * masse by this CompoundEdit
- */
- protected Vector edits = new Vector();
-
- /**
- * TODO
- */
- private boolean inProgress = false;
-
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Create new Compound Edit
- */
- public CompoundEdit() {
- } // CompoundEdit()
-
-
- //-------------------------------------------------------------
- // Interface: UndoableEdit ------------------------------------
- //-------------------------------------------------------------
-
- /**
- * addEdit
- * @param anEdit TODO
- * @returns TODO
- */
- public boolean addEdit(UndoableEdit anEdit) {
-
- // Variables
- UndoableEdit lastEdit;
-
- if (inProgress == true) {
-
- // Get Last Edit
- lastEdit = lastEdit();
-
- // Check for null
- if (lastEdit != null) {
-
- if (lastEdit.addEdit(anEdit) == false) {
- if (lastEdit.replaceEdit(anEdit) == false) {
- edits.add(anEdit);
- }
- }
-
- } // if: lastEdit
-
- return true;
-
- } else {
- return false;
- }
- } // addEdit()
-
- /**
- * canRedo
- * @returns TODO
- */
- public boolean canRedo() {
- if (isInProgress() == true || super.canRedo() == false) {
- return false;
- }
- return true;
- } // canRedo()
-
- /**
- * canUndo
- * @returns TODO
- */
- public boolean canUndo() {
- if (isInProgress() == true || super.canUndo() == false) {
- return false;
- }
- return true;
- } // canUndo()
-
- /**
- * die
- */
- public void die() {
-
- // Variables
- int index;
- UndoableEdit current;
-
- // Loop through all contained UndoableEdits
- for (index = edits.size() - 1; index >= 0; index--) {
- current = (UndoableEdit) edits.elementAt(index);
- current.die();
- } // for: index
-
- } // die()
-
- /**
- * end
- */
- public void end() {
- inProgress = false;
- } // end()
-
- /**
- * getPresentationName
- * @returns TODO
- */
- public String getPresentationName() {
- if (edits.size() == 0) {
- return super.getPresentationName();
- } else {
- return lastEdit().getPresentationName();
- }
- } // getPresentationName()
-
- /**
- * getRedoPresentationName
- * @returns TODO
- */
- public String getRedoPresentationName() {
- if (edits.size() == 0) {
- return super.getRedoPresentationName();
- } else {
- return lastEdit().getRedoPresentationName();
- }
- } // getRedoPresentationName()
-
- /**
- * getUndoPresentationName
- * @returns TODO
- */
- public String getUndoPresentationName() {
- if (edits.size() == 0) {
- return super.getUndoPresentationName();
- } else {
- return lastEdit().getUndoPresentationName();
- }
- } // getUndoPresentationName()
-
- /**
- * isInProgress
- * @returns TODO
- */
- public boolean isInProgress() {
- return inProgress;
- } // isInProgress()
-
-
- /**
- * isSignigicant
- * @returns TODO
- */
- public boolean isSignificant() {
-
- // Variables
- int index;
- UndoableEdit current;
-
- // Check each edit
- for (index = 0; index < edits.size(); index++) {
- current = (UndoableEdit) edits.elementAt(index);
- if (current.isSignificant() == true) {
- return true;
- }
- } // for: index
-
- return false;
-
- } // isSignificant()
-
- /**
- * lastEdit
- * @returns TODO
- */
- protected UndoableEdit lastEdit() {
- if (edits.size() == 0) {
- return null;
- }
- return (UndoableEdit) edits.elementAt(edits.size() - 1);
- } // lastEdit()
-
- /**
- * redo
- * @throws CannotRedoException TODO
- */
- public void redo() throws CannotRedoException {
-
- // Variables
- int index;
- UndoableEdit current;
-
- // Loop through all contained UndoableEdits
- for (index = 0; index < edits.size(); index++) {
- current = (UndoableEdit) edits.elementAt(index);
- current.redo();
- } // for: index
-
- } // redo()
-
- /**
- * String representation
- * @returns String representation
- */
- public String toString() {
- return null; // TODO
- } // toString()
-
- /**
- * undo
- * @throws CannotUndoException TODO
- */
- public void undo() throws CannotUndoException {
-
- // Variables
- int index;
- UndoableEdit current;
-
- // Loop through all contained UndoableEdits
- for (index = edits.size() - 1; index >= 0; index--) {
- current = (UndoableEdit) edits.elementAt(index);
- current.undo();
- } // for: index
-
- } // undo()
-
-
-} // CompoundEdit
+public class CompoundEdit
+ extends AbstractUndoableEdit
+{
+ /**
+ * The <code>UndoableEdit</code>s being combined into a compound
+ * editing action.
+ */
+ protected Vector edits;
+
+
+ /**
+ * Indicates whether the creation of this CompoundEdit is still in
+ * progress. Initially, the value of this flag is
+ * <code>true</code>. The {@link #end()} method changes the flag to
+ * <code>false</code>.
+ */
+ private boolean inProgress;
+
+
+ /**
+ * Constructs a new CompoundEdit.
+ */
+ public CompoundEdit()
+ {
+ edits = new Vector();
+ inProgress = true;
+ }
+
+
+ /**
+ * Undoes all edits that are part of of this
+ * <code>CompoundEdit</code>. The compound elements will receive the
+ * <code>undo</code> message in the reverse order of addition.
+ *
+ * @throws CannotUndoException if {@link #canUndo()} returns
+ * <code>false</code>. This can happen if {@link #end()} has not
+ * been called on this <code>CompoundEdit</code>, or if this edit
+ * has already been undone.
+ *
+ * @see #canUndo()
+ * @see #redo()
+ */
+ public void undo()
+ throws CannotUndoException
+ {
+ // AbstractUndoableEdit.undo() will throw a CannotUndoException if
+ // canUndo returns false.
+ super.undo();
+
+ for (int i = edits.size() - 1; i >= 0; i--)
+ ((UndoableEdit) edits.elementAt(i)).undo();
+ }
+
+
+ /**
+ * Redoes all edits that are part of of this
+ * <code>CompoundEdit</code>. The compound elements will receive the
+ * <code>undo</code> message in the same order as they were added.
+ *
+ * @throws CannotRedoException if {@link #canRedo()} returns
+ * <code>false</code>. This can happen if {@link #end()} has not
+ * been called on this <code>CompoundEdit</code>, or if this edit
+ * has already been redone.
+ *
+ * @see #canRedo()
+ * @see #undo()
+ */
+ public void redo()
+ throws CannotRedoException
+ {
+ // AbstractUndoableEdit.redo() will throw a CannotRedoException if
+ // canRedo returns false.
+ super.redo();
+
+ for (int i = 0; i < edits.size(); i++)
+ ((UndoableEdit) edits.elementAt(i)).redo();
+ }
+
+
+ /**
+ * Returns the the <code>UndoableEdit</code> that was last added to
+ * this compound.
+ */
+ protected UndoableEdit lastEdit()
+ {
+ if (edits.size() == 0)
+ return null;
+ else
+ return (UndoableEdit) edits.elementAt(edits.size() - 1);
+ }
+
+
+ /**
+ * Informs this edit action, and all compound edits, that they will
+ * no longer be used. Some actions might use this information to
+ * release resources such as open files. Called by {@link
+ * UndoManager} before this action is removed from the edit queue.
+ *
+ * <p>The compound elements will receive the
+ * <code>die</code> message in the reverse order of addition.
+ */
+ public void die()
+ {
+ for (int i = edits.size() - 1; i >= 0; i--)
+ ((UndoableEdit) edits.elementAt(i)).die();
+
+ super.die();
+ }
+
+
+ /**
+ * Incorporates another editing action into this one, thus forming a
+ * combined edit.
+ *
+ * <p>If this edit&#x2019;s {@link #end()} method has been called
+ * before, <code>false</code> is returned immediately. Otherwise,
+ * the {@linkplain #lastEdit() last added edit} is given the
+ * opportunity to {@linkplain UndoableEdit#addEdit(UndoableEdit)
+ * incorporate} <code>edit</code>. If this fails, <code>edit</code>
+ * is given the opportunity to {@linkplain
+ * UndoableEdit#replaceEdit(UndoableEdit) replace} the last added
+ * edit. If this fails as well, <code>edit</code> gets added as a
+ * new compound to {@link #edits}.
+ *
+ * @param edit the editing action being added.
+ *
+ * @return <code>true</code> if <code>edit</code> could somehow be
+ * incorporated; <code>false</code> if <code>edit</code> has not
+ * been incorporated because {@link #end()} was called before.
+ */
+ public boolean addEdit(UndoableEdit edit)
+ {
+ UndoableEdit last;
+
+ // If end has been called before, do nothing.
+ if (!inProgress)
+ return false;
+
+ last = lastEdit();
+
+ // If edit is the very first edit, just add it to the list.
+ if (last == null)
+ {
+ edits.add(edit);
+ return true;
+ }
+
+ // Try to incorporate edit into last.
+ if (last.addEdit(edit))
+ return true;
+
+ // Try to replace last by edit.
+ if (edit.replaceEdit(last))
+ {
+ edits.set(edits.size() - 1, edit);
+ return true;
+ }
+
+ // If everything else has failed, add edit to the list of compound
+ // edits.
+ edits.add(edit);
+ return true;
+ }
+
+
+ /**
+ * Informs this <code>CompoundEdit</code> that its construction
+ * phase has been completed. After this method has been called,
+ * {@link #undo()} and {@link #redo()} may be called, {@link
+ * #isInProgress()} will return <code>false</code>, and all attempts
+ * to {@linkplain #addEdit(UndoableEdit) add further edits} will
+ * fail.
+ */
+ public void end()
+ {
+ inProgress = false;
+ }
+
+
+ /**
+ * Determines whether it would be possible to undo this editing
+ * action. The result will be <code>true</code> if {@link #end()}
+ * has been called on this <code>CompoundEdit</code>, {@link #die()}
+ * has not yet been called, and the edit has not been undone
+ * already.
+ *
+ * @return <code>true</code> to indicate that this action can be
+ * undone; <code>false</code> otherwise.
+ *
+ * @see #undo()
+ * @see #canRedo()
+ */
+ public boolean canUndo()
+ {
+ return !inProgress && super.canUndo();
+ }
+
+
+ /**
+ * Determines whether it would be possible to redo this editing
+ * action. The result will be <code>true</code> if {@link #end()}
+ * has been called on this <code>CompoundEdit</code>, {@link #die()}
+ * has not yet been called, and the edit has not been redone
+ * already.
+ *
+ * @return <code>true</code> to indicate that this action can be
+ * redone; <code>false</code> otherwise.
+ *
+ * @see #redo()
+ * @see #canUndo()
+ */
+ public boolean canRedo()
+ {
+ return !inProgress && super.canRedo();
+ }
+
+
+ /**
+ * Determines whether the initial construction phase of this
+ * <code>CompoundEdit</code> is still in progress. During this
+ * phase, edits {@linkplain #addEdit(UndoableEdit) may be
+ * added}. After initialization has been terminated by calling
+ * {@link #end()}, {@link #undo()} and {@link #redo()} can be used.
+ *
+ * @return <code>true</code> if the initialization phase is still in
+ * progress; <code>false</code> if {@link #end()} has been called.
+ *
+ * @see #end()
+ */
+ public boolean isInProgress()
+ {
+ return inProgress;
+ }
+
+
+ /**
+ * Determines whether this editing action is significant enough for
+ * being seperately undoable by the user. A typical significant
+ * action would be the resizing of an object. However, changing the
+ * selection in a text document would usually not be considered
+ * significant.
+ *
+ * <p>A <code>CompoundEdit</code> is significant if any of its
+ * elements are significant.
+ */
+ public boolean isSignificant()
+ {
+ for (int i = edits.size() - 1; i >= 0; i--)
+ if (((UndoableEdit) edits.elementAt(i)).isSignificant())
+ return true;
+
+ return false;
+ }
+
+
+ /**
+ * Returns a human-readable, localized name that describes this
+ * editing action and can be displayed to the user.
+ *
+ * <p>The implementation delegates the call to the {@linkplain
+ * #lastEdit() last added edit action}. If no edit has been added
+ * yet, the inherited implementation will be invoked, which always
+ * returns an empty string.
+ */
+ public String getPresentationName()
+ {
+ UndoableEdit last;
+
+ last = lastEdit();
+ if (last == null)
+ return super.getPresentationName();
+ else
+ return last.getPresentationName();
+ }
+
+
+ /**
+ * Calculates a localized message text for presenting the undo
+ * action to the user.
+ *
+ * <p>The implementation delegates the call to the {@linkplain
+ * #lastEdit() last added edit action}. If no edit has been added
+ * yet, the {@linkplain
+ * AbstractUndoableEdit#getUndoPresentationName() inherited
+ * implementation} will be invoked.
+ */
+ public String getUndoPresentationName()
+ {
+ UndoableEdit last;
+
+ last = lastEdit();
+ if (last == null)
+ return super.getUndoPresentationName();
+ else
+ return last.getUndoPresentationName();
+ }
+
+
+ /**
+ * Calculates a localized message text for presenting the redo
+ * action to the user.
+ *
+ * <p>The implementation delegates the call to the {@linkplain
+ * #lastEdit() last added edit action}. If no edit has been added
+ * yet, the {@linkplain
+ * AbstractUndoableEdit#getRedoPresentationName() inherited
+ * implementation} will be invoked.
+ */
+ public String getRedoPresentationName()
+ {
+ UndoableEdit last;
+
+ last = lastEdit();
+ if (last == null)
+ return super.getRedoPresentationName();
+ else
+ return last.getRedoPresentationName();
+ }
+
+
+ /**
+ * Calculates a string that may be useful for debugging.
+ */
+ public String toString()
+ {
+ return super.toString()
+ + " inProgress: " + inProgress
+ + " edits: " + edits;
+ }
+}
diff --git a/libjava/javax/swing/undo/StateEdit.java b/libjava/javax/swing/undo/StateEdit.java
index 6a32fbd..00f1e2d 100644
--- a/libjava/javax/swing/undo/StateEdit.java
+++ b/libjava/javax/swing/undo/StateEdit.java
@@ -1,4 +1,4 @@
-/* StateEdit.java --
+/* StateEdit.java -- UndoableEdit for StateEditable implementations.
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,59 +42,118 @@ import java.util.Hashtable;
import java.util.Iterator;
/**
- * StateEdit
- * @author Andrew Selkirk
+ * A helper class, making it easy to support undo and redo.
+ *
+ * <p>The following example shows how to use this class.
+ *
+ * <pre> Foo foo; // class Foo implements {@link StateEditable}
+ * StateEdit edit;
+ *
+ * edit = new StateEdit(foo, "Name Change");
+ * foo.setName("Jane Doe");
+ * edit.end();
+ * undoManager.addEdit(edit);</pre>
+ *
+ * <p>If <code>Foo</code>&#x2019;s implementation of {@link
+ * StateEditable} considers the name as part of the editable state,
+ * the user can now choose &#x201c;Undo Name Change&#x201d; or
+ * &#x201c;Redo Name Change&#x201d; from the respective menu. No
+ * further undo support is needed from the application.
+ *
+ * <p>The following explains what happens in the example.
+ *
+ * <p><ol><li>When a <code>StateEdit</code> is created, the associated
+ * {@link StateEditable} gets asked to store its state into a hash
+ * table, {@link #preState}.</li>
+ *
+ * <li>The application will now perform some changes to the edited
+ * object. This typically happens by invoking methods on the edited
+ * object.</li>
+ *
+ * <li>The editing phase is terminated by invoking the {@link #end()}
+ * method of the <code>StateEdit</code>. The <code>end()</code> method
+ * does two things.
+ *
+ * <ul><li>The edited object receives a second request for storing
+ * its state. This time, it will use a different hash table, {@link
+ * #postState}.</li>
+ *
+ * <li>To increase efficiency, the <code>StateEdit</code> now removes
+ * any entries from {@link #preState} and {@link #postState} that have
+ * the same key, and whose values are equal. Equality is determined
+ * by invoking the <code>equals</code> method inherited from
+ * {@link java.lang.Object}.</li></ul></li>
+ *
+ * <li>When the user later chooses to undo the <code>StateEdit</code>,
+ * the edited object is asked to {@linkplain StateEditable#restoreState
+ * restore its state} from the {@link #preState} table. Similarly,
+ * when the user chooses to <i>redo</i> the <code>StateEdit</code>,
+ * the edited object gets asked to restore its state from the {@link
+ * #postState}.</li></ol>
+ *
+ * @author Andrew Selkirk (aselkirk@sympatico.ca)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class StateEdit extends AbstractUndoableEdit
+public class StateEdit
+ extends AbstractUndoableEdit
{
-
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
-
/**
- * RCSID
+ * The ID of the Java source file in Sun&#x2019;s Revision Control
+ * System (RCS). This certainly should not be part of the API
+ * specification. But in order to be API-compatible with
+ * Sun&#x2019;s reference implementation, GNU Classpath also has to
+ * provide this field. However, we do not try to match its value.
*/
- protected static final String RCSID = ""; // TODO
+ protected static final String RCSID = "";
+
/**
- * object
+ * The object which is being edited by this <code>StateEdit</code>.
*/
protected StateEditable object;
+
/**
- * preState
+ * The state of <code>object</code> at the time of constructing
+ * this <code>StateEdit</code>.
*/
protected Hashtable preState;
+
/**
- * postState
+ * The state of <code>object</code> at the time when {@link #end()}
+ * was called.
*/
protected Hashtable postState;
+
/**
- * undoRedoName
+ * A human-readable name for this edit action.
*/
protected String undoRedoName;
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
/**
- * Constructor StateEdit
- * @param obj Object to edit
+ * Constructs a <code>StateEdit</code>, specifying the object whose
+ * state is being edited.
+ *
+ * @param obj the object whose state is being edited by this
+ * <code>StateEdit</code>.
*/
public StateEdit(StateEditable obj)
{
init(obj, null);
}
+
/**
- * Constructor StateEdit
- * @param obj Object to edit
- * @param name Presentation name
+ * Constructs a <code>StateEdit</code>, specifying the object whose
+ * state is being edited.
+ *
+ * @param obj the object whose state is being edited by this
+ * <code>StateEdit</code>.
+ *
+ * @param name the human-readable name of the editing action.
*/
public StateEdit(StateEditable obj, String name)
{
@@ -102,14 +161,13 @@ public class StateEdit extends AbstractUndoableEdit
}
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
/**
- * Initialize this object.
- * @param obj Object to edit
- * @param name Presentation name
+ * Initializes this <code>StateEdit</code>. The edited object will
+ * be asked to store its current state into {@link #preState}.
+ *
+ * @param obj the object being edited.
+ *
+ * @param name the human-readable name of the editing action.
*/
protected void init(StateEditable obj, String name)
{
@@ -120,9 +178,12 @@ public class StateEdit extends AbstractUndoableEdit
obj.storeState(preState);
}
+
/**
- * Indicate that all edits are finished, and update this object
- * with final state.
+ * Informs this <code>StateEdit</code> that all edits are finished.
+ * The edited object will be asked to store its state into {@link
+ * #postState}, and any redundant entries will get removed from
+ * {@link #preState} and {@link #postState}.
*/
public void end()
{
@@ -130,33 +191,56 @@ public class StateEdit extends AbstractUndoableEdit
removeRedundantState();
}
+
/**
- * Undo this edit by applying the initial state to the edited object.
+ * Undoes this edit operation. The edited object will be asked to
+ * {@linkplain StateEditable#restoreState restore its state} from
+ * {@link #preState}.
+ *
+ * @throws CannotUndoException if {@link #canUndo()} returns
+ * <code>false</code>, for example because this action has already
+ * been undone.
*/
public void undo()
{
+ super.undo();
object.restoreState(preState);
}
+
/**
- * Undo this edit by applying the final state to the edited object.
+ * Redoes this edit operation. The edited object will be asked to
+ * {@linkplain StateEditable#restoreState restore its state} from
+ * {@link #postState}.
+ *
+ * @throws CannotRedoException if {@link #canRedo()} returns
+ * <code>false</code>, for example because this action has not yet
+ * been undone.
*/
public void redo()
{
+ super.redo();
object.restoreState(postState);
}
+
/**
- * Return the presentation name of this object.
- * @returns The name, or null if not set
+ * Returns a human-readable, localized name that describes this
+ * editing action and can be displayed to the user.
+ *
+ * @return the name, or <code>null</code> if no presentation
+ * name is available.
*/
public String getPresentationName()
{
return undoRedoName;
}
+
/**
- * removeRedundantState
+ * Removes all redundant entries from the pre- and post-edit state
+ * hash tables. An entry is considered redundant if it is present
+ * both before and after the edit, and if the two values are equal.
*/
protected void removeRedundantState()
{
diff --git a/libjava/javax/swing/undo/StateEditable.java b/libjava/javax/swing/undo/StateEditable.java
index 016a543..d3f9d4c 100644
--- a/libjava/javax/swing/undo/StateEditable.java
+++ b/libjava/javax/swing/undo/StateEditable.java
@@ -1,4 +1,4 @@
-/* StateEditable.java --
+/* StateEditable.java -- Interface for collaborating with StateEdit.
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,29 +37,76 @@ exception statement from your version. */
package javax.swing.undo;
-// Imports
import java.util.Hashtable;
+
/**
- * StateEditable public interface
- * @author Andrew Selkirk
+ * The interface for objects whose state can be undone or redone by a
+ * {@link StateEdit} action.
+ *
+ * <p>The following example shows how to write a class that implements
+ * this interface.
+ *
+ * <pre> class Foo
+ * implements StateEditable
+ * {
+ * private String name;
+ *
+ * public void setName(String n) { name = n; }
+ *
+ * public void restoreState(Hashtable h)
+ * {
+ * if (h.containsKey("name"))
+ * setName((String) h.get("name"));
+ * }
+ *
+ * public void storeState(Hashtable s)
+ * {
+ * s.put("name", name);
+ * }
+ * }</pre>
+ *
+ * @see StateEdit
+ *
+ * @author Andrew Selkirk (aselkirk@sympatico.ca)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
public interface StateEditable
{
/**
- * Restore State
- * @param state State
+ * The ID of the Java source file in Sun&#x2019;s Revision Control
+ * System (RCS). This certainly should not be part of the API
+ * specification. But in order to be API-compatible with
+ * Sun&#x2019;s reference implementation, GNU Classpath also has to
+ * provide this field. However, we do not try to match its value.
*/
- void restoreState(Hashtable state);
+ static final String RCSID = "";
+
/**
- * Store State
- * @param state State
+ * Performs an edit action, taking any editable state information
+ * from the specified hash table.
+ *
+ * <p><b>Note to implementors of this interface:</b> To increase
+ * efficiency, the <code>StateEdit</code> class {@linkplan
+ * StateEdit#removeRedundantState() removes redundant state
+ * information}. Therefore, implementations of this interface must be
+ * prepared for the case where certain keys were stored into the
+ * table by {@link #storeState}, but are not present anymore
+ * when the <code>restoreState</code> method gets called.
+ *
+ * @param state a hash table containing the relevant state
+ * information.
*/
- void storeState(Hashtable state);
+ void restoreState(Hashtable state);
+
/**
- * For some reason, Sun made the RCS IDs visible.
+ * Stores any editable state information into the specified hash
+ * table.
+ *
+ * @param state a hash table for storing relevant state
+ * information.
*/
- String RCSID = "We aren't compatible";
-} // StateEditable
+ void storeState(Hashtable state);
+}