feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
278
jdkSrc/jdk8/javax/swing/undo/AbstractUndoableEdit.java
Normal file
278
jdkSrc/jdk8/javax/swing/undo/AbstractUndoableEdit.java
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* An abstract implementation of <code>UndoableEdit</code>,
|
||||
* implementing simple responses to all boolean methods in
|
||||
* that interface.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public class AbstractUndoableEdit implements UndoableEdit, Serializable {
|
||||
|
||||
/**
|
||||
* String returned by <code>getUndoPresentationName</code>;
|
||||
* as of Java 2 platform v1.3.1 this field is no longer used. This value
|
||||
* is now localized and comes from the defaults table with key
|
||||
* <code>AbstractUndoableEdit.undoText</code>.
|
||||
*
|
||||
* @see javax.swing.UIDefaults
|
||||
*/
|
||||
protected static final String UndoName = "Undo";
|
||||
|
||||
/**
|
||||
* String returned by <code>getRedoPresentationName</code>;
|
||||
* as of Java 2 platform v1.3.1 this field is no longer used. This value
|
||||
* is now localized and comes from the defaults table with key
|
||||
* <code>AbstractUndoableEdit.redoText</code>.
|
||||
*
|
||||
* @see javax.swing.UIDefaults
|
||||
*/
|
||||
protected static final String RedoName = "Redo";
|
||||
|
||||
/**
|
||||
* Defaults to true; becomes false if this edit is undone, true
|
||||
* again if it is redone.
|
||||
*/
|
||||
boolean hasBeenDone;
|
||||
|
||||
/**
|
||||
* True if this edit has not received <code>die</code>; defaults
|
||||
* to <code>true</code>.
|
||||
*/
|
||||
boolean alive;
|
||||
|
||||
/**
|
||||
* Creates an <code>AbstractUndoableEdit</code> which defaults
|
||||
* <code>hasBeenDone</code> and <code>alive</code> to <code>true</code>.
|
||||
*/
|
||||
public AbstractUndoableEdit() {
|
||||
super();
|
||||
|
||||
hasBeenDone = true;
|
||||
alive = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets <code>alive</code> to false. Note that this
|
||||
* is a one way operation; dead edits cannot be resurrected.
|
||||
* Sending <code>undo</code> or <code>redo</code> to
|
||||
* a dead edit results in an exception being thrown.
|
||||
*
|
||||
* <p>Typically an edit is killed when it is consolidated by
|
||||
* another edit's <code>addEdit</code> or <code>replaceEdit</code>
|
||||
* method, or when it is dequeued from an <code>UndoManager</code>.
|
||||
*/
|
||||
public void die() {
|
||||
alive = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws <code>CannotUndoException</code> if <code>canUndo</code>
|
||||
* returns <code>false</code>. Sets <code>hasBeenDone</code>
|
||||
* to <code>false</code>. Subclasses should override to undo the
|
||||
* operation represented by this edit. Override should begin with
|
||||
* a call to super.
|
||||
*
|
||||
* @exception CannotUndoException if <code>canUndo</code>
|
||||
* returns <code>false</code>
|
||||
* @see #canUndo
|
||||
*/
|
||||
public void undo() throws CannotUndoException {
|
||||
if (!canUndo()) {
|
||||
throw new CannotUndoException();
|
||||
}
|
||||
hasBeenDone = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this edit is <code>alive</code>
|
||||
* and <code>hasBeenDone</code> is <code>true</code>.
|
||||
*
|
||||
* @return true if this edit is <code>alive</code>
|
||||
* and <code>hasBeenDone</code> is <code>true</code>
|
||||
*
|
||||
* @see #die
|
||||
* @see #undo
|
||||
* @see #redo
|
||||
*/
|
||||
public boolean canUndo() {
|
||||
return alive && hasBeenDone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws <code>CannotRedoException</code> if <code>canRedo</code>
|
||||
* returns false. Sets <code>hasBeenDone</code> to <code>true</code>.
|
||||
* Subclasses should override to redo the operation represented by
|
||||
* this edit. Override should begin with a call to super.
|
||||
*
|
||||
* @exception CannotRedoException if <code>canRedo</code>
|
||||
* returns <code>false</code>
|
||||
* @see #canRedo
|
||||
*/
|
||||
public void redo() throws CannotRedoException {
|
||||
if (!canRedo()) {
|
||||
throw new CannotRedoException();
|
||||
}
|
||||
hasBeenDone = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this edit is <code>alive</code>
|
||||
* and <code>hasBeenDone</code> is <code>false</code>.
|
||||
*
|
||||
* @return <code>true</code> if this edit is <code>alive</code>
|
||||
* and <code>hasBeenDone</code> is <code>false</code>
|
||||
* @see #die
|
||||
* @see #undo
|
||||
* @see #redo
|
||||
*/
|
||||
public boolean canRedo() {
|
||||
return alive && !hasBeenDone;
|
||||
}
|
||||
|
||||
/**
|
||||
* This default implementation returns false.
|
||||
*
|
||||
* @param anEdit the edit to be added
|
||||
* @return false
|
||||
*
|
||||
* @see UndoableEdit#addEdit
|
||||
*/
|
||||
public boolean addEdit(UndoableEdit anEdit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This default implementation returns false.
|
||||
*
|
||||
* @param anEdit the edit to replace
|
||||
* @return false
|
||||
*
|
||||
* @see UndoableEdit#replaceEdit
|
||||
*/
|
||||
public boolean replaceEdit(UndoableEdit anEdit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This default implementation returns true.
|
||||
*
|
||||
* @return true
|
||||
* @see UndoableEdit#isSignificant
|
||||
*/
|
||||
public boolean isSignificant() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This default implementation returns "". Used by
|
||||
* <code>getUndoPresentationName</code> and
|
||||
* <code>getRedoPresentationName</code> to
|
||||
* construct the strings they return. Subclasses should override to
|
||||
* return an appropriate description of the operation this edit
|
||||
* represents.
|
||||
*
|
||||
* @return the empty string ""
|
||||
*
|
||||
* @see #getUndoPresentationName
|
||||
* @see #getRedoPresentationName
|
||||
*/
|
||||
public String getPresentationName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives the value from the defaults table with key
|
||||
* <code>AbstractUndoableEdit.undoText</code> and returns
|
||||
* that value followed by a space, followed by
|
||||
* <code>getPresentationName</code>.
|
||||
* If <code>getPresentationName</code> returns "",
|
||||
* then the defaults value is returned alone.
|
||||
*
|
||||
* @return the value from the defaults table with key
|
||||
* <code>AbstractUndoableEdit.undoText</code>, followed
|
||||
* by a space, followed by <code>getPresentationName</code>
|
||||
* unless <code>getPresentationName</code> is "" in which
|
||||
* case, the defaults value is returned alone.
|
||||
* @see #getPresentationName
|
||||
*/
|
||||
public String getUndoPresentationName() {
|
||||
String name = getPresentationName();
|
||||
if (!"".equals(name)) {
|
||||
name = UIManager.getString("AbstractUndoableEdit.undoText") +
|
||||
" " + name;
|
||||
} else {
|
||||
name = UIManager.getString("AbstractUndoableEdit.undoText");
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives the value from the defaults table with key
|
||||
* <code>AbstractUndoableEdit.redoText</code> and returns
|
||||
* that value followed by a space, followed by
|
||||
* <code>getPresentationName</code>.
|
||||
* If <code>getPresentationName</code> returns "",
|
||||
* then the defaults value is returned alone.
|
||||
*
|
||||
* @return the value from the defaults table with key
|
||||
* <code>AbstractUndoableEdit.redoText</code>, followed
|
||||
* by a space, followed by <code>getPresentationName</code>
|
||||
* unless <code>getPresentationName</code> is "" in which
|
||||
* case, the defaults value is returned alone.
|
||||
* @see #getPresentationName
|
||||
*/
|
||||
public String getRedoPresentationName() {
|
||||
String name = getPresentationName();
|
||||
if (!"".equals(name)) {
|
||||
name = UIManager.getString("AbstractUndoableEdit.redoText") +
|
||||
" " + name;
|
||||
} else {
|
||||
name = UIManager.getString("AbstractUndoableEdit.redoText");
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that displays and identifies this
|
||||
* object's properties.
|
||||
*
|
||||
* @return a String representation of this object
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return super.toString()
|
||||
+ " hasBeenDone: " + hasBeenDone
|
||||
+ " alive: " + alive;
|
||||
}
|
||||
}
|
||||
42
jdkSrc/jdk8/javax/swing/undo/CannotRedoException.java
Normal file
42
jdkSrc/jdk8/javax/swing/undo/CannotRedoException.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package javax.swing.undo;
|
||||
|
||||
/**
|
||||
* Thrown when an UndoableEdit is told to <code>redo()</code> and can't.
|
||||
* <p>
|
||||
* <strong>Warning:</strong>
|
||||
* Serialized objects of this class will not be compatible with
|
||||
* future Swing releases. The current serialization support is
|
||||
* appropriate for short term storage or RMI between applications running
|
||||
* the same version of Swing. As of 1.4, support for long term storage
|
||||
* of all JavaBeans™
|
||||
* has been added to the <code>java.beans</code> package.
|
||||
* Please see {@link java.beans.XMLEncoder}.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public class CannotRedoException extends RuntimeException {
|
||||
}
|
||||
43
jdkSrc/jdk8/javax/swing/undo/CannotUndoException.java
Normal file
43
jdkSrc/jdk8/javax/swing/undo/CannotUndoException.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
/**
|
||||
* Thrown when an UndoableEdit is told to <code>undo()</code> and can't.
|
||||
* <p>
|
||||
* <strong>Warning:</strong>
|
||||
* Serialized objects of this class will not be compatible with
|
||||
* future Swing releases. The current serialization support is
|
||||
* appropriate for short term storage or RMI between applications running
|
||||
* the same version of Swing. As of 1.4, support for long term storage
|
||||
* of all JavaBeans™
|
||||
* has been added to the <code>java.beans</code> package.
|
||||
* Please see {@link java.beans.XMLEncoder}.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public class CannotUndoException extends RuntimeException {
|
||||
}
|
||||
262
jdkSrc/jdk8/javax/swing/undo/CompoundEdit.java
Normal file
262
jdkSrc/jdk8/javax/swing/undo/CompoundEdit.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package javax.swing.undo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A concrete subclass of AbstractUndoableEdit, used to assemble little
|
||||
* UndoableEdits into great big ones.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public class CompoundEdit extends AbstractUndoableEdit {
|
||||
/**
|
||||
* True if this edit has never received <code>end</code>.
|
||||
*/
|
||||
boolean inProgress;
|
||||
|
||||
/**
|
||||
* The collection of <code>UndoableEdit</code>s
|
||||
* undone/redone en masse by this <code>CompoundEdit</code>.
|
||||
*/
|
||||
protected Vector<UndoableEdit> edits;
|
||||
|
||||
public CompoundEdit() {
|
||||
super();
|
||||
inProgress = true;
|
||||
edits = new Vector<UndoableEdit>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends <code>undo</code> to all contained
|
||||
* <code>UndoableEdits</code> in the reverse of
|
||||
* the order in which they were added.
|
||||
*/
|
||||
public void undo() throws CannotUndoException {
|
||||
super.undo();
|
||||
int i = edits.size();
|
||||
while (i-- > 0) {
|
||||
UndoableEdit e = edits.elementAt(i);
|
||||
e.undo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends <code>redo</code> to all contained
|
||||
* <code>UndoableEdit</code>s in the order in
|
||||
* which they were added.
|
||||
*/
|
||||
public void redo() throws CannotRedoException {
|
||||
super.redo();
|
||||
Enumeration cursor = edits.elements();
|
||||
while (cursor.hasMoreElements()) {
|
||||
((UndoableEdit)cursor.nextElement()).redo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last <code>UndoableEdit</code> in
|
||||
* <code>edits</code>, or <code>null</code>
|
||||
* if <code>edits</code> is empty.
|
||||
*/
|
||||
protected UndoableEdit lastEdit() {
|
||||
int count = edits.size();
|
||||
if (count > 0)
|
||||
return edits.elementAt(count-1);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends <code>die</code> to each subedit,
|
||||
* in the reverse of the order that they were added.
|
||||
*/
|
||||
public void die() {
|
||||
int size = edits.size();
|
||||
for (int i = size-1; i >= 0; i--)
|
||||
{
|
||||
UndoableEdit e = edits.elementAt(i);
|
||||
// System.out.println("CompoundEdit(" + i + "): Discarding " +
|
||||
// e.getUndoPresentationName());
|
||||
e.die();
|
||||
}
|
||||
super.die();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this edit is <code>inProgress</code>,
|
||||
* accepts <code>anEdit</code> and returns true.
|
||||
*
|
||||
* <p>The last edit added to this <code>CompoundEdit</code>
|
||||
* is given a chance to <code>addEdit(anEdit)</code>.
|
||||
* If it refuses (returns false), <code>anEdit</code> is
|
||||
* given a chance to <code>replaceEdit</code> the last edit.
|
||||
* If <code>anEdit</code> returns false here,
|
||||
* it is added to <code>edits</code>.
|
||||
*
|
||||
* @param anEdit the edit to be added
|
||||
* @return true if the edit is <code>inProgress</code>;
|
||||
* otherwise returns false
|
||||
*/
|
||||
public boolean addEdit(UndoableEdit anEdit) {
|
||||
if (!inProgress) {
|
||||
return false;
|
||||
} else {
|
||||
UndoableEdit last = lastEdit();
|
||||
|
||||
// If this is the first subedit received, just add it.
|
||||
// Otherwise, give the last one a chance to absorb the new
|
||||
// one. If it won't, give the new one a chance to absorb
|
||||
// the last one.
|
||||
|
||||
if (last == null) {
|
||||
edits.addElement(anEdit);
|
||||
}
|
||||
else if (!last.addEdit(anEdit)) {
|
||||
if (anEdit.replaceEdit(last)) {
|
||||
edits.removeElementAt(edits.size()-1);
|
||||
}
|
||||
edits.addElement(anEdit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets <code>inProgress</code> to false.
|
||||
*
|
||||
* @see #canUndo
|
||||
* @see #canRedo
|
||||
*/
|
||||
public void end() {
|
||||
inProgress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false if <code>isInProgress</code> or if super
|
||||
* returns false.
|
||||
*
|
||||
* @see #isInProgress
|
||||
*/
|
||||
public boolean canUndo() {
|
||||
return !isInProgress() && super.canUndo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false if <code>isInProgress</code> or if super
|
||||
* returns false.
|
||||
*
|
||||
* @see #isInProgress
|
||||
*/
|
||||
public boolean canRedo() {
|
||||
return !isInProgress() && super.canRedo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this edit is in progress--that is, it has not
|
||||
* received end. This generally means that edits are still being
|
||||
* added to it.
|
||||
*
|
||||
* @see #end
|
||||
*/
|
||||
public boolean isInProgress() {
|
||||
return inProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any of the <code>UndoableEdit</code>s
|
||||
* in <code>edits</code> do.
|
||||
* Returns false if they all return false.
|
||||
*/
|
||||
public boolean isSignificant() {
|
||||
Enumeration cursor = edits.elements();
|
||||
while (cursor.hasMoreElements()) {
|
||||
if (((UndoableEdit)cursor.nextElement()).isSignificant()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>getPresentationName</code> from the
|
||||
* last <code>UndoableEdit</code> added to
|
||||
* <code>edits</code>. If <code>edits</code> is empty,
|
||||
* calls super.
|
||||
*/
|
||||
public String getPresentationName() {
|
||||
UndoableEdit last = lastEdit();
|
||||
if (last != null) {
|
||||
return last.getPresentationName();
|
||||
} else {
|
||||
return super.getPresentationName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>getUndoPresentationName</code>
|
||||
* from the last <code>UndoableEdit</code>
|
||||
* added to <code>edits</code>.
|
||||
* If <code>edits</code> is empty, calls super.
|
||||
*/
|
||||
public String getUndoPresentationName() {
|
||||
UndoableEdit last = lastEdit();
|
||||
if (last != null) {
|
||||
return last.getUndoPresentationName();
|
||||
} else {
|
||||
return super.getUndoPresentationName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>getRedoPresentationName</code>
|
||||
* from the last <code>UndoableEdit</code>
|
||||
* added to <code>edits</code>.
|
||||
* If <code>edits</code> is empty, calls super.
|
||||
*/
|
||||
public String getRedoPresentationName() {
|
||||
UndoableEdit last = lastEdit();
|
||||
if (last != null) {
|
||||
return last.getRedoPresentationName();
|
||||
} else {
|
||||
return super.getRedoPresentationName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that displays and identifies this
|
||||
* object's properties.
|
||||
*
|
||||
* @return a String representation of this object
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return super.toString()
|
||||
+ " inProgress: " + inProgress
|
||||
+ " edits: " + edits;
|
||||
}
|
||||
}
|
||||
193
jdkSrc/jdk8/javax/swing/undo/StateEdit.java
Normal file
193
jdkSrc/jdk8/javax/swing/undo/StateEdit.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* <P>StateEdit is a general edit for objects that change state.
|
||||
* Objects being edited must conform to the StateEditable interface.</P>
|
||||
*
|
||||
* <P>This edit class works by asking an object to store it's state in
|
||||
* Hashtables before and after editing occurs. Upon undo or redo the
|
||||
* object is told to restore it's state from these Hashtables.</P>
|
||||
*
|
||||
* A state edit is used as follows:
|
||||
* <PRE>
|
||||
* // Create the edit during the "before" state of the object
|
||||
* StateEdit newEdit = new StateEdit(myObject);
|
||||
* // Modify the object
|
||||
* myObject.someStateModifyingMethod();
|
||||
* // "end" the edit when you are done modifying the object
|
||||
* newEdit.end();
|
||||
* </PRE>
|
||||
*
|
||||
* <P><EM>Note that when a StateEdit ends, it removes redundant state from
|
||||
* the Hashtables - A state Hashtable is not guaranteed to contain all
|
||||
* keys/values placed into it when the state is stored!</EM></P>
|
||||
*
|
||||
* @see StateEditable
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
|
||||
public class StateEdit
|
||||
extends AbstractUndoableEdit {
|
||||
|
||||
protected static final String RCSID = "$Id: StateEdit.java,v 1.6 1997/10/01 20:05:51 sandipc Exp $";
|
||||
|
||||
//
|
||||
// Attributes
|
||||
//
|
||||
|
||||
/**
|
||||
* The object being edited
|
||||
*/
|
||||
protected StateEditable object;
|
||||
|
||||
/**
|
||||
* The state information prior to the edit
|
||||
*/
|
||||
protected Hashtable<Object,Object> preState;
|
||||
|
||||
/**
|
||||
* The state information after the edit
|
||||
*/
|
||||
protected Hashtable<Object,Object> postState;
|
||||
|
||||
/**
|
||||
* The undo/redo presentation name
|
||||
*/
|
||||
protected String undoRedoName;
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
|
||||
/**
|
||||
* Create and return a new StateEdit.
|
||||
*
|
||||
* @param anObject The object to watch for changing state
|
||||
*
|
||||
* @see StateEdit
|
||||
*/
|
||||
public StateEdit(StateEditable anObject) {
|
||||
super();
|
||||
init (anObject,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new StateEdit with a presentation name.
|
||||
*
|
||||
* @param anObject The object to watch for changing state
|
||||
* @param name The presentation name to be used for this edit
|
||||
*
|
||||
* @see StateEdit
|
||||
*/
|
||||
public StateEdit(StateEditable anObject, String name) {
|
||||
super();
|
||||
init (anObject,name);
|
||||
}
|
||||
|
||||
protected void init (StateEditable anObject, String name) {
|
||||
this.object = anObject;
|
||||
this.preState = new Hashtable<Object, Object>(11);
|
||||
this.object.storeState(this.preState);
|
||||
this.postState = null;
|
||||
this.undoRedoName = name;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Operation
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* Gets the post-edit state of the StateEditable object and
|
||||
* ends the edit.
|
||||
*/
|
||||
public void end() {
|
||||
this.postState = new Hashtable<Object, Object>(11);
|
||||
this.object.storeState(this.postState);
|
||||
this.removeRedundantState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the edited object to apply the state prior to the edit
|
||||
*/
|
||||
public void undo() {
|
||||
super.undo();
|
||||
this.object.restoreState(preState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the edited object to apply the state after the edit
|
||||
*/
|
||||
public void redo() {
|
||||
super.redo();
|
||||
this.object.restoreState(postState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the presentation name for this edit
|
||||
*/
|
||||
public String getPresentationName() {
|
||||
return this.undoRedoName;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Internal support
|
||||
//
|
||||
|
||||
/**
|
||||
* Remove redundant key/values in state hashtables.
|
||||
*/
|
||||
protected void removeRedundantState() {
|
||||
Vector<Object> uselessKeys = new Vector<Object>();
|
||||
Enumeration myKeys = preState.keys();
|
||||
|
||||
// Locate redundant state
|
||||
while (myKeys.hasMoreElements()) {
|
||||
Object myKey = myKeys.nextElement();
|
||||
if (postState.containsKey(myKey) &&
|
||||
postState.get(myKey).equals(preState.get(myKey))) {
|
||||
uselessKeys.addElement(myKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove redundant state
|
||||
for (int i = uselessKeys.size()-1; i >= 0; i--) {
|
||||
Object myKey = uselessKeys.elementAt(i);
|
||||
preState.remove(myKey);
|
||||
postState.remove(myKey);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of class StateEdit
|
||||
54
jdkSrc/jdk8/javax/swing/undo/StateEditable.java
Normal file
54
jdkSrc/jdk8/javax/swing/undo/StateEditable.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
|
||||
/**
|
||||
* StateEditable defines the interface for objects that can have
|
||||
* their state undone/redone by a StateEdit.
|
||||
*
|
||||
* @see StateEdit
|
||||
*/
|
||||
|
||||
public interface StateEditable {
|
||||
|
||||
/** Resource ID for this class. */
|
||||
public static final String RCSID = "$Id: StateEditable.java,v 1.2 1997/09/08 19:39:08 marklin Exp $";
|
||||
|
||||
/**
|
||||
* Upon receiving this message the receiver should place any relevant
|
||||
* state into <EM>state</EM>.
|
||||
*/
|
||||
public void storeState(Hashtable<Object,Object> state);
|
||||
|
||||
/**
|
||||
* Upon receiving this message the receiver should extract any relevant
|
||||
* state out of <EM>state</EM>.
|
||||
*/
|
||||
public void restoreState(Hashtable<?,?> state);
|
||||
} // End of interface StateEditable
|
||||
624
jdkSrc/jdk8/javax/swing/undo/UndoManager.java
Normal file
624
jdkSrc/jdk8/javax/swing/undo/UndoManager.java
Normal file
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.UIManager;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* {@code UndoManager} manages a list of {@code UndoableEdits},
|
||||
* providing a way to undo or redo the appropriate edits. There are
|
||||
* two ways to add edits to an <code>UndoManager</code>. Add the edit
|
||||
* directly using the <code>addEdit</code> method, or add the
|
||||
* <code>UndoManager</code> to a bean that supports
|
||||
* <code>UndoableEditListener</code>. The following examples creates
|
||||
* an <code>UndoManager</code> and adds it as an
|
||||
* <code>UndoableEditListener</code> to a <code>JTextField</code>:
|
||||
* <pre>
|
||||
* UndoManager undoManager = new UndoManager();
|
||||
* JTextField tf = ...;
|
||||
* tf.getDocument().addUndoableEditListener(undoManager);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <code>UndoManager</code> maintains an ordered list of edits and the
|
||||
* index of the next edit in that list. The index of the next edit is
|
||||
* either the size of the current list of edits, or if
|
||||
* <code>undo</code> has been invoked it corresponds to the index
|
||||
* of the last significant edit that was undone. When
|
||||
* <code>undo</code> is invoked all edits from the index of the next
|
||||
* edit to the last significant edit are undone, in reverse order.
|
||||
* For example, consider an <code>UndoManager</code> consisting of the
|
||||
* following edits: <b>A</b> <i>b</i> <i>c</i> <b>D</b>. Edits with a
|
||||
* upper-case letter in bold are significant, those in lower-case
|
||||
* and italicized are insignificant.
|
||||
* <p>
|
||||
* <a name="figure1"></a>
|
||||
* <table border=0 summary="">
|
||||
* <tr><td>
|
||||
* <img src="doc-files/UndoManager-1.gif" alt="">
|
||||
* <tr><td align=center>Figure 1
|
||||
* </table>
|
||||
* <p>
|
||||
* As shown in <a href="#figure1">figure 1</a>, if <b>D</b> was just added, the
|
||||
* index of the next edit will be 4. Invoking <code>undo</code>
|
||||
* results in invoking <code>undo</code> on <b>D</b> and setting the
|
||||
* index of the next edit to 3 (edit <i>c</i>), as shown in the following
|
||||
* figure.
|
||||
* <p>
|
||||
* <a name="figure2"></a>
|
||||
* <table border=0 summary="">
|
||||
* <tr><td>
|
||||
* <img src="doc-files/UndoManager-2.gif" alt="">
|
||||
* <tr><td align=center>Figure 2
|
||||
* </table>
|
||||
* <p>
|
||||
* The last significant edit is <b>A</b>, so that invoking
|
||||
* <code>undo</code> again invokes <code>undo</code> on <i>c</i>,
|
||||
* <i>b</i>, and <b>A</b>, in that order, setting the index of the
|
||||
* next edit to 0, as shown in the following figure.
|
||||
* <p>
|
||||
* <a name="figure3"></a>
|
||||
* <table border=0 summary="">
|
||||
* <tr><td>
|
||||
* <img src="doc-files/UndoManager-3.gif" alt="">
|
||||
* <tr><td align=center>Figure 3
|
||||
* </table>
|
||||
* <p>
|
||||
* Invoking <code>redo</code> results in invoking <code>redo</code> on
|
||||
* all edits between the index of the next edit and the next
|
||||
* significant edit (or the end of the list). Continuing with the previous
|
||||
* example if <code>redo</code> were invoked, <code>redo</code> would in
|
||||
* turn be invoked on <b>A</b>, <i>b</i> and <i>c</i>. In addition
|
||||
* the index of the next edit is set to 3 (as shown in <a
|
||||
* href="#figure2">figure 2</a>).
|
||||
* <p>
|
||||
* Adding an edit to an <code>UndoManager</code> results in
|
||||
* removing all edits from the index of the next edit to the end of
|
||||
* the list. Continuing with the previous example, if a new edit,
|
||||
* <i>e</i>, is added the edit <b>D</b> is removed from the list
|
||||
* (after having <code>die</code> invoked on it). If <i>c</i> is not
|
||||
* incorporated by the next edit
|
||||
* (<code><i>c</i>.addEdit(<i>e</i>)</code> returns true), or replaced
|
||||
* by it (<code><i>e</i>.replaceEdit(<i>c</i>)</code> returns true),
|
||||
* the new edit is added after <i>c</i>, as shown in the following
|
||||
* figure.
|
||||
* <p>
|
||||
* <a name="figure4"></a>
|
||||
* <table border=0 summary="">
|
||||
* <tr><td>
|
||||
* <img src="doc-files/UndoManager-4.gif" alt="">
|
||||
* <tr><td align=center>Figure 4
|
||||
* </table>
|
||||
* <p>
|
||||
* Once <code>end</code> has been invoked on an <code>UndoManager</code>
|
||||
* the superclass behavior is used for all <code>UndoableEdit</code>
|
||||
* methods. Refer to <code>CompoundEdit</code> for more details on its
|
||||
* behavior.
|
||||
* <p>
|
||||
* Unlike the rest of Swing, this class is thread safe.
|
||||
* <p>
|
||||
* <strong>Warning:</strong>
|
||||
* Serialized objects of this class will not be compatible with
|
||||
* future Swing releases. The current serialization support is
|
||||
* appropriate for short term storage or RMI between applications running
|
||||
* the same version of Swing. As of 1.4, support for long term storage
|
||||
* of all JavaBeans™
|
||||
* has been added to the <code>java.beans</code> package.
|
||||
* Please see {@link java.beans.XMLEncoder}.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public class UndoManager extends CompoundEdit implements UndoableEditListener {
|
||||
int indexOfNextAdd;
|
||||
int limit;
|
||||
|
||||
/**
|
||||
* Creates a new <code>UndoManager</code>.
|
||||
*/
|
||||
public UndoManager() {
|
||||
super();
|
||||
indexOfNextAdd = 0;
|
||||
limit = 100;
|
||||
edits.ensureCapacity(limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of edits this {@code UndoManager}
|
||||
* holds. A value less than 0 indicates the number of edits is not
|
||||
* limited.
|
||||
*
|
||||
* @return the maximum number of edits this {@code UndoManager} holds
|
||||
* @see #addEdit
|
||||
* @see #setLimit
|
||||
*/
|
||||
public synchronized int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the undo manager sending each edit a <code>die</code> message
|
||||
* in the process.
|
||||
*
|
||||
* @see AbstractUndoableEdit#die
|
||||
*/
|
||||
public synchronized void discardAllEdits() {
|
||||
for (UndoableEdit e : edits) {
|
||||
e.die();
|
||||
}
|
||||
edits = new Vector<UndoableEdit>();
|
||||
indexOfNextAdd = 0;
|
||||
// PENDING(rjrjr) when vector grows a removeRange() method
|
||||
// (expected in JDK 1.2), trimEdits() will be nice and
|
||||
// efficient, and this method can call that instead.
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the number of queued edits to a range of size limit,
|
||||
* centered on the index of the next edit.
|
||||
*/
|
||||
protected void trimForLimit() {
|
||||
if (limit >= 0) {
|
||||
int size = edits.size();
|
||||
// System.out.print("limit: " + limit +
|
||||
// " size: " + size +
|
||||
// " indexOfNextAdd: " + indexOfNextAdd +
|
||||
// "\n");
|
||||
|
||||
if (size > limit) {
|
||||
int halfLimit = limit/2;
|
||||
int keepFrom = indexOfNextAdd - 1 - halfLimit;
|
||||
int keepTo = indexOfNextAdd - 1 + halfLimit;
|
||||
|
||||
// These are ints we're playing with, so dividing by two
|
||||
// rounds down for odd numbers, so make sure the limit was
|
||||
// honored properly. Note that the keep range is
|
||||
// inclusive.
|
||||
|
||||
if (keepTo - keepFrom + 1 > limit) {
|
||||
keepFrom++;
|
||||
}
|
||||
|
||||
// The keep range is centered on indexOfNextAdd,
|
||||
// but odds are good that the actual edits Vector
|
||||
// isn't. Move the keep range to keep it legal.
|
||||
|
||||
if (keepFrom < 0) {
|
||||
keepTo -= keepFrom;
|
||||
keepFrom = 0;
|
||||
}
|
||||
if (keepTo >= size) {
|
||||
int delta = size - keepTo - 1;
|
||||
keepTo += delta;
|
||||
keepFrom += delta;
|
||||
}
|
||||
|
||||
// System.out.println("Keeping " + keepFrom + " " + keepTo);
|
||||
trimEdits(keepTo+1, size-1);
|
||||
trimEdits(0, keepFrom-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes edits in the specified range.
|
||||
* All edits in the given range (inclusive, and in reverse order)
|
||||
* will have <code>die</code> invoked on them and are removed from
|
||||
* the list of edits. This has no effect if
|
||||
* <code>from</code> > <code>to</code>.
|
||||
*
|
||||
* @param from the minimum index to remove
|
||||
* @param to the maximum index to remove
|
||||
*/
|
||||
protected void trimEdits(int from, int to) {
|
||||
if (from <= to) {
|
||||
// System.out.println("Trimming " + from + " " + to + " with index " +
|
||||
// indexOfNextAdd);
|
||||
for (int i = to; from <= i; i--) {
|
||||
UndoableEdit e = edits.elementAt(i);
|
||||
// System.out.println("JUM: Discarding " +
|
||||
// e.getUndoPresentationName());
|
||||
e.die();
|
||||
// PENDING(rjrjr) when Vector supports range deletion (JDK
|
||||
// 1.2) , we can optimize the next line considerably.
|
||||
edits.removeElementAt(i);
|
||||
}
|
||||
|
||||
if (indexOfNextAdd > to) {
|
||||
// System.out.print("...right...");
|
||||
indexOfNextAdd -= to-from+1;
|
||||
} else if (indexOfNextAdd >= from) {
|
||||
// System.out.println("...mid...");
|
||||
indexOfNextAdd = from;
|
||||
}
|
||||
|
||||
// System.out.println("new index " + indexOfNextAdd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of edits this <code>UndoManager</code>
|
||||
* holds. A value less than 0 indicates the number of edits is not
|
||||
* limited. If edits need to be discarded to shrink the limit,
|
||||
* <code>die</code> will be invoked on them in the reverse
|
||||
* order they were added. The default is 100.
|
||||
*
|
||||
* @param l the new limit
|
||||
* @throws RuntimeException if this {@code UndoManager} is not in progress
|
||||
* ({@code end} has been invoked)
|
||||
* @see #isInProgress
|
||||
* @see #end
|
||||
* @see #addEdit
|
||||
* @see #getLimit
|
||||
*/
|
||||
public synchronized void setLimit(int l) {
|
||||
if (!inProgress) throw new RuntimeException("Attempt to call UndoManager.setLimit() after UndoManager.end() has been called");
|
||||
limit = l;
|
||||
trimForLimit();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the the next significant edit to be undone if <code>undo</code>
|
||||
* is invoked. This returns <code>null</code> if there are no edits
|
||||
* to be undone.
|
||||
*
|
||||
* @return the next significant edit to be undone
|
||||
*/
|
||||
protected UndoableEdit editToBeUndone() {
|
||||
int i = indexOfNextAdd;
|
||||
while (i > 0) {
|
||||
UndoableEdit edit = edits.elementAt(--i);
|
||||
if (edit.isSignificant()) {
|
||||
return edit;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the next significant edit to be redone if <code>redo</code>
|
||||
* is invoked. This returns <code>null</code> if there are no edits
|
||||
* to be redone.
|
||||
*
|
||||
* @return the next significant edit to be redone
|
||||
*/
|
||||
protected UndoableEdit editToBeRedone() {
|
||||
int count = edits.size();
|
||||
int i = indexOfNextAdd;
|
||||
|
||||
while (i < count) {
|
||||
UndoableEdit edit = edits.elementAt(i++);
|
||||
if (edit.isSignificant()) {
|
||||
return edit;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes all changes from the index of the next edit to
|
||||
* <code>edit</code>, updating the index of the next edit appropriately.
|
||||
*
|
||||
* @throws CannotUndoException if one of the edits throws
|
||||
* <code>CannotUndoException</code>
|
||||
*/
|
||||
protected void undoTo(UndoableEdit edit) throws CannotUndoException {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
UndoableEdit next = edits.elementAt(--indexOfNextAdd);
|
||||
next.undo();
|
||||
done = next == edit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redoes all changes from the index of the next edit to
|
||||
* <code>edit</code>, updating the index of the next edit appropriately.
|
||||
*
|
||||
* @throws CannotRedoException if one of the edits throws
|
||||
* <code>CannotRedoException</code>
|
||||
*/
|
||||
protected void redoTo(UndoableEdit edit) throws CannotRedoException {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
UndoableEdit next = edits.elementAt(indexOfNextAdd++);
|
||||
next.redo();
|
||||
done = next == edit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that invokes one of <code>undo</code> or
|
||||
* <code>redo</code>. If any edits have been undone (the index of
|
||||
* the next edit is less than the length of the edits list) this
|
||||
* invokes <code>redo</code>, otherwise it invokes <code>undo</code>.
|
||||
*
|
||||
* @see #canUndoOrRedo
|
||||
* @see #getUndoOrRedoPresentationName
|
||||
* @throws CannotUndoException if one of the edits throws
|
||||
* <code>CannotUndoException</code>
|
||||
* @throws CannotRedoException if one of the edits throws
|
||||
* <code>CannotRedoException</code>
|
||||
*/
|
||||
public synchronized void undoOrRedo() throws CannotRedoException,
|
||||
CannotUndoException {
|
||||
if (indexOfNextAdd == edits.size()) {
|
||||
undo();
|
||||
} else {
|
||||
redo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it is possible to invoke <code>undo</code> or
|
||||
* <code>redo</code>.
|
||||
*
|
||||
* @return true if invoking <code>canUndoOrRedo</code> is valid
|
||||
* @see #undoOrRedo
|
||||
*/
|
||||
public synchronized boolean canUndoOrRedo() {
|
||||
if (indexOfNextAdd == edits.size()) {
|
||||
return canUndo();
|
||||
} else {
|
||||
return canRedo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes the appropriate edits. If <code>end</code> has been
|
||||
* invoked this calls through to the superclass, otherwise
|
||||
* this invokes <code>undo</code> on all edits between the
|
||||
* index of the next edit and the last significant edit, updating
|
||||
* the index of the next edit appropriately.
|
||||
*
|
||||
* @throws CannotUndoException if one of the edits throws
|
||||
* <code>CannotUndoException</code> or there are no edits
|
||||
* to be undone
|
||||
* @see CompoundEdit#end
|
||||
* @see #canUndo
|
||||
* @see #editToBeUndone
|
||||
*/
|
||||
public synchronized void undo() throws CannotUndoException {
|
||||
if (inProgress) {
|
||||
UndoableEdit edit = editToBeUndone();
|
||||
if (edit == null) {
|
||||
throw new CannotUndoException();
|
||||
}
|
||||
undoTo(edit);
|
||||
} else {
|
||||
super.undo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if edits may be undone. If <code>end</code> has
|
||||
* been invoked, this returns the value from super. Otherwise
|
||||
* this returns true if there are any edits to be undone
|
||||
* (<code>editToBeUndone</code> returns non-<code>null</code>).
|
||||
*
|
||||
* @return true if there are edits to be undone
|
||||
* @see CompoundEdit#canUndo
|
||||
* @see #editToBeUndone
|
||||
*/
|
||||
public synchronized boolean canUndo() {
|
||||
if (inProgress) {
|
||||
UndoableEdit edit = editToBeUndone();
|
||||
return edit != null && edit.canUndo();
|
||||
} else {
|
||||
return super.canUndo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redoes the appropriate edits. If <code>end</code> has been
|
||||
* invoked this calls through to the superclass. Otherwise
|
||||
* this invokes <code>redo</code> on all edits between the
|
||||
* index of the next edit and the next significant edit, updating
|
||||
* the index of the next edit appropriately.
|
||||
*
|
||||
* @throws CannotRedoException if one of the edits throws
|
||||
* <code>CannotRedoException</code> or there are no edits
|
||||
* to be redone
|
||||
* @see CompoundEdit#end
|
||||
* @see #canRedo
|
||||
* @see #editToBeRedone
|
||||
*/
|
||||
public synchronized void redo() throws CannotRedoException {
|
||||
if (inProgress) {
|
||||
UndoableEdit edit = editToBeRedone();
|
||||
if (edit == null) {
|
||||
throw new CannotRedoException();
|
||||
}
|
||||
redoTo(edit);
|
||||
} else {
|
||||
super.redo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if edits may be redone. If <code>end</code> has
|
||||
* been invoked, this returns the value from super. Otherwise,
|
||||
* this returns true if there are any edits to be redone
|
||||
* (<code>editToBeRedone</code> returns non-<code>null</code>).
|
||||
*
|
||||
* @return true if there are edits to be redone
|
||||
* @see CompoundEdit#canRedo
|
||||
* @see #editToBeRedone
|
||||
*/
|
||||
public synchronized boolean canRedo() {
|
||||
if (inProgress) {
|
||||
UndoableEdit edit = editToBeRedone();
|
||||
return edit != null && edit.canRedo();
|
||||
} else {
|
||||
return super.canRedo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an <code>UndoableEdit</code> to this
|
||||
* <code>UndoManager</code>, if it's possible. This removes all
|
||||
* edits from the index of the next edit to the end of the edits
|
||||
* list. If <code>end</code> has been invoked the edit is not added
|
||||
* and <code>false</code> is returned. If <code>end</code> hasn't
|
||||
* been invoked this returns <code>true</code>.
|
||||
*
|
||||
* @param anEdit the edit to be added
|
||||
* @return true if <code>anEdit</code> can be incorporated into this
|
||||
* edit
|
||||
* @see CompoundEdit#end
|
||||
* @see CompoundEdit#addEdit
|
||||
*/
|
||||
public synchronized boolean addEdit(UndoableEdit anEdit) {
|
||||
boolean retVal;
|
||||
|
||||
// Trim from the indexOfNextAdd to the end, as we'll
|
||||
// never reach these edits once the new one is added.
|
||||
trimEdits(indexOfNextAdd, edits.size()-1);
|
||||
|
||||
retVal = super.addEdit(anEdit);
|
||||
if (inProgress) {
|
||||
retVal = true;
|
||||
}
|
||||
|
||||
// Maybe super added this edit, maybe it didn't (perhaps
|
||||
// an in progress compound edit took it instead. Or perhaps
|
||||
// this UndoManager is no longer in progress). So make sure
|
||||
// the indexOfNextAdd is pointed at the right place.
|
||||
indexOfNextAdd = edits.size();
|
||||
|
||||
// Enforce the limit
|
||||
trimForLimit();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns this <code>UndoManager</code> into a normal
|
||||
* <code>CompoundEdit</code>. This removes all edits that have
|
||||
* been undone.
|
||||
*
|
||||
* @see CompoundEdit#end
|
||||
*/
|
||||
public synchronized void end() {
|
||||
super.end();
|
||||
this.trimEdits(indexOfNextAdd, edits.size()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns either
|
||||
* <code>getUndoPresentationName</code> or
|
||||
* <code>getRedoPresentationName</code>. If the index of the next
|
||||
* edit equals the size of the edits list,
|
||||
* <code>getUndoPresentationName</code> is returned, otherwise
|
||||
* <code>getRedoPresentationName</code> is returned.
|
||||
*
|
||||
* @return undo or redo name
|
||||
*/
|
||||
public synchronized String getUndoOrRedoPresentationName() {
|
||||
if (indexOfNextAdd == edits.size()) {
|
||||
return getUndoPresentationName();
|
||||
} else {
|
||||
return getRedoPresentationName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the undoable form of this edit.
|
||||
* If <code>end</code> has been invoked this calls into super.
|
||||
* Otherwise if there are edits to be undone, this returns
|
||||
* the value from the next significant edit that will be undone.
|
||||
* If there are no edits to be undone and <code>end</code> has not
|
||||
* been invoked this returns the value from the <code>UIManager</code>
|
||||
* property "AbstractUndoableEdit.undoText".
|
||||
*
|
||||
* @return a description of the undoable form of this edit
|
||||
* @see #undo
|
||||
* @see CompoundEdit#getUndoPresentationName
|
||||
*/
|
||||
public synchronized String getUndoPresentationName() {
|
||||
if (inProgress) {
|
||||
if (canUndo()) {
|
||||
return editToBeUndone().getUndoPresentationName();
|
||||
} else {
|
||||
return UIManager.getString("AbstractUndoableEdit.undoText");
|
||||
}
|
||||
} else {
|
||||
return super.getUndoPresentationName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the redoable form of this edit.
|
||||
* If <code>end</code> has been invoked this calls into super.
|
||||
* Otherwise if there are edits to be redone, this returns
|
||||
* the value from the next significant edit that will be redone.
|
||||
* If there are no edits to be redone and <code>end</code> has not
|
||||
* been invoked this returns the value from the <code>UIManager</code>
|
||||
* property "AbstractUndoableEdit.redoText".
|
||||
*
|
||||
* @return a description of the redoable form of this edit
|
||||
* @see #redo
|
||||
* @see CompoundEdit#getRedoPresentationName
|
||||
*/
|
||||
public synchronized String getRedoPresentationName() {
|
||||
if (inProgress) {
|
||||
if (canRedo()) {
|
||||
return editToBeRedone().getRedoPresentationName();
|
||||
} else {
|
||||
return UIManager.getString("AbstractUndoableEdit.redoText");
|
||||
}
|
||||
} else {
|
||||
return super.getRedoPresentationName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An <code>UndoableEditListener</code> method. This invokes
|
||||
* <code>addEdit</code> with <code>e.getEdit()</code>.
|
||||
*
|
||||
* @param e the <code>UndoableEditEvent</code> the
|
||||
* <code>UndoableEditEvent</code> will be added from
|
||||
* @see #addEdit
|
||||
*/
|
||||
public void undoableEditHappened(UndoableEditEvent e) {
|
||||
addEdit(e.getEdit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that displays and identifies this
|
||||
* object's properties.
|
||||
*
|
||||
* @return a String representation of this object
|
||||
*/
|
||||
public String toString() {
|
||||
return super.toString() + " limit: " + limit +
|
||||
" indexOfNextAdd: " + indexOfNextAdd;
|
||||
}
|
||||
}
|
||||
201
jdkSrc/jdk8/javax/swing/undo/UndoableEdit.java
Normal file
201
jdkSrc/jdk8/javax/swing/undo/UndoableEdit.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
import javax.swing.event.*;
|
||||
|
||||
/**
|
||||
* An <code>UndoableEdit</code> represents an edit. The edit may
|
||||
* be undone, or if already undone the edit may be redone.
|
||||
* <p>
|
||||
* <code>UndoableEdit</code> is designed to be used with the
|
||||
* <code>UndoManager</code>. As <code>UndoableEdit</code>s are generated
|
||||
* by an <code>UndoableEditListener</code> they are typically added to
|
||||
* the <code>UndoManager</code>. When an <code>UndoableEdit</code>
|
||||
* is added to an <code>UndoManager</code> the following occurs (assuming
|
||||
* <code>end</code> has not been called on the <code>UndoManager</code>):
|
||||
* <ol>
|
||||
* <li>If the <code>UndoManager</code> contains edits it will call
|
||||
* <code>addEdit</code> on the current edit passing in the new edit
|
||||
* as the argument. If <code>addEdit</code> returns true the
|
||||
* new edit is assumed to have been incorporated into the current edit and
|
||||
* the new edit will not be added to the list of current edits.
|
||||
* Edits can use <code>addEdit</code> as a way for smaller edits to
|
||||
* be incorporated into a larger edit and treated as a single edit.
|
||||
* <li>If <code>addEdit</code> returns false <code>replaceEdit</code>
|
||||
* is called on the new edit with the current edit passed in as the
|
||||
* argument. This is the inverse of <code>addEdit</code> —
|
||||
* if the new edit returns true from <code>replaceEdit</code>, the new
|
||||
* edit replaces the current edit.
|
||||
* </ol>
|
||||
* The <code>UndoManager</code> makes use of
|
||||
* <code>isSignificant</code> to determine how many edits should be
|
||||
* undone or redone. The <code>UndoManager</code> will undo or redo
|
||||
* all insignificant edits (<code>isSignificant</code> returns false)
|
||||
* between the current edit and the last or
|
||||
* next significant edit. <code>addEdit</code> and
|
||||
* <code>replaceEdit</code> can be used to treat multiple edits as
|
||||
* a single edit, returning false from <code>isSignificant</code>
|
||||
* allows for treating can be used to
|
||||
* have many smaller edits undone or redone at once. Similar functionality
|
||||
* can also be done using the <code>addEdit</code> method.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public interface UndoableEdit {
|
||||
/**
|
||||
* Undo the edit.
|
||||
*
|
||||
* @throws CannotUndoException if this edit can not be undone
|
||||
*/
|
||||
public void undo() throws CannotUndoException;
|
||||
|
||||
/**
|
||||
* Returns true if this edit may be undone.
|
||||
*
|
||||
* @return true if this edit may be undone
|
||||
*/
|
||||
public boolean canUndo();
|
||||
|
||||
/**
|
||||
* Re-applies the edit.
|
||||
*
|
||||
* @throws CannotRedoException if this edit can not be redone
|
||||
*/
|
||||
public void redo() throws CannotRedoException;
|
||||
|
||||
/**
|
||||
* Returns true if this edit may be redone.
|
||||
*
|
||||
* @return true if this edit may be redone
|
||||
*/
|
||||
public boolean canRedo();
|
||||
|
||||
/**
|
||||
* Informs the edit that it should no longer be used. Once an
|
||||
* <code>UndoableEdit</code> has been marked as dead it can no longer
|
||||
* be undone or redone.
|
||||
* <p>
|
||||
* This is a useful hook for cleaning up state no longer
|
||||
* needed once undoing or redoing is impossible--for example,
|
||||
* deleting file resources used by objects that can no longer be
|
||||
* undeleted. <code>UndoManager</code> calls this before it dequeues edits.
|
||||
* <p>
|
||||
* Note that this is a one-way operation. There is no "un-die"
|
||||
* method.
|
||||
*
|
||||
* @see CompoundEdit#die
|
||||
*/
|
||||
public void die();
|
||||
|
||||
/**
|
||||
* Adds an <code>UndoableEdit</code> to this <code>UndoableEdit</code>.
|
||||
* This method can be used to coalesce smaller edits into a larger
|
||||
* compound edit. For example, text editors typically allow
|
||||
* undo operations to apply to words or sentences. The text
|
||||
* editor may choose to generate edits on each key event, but allow
|
||||
* those edits to be coalesced into a more user-friendly unit, such as
|
||||
* a word. In this case, the <code>UndoableEdit</code> would
|
||||
* override <code>addEdit</code> to return true when the edits may
|
||||
* be coalesced.
|
||||
* <p>
|
||||
* A return value of true indicates <code>anEdit</code> was incorporated
|
||||
* into this edit. A return value of false indicates <code>anEdit</code>
|
||||
* may not be incorporated into this edit.
|
||||
* <p>Typically the receiver is already in the queue of a
|
||||
* <code>UndoManager</code> (or other <code>UndoableEditListener</code>),
|
||||
* and is being given a chance to incorporate <code>anEdit</code>
|
||||
* rather than letting it be added to the queue in turn.</p>
|
||||
*
|
||||
* <p>If true is returned, from now on <code>anEdit</code> must return
|
||||
* false from <code>canUndo</code> and <code>canRedo</code>,
|
||||
* and must throw the appropriate exception on <code>undo</code> or
|
||||
* <code>redo</code>.</p>
|
||||
*
|
||||
* @param anEdit the edit to be added
|
||||
* @return true if <code>anEdit</code> may be incorporated into this
|
||||
* edit
|
||||
*/
|
||||
public boolean addEdit(UndoableEdit anEdit);
|
||||
|
||||
/**
|
||||
* Returns true if this <code>UndoableEdit</code> should replace
|
||||
* <code>anEdit</code>. This method is used by <code>CompoundEdit</code>
|
||||
* and the <code>UndoManager</code>; it is called if
|
||||
* <code>anEdit</code> could not be added to the current edit
|
||||
* (<code>addEdit</code> returns false).
|
||||
* <p>
|
||||
* This method provides a way for an edit to replace an existing edit.
|
||||
* <p>This message is the opposite of addEdit--anEdit has typically
|
||||
* already been queued in an <code>UndoManager</code> (or other
|
||||
* UndoableEditListener), and the receiver is being given a chance
|
||||
* to take its place.</p>
|
||||
*
|
||||
* <p>If true is returned, from now on anEdit must return false from
|
||||
* canUndo() and canRedo(), and must throw the appropriate
|
||||
* exception on undo() or redo().</p>
|
||||
*
|
||||
* @param anEdit the edit that replaces the current edit
|
||||
* @return true if this edit should replace <code>anEdit</code>
|
||||
*/
|
||||
public boolean replaceEdit(UndoableEdit anEdit);
|
||||
|
||||
/**
|
||||
* Returns true if this edit is considered significant. A significant
|
||||
* edit is typically an edit that should be presented to the user, perhaps
|
||||
* on a menu item or tooltip. The <code>UndoManager</code> will undo,
|
||||
* or redo, all insignificant edits to the next significant edit.
|
||||
*
|
||||
* @return true if this edit is significant
|
||||
*/
|
||||
public boolean isSignificant();
|
||||
|
||||
/**
|
||||
* Returns a localized, human-readable description of this edit, suitable
|
||||
* for use in a change log, for example.
|
||||
*
|
||||
* @return description of this edit
|
||||
*/
|
||||
public String getPresentationName();
|
||||
|
||||
/**
|
||||
* Returns a localized, human-readable description of the undoable form of
|
||||
* this edit, suitable for use as an Undo menu item, for example.
|
||||
* This is typically derived from <code>getPresentationName</code>.
|
||||
*
|
||||
* @return a description of the undoable form of this edit
|
||||
*/
|
||||
public String getUndoPresentationName();
|
||||
|
||||
/**
|
||||
* Returns a localized, human-readable description of the redoable form of
|
||||
* this edit, suitable for use as a Redo menu item, for example. This is
|
||||
* typically derived from <code>getPresentationName</code>.
|
||||
*
|
||||
* @return a description of the redoable form of this edit
|
||||
*/
|
||||
public String getRedoPresentationName();
|
||||
}
|
||||
176
jdkSrc/jdk8/javax/swing/undo/UndoableEditSupport.java
Normal file
176
jdkSrc/jdk8/javax/swing/undo/UndoableEditSupport.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.swing.undo;
|
||||
|
||||
import javax.swing.event.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A support class used for managing <code>UndoableEdit</code> listeners.
|
||||
*
|
||||
* @author Ray Ryan
|
||||
*/
|
||||
public class UndoableEditSupport {
|
||||
protected int updateLevel;
|
||||
protected CompoundEdit compoundEdit;
|
||||
protected Vector<UndoableEditListener> listeners;
|
||||
protected Object realSource;
|
||||
|
||||
/**
|
||||
* Constructs an <code>UndoableEditSupport</code> object.
|
||||
*/
|
||||
public UndoableEditSupport() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <code>UndoableEditSupport</code> object.
|
||||
*
|
||||
* @param r an <code>Object</code>
|
||||
*/
|
||||
public UndoableEditSupport(Object r) {
|
||||
realSource = r == null ? this : r;
|
||||
updateLevel = 0;
|
||||
compoundEdit = null;
|
||||
listeners = new Vector<UndoableEditListener>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an <code>UndoableEditListener</code>.
|
||||
* The listener is notified whenever an edit occurs which can be undone.
|
||||
*
|
||||
* @param l an <code>UndoableEditListener</code> object
|
||||
* @see #removeUndoableEditListener
|
||||
*/
|
||||
public synchronized void addUndoableEditListener(UndoableEditListener l) {
|
||||
listeners.addElement(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an <code>UndoableEditListener</code>.
|
||||
*
|
||||
* @param l the <code>UndoableEditListener</code> object to be removed
|
||||
* @see #addUndoableEditListener
|
||||
*/
|
||||
public synchronized void removeUndoableEditListener(UndoableEditListener l)
|
||||
{
|
||||
listeners.removeElement(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the <code>UndoableEditListener</code>s added
|
||||
* to this UndoableEditSupport with addUndoableEditListener().
|
||||
*
|
||||
* @return all of the <code>UndoableEditListener</code>s added or an empty
|
||||
* array if no listeners have been added
|
||||
* @since 1.4
|
||||
*/
|
||||
public synchronized UndoableEditListener[] getUndoableEditListeners() {
|
||||
return listeners.toArray(new UndoableEditListener[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only from <code>postEdit</code> and <code>endUpdate</code>. Calls
|
||||
* <code>undoableEditHappened</code> in all listeners. No synchronization
|
||||
* is performed here, since the two calling methods are synchronized.
|
||||
*/
|
||||
protected void _postEdit(UndoableEdit e) {
|
||||
UndoableEditEvent ev = new UndoableEditEvent(realSource, e);
|
||||
Enumeration cursor = ((Vector)listeners.clone()).elements();
|
||||
while (cursor.hasMoreElements()) {
|
||||
((UndoableEditListener)cursor.nextElement()).
|
||||
undoableEditHappened(ev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEADLOCK WARNING: Calling this method may call
|
||||
* <code>undoableEditHappened</code> in all listeners.
|
||||
* It is unwise to call this method from one of its listeners.
|
||||
*/
|
||||
public synchronized void postEdit(UndoableEdit e) {
|
||||
if (updateLevel == 0) {
|
||||
_postEdit(e);
|
||||
} else {
|
||||
// PENDING(rjrjr) Throw an exception if this fails?
|
||||
compoundEdit.addEdit(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the update level value.
|
||||
*
|
||||
* @return an integer representing the update level
|
||||
*/
|
||||
public int getUpdateLevel() {
|
||||
return updateLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public synchronized void beginUpdate() {
|
||||
if (updateLevel == 0) {
|
||||
compoundEdit = createCompoundEdit();
|
||||
}
|
||||
updateLevel++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only from <code>beginUpdate</code>.
|
||||
* Exposed here for subclasses' use.
|
||||
*/
|
||||
protected CompoundEdit createCompoundEdit() {
|
||||
return new CompoundEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* DEADLOCK WARNING: Calling this method may call
|
||||
* <code>undoableEditHappened</code> in all listeners.
|
||||
* It is unwise to call this method from one of its listeners.
|
||||
*/
|
||||
public synchronized void endUpdate() {
|
||||
updateLevel--;
|
||||
if (updateLevel == 0) {
|
||||
compoundEdit.end();
|
||||
_postEdit(compoundEdit);
|
||||
compoundEdit = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that displays and identifies this
|
||||
* object's properties.
|
||||
*
|
||||
* @return a <code>String</code> representation of this object
|
||||
*/
|
||||
public String toString() {
|
||||
return super.toString() +
|
||||
" updateLevel: " + updateLevel +
|
||||
" listeners: " + listeners +
|
||||
" compoundEdit: " + compoundEdit;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user