Java tutorial
/* Definitive Guide to Swing for Java 2, Second Edition By John Zukowski ISBN: 1-893115-78-X Publisher: APress */ import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.awt.Polygon; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JToolBar; 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; import javax.swing.undo.UndoableEditSupport; public class UndoDrawing { public static void main(String args[]) { JFrame frame = new JFrame("Drawing Sample"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); UndoableDrawingPanel drawingPanel = new UndoableDrawingPanel(); UndoManager manager = new UndoManager(); drawingPanel.addUndoableEditListener(manager); JToolBar toolbar = new JToolBar(); toolbar.add(UndoManagerHelper.getUndoAction(manager)); toolbar.add(UndoManagerHelper.getRedoAction(manager)); Container content = frame.getContentPane(); content.add(toolbar, BorderLayout.NORTH); content.add(drawingPanel, BorderLayout.CENTER); frame.setSize(300, 150); frame.setVisible(true); } } class UndoableDrawingPanel extends JPanel { UndoableEditSupport undoableEditSupport = new UndoableEditSupport(this); Polygon polygon = new Polygon(); public UndoableDrawingPanel() { MouseListener mouseListener = new MouseAdapter() { public void mouseReleased(MouseEvent mouseEvent) { undoableEditSupport.postEdit(new UndoableDrawEdit(UndoableDrawingPanel.this)); polygon.addPoint(mouseEvent.getX(), mouseEvent.getY()); repaint(); } }; addMouseListener(mouseListener); } public void addUndoableEditListener(UndoableEditListener undoableEditListener) { undoableEditSupport.addUndoableEditListener(undoableEditListener); } public void removeUndoableEditListener(UndoableEditListener undoableEditListener) { undoableEditSupport.removeUndoableEditListener(undoableEditListener); } public void setPolygon(Polygon newValue) { polygon = newValue; repaint(); } public Polygon getPolygon() { Polygon returnValue; if (polygon.npoints == 0) { returnValue = new Polygon(); } else { returnValue = new Polygon(polygon.xpoints, polygon.ypoints, polygon.npoints); } return returnValue; } protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawPolygon(polygon); } } class UndoManagerHelper { public static Action getUndoAction(UndoManager manager, String label) { return new UndoAction(manager, label); } public static Action getUndoAction(UndoManager manager) { return new UndoAction(manager, "Undo"); } public static Action getRedoAction(UndoManager manager, String label) { return new RedoAction(manager, label); } public static Action getRedoAction(UndoManager manager) { return new RedoAction(manager, "Redo"); } private abstract static 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); } } } public static 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()); } } } public static class RedoAction extends UndoRedoAction { String errorMessage = "Cannot redo"; String errorTitle = "Redo Problem"; 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()); } } } } class UndoableDrawEdit extends AbstractUndoableEdit { UndoableDrawingPanel panel; Polygon polygon, savedPolygon; public UndoableDrawEdit(UndoableDrawingPanel panel) { this.panel = panel; polygon = panel.getPolygon(); } public String getPresentationName() { return "Polygon of size " + polygon.npoints; } public void redo() throws CannotRedoException { super.redo(); if (savedPolygon == null) { // Should never get here, as super() doesn't permit redoing throw new CannotRedoException(); } else { panel.setPolygon(savedPolygon); savedPolygon = null; } } public void undo() throws CannotUndoException { super.undo(); savedPolygon = panel.getPolygon(); panel.setPolygon(polygon); } }