Java tutorial
/* Java Swing, 2nd Edition By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole ISBN: 0-596-00408-7 Publisher: O'Reilly */ // UndoableToggleApp4.java //A sample app showing the use of StateEdit(able). // import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Hashtable; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JRadioButton; import javax.swing.JToggleButton; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.StateEdit; import javax.swing.undo.StateEditable; public class UndoableToggleApp4 extends JFrame implements StateEditable { private JToggleButton tog; private JCheckBox cb; private JRadioButton radio; private JButton undoButton; private JButton redoButton; private JButton startButton; private JButton endButton; private StateEdit edit; // Create the main frame and everything in it. public UndoableToggleApp4() { // Create some toggle buttons (and subclasses). tog = new JToggleButton("ToggleButton"); cb = new JCheckBox("CheckBox"); radio = new JRadioButton("RadioButton"); // Add our listener to the buttons. SimpleListener sl = new SimpleListener(); tog.addActionListener(sl); cb.addActionListener(sl); radio.addActionListener(sl); // Lay out the buttons. Box buttonBox = new Box(BoxLayout.Y_AXIS); buttonBox.add(tog); buttonBox.add(cb); buttonBox.add(radio); // Create undo, redo, start, and end buttons. startButton = new JButton("Start"); endButton = new JButton("End"); undoButton = new JButton("Undo"); redoButton = new JButton("Redo"); startButton.setEnabled(true); endButton.setEnabled(false); undoButton.setEnabled(false); redoButton.setEnabled(false); // Add a listener to the start button. It creates a new StateEdit, // passing in this frame as the StateEditable. startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { edit = new StateEdit(UndoableToggleApp4.this); startButton.setEnabled(false); endButton.setEnabled(true); //undoButton.setEnabled(edit.canUndo()); // // NOTE: We really don't want to be able to undo until end() is // pressed, // but StateEdit does not enforce this for us! undoButton.setEnabled(false); redoButton.setEnabled(edit.canRedo()); } }); // Add a listener to the end button. It will call end() on the // StateEdit. endButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { edit.end(); startButton.setEnabled(true); endButton.setEnabled(false); undoButton.setEnabled(edit.canUndo()); redoButton.setEnabled(edit.canRedo()); } }); // Add a listener to the undo button. It attempts to call undo() on the // current edit, then enables/disables the undo/redo buttons as // appropriate. undoButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { try { edit.undo(); } catch (CannotUndoException ex) { ex.printStackTrace(); } finally { undoButton.setEnabled(edit.canUndo()); redoButton.setEnabled(edit.canRedo()); } } }); // Add a redo listener: just like the undo listener. redoButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { try { edit.redo(); } catch (CannotRedoException ex) { ex.printStackTrace(); } finally { undoButton.setEnabled(edit.canUndo()); redoButton.setEnabled(edit.canRedo()); } } }); // Lay out the state/end and undo/redo buttons. Box undoRedoBox = new Box(BoxLayout.X_AXIS); undoRedoBox.add(Box.createGlue()); undoRedoBox.add(startButton); undoRedoBox.add(Box.createHorizontalStrut(2)); undoRedoBox.add(endButton); undoRedoBox.add(Box.createHorizontalStrut(2)); undoRedoBox.add(undoButton); undoRedoBox.add(Box.createHorizontalStrut(2)); undoRedoBox.add(redoButton); undoRedoBox.add(Box.createGlue()); // Lay out the main frame. Container content = getContentPane(); content.setLayout(new BorderLayout()); content.add(buttonBox, BorderLayout.CENTER); content.add(undoRedoBox, BorderLayout.SOUTH); setSize(400, 150); } public class SimpleListener implements ActionListener { // When any toggle button is clicked, we turn off the undo and redo // buttons, reflecting the fact that we can only undo/redo the last // set of state changes as long as no additional changes have been made. public void actionPerformed(ActionEvent ev) { undoButton.setEnabled(false); redoButton.setEnabled(false); } } // Save the state of the app by storing the current state of the three // buttons. We'll use the buttons themselves as keys and their selected // state as values. public void storeState(Hashtable ht) { ht.put(tog, new Boolean(tog.isSelected())); ht.put(cb, new Boolean(cb.isSelected())); ht.put(radio, new Boolean(radio.isSelected())); } // Restore state based on the values we saved when storeState() was called. // Note that StateEdit discards any state info that did not change from // between the start state and the end state, so we can't assume that the // state for all 3 buttons is in the Hashtable. public void restoreState(Hashtable ht) { Boolean b1 = (Boolean) ht.get(tog); if (b1 != null) tog.setSelected(b1.booleanValue()); Boolean b2 = (Boolean) ht.get(cb); if (b2 != null) cb.setSelected(b2.booleanValue()); Boolean b3 = (Boolean) ht.get(radio); if (b3 != null) radio.setSelected(b3.booleanValue()); } // Main program just creates the frame and displays it. public static void main(String[] args) { JFrame f = new UndoableToggleApp4(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } }