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.logisim.circuit.appear; import java.awt.Color; import java.awt.Graphics; import java.util.Arrays; import java.util.List; 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.Handle; import com.cburch.draw.model.HandleGesture; import com.cburch.logisim.data.Attribute; import com.cburch.logisim.data.Attributes; import com.cburch.logisim.data.Bounds; import com.cburch.logisim.data.Direction; import com.cburch.logisim.data.Location; import static com.cburch.logisim.util.LocaleString.*; public class AppearanceAnchor extends AppearanceElement { public static final Attribute<Direction> FACING = Attributes.forDirection("facing", __("appearanceFacingAttr")); static final List<Attribute<?>> ATTRIBUTES = UnmodifiableList .decorate(Arrays.asList(new Attribute<?>[] { FACING })); private static final int RADIUS = 3; private static final int INDICATOR_LENGTH = 8; private static final Color SYMBOL_COLOR = new Color(0, 128, 0); private Direction facing; public AppearanceAnchor(Location location) { super(location); facing = Direction.EAST; } @Override public boolean matches(CanvasObject other) { if (other instanceof AppearanceAnchor) { AppearanceAnchor that = (AppearanceAnchor) other; return super.matches(that) && this.facing.equals(that.facing); } else { return false; } } @Override public int matchesHashCode() { return super.matchesHashCode() * 31 + facing.hashCode(); } @Override public String getDisplayName() { return _("circuitAnchor"); } @Override public Element toSvgElement(Document doc) { Location loc = getLocation(); Element ret = doc.createElement("circ-anchor"); ret.setAttribute("x", "" + (loc.getX() - RADIUS)); ret.setAttribute("y", "" + (loc.getY() - RADIUS)); ret.setAttribute("width", "" + 2 * RADIUS); ret.setAttribute("height", "" + 2 * RADIUS); ret.setAttribute("facing", facing.toString()); return ret; } public Direction getFacing() { return facing; } @Override public List<Attribute<?>> getAttributes() { return ATTRIBUTES; } @Override @SuppressWarnings("unchecked") public <V> V getValue(Attribute<V> attr) { if (attr == FACING) { return (V) facing; } else { return super.getValue(attr); } } @Override protected void updateValue(Attribute<?> attr, Object value) { if (attr == FACING) { facing = (Direction) value; } else { super.updateValue(attr, value); } } @Override public void paint(Graphics g, HandleGesture gesture) { Location location = getLocation(); int x = location.getX(); int y = location.getY(); g.setColor(SYMBOL_COLOR); g.drawOval(x - RADIUS, y - RADIUS, 2 * RADIUS, 2 * RADIUS); Location e0 = location.translate(facing, RADIUS); Location e1 = location.translate(facing, RADIUS + INDICATOR_LENGTH); g.drawLine(e0.getX(), e0.getY(), e1.getX(), e1.getY()); } @Override public Bounds getBounds() { Bounds bds = super.getBounds(RADIUS); Location center = getLocation(); Location end = center.translate(facing, RADIUS + INDICATOR_LENGTH); return bds.add(end); } @Override public boolean contains(Location loc, boolean assumeFilled) { if (super.isInCircle(loc, RADIUS)) { return true; } else { Location center = getLocation(); Location end = center.translate(facing, RADIUS + INDICATOR_LENGTH); if (facing == Direction.EAST || facing == Direction.WEST) { return Math.abs(loc.getY() - center.getY()) < 2 && (loc.getX() < center.getX()) != (loc.getX() < end.getX()); } else { return Math.abs(loc.getX() - center.getX()) < 2 && (loc.getY() < center.getY()) != (loc.getY() < end.getY()); } } } @Override public List<Handle> getHandles(HandleGesture gesture) { Location c = getLocation(); Location end = c.translate(facing, RADIUS + INDICATOR_LENGTH); return UnmodifiableList .decorate(Arrays.asList(new Handle[] { new Handle(this, c), new Handle(this, end) })); } }