UndoableToggleApp3.java Source code

Java tutorial

Introduction

Here is the source code for UndoableToggleApp3.java

Source

/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O'Reilly 
*/
// UndoableToggleApp3.java
//A sample app showing the use of UndoManager.
//

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

public class UndoableToggleApp3 extends JFrame {

    private UndoManager manager = new UndoManager();

    private JButton undoButton;

    private JButton redoButton;

    // Create the main frame and everything in it.
    public UndoableToggleApp3() {

        // Create some toggle buttons.
        UndoableJToggleButton tog1 = new UndoableJToggleButton("One");
        UndoableJToggleButton tog2 = new UndoableJToggleButton("Two");
        UndoableJToggleButton tog3 = new UndoableJToggleButton("Three");

        // Add our listener to each toggle button.
        SimpleUEListener sl = new SimpleUEListener();
        tog1.addUndoableEditListener(sl);
        tog2.addUndoableEditListener(sl);
        tog3.addUndoableEditListener(sl);

        // Lay out the buttons.
        Box buttonBox = new Box(BoxLayout.Y_AXIS);
        buttonBox.add(tog1);
        buttonBox.add(tog2);
        buttonBox.add(tog3);

        // Create undo and redo buttons (initially disabled).
        undoButton = new JButton("Undo");
        redoButton = new JButton("Redo");
        undoButton.setEnabled(false);
        redoButton.setEnabled(false);

        // Add a listener to the undo button. It attempts to call undo() on the
        // UndoManager, then enables/disables the undo/redo buttons as
        // appropriate.
        undoButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ev) {
                try {
                    manager.undo();
                } catch (CannotUndoException ex) {
                    ex.printStackTrace();
                } finally {
                    updateButtons();
                }
            }
        });

        // Add a redo listener: just like the undo listener.
        redoButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ev) {
                try {
                    manager.redo();
                } catch (CannotRedoException ex) {
                    ex.printStackTrace();
                } finally {
                    updateButtons();
                }
            }
        });

        // Lay out the undo/redo buttons.
        Box undoRedoBox = new Box(BoxLayout.X_AXIS);
        undoRedoBox.add(Box.createGlue());
        undoRedoBox.add(undoButton);
        undoRedoBox.add(Box.createHorizontalStrut(2));
        undoRedoBox.add(redoButton);
        undoRedoBox.add(Box.createGlue());

        // Lay out the main frame.
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(buttonBox, BorderLayout.CENTER);
        getContentPane().add(undoRedoBox, BorderLayout.SOUTH);
        setSize(400, 150);
    }

    public class SimpleUEListener implements UndoableEditListener {
        // When an UndoableEditEvent is generated (each time one of the buttons
        // is pressed), we add it to the UndoManager and then get the manager's
        // undo/redo names and set the undo/redo button labels. Finally, we
        // enable/disable these buttons by asking the manager what we are
        // allowed to do.
        public void undoableEditHappened(UndoableEditEvent ev) {
            manager.addEdit(ev.getEdit());
            updateButtons();
        }
    }

    // Method to set the text and state of the undo/redo buttons.
    protected void updateButtons() {
        undoButton.setText(manager.getUndoPresentationName());
        redoButton.setText(manager.getRedoPresentationName());
        undoButton.getParent().validate();
        undoButton.setEnabled(manager.canUndo());
        redoButton.setEnabled(manager.canRedo());
    }

    // Main program just creates the frame and displays it.
    public static void main(String[] args) {
        JFrame f = new UndoableToggleApp3();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}

//UndoableJToggleButton.java
//Sample undoable toggle button class. Supports only a single listener to
//simplify the code.
//

class UndoableJToggleButton extends JToggleButton {
    private UndoableEditListener listener;

    // For this example, we'll just provide one constructor . . .
    public UndoableJToggleButton(String txt) {
        super(txt);
    }

    // Set the UndoableEditListener.
    public void addUndoableEditListener(UndoableEditListener l) {
        listener = l; // Should ideally throw an exception if listener != null
    }

    // Remove the UndoableEditListener.
    public void removeUndoableEditListener(UndoableEditListener l) {
        listener = null;
    }

    // We override this method to call the super implementation first (to fire
    // the
    // action event) and then fire a new UndoableEditEvent to our listener.
    protected void fireActionPerformed(ActionEvent ev) {

        // Fire the ActionEvent as usual.
        super.fireActionPerformed(ev);

        if (listener != null) {
            listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit(this)));
        }
    }
}

//UndoableToggleEdit.java
//An UndoableEdit used to undo the pressing of a JToggleButton.
//

class UndoableToggleEdit extends AbstractUndoableEdit {

    private JToggleButton button;

    private boolean selected;

    // Create a new edit for a JToggleButton that has just been toggled.
    public UndoableToggleEdit(JToggleButton button) {
        this.button = button;
        selected = button.isSelected();
    }

    // Return a reasonable name for this edit.
    public String getPresentationName() {
        return "Toggle " + button.getText() + " " + (selected ? "on" : "off");
    }

    // Redo by setting the button state as it was initially.
    public void redo() throws CannotRedoException {
        super.redo();
        button.setSelected(selected);
    }

    // Undo by setting the button state to the opposite value.
    public void undo() throws CannotUndoException {
        super.undo();
        button.setSelected(!selected);
    }
}