aboutsummaryrefslogtreecommitdiff
path: root/libjava/javax/swing/undo/CompoundEdit.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/javax/swing/undo/CompoundEdit.java')
-rw-r--r--libjava/javax/swing/undo/CompoundEdit.java590
1 files changed, 350 insertions, 240 deletions
diff --git a/libjava/javax/swing/undo/CompoundEdit.java b/libjava/javax/swing/undo/CompoundEdit.java
index be612dad77b..12ff2bd36ec 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;
+ }
+}