Memento pattern in Java : Memento Pattern « Design Pattern « Java






Memento pattern in Java

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;
  }
}

           
       








Related examples in the same category

1.Memento Pattern 2