Java tutorial
/* Copyright (c) 2010, Carl Burch. License information is located in the * com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */ package com.cburch.draw.shapes; import java.awt.Color; import java.awt.Graphics; import java.util.Arrays; import java.util.List; import java.util.Random; import org.apache.commons.collections15.list.UnmodifiableList; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.cburch.draw.model.CanvasObject; import com.cburch.draw.model.AbstractCanvasObject; import com.cburch.draw.model.Handle; import com.cburch.draw.model.HandleGesture; import com.cburch.logisim.data.Attribute; import com.cburch.logisim.data.Bounds; import com.cburch.logisim.data.Location; import static com.cburch.logisim.util.LocaleString.*; public class Line extends AbstractCanvasObject { static final int ON_LINE_THRESH = 2; private int x0; private int y0; private int x1; private int y1; private Bounds bounds; private int strokeWidth; private Color strokeColor; public Line(int x0, int y0, int x1, int y1) { this.x0 = x0; this.y0 = y0; this.x1 = x1; this.y1 = y1; bounds = Bounds.create(x0, y0, 0, 0).add(x1, y1); strokeWidth = 1; strokeColor = Color.BLACK; } @Override public boolean matches(CanvasObject other) { if (other instanceof Line) { Line that = (Line) other; return this.x0 == that.x0 && this.y0 == that.x1 && this.x1 == that.y0 && this.y1 == that.y1 && this.strokeWidth == that.strokeWidth && this.strokeColor.equals(that.strokeColor); } else { return false; } } @Override public int matchesHashCode() { int ret = x0 * 31 + y0; ret = ret * 31 * 31 + x1 * 31 + y1; ret = ret * 31 + strokeWidth; ret = ret * 31 + strokeColor.hashCode(); return ret; } @Override public Element toSvgElement(Document doc) { return SvgCreator.createLine(doc, this); } public Location getEnd0() { return Location.create(x0, y0); } public Location getEnd1() { return Location.create(x1, y1); } @Override public String getDisplayName() { return _("shapeLine"); } @Override public List<Attribute<?>> getAttributes() { return DrawAttr.ATTRS_STROKE; } @Override @SuppressWarnings("unchecked") public <V> V getValue(Attribute<V> attr) { if (attr == DrawAttr.STROKE_COLOR) { return (V) strokeColor; } else if (attr == DrawAttr.STROKE_WIDTH) { return (V) Integer.valueOf(strokeWidth); } else { return null; } } @Override public void updateValue(Attribute<?> attr, Object value) { if (attr == DrawAttr.STROKE_COLOR) { strokeColor = (Color) value; } else if (attr == DrawAttr.STROKE_WIDTH) { strokeWidth = ((Integer) value).intValue(); } } @Override public Bounds getBounds() { return bounds; } @Override public Location getRandomPoint(Bounds bds, Random rand) { double u = rand.nextDouble(); int x = (int) Math.round(x0 + u * (x1 - x0)); int y = (int) Math.round(y0 + u * (y1 - y0)); int w = strokeWidth; if (w > 1) { x += (rand.nextInt(w) - w / 2); y += (rand.nextInt(w) - w / 2); } return Location.create(x, y); } @Override public boolean contains(Location loc, boolean assumeFilled) { int xq = loc.getX(); int yq = loc.getY(); double d = LineUtil.ptDistSqSegment(x0, y0, x1, y1, xq, yq); int thresh = Math.max(ON_LINE_THRESH, strokeWidth / 2); return d < thresh * thresh; } @Override public void translate(int dx, int dy) { x0 += dx; y0 += dy; x1 += dx; y1 += dy; } public List<Handle> getHandles() { return getHandles(null); } @Override public List<Handle> getHandles(HandleGesture gesture) { if (gesture == null) { return UnmodifiableList .decorate(Arrays.asList(new Handle[] { new Handle(this, x0, y0), new Handle(this, x1, y1) })); } else { Handle h = gesture.getHandle(); int dx = gesture.getDeltaX(); int dy = gesture.getDeltaY(); Handle[] ret = new Handle[2]; ret[0] = new Handle(this, h.isAt(x0, y0) ? Location.create(x0 + dx, y0 + dy) : Location.create(x0, y0)); ret[1] = new Handle(this, h.isAt(x1, y1) ? Location.create(x1 + dx, y1 + dy) : Location.create(x1, y1)); return UnmodifiableList.decorate(Arrays.asList(ret)); } } @Override public boolean canMoveHandle(Handle handle) { return true; } @Override public Handle moveHandle(HandleGesture gesture) { Handle h = gesture.getHandle(); int dx = gesture.getDeltaX(); int dy = gesture.getDeltaY(); Handle ret = null; if (h.isAt(x0, y0)) { x0 += dx; y0 += dy; ret = new Handle(this, x0, y0); } if (h.isAt(x1, y1)) { x1 += dx; y1 += dy; ret = new Handle(this, x1, y1); } bounds = Bounds.create(x0, y0, 0, 0).add(x1, y1); return ret; } @Override public void paint(Graphics g, HandleGesture gesture) { if (setForStroke(g)) { int x0 = this.x0; int y0 = this.y0; int x1 = this.x1; int y1 = this.y1; Handle h = gesture.getHandle(); if (h.isAt(x0, y0)) { x0 += gesture.getDeltaX(); y0 += gesture.getDeltaY(); } if (h.isAt(x1, y1)) { x1 += gesture.getDeltaX(); y1 += gesture.getDeltaY(); } g.drawLine(x0, y0, x1, y1); } } }