Java tutorial
/* Core SWING Advanced Programming By Kim Topley ISBN: 0 13 083292 8 Publisher: Prentice Hall */ import java.awt.BorderLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.UIManager; import javax.swing.event.UndoableEditListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; import javax.swing.undo.UndoableEditSupport; public class UndoExample3 extends JFrame { public UndoExample3() { super("Undo/Redo Example 3"); DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("root"); DefaultMutableTreeNode node = new DefaultMutableTreeNode("Apollo 8"); rootNode.add(node); node.add(new DefaultMutableTreeNode("Borman")); node.add(new DefaultMutableTreeNode("Lovell")); node.add(new DefaultMutableTreeNode("Anders")); node = new DefaultMutableTreeNode("Apollo 11"); rootNode.add(node); node.add(new DefaultMutableTreeNode("Armstrong")); node.add(new DefaultMutableTreeNode("Aldrin")); node.add(new DefaultMutableTreeNode("Collins")); node = new DefaultMutableTreeNode("Apollo 12"); rootNode.add(node); node.add(new DefaultMutableTreeNode("Conrad")); node.add(new DefaultMutableTreeNode("Gordon")); node.add(new DefaultMutableTreeNode("Bean")); UndoableTree tree = new UndoableTree(rootNode); getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); // Create the undo manager and actions UndoManager manager = new UndoManager(); tree.addUndoableEditListener(manager); Action undoAction = new UndoAction(manager); Action redoAction = new RedoAction(manager); // Add the actions to buttons JPanel panel = new JPanel(); JButton undoButton = new JButton("Undo"); JButton redoButton = new JButton("Redo"); undoButton.addActionListener(undoAction); redoButton.addActionListener(redoAction); panel.add(undoButton); panel.add(redoButton); getContentPane().add(panel, BorderLayout.SOUTH); // Assign the actions to keys ((JComponent) getContentPane()).registerKeyboardAction(undoAction, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); ((JComponent) getContentPane()).registerKeyboardAction(redoAction, KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); } // The Undo action public class UndoAction extends AbstractAction { public UndoAction(UndoManager manager) { this.manager = manager; } public void actionPerformed(ActionEvent evt) { try { manager.undo(); } catch (CannotUndoException e) { Toolkit.getDefaultToolkit().beep(); } } private UndoManager manager; } // The Redo action public class RedoAction extends AbstractAction { public RedoAction(UndoManager manager) { this.manager = manager; } public void actionPerformed(ActionEvent evt) { try { manager.redo(); } catch (CannotRedoException e) { Toolkit.getDefaultToolkit().beep(); } } private UndoManager manager; } public static void main(String[] args) { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (Exception evt) { } JFrame f = new UndoExample3(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); f.pack(); f.setVisible(true); } } class UndoableTree extends JTree { // Only one constructor for brevity public UndoableTree(TreeNode root) { super(root); } public void addUndoableEditListener(UndoableEditListener l) { support.addUndoableEditListener(l); } public void removeUndoableEditListener(UndoableEditListener l) { support.removeUndoableEditListener(l); } public void collapsePath(TreePath path) { boolean wasExpanded = isExpanded(path); super.collapsePath(path); boolean isExpanded = isExpanded(path); if (isExpanded != wasExpanded) { support.postEdit(new CollapseEdit(path)); } } public void expandPath(TreePath path) { boolean wasExpanded = isExpanded(path); super.expandPath(path); boolean isExpanded = isExpanded(path); if (isExpanded != wasExpanded) { support.postEdit(new ExpandEdit(path)); } } private void undoExpansion(TreePath path) { super.collapsePath(path); } private void undoCollapse(TreePath path) { super.expandPath(path); } private class CollapseEdit extends AbstractUndoableEdit { public CollapseEdit(TreePath path) { this.path = path; } public void undo() throws CannotUndoException { super.undo(); UndoableTree.this.undoCollapse(path); } public void redo() throws CannotRedoException { super.redo(); UndoableTree.this.undoExpansion(path); } public String getPresentationName() { return "node collapse"; } private TreePath path; } private class ExpandEdit extends AbstractUndoableEdit { public ExpandEdit(TreePath path) { this.path = path; } public void undo() throws CannotUndoException { super.undo(); UndoableTree.this.undoExpansion(path); } public void redo() throws CannotRedoException { super.redo(); UndoableTree.this.undoCollapse(path); } public String getPresentationName() { return "node expansion"; } private TreePath path; } private UndoableEditSupport support = new UndoableEditSupport(this); }