/* PaintState.java Written by Shinya Kasatani */ import java.awt.*; import java.util.Observable; public class PaintState extends Observable { OperationList list; PaintContext currentContext; public PaintState() { currentContext = new PaintContext(); list = new OperationList(currentContext); } public void setCurrent(OperationNode node) { list.warp(node); //currentContext = list.getCurrent().getContext(); setChanged(); notifyObservers(); } public void drawCurrent(Graphics g, Xform xf) { DrawLink.draw(list.getCurrent(), g, xf); } public void draw(OperationNode node, Graphics g, Xform xf) { DrawLink.draw(node, g, xf); } public OperationNode getCurrent() { return list.getCurrent(); } public void setColor(Color color) { currentContext = new PaintContext(currentContext, color); } public Color getColor() { return currentContext.getColor(); } public void line(int x1, int y1, int x2, int y2) { list.add(new LineOperation(currentContext, x1, y1, x2, y2)); setChanged(); notifyObservers(getCurrent()); } public void freehand(int x[], int y[], int points) { list.add(new FreeHandOperation(currentContext, x, y, points)); setChanged(); notifyObservers(getCurrent()); } public interface Xform { public Point xform(int x, int y); public void xform(int inX[], int inY[], int points, int outX[], int outY[]); public Dimension getSize(); } protected class PaintContext { protected Color color; public PaintContext() { color = Color.black; } public PaintContext(PaintContext context) { this.color = context.getColor(); } public PaintContext(PaintContext context, Color color) { this(context); this.color = color; } public Color getColor() { return color; } public void update(Graphics g) { g.setColor(color); } } public static abstract class Operation { public static final int CLEAR = 1; public static final int LINE = 2; public static final int FREEHAND = 3; protected int type; protected PaintContext context; public Operation(PaintContext context, int type) { this.context = context; this.type = type; } public PaintContext getContext() { return context; } public abstract void draw(Graphics g, Xform xf); } protected static class LineOperation extends Operation { protected int x1, y1, x2, y2; public LineOperation(PaintContext context, int x1, int y1, int x2, int y2) { super(context, LINE); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public void draw(Graphics g, Xform xf) { context.update(g); Point p1 = xf.xform(x1, y1); Point p2 = xf.xform(x2, y2); g.drawLine(p1.x, p1.y, p2.x, p2.y); } } protected static class FreeHandOperation extends Operation { protected int x[], y[], points; public FreeHandOperation(PaintContext context, int x[], int y[], int points) { super(context, FREEHAND); this.x = x; this.y = y; this.points = points; } public void draw(Graphics g, Xform xf) { context.update(g); int nx[] = new int[points]; int ny[] = new int[points]; xf.xform(x, y, points, nx, ny); g.drawPolyline(nx, ny, points); } } protected static class ClearOperation extends Operation { public ClearOperation(PaintContext context) { super(context, CLEAR); } public void draw(Graphics g, Xform xf) { context.update(g); Dimension size = xf.getSize(); g.clearRect(0, 0, size.width, size.height); } } protected static class OperationList { OperationNode root; OperationNode current; public OperationList(PaintContext context) { root = new OperationNode(new ClearOperation(context), null); current = root; } public void add(Operation op) { current = current.add(op); } public OperationNode getCurrent() { return current; } public void warp(OperationNode node) { this.current = node; OperationNode parent; while (node != null) { parent = node.getParent(); if (parent != null) { parent.setChild(node); } node = parent; } } public OperationNode getRoot() { return root; } } public static class OperationNode { Operation op; OperationNode child; OperationNode parent; OperationNode nextSibling; OperationNode prevSibling; public OperationNode(Operation op, OperationNode parent) { this.op = op; this.parent = parent; //sibling = this; } public OperationNode add(Operation op) { if (child == null) { child = new OperationNode(op, this); } else { child = child.addSibling(op); } return child; } protected OperationNode addSibling(Operation op) { OperationNode node = new OperationNode(op, parent); prevSibling = node; node.nextSibling = this; /* node.sibling = sibling; sibling = node; */ return node; } public void draw(Graphics g, Xform xf) { op.draw(g, xf); } public OperationNode getParent() { return parent; } public OperationNode getChild() { return child; } public void setChild(OperationNode node) { this.child = node; } public PaintContext getContext() { return op.getContext(); } public OperationNode nextSibling() { return nextSibling; } public OperationNode prevSibling() { return prevSibling; } } protected static class DrawLink { OperationNode node; DrawLink parent; DrawLink child; public DrawLink(OperationNode node, DrawLink child) { this.node = node; this.child = child; if (child != null) { child.parent = this; } } public static void draw(OperationNode node, Graphics g, Xform xf) { DrawLink link = null; // create link while (node != null) { link = new DrawLink(node, link); node = node.getParent(); } // draw while (link != null) { link.node.draw(g, xf); link = link.child; } } } }