StateEdit.java (getPresentationName): Docfix.
2003-11-26 Sascha Brawer <brawer@dandelis.ch> * javax/swing/undo/StateEdit.java (getPresentationName): Docfix. * javax/swing/undo/AbstractUndoableEdit.java (canUndo, canRedo, isSignificant): Likewise. 2003-11-26 Sascha Brawer <brawer@dandelis.ch> * javax/swing/undo/CompoundEdit.java: Re-format, document. (inProgress): Set initial value to true. (undo, redo, die, canUndo, canRedo): Also call inherited implementation; simplify code structure. (getPresentationName, getUndoPresentationName, getRedoPresentationName): Make behavior dependent on lastEdit. (addEdit, isSignificant): Completely re-written. 2003-11-26 Sascha Brawer <brawer@dandelis.ch> * javax/swing/undo/StateEdit.java: Re-format, document. (undo, redo): Also call inherited implementation. 2003-11-26 Sascha Brawer <brawer@dandelis.ch> * javax/swing/undo/StateEditable.java: Re-format, document. 2003-11-26 Sascha Brawer <brawer@dandelis.ch> * javax/swing/undo/AbstractUndoableEdit.java: Re-format, document. (AbstractUndoableEdit): Initialize hasBeenDone to true. (canUndo, canRedo): Simplify. (getUndoPresentationName, getRedoPresentationName): Support localized message; call getPresentationName() only once. From-SVN: r73967
This commit is contained in:
parent
034f23169e
commit
aef81a9acb
7 changed files with 814 additions and 430 deletions
|
@ -1,3 +1,36 @@
|
||||||
|
2003-11-26 Sascha Brawer <brawer@dandelis.ch>
|
||||||
|
|
||||||
|
* javax/swing/undo/StateEdit.java (getPresentationName): Docfix.
|
||||||
|
* javax/swing/undo/AbstractUndoableEdit.java (canUndo, canRedo,
|
||||||
|
isSignificant): Likewise.
|
||||||
|
|
||||||
|
2003-11-26 Sascha Brawer <brawer@dandelis.ch>
|
||||||
|
|
||||||
|
* javax/swing/undo/CompoundEdit.java: Re-format, document.
|
||||||
|
(inProgress): Set initial value to true.
|
||||||
|
(undo, redo, die, canUndo, canRedo): Also call inherited
|
||||||
|
implementation; simplify code structure.
|
||||||
|
(getPresentationName, getUndoPresentationName,
|
||||||
|
getRedoPresentationName): Make behavior dependent on lastEdit.
|
||||||
|
(addEdit, isSignificant): Completely re-written.
|
||||||
|
|
||||||
|
2003-11-26 Sascha Brawer <brawer@dandelis.ch>
|
||||||
|
|
||||||
|
* javax/swing/undo/StateEdit.java: Re-format, document.
|
||||||
|
(undo, redo): Also call inherited implementation.
|
||||||
|
|
||||||
|
2003-11-26 Sascha Brawer <brawer@dandelis.ch>
|
||||||
|
|
||||||
|
* javax/swing/undo/StateEditable.java: Re-format, document.
|
||||||
|
|
||||||
|
2003-11-26 Sascha Brawer <brawer@dandelis.ch>
|
||||||
|
|
||||||
|
* javax/swing/undo/AbstractUndoableEdit.java: Re-format, document.
|
||||||
|
(AbstractUndoableEdit): Initialize hasBeenDone to true.
|
||||||
|
(canUndo, canRedo): Simplify.
|
||||||
|
(getUndoPresentationName, getRedoPresentationName): Support
|
||||||
|
localized message; call getPresentationName() only once.
|
||||||
|
|
||||||
2003-11-26 David Belanger <dbelan2@cs.mcgill.ca>
|
2003-11-26 David Belanger <dbelan2@cs.mcgill.ca>
|
||||||
|
|
||||||
* java/util/zip/ZipFile (Zipfile(File)): Set file path as name.
|
* java/util/zip/ZipFile (Zipfile(File)): Set file path as name.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* AbstractTableModel.java --
|
/* AbstractUndoableEdit.java
|
||||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
@ -39,180 +39,285 @@ exception statement from your version. */
|
||||||
package javax.swing.undo;
|
package javax.swing.undo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractUndoableEdit
|
* A default implementation of <code>UndoableEdit</code> that can be
|
||||||
* @author Andrew Selkirk
|
* 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;
|
static final long serialVersionUID = 580150227676302096L;
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
// Constants --------------------------------------------------
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String returned by getRedoPresentationName()
|
* The constant string “Undo”, which was returned by
|
||||||
*/
|
* {@link #getUndoPresentationName()} on early versions of the
|
||||||
protected static final String RedoName = "Redo";
|
* 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
|
||||||
* String returned by getUndoPresentationName()
|
* <code>“AbstractUndoableEdit.undoText”</code>.
|
||||||
*/
|
*/
|
||||||
protected static final String UndoName = "Undo";
|
protected static final String UndoName = "Undo";
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
// Variables --------------------------------------------------
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* The constant string “Redo”, 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>“AbstractUndoableEdit.redoText”</code>.
|
||||||
*/
|
*/
|
||||||
private boolean hasBeenDone = false;
|
protected static final String RedoName = "Redo";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The edit is alive
|
* 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 alive = true;
|
private boolean hasBeenDone;
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
// Initialization ---------------------------------------------
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new AbstractUndoableEdit
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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()
|
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
|
* Undoes this editing action.
|
||||||
* @param anEdit TODO
|
*
|
||||||
* @returns TODO
|
* @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;
|
if (!canUndo())
|
||||||
} // addEdit()
|
throw new CannotUndoException();
|
||||||
|
hasBeenDone = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* canRedo()
|
* Determines whether it would be possible to undo this editing
|
||||||
* @returns true if redoable, false otherwise
|
* action.
|
||||||
*/
|
*
|
||||||
public boolean canRedo()
|
* @return <code>true</code> to indicate that this action can be
|
||||||
{
|
* undone, <code>false</code> otherwise.
|
||||||
if (alive == true && hasBeenDone == false)
|
*
|
||||||
return true;
|
* @see #undo()
|
||||||
return false;
|
* @see #canRedo()
|
||||||
} // canRedo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* canUndo()
|
|
||||||
* @returns true if undoable, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public boolean canUndo()
|
public boolean canUndo()
|
||||||
{
|
{
|
||||||
if (alive == true && hasBeenDone == true)
|
return alive && hasBeenDone;
|
||||||
return true;
|
}
|
||||||
return false;
|
|
||||||
} // canUndo()
|
|
||||||
|
/**
|
||||||
|
* 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 void redo()
|
||||||
|
throws CannotRedoException
|
||||||
|
{
|
||||||
|
if (!canRedo())
|
||||||
|
throw new CannotRedoException();
|
||||||
|
hasBeenDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 boolean canRedo()
|
||||||
|
{
|
||||||
|
return alive && !hasBeenDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* die
|
* 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 void die()
|
public void die()
|
||||||
{
|
{
|
||||||
alive = false;
|
alive = false;
|
||||||
} // die()
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getPresentation
|
* Incorporates another editing action into this one, thus forming a
|
||||||
* @returns TODO
|
* 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 getPresentationName()
|
public boolean addEdit(UndoableEdit edit)
|
||||||
{
|
{
|
||||||
return "";
|
return false;
|
||||||
} // getPresentationName()
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getRedoPresentationName
|
* Incorporates another editing action into this one, thus forming a
|
||||||
* @returns TODO
|
* 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 getRedoPresentationName()
|
public boolean replaceEdit(UndoableEdit edit)
|
||||||
{
|
{
|
||||||
if (getPresentationName().equals(""))
|
return false;
|
||||||
return RedoName;
|
}
|
||||||
return RedoName + " " + getPresentationName();
|
|
||||||
} // getRedoPresentationName()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getUndoPresentationName
|
* Determines whether this editing action is significant enough for
|
||||||
* @returns TODO
|
* being seperately undoable by the user. A typical significant
|
||||||
*/
|
* action would be the resizing of an object. However, changing the
|
||||||
public String getUndoPresentationName()
|
* selection in a text document would usually not be considered
|
||||||
{
|
* significant.
|
||||||
if (getPresentationName().equals(""))
|
*
|
||||||
return UndoName;
|
* <p>The default implementation returns <code>true</code>.
|
||||||
return UndoName + " " + getPresentationName();
|
*
|
||||||
} // getUndoPresentationName()
|
* @return <code>true</code> to indicate that the action is
|
||||||
|
* significant enough for being separately undoable, or
|
||||||
/**
|
* <code>false</code> otherwise.
|
||||||
* isSignificant
|
|
||||||
* @returns true
|
|
||||||
*/
|
*/
|
||||||
public boolean isSignificant()
|
public boolean isSignificant()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
} // isSignificant()
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* redo
|
* Returns a human-readable, localized name that describes this
|
||||||
* @throws CannotRedoException TODO
|
* 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())
|
return "";
|
||||||
throw new CannotRedoException();
|
|
||||||
hasBeenDone = true;
|
|
||||||
} // redo()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* replaceEdit
|
|
||||||
* @param anEdit TODO
|
|
||||||
* @returns TODO
|
|
||||||
*/
|
|
||||||
public boolean replaceEdit(UndoableEdit anEdit)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
} // replaceEdit()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String representation
|
|
||||||
* @returns String representation
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return (super.toString() + " hasBeenDone: " + hasBeenDone
|
|
||||||
+ " alive: " + alive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* undo
|
* Calculates a localized name for presenting the undo action to the
|
||||||
* @throws CannotUndoException TODO
|
* user.
|
||||||
|
*
|
||||||
|
* <p>The default implementation returns the concatenation of the
|
||||||
|
* string “Undo” and the action name, which is
|
||||||
|
* determined by calling {@link #getPresentationName()}.
|
||||||
|
*
|
||||||
|
* <p>The string “Undo” is retrieved from the {@link
|
||||||
|
* javax.swing.UIManager}, using the key
|
||||||
|
* <code>“AbstractUndoableEdit.undoText”</code>. This
|
||||||
|
* allows the text to be localized.
|
||||||
*/
|
*/
|
||||||
public void undo() throws CannotUndoException
|
public String getUndoPresentationName()
|
||||||
{
|
{
|
||||||
if (! canUndo())
|
String msg, pres;
|
||||||
throw new CannotUndoException();
|
|
||||||
hasBeenDone = false;
|
msg = UIManager.getString("AbstractUndoableEdit.undoText");
|
||||||
} // undo()
|
if (msg == null)
|
||||||
} // AbstractUndoableEdit
|
msg = UndoName;
|
||||||
|
|
||||||
|
pres = getPresentationName();
|
||||||
|
if ((pres == null) || (pres.length() == 0))
|
||||||
|
return msg;
|
||||||
|
else
|
||||||
|
return msg + ' ' + pres;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates a localized name for presenting the redo action to the
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* <p>The default implementation returns the concatenation of the
|
||||||
|
* string “Redo” and the action name, which is
|
||||||
|
* determined by calling {@link #getPresentationName()}.
|
||||||
|
*
|
||||||
|
* <p>The string “Redo” is retrieved from the {@link
|
||||||
|
* javax.swing.UIManager}, using the key
|
||||||
|
* <code>“AbstractUndoableEdit.redoText”</code>. This
|
||||||
|
* allows the text to be localized.
|
||||||
|
*/
|
||||||
|
public String getRedoPresentationName()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return super.toString()
|
||||||
|
+ " hasBeenDone: " + hasBeenDone
|
||||||
|
+ " alive: " + alive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractTableModel.java --
|
/* CannotRedoException.java
|
||||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -38,17 +38,19 @@ exception statement from your version. */
|
||||||
package javax.swing.undo;
|
package javax.swing.undo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CannotRedoException
|
* An exception which indicates that an editing action cannot be
|
||||||
* @author Andrew Selkirk
|
* redone.
|
||||||
|
*
|
||||||
|
* @author Andrew Selkirk (aselkirk@sympatico.ca)
|
||||||
|
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||||
*/
|
*/
|
||||||
public class CannotRedoException extends RuntimeException {
|
public class CannotRedoException
|
||||||
|
extends RuntimeException
|
||||||
/**
|
{
|
||||||
* Create exception
|
/**
|
||||||
*/
|
* Constructs a new instance of a <code>CannotRedoException</code>.
|
||||||
public CannotRedoException() {
|
*/
|
||||||
super();
|
public CannotRedoException()
|
||||||
} // CannotRedoException()
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
} // CannotRedoException
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractTableModel.java --
|
/* CannotUndoException.java
|
||||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -37,18 +37,21 @@ exception statement from your version. */
|
||||||
|
|
||||||
package javax.swing.undo;
|
package javax.swing.undo;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CannotUndoException
|
* An exception which indicates that an editing action cannot be
|
||||||
* @author Andrew Selkirk
|
* undone.
|
||||||
|
*
|
||||||
|
* @author Andrew Selkirk (aselkirk@sympatico.ca)
|
||||||
|
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||||
*/
|
*/
|
||||||
public class CannotUndoException extends RuntimeException {
|
public class CannotUndoException
|
||||||
|
extends RuntimeException
|
||||||
/**
|
{
|
||||||
* Create exception
|
/**
|
||||||
*/
|
* Constructs a new instance of a <code>CannotUndoException</code>.
|
||||||
public CannotUndoException() {
|
*/
|
||||||
super();
|
public CannotUndoException()
|
||||||
} // CannotUndoException()
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
} // CannotUndoException
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractTableModel.java --
|
/* CompoundEdit.java -- Combines multiple UndoableEdits.
|
||||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -41,242 +41,352 @@ package javax.swing.undo;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompoundEdit
|
* An editing action that consists of multiple
|
||||||
* @author Andrew Selkirk
|
* <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 {
|
public class CompoundEdit
|
||||||
|
extends AbstractUndoableEdit
|
||||||
//-------------------------------------------------------------
|
{
|
||||||
// Variables --------------------------------------------------
|
/**
|
||||||
//-------------------------------------------------------------
|
* The <code>UndoableEdit</code>s being combined into a compound
|
||||||
|
* editing action.
|
||||||
/**
|
*/
|
||||||
* The collection of UndoableEdits undone/redone en
|
protected Vector edits;
|
||||||
* masse by this CompoundEdit
|
|
||||||
*/
|
|
||||||
protected Vector edits = new Vector();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
*/
|
|
||||||
private boolean inProgress = false;
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
/**
|
||||||
// Initialization ---------------------------------------------
|
* 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>.
|
||||||
* Create new Compound Edit
|
*/
|
||||||
*/
|
private boolean inProgress;
|
||||||
public CompoundEdit() {
|
|
||||||
} // CompoundEdit()
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
/**
|
||||||
// Interface: UndoableEdit ------------------------------------
|
* Constructs a new CompoundEdit.
|
||||||
//-------------------------------------------------------------
|
*/
|
||||||
|
public CompoundEdit()
|
||||||
|
{
|
||||||
|
edits = new Vector();
|
||||||
|
inProgress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* addEdit
|
* Undoes all edits that are part of of this
|
||||||
* @param anEdit TODO
|
* <code>CompoundEdit</code>. The compound elements will receive the
|
||||||
* @returns TODO
|
* <code>undo</code> message in the reverse order of addition.
|
||||||
*/
|
*
|
||||||
public boolean addEdit(UndoableEdit anEdit) {
|
* @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();
|
||||||
|
|
||||||
// Variables
|
for (int i = edits.size() - 1; i >= 0; i--)
|
||||||
UndoableEdit lastEdit;
|
((UndoableEdit) edits.elementAt(i)).undo();
|
||||||
|
}
|
||||||
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
|
* Redoes all edits that are part of of this
|
||||||
* @returns TODO
|
* <code>CompoundEdit</code>. The compound elements will receive the
|
||||||
*/
|
* <code>undo</code> message in the same order as they were added.
|
||||||
public boolean isSignificant() {
|
*
|
||||||
|
* @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();
|
||||||
|
|
||||||
// Variables
|
for (int i = 0; i < edits.size(); i++)
|
||||||
int index;
|
((UndoableEdit) edits.elementAt(i)).redo();
|
||||||
UndoableEdit current;
|
}
|
||||||
|
|
||||||
// Check each edit
|
|
||||||
for (index = 0; index < edits.size(); index++) {
|
/**
|
||||||
current = (UndoableEdit) edits.elementAt(index);
|
* Returns the the <code>UndoableEdit</code> that was last added to
|
||||||
if (current.isSignificant() == true) {
|
* this compound.
|
||||||
return true;
|
*/
|
||||||
}
|
protected UndoableEdit lastEdit()
|
||||||
} // for: index
|
{
|
||||||
|
if (edits.size() == 0)
|
||||||
return false;
|
return null;
|
||||||
|
else
|
||||||
} // isSignificant()
|
return (UndoableEdit) edits.elementAt(edits.size() - 1);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 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
|
/**
|
||||||
|
* 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’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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* StateEdit.java --
|
/* StateEdit.java -- UndoableEdit for StateEditable implementations.
|
||||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
@ -42,59 +42,118 @@ import java.util.Hashtable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StateEdit
|
* A helper class, making it easy to support undo and redo.
|
||||||
* @author Andrew Selkirk
|
*
|
||||||
|
* <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>’s implementation of {@link
|
||||||
|
* StateEditable} considers the name as part of the editable state,
|
||||||
|
* the user can now choose “Undo Name Change” or
|
||||||
|
* “Redo Name Change” 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’s Revision Control
|
||||||
|
* System (RCS). This certainly should not be part of the API
|
||||||
|
* specification. But in order to be API-compatible with
|
||||||
|
* Sun’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;
|
protected StateEditable object;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* preState
|
* The state of <code>object</code> at the time of constructing
|
||||||
|
* this <code>StateEdit</code>.
|
||||||
*/
|
*/
|
||||||
protected Hashtable preState;
|
protected Hashtable preState;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* postState
|
* The state of <code>object</code> at the time when {@link #end()}
|
||||||
|
* was called.
|
||||||
*/
|
*/
|
||||||
protected Hashtable postState;
|
protected Hashtable postState;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* undoRedoName
|
* A human-readable name for this edit action.
|
||||||
*/
|
*/
|
||||||
protected String undoRedoName;
|
protected String undoRedoName;
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
// Initialization ---------------------------------------------
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor StateEdit
|
* Constructs a <code>StateEdit</code>, specifying the object whose
|
||||||
* @param obj Object to edit
|
* state is being edited.
|
||||||
|
*
|
||||||
|
* @param obj the object whose state is being edited by this
|
||||||
|
* <code>StateEdit</code>.
|
||||||
*/
|
*/
|
||||||
public StateEdit(StateEditable obj)
|
public StateEdit(StateEditable obj)
|
||||||
{
|
{
|
||||||
init(obj, null);
|
init(obj, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor StateEdit
|
* Constructs a <code>StateEdit</code>, specifying the object whose
|
||||||
* @param obj Object to edit
|
* state is being edited.
|
||||||
* @param name Presentation name
|
*
|
||||||
|
* @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)
|
public StateEdit(StateEditable obj, String name)
|
||||||
{
|
{
|
||||||
|
@ -102,14 +161,13 @@ public class StateEdit extends AbstractUndoableEdit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
// Methods ----------------------------------------------------
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this object.
|
* Initializes this <code>StateEdit</code>. The edited object will
|
||||||
* @param obj Object to edit
|
* be asked to store its current state into {@link #preState}.
|
||||||
* @param name Presentation name
|
*
|
||||||
|
* @param obj the object being edited.
|
||||||
|
*
|
||||||
|
* @param name the human-readable name of the editing action.
|
||||||
*/
|
*/
|
||||||
protected void init(StateEditable obj, String name)
|
protected void init(StateEditable obj, String name)
|
||||||
{
|
{
|
||||||
|
@ -120,9 +178,12 @@ public class StateEdit extends AbstractUndoableEdit
|
||||||
obj.storeState(preState);
|
obj.storeState(preState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate that all edits are finished, and update this object
|
* Informs this <code>StateEdit</code> that all edits are finished.
|
||||||
* with final state.
|
* 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()
|
public void end()
|
||||||
{
|
{
|
||||||
|
@ -130,33 +191,56 @@ public class StateEdit extends AbstractUndoableEdit
|
||||||
removeRedundantState();
|
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()
|
public void undo()
|
||||||
{
|
{
|
||||||
|
super.undo();
|
||||||
object.restoreState(preState);
|
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()
|
public void redo()
|
||||||
{
|
{
|
||||||
|
super.redo();
|
||||||
object.restoreState(postState);
|
object.restoreState(postState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the presentation name of this object.
|
* Returns a human-readable, localized name that describes this
|
||||||
* @returns The name, or null if not set
|
* 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()
|
public String getPresentationName()
|
||||||
{
|
{
|
||||||
return undoRedoName;
|
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()
|
protected void removeRedundantState()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* StateEditable.java --
|
/* StateEditable.java -- Interface for collaborating with StateEdit.
|
||||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
@ -37,29 +37,76 @@ exception statement from your version. */
|
||||||
|
|
||||||
package javax.swing.undo;
|
package javax.swing.undo;
|
||||||
|
|
||||||
// Imports
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StateEditable public interface
|
* The interface for objects whose state can be undone or redone by a
|
||||||
* @author Andrew Selkirk
|
* {@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
|
public interface StateEditable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Restore State
|
* The ID of the Java source file in Sun’s Revision Control
|
||||||
* @param state State
|
* System (RCS). This certainly should not be part of the API
|
||||||
|
* specification. But in order to be API-compatible with
|
||||||
|
* Sun’s reference implementation, GNU Classpath also has to
|
||||||
|
* provide this field. However, we do not try to match its value.
|
||||||
|
*/
|
||||||
|
static final String RCSID = "";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 restoreState(Hashtable state);
|
void restoreState(Hashtable state);
|
||||||
|
|
||||||
/**
|
|
||||||
* Store State
|
|
||||||
* @param state State
|
|
||||||
*/
|
|
||||||
void storeState(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";
|
void storeState(Hashtable state);
|
||||||
} // StateEditable
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue