UndoExample4.java Source code

Java tutorial

Introduction

Here is the source code for UndoExample4.java

Source

/*
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 UndoExample4 extends JFrame {
    public UndoExample4() {
        super("Undo/Redo Example 4");

        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"));

        UndoableTree2 tree = new UndoableTree2(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 UndoExample4();
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
                System.exit(0);
            }
        });
        f.pack();
        f.setVisible(true);
    }
}

class UndoableTree2 extends JTree {
    public UndoableTree2(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);
        TreePath[] selections = getSelectionPaths();

        super.collapsePath(path);

        boolean isExpanded = isExpanded(path);
        if (isExpanded != wasExpanded) {
            TreePath[] newSelections = getSelectionPaths();
            support.beginUpdate();
            support.postEdit(new SelectionEdit(selections, newSelections));
            support.postEdit(new CollapseEdit(path));
            support.endUpdate();
        }
    }

    public void expandPath(TreePath path) {
        boolean wasExpanded = isExpanded(path);
        TreePath[] selections = getSelectionPaths();

        super.expandPath(path);

        boolean isExpanded = isExpanded(path);
        if (isExpanded != wasExpanded) {
            TreePath[] newSelections = getSelectionPaths();
            support.beginUpdate();
            support.postEdit(new SelectionEdit(selections, newSelections));
            support.postEdit(new ExpandEdit(path));
            support.endUpdate();
        }
    }

    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();
            UndoableTree2.this.undoCollapse(path);
        }

        public void redo() throws CannotRedoException {
            super.redo();
            UndoableTree2.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();
            UndoableTree2.this.undoExpansion(path);
        }

        public void redo() throws CannotRedoException {
            super.redo();
            UndoableTree2.this.undoCollapse(path);
        }

        public String getPresentationName() {
            return "node expansion";
        }

        private TreePath path;
    }

    private class SelectionEdit extends AbstractUndoableEdit {
        public SelectionEdit(TreePath[] oldSelections, TreePath[] newSelections) {
            this.oldSelections = oldSelections;
            this.newSelections = newSelections;
        }

        public void undo() throws CannotUndoException {
            super.undo();
            UndoableTree2.this.setSelectionPaths(oldSelections);
        }

        public void redo() throws CannotRedoException {
            super.redo();
            UndoableTree2.this.setSelectionPaths(newSelections);
        }

        public String getPresentationName() {
            return "selection change";
        }

        private TreePath[] oldSelections;

        private TreePath[] newSelections;
    }

    private UndoableEditSupport support = new UndoableEditSupport(this);
}