Java by API/javax.swing.undo/UndoManager
Содержание
- 1 new UndoManager()
- 2 UndoManager: addEdit(UndoableEdit anEdit)
- 3 UndoManager: canRedo()
- 4 UndoManager: canUndo()
- 5 UndoManager: discardAllEdits()
- 6 UndoManager: end()
- 7 UndoManager: getRedoPresentationName()
- 8 UndoManager: getUndoPresentationName()
- 9 UndoManager: redo()
- 10 UndoManager: setLimit(int l)
- 11 UndoManager: undo()
- 12 UndoManager: undoOrRedo()
new UndoManager()
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class MainClass {
public static void main(final String args[]) {
JFrame frame = new JFrame("Undo Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
UndoManager manager = new UndoManager();
textArea.getDocument().addUndoableEditListener(manager);
JToolBar toolbar = new JToolBar();
JButton undoButton = new JButton(new UndoAction(manager, (String) UIManager
.get("AbstractUndoableEdit.undoText")));
toolbar.add(undoButton);
Container content = frame.getContentPane();
content.add(toolbar, BorderLayout.NORTH);
content.add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
abstract class UndoRedoAction extends AbstractAction {
UndoManager undoManager = new UndoManager();
String errorMessage = "Cannot undo";
String errorTitle = "Undo Problem";
protected UndoRedoAction(UndoManager manager, String name) {
super(name);
undoManager = manager;
}
public void setErrorMessage(String newValue) {
errorMessage = newValue;
}
public void setErrorTitle(String newValue) {
errorTitle = newValue;
}
protected void showMessage(Object source) {
if (source instanceof Component) {
JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle,
JOptionPane.WARNING_MESSAGE);
} else {
System.err.println(errorMessage);
}
}
}
class UndoAction extends UndoRedoAction {
public UndoAction(UndoManager manager, String name) {
super(manager, name);
setErrorMessage("Cannot undo");
setErrorTitle("Undo Problem");
}
public void actionPerformed(ActionEvent actionEvent) {
try {
undoManager.undo();
} catch (CannotUndoException cannotUndoException) {
showMessage(actionEvent.getSource());
}
}
}
UndoManager: addEdit(UndoableEdit anEdit)
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}
UndoManager: canRedo()
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}
UndoManager: canUndo()
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}
UndoManager: discardAllEdits()
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}
UndoManager: end()
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}
UndoManager: getRedoPresentationName()
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
public class Main extends JFrame {
protected JTextArea textArea = new JTextArea();
protected UndoManager undoManager = new UndoManager();
protected JButton undoButton = new JButton("Undo");
protected JButton redoButton = new JButton("Redo");
public Main() {
super("Undo/Redo Demo");
undoButton.setEnabled(false);
redoButton.setEnabled(false);
JPanel buttonPanel = new JPanel(new GridLayout());
buttonPanel.add(undoButton);
buttonPanel.add(redoButton);
JScrollPane scroller = new JScrollPane(textArea);
getContentPane().add(buttonPanel, BorderLayout.NORTH);
getContentPane().add(scroller, BorderLayout.CENTER);
textArea.getDocument().addUndoableEditListener(
new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
updateButtons();
}
});
undoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
}
updateButtons();
}
});
redoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
undoManager.redo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
}
updateButtons();
}
});
setSize(400, 300);
setVisible(true);
}
public void updateButtons() {
undoButton.setText(undoManager.getUndoPresentationName());
redoButton.setText(undoManager.getRedoPresentationName());
undoButton.setEnabled(undoManager.canUndo());
redoButton.setEnabled(undoManager.canRedo());
}
public static void main(String argv[]) {
new Main();
}
}
UndoManager: getUndoPresentationName()
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
public class Main extends JFrame {
protected JTextArea textArea = new JTextArea();
protected UndoManager undoManager = new UndoManager();
protected JButton undoButton = new JButton("Undo");
protected JButton redoButton = new JButton("Redo");
public Main() {
super("Undo/Redo Demo");
undoButton.setEnabled(false);
redoButton.setEnabled(false);
JPanel buttonPanel = new JPanel(new GridLayout());
buttonPanel.add(undoButton);
buttonPanel.add(redoButton);
JScrollPane scroller = new JScrollPane(textArea);
getContentPane().add(buttonPanel, BorderLayout.NORTH);
getContentPane().add(scroller, BorderLayout.CENTER);
textArea.getDocument().addUndoableEditListener(
new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
updateButtons();
}
});
undoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
}
updateButtons();
}
});
redoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
undoManager.redo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
}
updateButtons();
}
});
setSize(400, 300);
setVisible(true);
}
public void updateButtons() {
undoButton.setText(undoManager.getUndoPresentationName());
redoButton.setText(undoManager.getRedoPresentationName());
undoButton.setEnabled(undoManager.canUndo());
redoButton.setEnabled(undoManager.canRedo());
}
public static void main(String argv[]) {
new Main();
}
}
UndoManager: redo()
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class MainClass {
public static void main(final String args[]) {
JFrame frame = new JFrame("Undo Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
UndoManager manager = new UndoManager();
textArea.getDocument().addUndoableEditListener(manager);
JToolBar toolbar = new JToolBar();
JButton undoButton = new JButton(new UndoAction(manager, (String) UIManager
.get("AbstractUndoableEdit.undoText")));
toolbar.add(undoButton);
JButton redoButton = new JButton(new RedoAction(manager, (String) UIManager
.get("AbstractUndoableEdit.redoText")));
toolbar.add(redoButton);
Container content = frame.getContentPane();
content.add(toolbar, BorderLayout.NORTH);
content.add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
abstract class UndoRedoAction extends AbstractAction {
UndoManager undoManager = new UndoManager();
String errorMessage = "Cannot undo";
String errorTitle = "Undo Problem";
protected UndoRedoAction(UndoManager manager, String name) {
super(name);
undoManager = manager;
}
public void setErrorMessage(String newValue) {
errorMessage = newValue;
}
public void setErrorTitle(String newValue) {
errorTitle = newValue;
}
protected void showMessage(Object source) {
if (source instanceof Component) {
JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle,
JOptionPane.WARNING_MESSAGE);
} else {
System.err.println(errorMessage);
}
}
}
class UndoAction extends UndoRedoAction {
public UndoAction(UndoManager manager, String name) {
super(manager, name);
setErrorMessage("Cannot undo");
setErrorTitle("Undo Problem");
}
public void actionPerformed(ActionEvent actionEvent) {
try {
undoManager.undo();
} catch (CannotUndoException cannotUndoException) {
showMessage(actionEvent.getSource());
}
}
}
class RedoAction extends UndoRedoAction {
public RedoAction(UndoManager manager, String name) {
super(manager, name);
setErrorMessage("Cannot redo");
setErrorTitle("Redo Problem");
}
public void actionPerformed(ActionEvent actionEvent) {
try {
undoManager.redo();
} catch (CannotRedoException cannotRedoException) {
showMessage(actionEvent.getSource());
}
}
}
UndoManager: setLimit(int l)
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}
UndoManager: undo()
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class MainClass {
public static void main(final String args[]) {
JFrame frame = new JFrame("Undo Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
UndoManager manager = new UndoManager();
textArea.getDocument().addUndoableEditListener(manager);
JToolBar toolbar = new JToolBar();
JButton undoButton = new JButton(new UndoAction(manager, (String) UIManager
.get("AbstractUndoableEdit.undoText")));
toolbar.add(undoButton);
Container content = frame.getContentPane();
content.add(toolbar, BorderLayout.NORTH);
content.add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
abstract class UndoRedoAction extends AbstractAction {
UndoManager undoManager = new UndoManager();
String errorMessage = "Cannot undo";
String errorTitle = "Undo Problem";
protected UndoRedoAction(UndoManager manager, String name) {
super(name);
undoManager = manager;
}
public void setErrorMessage(String newValue) {
errorMessage = newValue;
}
public void setErrorTitle(String newValue) {
errorTitle = newValue;
}
protected void showMessage(Object source) {
if (source instanceof Component) {
JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle,
JOptionPane.WARNING_MESSAGE);
} else {
System.err.println(errorMessage);
}
}
}
class UndoAction extends UndoRedoAction {
public UndoAction(UndoManager manager, String name) {
super(manager, name);
setErrorMessage("Cannot undo");
setErrorTitle("Undo Problem");
}
public void actionPerformed(ActionEvent actionEvent) {
try {
undoManager.undo();
} catch (CannotUndoException cannotUndoException) {
showMessage(actionEvent.getSource());
}
}
}
UndoManager: undoOrRedo()
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
public static void main(String[] args) {
UndoManager mgr = new UndoManager();
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
System.out.println("Insignificant edit example");
mgr.undo();
mgr.redo();
System.out.println(mgr.canRedo()); // No more sig. edits
// Show how edits that call add/replace are used.
//
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Absorbed (by addEdit) edit example");
mgr.undo();
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
System.out.println("Absorbed (by replaceEdit) edit example");
mgr.undo();
System.out.println(mgr.canUndo());
// Show how changing limit works.
mgr.discardAllEdits();
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
System.out.println("Changing limit example");
mgr.undo();
mgr.undo();
mgr.undo(); // Now 3 undoable, 3 redoable
mgr.setLimit(4); // Now 2 undoable, 2 redoable!
while (mgr.canUndo())
mgr.undo();
while (mgr.canRedo())
mgr.redo();
// undoOrRedo example
mgr.discardAllEdits();
mgr.setLimit(1);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
System.out.println("undoOrRedo example");
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
System.out.println(mgr.getUndoOrRedoPresentationName());
mgr.undoOrRedo();
// Show how UndoManager becomes a CompositeEdit.
mgr.discardAllEdits();
mgr.setLimit(100);
// # adds? sig? replace?
mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
System.out.println("Transform to composite example");
mgr.end();
mgr.undo();
mgr.redo();
// Show that adds are no longer allowed. Note that addEdit() returns true in
// pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
mgr.undo(); // note that edit 4 is not there
}
}
class SampleUndoableEdit extends AbstractUndoableEdit {
private boolean isSignificant;
private boolean isReplacer;
private int number;
private boolean allowAdds;
private Vector addedEdits;
private UndoableEdit replaced;
// Create a new edit with an identifying number. The boolean arguments define
// the edit"s behavior.
public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
this.number = number;
this.allowAdds = allowAdds;
if (allowAdds)
addedEdits = new Vector();
this.isSignificant = isSignificant;
this.isReplacer = isReplacer;
}
// "Undo" the edit by printing a message to the screen.
public void undo() throws CannotUndoException {
super.undo();
System.out.print("Undo " + number);
dumpState();
}
// "Redo" the edit by printing a message to the screen.
public void redo() throws CannotRedoException {
super.redo();
System.out.print("Redo " + number);
dumpState();
}
// If allowAdds is true, we store the input edit. If not, just return false.
public boolean addEdit(UndoableEdit anEdit) {
if (allowAdds) {
addedEdits.addElement(anEdit);
return true;
} else
return false;
}
// If isReplacer is true, we store the edit we are replacing.
public boolean replaceEdit(UndoableEdit anEdit) {
if (isReplacer) {
replaced = anEdit;
return true;
} else
return false;
}
// Significance is based on constructor parameter.
public boolean isSignificant() {
return isSignificant;
}
// Just return our identifier.
public String toString() {
return "<" + number + ">";
}
// Debug output.
public void dumpState() {
if (allowAdds && addedEdits.size() > 0) {
Enumeration e = addedEdits.elements();
System.out.print(" (absorbed: ");
while (e.hasMoreElements()) {
System.out.print(e.nextElement());
}
System.out.print(")");
}
if (isReplacer && replaced != null) {
System.out.print(" (replaced: " + replaced + ")");
}
System.out.println();
}
}