Commandパターン
undo処理について、理解が追いつかない。repaintでpaintが呼ばれる。
今度のプロジェクトでJavaScriptで似たようなことを実装しないといけないのに。。
まぁ、いいか。
% find . -name "*.java" -print0 |xargs -0 cat [] package command; public interface Command { public void execute(); } package command; import java.util.Iterator; import java.util.Stack; public class MacroCommand implements Command { private Stack<Command> commands = new Stack<>(); @Override public void execute() { Iterator<Command> it = commands.iterator(); while (it.hasNext()) { it.next().execute(); } } public void append(Command cmd) { if (cmd != this) { commands.push(cmd); } } public void undo() { if (!commands.empty()) { commands.pop(); } } public void clear() { commands.clear(); } } package drawer; public interface Drawable { public void draw(int x, int y); } package drawer; import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics; import command.MacroCommand; public class DrawCanvas extends Canvas implements Drawable { private static final long serialVersionUID = 1L; private Color color = Color.red; private int radius = 6; private MacroCommand history; public DrawCanvas(int width, int height, MacroCommand history) { setSize(width, height); setBackground(Color.white); this.history = history; } @Override public void paint(Graphics g) { System.out.println("DrawCanvas.paint"); history.execute(); } @Override public void draw(int x, int y) { Graphics g = getGraphics(); g.setColor(color); g.fillOval(x - radius, y - radius, radius * 2, radius * 2); } } package drawer; import java.awt.Point; import command.Command; public class DrawCommand implements Command { protected Drawable drawable; private Point position; public DrawCommand(Drawable drawable, Point position) { this.drawable = drawable; this.position = position; } @Override public void execute() { drawable.draw(position.x, position.y); } } import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import command.Command; import command.MacroCommand; import drawer.DrawCanvas; import drawer.DrawCommand; public class Main extends JFrame implements ActionListener, MouseMotionListener, WindowListener { private static final long serialVersionUID = 1L; private MacroCommand history = new MacroCommand(); private DrawCanvas canvas = new DrawCanvas(400, 400, history); private JButton clearButton = new JButton("clear"); private JButton undoButton = new JButton("undo"); public Main(String title) { super(title); this.addWindowListener(this); canvas.addMouseMotionListener(this); clearButton.addActionListener(this); undoButton.addActionListener(this); Box buttonBox = new Box(BoxLayout.X_AXIS); buttonBox.add(clearButton); buttonBox.add(undoButton); Box mainBox = new Box(BoxLayout.Y_AXIS); mainBox.add(buttonBox); mainBox.add(canvas); getContentPane().add(mainBox); pack(); setVisible(true); } @Override public void windowOpened(WindowEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void windowClosing(WindowEvent e) { System.exit(0); } @Override public void windowClosed(WindowEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void windowIconified(WindowEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void windowDeiconified(WindowEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void windowActivated(WindowEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void windowDeactivated(WindowEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void mouseDragged(MouseEvent e) { Command cmd = new DrawCommand(canvas, e.getPoint()); history.append(cmd); cmd.execute(); } @Override public void mouseMoved(MouseEvent e) { // TODO 自動生成されたメソッド・スタブ } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == clearButton) { history.clear(); canvas.repaint(); } if (e.getSource() == undoButton) { System.out.println("undoButton"); history.undo(); canvas.repaint(); } } public static void main(String[] args) { new Main("Command Pattern Sample"); } }