Mega Code Archive

 
Categories / Java / Design Pattern
 

Memento pattern in Java

/* The Design Patterns Java Companion Copyright (C) 1998, by James W. Cooper IBM Thomas J. Watson Research Center */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Vector; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JToggleButton; import javax.swing.JToolBar; public class MemDraw extends JFrame implements ActionListener {   JToolBar tbar;   Mediator med;      public MemDraw() {     super("Memento Drawing");     addWindowListener(new WindowAdapter() {       public void windowClosing(WindowEvent e) {         System.exit(0);       }     });     JPanel jp = new JPanel();     getContentPane().add(jp);     med = new Mediator();     jp.setLayout(new BorderLayout());     tbar = new JToolBar();     jp.add("North", tbar);     RectButton rect = new RectButton(this, med);     tbar.add(rect);     UndoButton undo = new UndoButton(this, med);     tbar.add(undo);     tbar.addSeparator();     ClearButton clr = new ClearButton(this, med);     tbar.add(clr);     JCanvas canvas = new JCanvas(med);     jp.add("Center", canvas);     MouseApp map = new MouseApp(med);     canvas.addMouseListener(map);     MouseMoveApp mvap = new MouseMoveApp(med);     canvas.addMouseMotionListener(mvap);     setSize(new Dimension(400, 300));     setVisible(true);   }      public void actionPerformed(ActionEvent e) {     Command comd = (Command) e.getSource();     comd.Execute();   }      static public void main(String[] argv) {     new MemDraw();   } } //============================== class MouseApp extends MouseAdapter {   Mediator med;   public MouseApp(Mediator md) {     super();     med = md;   }   public void mousePressed(MouseEvent e) {     med.createRect(e.getX(), e.getY());   }   public void mouseReleased(MouseEvent e) {     med.rememberPosition();   } } class MouseMoveApp extends MouseMotionAdapter {   Mediator med;   public MouseMoveApp(Mediator md) {     super();     med = md;   }   public void mouseDragged(MouseEvent e) {     med.drag(e.getX(), e.getY());   } } class ClearButton extends JButton implements Command {   Mediator med;   public ClearButton(ActionListener act, Mediator md) {     super("C");     setToolTipText("Clear");     addActionListener(act);     med = md;   }      public void Execute() {     med.clear();   } } class JCanvas extends JPanel {   Mediator med;   public JCanvas(Mediator md) {     med = md;     med.registerCanvas(this);     setBackground(Color.white);   }   public void paint(Graphics g) {     super.paint(g);     med.reDraw(g);   } } class Mediator {   boolean startRect;   boolean rectSelected;   Vector drawings;   Vector undoList;   RectButton rect;   JPanel canvas;   visRectangle selectedRectangle;   public Mediator() {     startRect = false;     rectSelected = false;     drawings = new Vector();     undoList = new Vector();   }      public void startRectangle() {     startRect = true;   }      public void createRect(int x, int y) {     unpick(); //make sure no rectangle is selected     if (startRect) //if rect button is depressed     {       Integer count = new Integer(drawings.size());       undoList.addElement(count); //Save previous drawing list size       visRectangle v = new visRectangle(x, y);       drawings.addElement(v); //add new element to list       startRect = false; //done with this rectangle       rect.setSelected(false); //unclick button       canvas.repaint();     } else       pickRect(x, y); //if not pressed look for rect to select   }      public void registerRectButton(RectButton rb) {     rect = rb;   }      public void registerCanvas(JPanel p) {     canvas = p;   }      private void unpick() {     rectSelected = false;     if (selectedRectangle != null) {       selectedRectangle.setSelected(false);       selectedRectangle = null;       repaint();     }   }      public void rememberPosition() {     if (rectSelected) {       Memento m = new Memento(selectedRectangle);       undoList.addElement(m);     }   }      public void pickRect(int x, int y) {     //save current selected rectangle to avoid double save of undo     visRectangle lastPick = selectedRectangle;     unpick();     for (int i = 0; i < drawings.size(); i++) {       visRectangle v = (visRectangle) drawings.elementAt(i);       if (v.contains(x, y)) //did click inside a rectangle       {         selectedRectangle = v; //save it         rectSelected = true;         if (selectedRectangle != lastPick) //but don't save twice           rememberPosition();         v.setSelected(true); //turn on handles         repaint(); //and redraw       }     }   }      public void clear() {     drawings = new Vector();     undoList = new Vector();     rectSelected = false;     selectedRectangle = null;     repaint();   }      private void repaint() {     canvas.repaint();   }      public void drag(int x, int y) {     if (rectSelected) {       if (selectedRectangle.contains(x, y)) {         selectedRectangle.move(x, y);         repaint();       }     }   }      public void reDraw(Graphics g) {     g.setColor(Color.black);     for (int i = 0; i < drawings.size(); i++) {       visRectangle v = (visRectangle) drawings.elementAt(i);       v.draw(g);     }   }      public void undo() {     if (undoList.size() > 0) {       //get last element in undo list       Object obj = undoList.lastElement();       undoList.removeElement(obj); //and remove it       //if this is an Integer, the last action was a new rectangle       if (obj instanceof Integer) {         //remove last created rectangle         Object drawObj = drawings.lastElement();         drawings.removeElement(drawObj);       }       //if this is a Memento, the last action was a move       if (obj instanceof Memento) {         //get the Memento         Memento m = (Memento) obj;         m.restore(); //and restore the old position       }       repaint();     }   } } interface Command {   public void Execute(); } class RectButton extends JToggleButton implements Command {   Mediator med;   public RectButton(ActionListener act, Mediator md) {     super("R");     //setSize(new Dimension(25,25));     //setBorder(new EmptyBorder(5,5,5,5));     setToolTipText("Draw rectangle");     addActionListener(act);     med = md;     med.registerRectButton(this);   }      public void Execute() {     if (isSelected()) {       med.startRectangle();     }   } } class UndoButton extends JButton implements Command {   Mediator med;   public UndoButton(ActionListener act, Mediator md) {     super("U");     //setSize(new Dimension(25,25));     //setBorder(new EmptyBorder(5,5,5,5));     setToolTipText("Undo");     addActionListener(act);     med = md;   }      public void Execute() {     med.undo();   } } class visRectangle {   int x, y, w, h;   Rectangle rect;   boolean selected;   public visRectangle(int xpt, int ypt) {     x = xpt;     y = ypt;     w = 40;     h = 30;     saveAsRect();   }      public void setSelected(boolean b) {     selected = b;   }      private void saveAsRect() {     rect = new Rectangle(x - w / 2, y - h / 2, w, h);   }      public void draw(Graphics g) {     g.drawRect(x, y, w, h);     if (selected) {       g.fillRect(x + w / 2, y - 2, 4, 4);       g.fillRect(x - 2, y + h / 2, 4, 4);       g.fillRect(x + w / 2, y + h - 2, 4, 4);       g.fillRect(x + w - 2, y + h / 2, 4, 4);     }   }      public boolean contains(int x, int y) {     return rect.contains(x, y);   }      public void move(int xpt, int ypt) {     x = xpt;     y = ypt;     saveAsRect();   } } //=============================================== class Memento {   visRectangle rect;   //saved fields- remember internal fields   //of the specified visual rectangle   int x, y, w, h;   public Memento(visRectangle r) {     rect = r;     x = rect.x;     y = rect.y;     w = rect.w;     h = rect.h;   }      public void restore() {     //restore the internal state of     //the specified rectangle     rect.x = x;     rect.y = y;     rect.h = h;     rect.w = w;   } }