com.cburch.draw.shapes.Line.java Source code

Java tutorial

Introduction

Here is the source code for com.cburch.draw.shapes.Line.java

Source

/* 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);
        }
    }

}