Beispiel #1
0
 public void draw(ComponentDrawContext context) {
   CircuitState state = context.getCircuitState();
   Graphics g = context.getGraphics();
   GraphicsUtil.switchToWidth(g, WIDTH);
   g.setColor(state.getValue(e0).getColor());
   g.drawLine(e0.getX(), e0.getY(), e1.getX(), e1.getY());
 }
Beispiel #2
0
  private void computeLabel(Instance instance) {
    GateAttributes attrs = (GateAttributes) instance.getAttributeSet();
    Direction facing = attrs.facing;
    int baseWidth = ((Integer) attrs.size.getValue()).intValue();

    int axis = baseWidth / 2 + (negateOutput ? 10 : 0);
    int perp = 0;
    if (AppPreferences.GATE_SHAPE.get().equals(AppPreferences.SHAPE_RECTANGULAR)) {
      perp += 6;
    }
    Location loc = instance.getLocation();
    int cx;
    int cy;
    if (facing == Direction.NORTH) {
      cx = loc.getX() + perp;
      cy = loc.getY() + axis;
    } else if (facing == Direction.SOUTH) {
      cx = loc.getX() - perp;
      cy = loc.getY() - axis;
    } else if (facing == Direction.WEST) {
      cx = loc.getX() + axis;
      cy = loc.getY() - perp;
    } else {
      cx = loc.getX() - axis;
      cy = loc.getY() + perp;
    }
    instance.setTextField(
        StdAttr.LABEL, StdAttr.LABEL_FONT, cx, cy, TextField.H_CENTER, TextField.V_CENTER);
  }
Beispiel #3
0
 @Override
 public void draw(Canvas canvas, Graphics g) {
   if (active) {
     Location start = mouseStart;
     Location end = mouseEnd;
     g.setColor(Color.GRAY);
     g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
   }
 }
Beispiel #4
0
 public boolean contains(Location q) {
   int qx = q.getX();
   int qy = q.getY();
   if (is_x_equal) {
     int wx = e0.getX();
     return qx >= wx - 2 && qx <= wx + 2 && e0.getY() <= qy && qy <= e1.getY();
   } else {
     int wy = e0.getY();
     return qy >= wy - 2 && qy <= wy + 2 && e0.getX() <= qx && qx <= e1.getX();
   }
 }
Beispiel #5
0
 private Handle[] getHandleArray(HandleGesture gesture) {
     if (gesture == null) {
         return new Handle[] { new Handle(this, p0), new Handle(this, p1),
                 new Handle(this, p2) };
     } else {
         Handle g = gesture.getHandle();
         int gx = g.getX() + gesture.getDeltaX();
         int gy = g.getY() + gesture.getDeltaY();
         Handle[] ret = { new Handle(this, p0), new Handle(this, p1),
                 new Handle(this, p2) };
         if (g.isAt(p0)) {
             if (gesture.isShiftDown()) {
                 Location p = LineUtil.snapTo8Cardinals(p2, gx, gy);
                 ret[0] = new Handle(this, p);
             } else {
                 ret[0] = new Handle(this, gx, gy);
             }
         } else if (g.isAt(p2)) {
             if (gesture.isShiftDown()) {
                 Location p = LineUtil.snapTo8Cardinals(p0, gx, gy);
                 ret[2] = new Handle(this, p);
             } else {
                 ret[2] = new Handle(this, gx, gy);
             }
         } else if (g.isAt(p1)) {
             if (gesture.isShiftDown()) {
                 double x0 = p0.getX();
                 double y0 = p0.getY();
                 double x1 = p2.getX();
                 double y1 = p2.getY();
                 double midx = (x0 + x1) / 2;
                 double midy = (y0 + y1) / 2;
                 double dx = x1 - x0;
                 double dy = y1 - y0;
                 double[] p = LineUtil.nearestPointInfinite(gx, gy,
                         midx, midy, midx - dy, midy + dx);
                 gx = (int) Math.round(p[0]);
                 gy = (int) Math.round(p[1]);
             }
             if (gesture.isAltDown()) {
                 double[] e0 = { p0.getX(), p0.getY() };
                 double[] e1 = { p2.getX(), p2.getY() };
                 double[] mid = { gx, gy };
                 double[] ct = CurveUtil.interpolate(e0, e1, mid);
                 gx = (int) Math.round(ct[0]);
                 gy = (int) Math.round(ct[1]);
             }
             ret[1] = new Handle(this, gx, gy);
         }
         return ret;
     }
 }
Beispiel #6
0
  private void drawInstance(InstancePainter painter, boolean isGhost) {
    Graphics2D g = (Graphics2D) painter.getGraphics().create();
    Location loc = painter.getLocation();
    g.translate(loc.getX(), loc.getY());

    Direction from = painter.getAttributeValue(StdAttr.FACING);
    int degrees = Direction.EAST.toDegrees() - from.toDegrees();
    double radians = Math.toRadians((degrees + 360) % 360);
    g.rotate(radians);

    GraphicsUtil.switchToWidth(g, Wire.WIDTH);
    if (!isGhost && painter.getShowState()) {
      g.setColor(painter.getPort(0).getColor());
    }
    g.drawLine(0, 0, 5, 0);

    GraphicsUtil.switchToWidth(g, 1);
    if (!isGhost && painter.shouldDrawColor()) {
      BitWidth width = painter.getAttributeValue(StdAttr.WIDTH);
      g.setColor(Value.repeat(Value.FALSE, width.getWidth()).getColor());
    }
    g.drawLine(6, -8, 6, 8);
    g.drawLine(9, -5, 9, 5);
    g.drawLine(12, -2, 12, 2);

    g.dispose();
  }
Beispiel #7
0
  private void paintBase(InstancePainter painter) {
    Graphics g = painter.getGraphics();
    Direction facing = painter.getAttributeValue(StdAttr.FACING);
    Location loc = painter.getLocation();
    int x = loc.getX();
    int y = loc.getY();
    g.translate(x, y);
    double rotate = 0.0;
    if (facing != null && facing != Direction.EAST && g instanceof Graphics2D) {
      rotate = -facing.toRadians();
      ((Graphics2D) g).rotate(rotate);
    }

    Object shape = painter.getGateShape();
    if (shape == AppPreferences.SHAPE_RECTANGULAR) {
      paintRectangularBase(g, painter);
    } else if (shape == AppPreferences.SHAPE_DIN40700) {
      int width = painter.getAttributeValue(ATTR_SIZE) == SIZE_NARROW ? 20 : 30;
      PainterDin.paintAnd(painter, width, 18, true);
    } else {
      PainterShaped.paintNot(painter);
    }

    if (rotate != 0.0) {
      ((Graphics2D) g).rotate(-rotate);
    }
    g.translate(-x, -y);
  }
Beispiel #8
0
  private void updateMouse(Canvas canvas, int mx, int my, int mods) {
    if (active) {
      boolean shift = (mods & MouseEvent.SHIFT_DOWN_MASK) != 0;
      Location newEnd;
      if (shift) {
        newEnd = LineUtil.snapTo8Cardinals(mouseStart, mx, my);
      } else {
        newEnd = Location.create(mx, my);
      }

      if ((mods & InputEvent.CTRL_DOWN_MASK) != 0) {
        int x = newEnd.getX();
        int y = newEnd.getY();
        x = canvas.snapX(x);
        y = canvas.snapY(y);
        newEnd = Location.create(x, y);
      }

      if (!newEnd.equals(mouseEnd)) {
        mouseEnd = newEnd;
        repaintArea(canvas);
      }
    }
    lastMouseX = mx;
    lastMouseY = my;
  }
 public Bounds getOffsetBounds() {
   InstanceComponent c = comp;
   if (c == null) {
     return factory.getOffsetBounds(attrs);
   } else {
     Location loc = c.getLocation();
     return c.getBounds().translate(-loc.getX(), -loc.getY());
   }
 }
Beispiel #10
0
 @Override
 public void mouseReleased(Canvas canvas, Graphics g, MouseEvent e) {
   Project proj = canvas.getProject();
   if (state == MOVING) {
     setState(proj, IDLE);
     computeDxDy(proj, e, g);
     int dx = curDx;
     int dy = curDy;
     if (dx != 0 || dy != 0) {
       if (!proj.getLogisimFile().contains(canvas.getCircuit())) {
         canvas.setErrorMessage(Strings.getter("cannotModifyError"));
       } else if (proj.getSelection().hasConflictWhenMoved(dx, dy)) {
         canvas.setErrorMessage(Strings.getter("exclusiveError"));
       } else {
         boolean connect = shouldConnect(canvas, e.getModifiersEx());
         drawConnections = false;
         ReplacementMap repl;
         if (connect) {
           MoveGesture gesture = moveGesture;
           if (gesture == null) {
             gesture =
                 new MoveGesture(
                     new MoveRequestHandler(canvas),
                     canvas.getCircuit(),
                     canvas.getSelection().getAnchoredComponents());
           }
           canvas.setErrorMessage(new ComputingMessage(dx, dy), COLOR_COMPUTING);
           MoveResult result = gesture.forceRequest(dx, dy);
           clearCanvasMessage(canvas, dx, dy);
           repl = result.getReplacementMap();
         } else {
           repl = null;
         }
         Selection sel = proj.getSelection();
         proj.doAction(SelectionActions.translate(sel, dx, dy, repl));
       }
     }
     moveGesture = null;
     proj.repaintCanvas();
   } else if (state == RECT_SELECT) {
     Bounds bds = Bounds.create(start).add(start.getX() + curDx, start.getY() + curDy);
     Circuit circuit = canvas.getCircuit();
     Selection sel = proj.getSelection();
     Collection<Component> in_sel = sel.getComponentsWithin(bds, g);
     for (Component comp : circuit.getAllWithin(bds, g)) {
       if (!in_sel.contains(comp)) sel.add(comp);
     }
     Action act = SelectionActions.drop(sel, in_sel);
     if (act != null) {
       proj.doAction(act);
     }
     setState(proj, IDLE);
     proj.repaintCanvas();
   }
 }
Beispiel #11
0
 private Wire(Location e0, Location e1) {
   this.is_x_equal = e0.getX() == e1.getX();
   if (is_x_equal) {
     if (e0.getY() > e1.getY()) {
       this.e0 = e1;
       this.e1 = e0;
     } else {
       this.e0 = e0;
       this.e1 = e1;
     }
   } else {
     if (e0.getX() > e1.getX()) {
       this.e0 = e1;
       this.e1 = e0;
     } else {
       this.e0 = e0;
       this.e1 = e1;
     }
   }
 }
Beispiel #12
0
  private void computeDxDy(Project proj, MouseEvent e, Graphics g) {
    Bounds bds = proj.getSelection().getBounds(g);
    int dx;
    int dy;
    if (bds == Bounds.EMPTY_BOUNDS) {
      dx = e.getX() - start.getX();
      dy = e.getY() - start.getY();
    } else {
      dx = Math.max(e.getX() - start.getX(), -bds.getX());
      dy = Math.max(e.getY() - start.getY(), -bds.getY());
    }

    Selection sel = proj.getSelection();
    if (sel.shouldSnap()) {
      dx = Canvas.snapXToGrid(dx);
      dy = Canvas.snapYToGrid(dy);
    }
    curDx = dx;
    curDy = dy;
  }
Beispiel #13
0
  private void configurePorts(Instance instance) {
    Object size = instance.getAttributeValue(ATTR_SIZE);
    Direction facing = instance.getAttributeValue(StdAttr.FACING);
    int dx = size == SIZE_NARROW ? -20 : -30;

    Port[] ports = new Port[2];
    ports[0] = new Port(0, 0, Port.OUTPUT, StdAttr.WIDTH);
    Location out = Location.create(0, 0).translate(facing, dx);
    ports[1] = new Port(out.getX(), out.getY(), Port.INPUT, StdAttr.WIDTH);
    instance.setPorts(ports);
  }
Beispiel #14
0
 static Location snapTo4Cardinals(Location from, int mx, int my) {
   int px = from.getX();
   int py = from.getY();
   if (mx != px && my != py) {
     if (Math.abs(my - py) < Math.abs(mx - px)) {
       return Location.create(mx, py);
     } else {
       return Location.create(px, my);
     }
   }
   return Location.create(mx, my); // should never happen
 }
Beispiel #15
0
  void computePorts(Instance instance) {
    GateAttributes attrs = (GateAttributes) instance.getAttributeSet();
    int inputs = attrs.inputs;

    Port[] ports = new Port[inputs + 1];
    ports[0] = new Port(0, 0, Port.OUTPUT, StdAttr.WIDTH);
    for (int i = 0; i < inputs; i++) {
      Location offs = getInputOffset(attrs, i);
      ports[i + 1] = new Port(offs.getX(), offs.getY(), Port.INPUT, StdAttr.WIDTH);
    }
    instance.setPorts(ports);
  }
Beispiel #16
0
 @Override
 public void paintInstance(InstancePainter painter) {
   Location loc = painter.getLocation();
   int x = loc.getX();
   int y = loc.getY();
   Graphics g = painter.getGraphics();
   g.translate(x, y);
   Value pull = getPullValue(painter.getAttributeSet());
   Value actual = painter.getPort(0);
   paintBase(painter, pull, pull.getColor(), actual.getColor());
   g.translate(-x, -y);
   painter.drawPorts();
 }
Beispiel #17
0
 @Override
 public void mouseDragged(Canvas canvas, Graphics g, MouseEvent e) {
   if (state == MOVING) {
     Project proj = canvas.getProject();
     computeDxDy(proj, e, g);
     handleMoveDrag(canvas, curDx, curDy, e.getModifiersEx());
   } else if (state == RECT_SELECT) {
     Project proj = canvas.getProject();
     curDx = e.getX() - start.getX();
     curDy = e.getY() - start.getY();
     proj.repaintCanvas();
   }
 }
Beispiel #18
0
 @Override
 public boolean contains(Location loc, AttributeSet attrsBase) {
   GateAttributes attrs = (GateAttributes) attrsBase;
   if (super.contains(loc, attrs)) {
     if (attrs.negated == 0) {
       return true;
     } else {
       Direction facing = attrs.facing;
       Bounds bds = getOffsetBounds(attrsBase);
       int delt;
       if (facing == Direction.NORTH) {
         delt = loc.getY() - (bds.getY() + bds.getHeight());
       } else if (facing == Direction.SOUTH) {
         delt = loc.getY() - bds.getY();
       } else if (facing == Direction.WEST) {
         delt = loc.getX() - (bds.getX() + bds.getHeight());
       } else {
         delt = loc.getX() - bds.getX();
       }
       if (Math.abs(delt) > 5) {
         return true;
       } else {
         int inputs = attrs.inputs;
         for (int i = 1; i <= inputs; i++) {
           Location offs = getInputOffset(attrs, i);
           if (loc.manhattanDistanceTo(offs) <= 5) {
             return true;
           }
         }
         return false;
       }
     }
   } else {
     return false;
   }
 }
Beispiel #19
0
 @Override
 public void mousePressed(Canvas canvas, MouseEvent e) {
   int x = e.getX();
   int y = e.getY();
   int mods = e.getModifiersEx();
   if ((mods & InputEvent.CTRL_DOWN_MASK) != 0) {
     x = canvas.snapX(x);
     y = canvas.snapY(y);
   }
   Location loc = Location.create(x, y);
   mouseStart = loc;
   mouseEnd = loc;
   lastMouseX = loc.getX();
   lastMouseY = loc.getY();
   active = canvas.getModel() != null;
   repaintArea(canvas);
 }
Beispiel #20
0
 static void configureLabel(Instance instance, boolean isRectangular, Location control) {
   Object facing = instance.getAttributeValue(StdAttr.FACING);
   Bounds bds = instance.getBounds();
   int x;
   int y;
   int halign;
   if (facing == Direction.NORTH || facing == Direction.SOUTH) {
     x = bds.getX() + bds.getWidth() / 2 + 2;
     y = bds.getY() - 2;
     halign = TextField.H_LEFT;
   } else { // west or east
     y = isRectangular ? bds.getY() - 2 : bds.getY();
     if (control != null && control.getY() == bds.getY()) {
       // the control line will get in the way
       x = control.getX() + 2;
       halign = TextField.H_LEFT;
     } else {
       x = bds.getX() + bds.getWidth() / 2;
       halign = TextField.H_CENTER;
     }
   }
   instance.setTextField(StdAttr.LABEL, StdAttr.LABEL_FONT, x, y, halign, TextField.V_BASELINE);
 }
Beispiel #21
0
    @Override
    public boolean contains(Location loc, boolean assumeFilled) {
        Object type = getPaintType();
        if (assumeFilled && type == DrawAttr.PAINT_STROKE) {
            type = DrawAttr.PAINT_STROKE_FILL;
        }
        if (type != DrawAttr.PAINT_FILL) {
            int stroke = getStrokeWidth();
            double[] q = toArray(loc);
            double[] p0 = toArray(this.p0);
            double[] p1 = toArray(this.p1);
            double[] p2 = toArray(this.p2);
            double[] p = CurveUtil.findNearestPoint(q, p0, p1, p2);
            if (p == null) {
                return false;
            }


            int thr;
            if (type == DrawAttr.PAINT_STROKE) {
                thr = Math.max(Line.ON_LINE_THRESH, stroke / 2);
            } else {
                thr = stroke / 2;
            }
            if (LineUtil.distanceSquared(p[0], p[1], q[0], q[1]) < thr * thr) {
                return true;
            }
        }
        if (type != DrawAttr.PAINT_STROKE) {
            QuadCurve2D curve = getCurve(null);
            if (curve.contains(loc.getX(), loc.getY())) {
                return true;
            }
        }
        return false;
    }
Beispiel #22
0
 private static double[] toArray(Location loc) {
     return new double[] { loc.getX(), loc.getY() };
 }
Beispiel #23
0
 public Handle(CanvasObject object, Location loc) {
   this(object, loc.getX(), loc.getY());
 }
Beispiel #24
0
 public boolean isAt(Location loc) {
   return x == loc.getX() && y == loc.getY();
 }
Beispiel #25
0
 public int getLength() {
   return (e1.getY() - e0.getY()) + (e1.getX() - e0.getX());
 }
Beispiel #26
0
  private void paintBase(InstancePainter painter) {
    GateAttributes attrs = (GateAttributes) painter.getAttributeSet();
    Direction facing = attrs.facing;
    int inputs = attrs.inputs;
    int negated = attrs.negated;

    Object shape = painter.getGateShape();
    Location loc = painter.getLocation();
    Bounds bds = painter.getOffsetBounds();
    int width = bds.getWidth();
    int height = bds.getHeight();
    if (facing == Direction.NORTH || facing == Direction.SOUTH) {
      int t = width;
      width = height;
      height = t;
    }
    if (negated != 0) {
      width -= 10;
    }

    Graphics g = painter.getGraphics();
    Color baseColor = g.getColor();
    if (shape == AppPreferences.SHAPE_SHAPED && paintInputLines) {
      PainterShaped.paintInputLines(painter, this);
    } else if (negated != 0) {
      for (int i = 0; i < inputs; i++) {
        int negatedBit = (negated >> i) & 1;
        if (negatedBit == 1) {
          Location in = getInputOffset(attrs, i);
          Location cen = in.translate(facing, 5);
          painter.drawDongle(loc.getX() + cen.getX(), loc.getY() + cen.getY());
        }
      }
    }

    g.setColor(baseColor);
    g.translate(loc.getX(), loc.getY());
    double rotate = 0.0;
    if (facing != Direction.EAST && g instanceof Graphics2D) {
      rotate = -facing.toRadians();
      Graphics2D g2 = (Graphics2D) g;
      g2.rotate(rotate);
    }

    if (shape == AppPreferences.SHAPE_RECTANGULAR) {
      paintRectangular(painter, width, height);
    } else if (shape == AppPreferences.SHAPE_DIN40700) {
      paintDinShape(painter, width, height, inputs);
      // SHAPE_SHAPED
    } else {
      if (negateOutput) {
        g.translate(-10, 0);
        paintShape(painter, width - 10, height);
        painter.drawDongle(5, 0);
        g.translate(10, 0);
      } else {
        paintShape(painter, width, height);
      }
    }

    if (rotate != 0.0) {
      ((Graphics2D) g).rotate(-rotate);
    }
    g.translate(-loc.getX(), -loc.getY());

    painter.drawLabel();
  }
Beispiel #27
0
  @Override
  public void mousePressed(Canvas canvas, Graphics g, MouseEvent e) {
    Project proj = canvas.getProject();
    Circuit circ = canvas.getCircuit();

    if (!proj.getLogisimFile().contains(circ)) {
      if (caret != null) caret.cancelEditing();
      canvas.setErrorMessage(Strings.getter("cannotModifyError"));
      return;
    }

    // Maybe user is clicking within the current caret.
    if (caret != null) {
      if (caret.getBounds(g).contains(e.getX(), e.getY())) { // Yes
        caret.mousePressed(e);
        proj.repaintCanvas();
        return;
      } else { // No. End the current caret.
        caret.stopEditing();
      }
    }
    // caret will be null at this point

    // Otherwise search for a new caret.
    int x = e.getX();
    int y = e.getY();
    Location loc = Location.create(x, y);
    ComponentUserEvent event = new ComponentUserEvent(canvas, x, y);

    // First search in selection.
    for (Component comp : proj.getSelection().getComponentsContaining(loc, g)) {
      TextEditable editable = (TextEditable) comp.getFeature(TextEditable.class);
      if (editable != null) {
        caret = editable.getTextCaret(event);
        if (caret != null) {
          proj.getFrame().viewComponentAttributes(circ, comp);
          caretComponent = comp;
          caretCreatingText = false;
          break;
        }
      }
    }

    // Then search in circuit
    if (caret == null) {
      for (Component comp : circ.getAllContaining(loc, g)) {
        TextEditable editable = (TextEditable) comp.getFeature(TextEditable.class);
        if (editable != null) {
          caret = editable.getTextCaret(event);
          if (caret != null) {
            proj.getFrame().viewComponentAttributes(circ, comp);
            caretComponent = comp;
            caretCreatingText = false;
            break;
          }
        }
      }
    }

    // if nothing found, create a new label
    if (caret == null) {
      if (loc.getX() < 0 || loc.getY() < 0) return;
      AttributeSet copy = (AttributeSet) attrs.clone();
      caretComponent = Text.FACTORY.createComponent(loc, copy);
      caretCreatingText = true;
      TextEditable editable = (TextEditable) caretComponent.getFeature(TextEditable.class);
      if (editable != null) {
        caret = editable.getTextCaret(event);
        proj.getFrame().viewComponentAttributes(circ, caretComponent);
      }
    }

    if (caret != null) {
      caretCanvas = canvas;
      caretCircuit = canvas.getCircuit();
      caret.addCaretListener(listener);
      caretCircuit.addCircuitListener(listener);
    }
    proj.repaintCanvas();
  }
Beispiel #28
0
 private boolean overlaps(Location q0, Location q1, boolean includeEnds) {
   if (is_x_equal) {
     int x0 = q0.getX();
     if (x0 != q1.getX() || x0 != e0.getX()) return false;
     if (includeEnds) {
       return e1.getY() >= q0.getY() && e0.getY() <= q1.getY();
     } else {
       return e1.getY() > q0.getY() && e0.getY() < q1.getY();
     }
   } else {
     int y0 = q0.getY();
     if (y0 != q1.getY() || y0 != e0.getY()) return false;
     if (includeEnds) {
       return e1.getX() >= q0.getX() && e0.getX() <= q1.getX();
     } else {
       return e1.getX() > q0.getX() && e0.getX() < q1.getX();
     }
   }
 }
Beispiel #29
0
 public QuadCurve2D getCurve2D() {
     return new QuadCurve2D.Double(p0.getX(), p0.getY(),
             p1.getX(), p1.getY(), p2.getX(), p2.getY());
 }
Beispiel #30
0
  @Override
  public void draw(Canvas canvas, ComponentDrawContext context) {
    Project proj = canvas.getProject();
    int dx = curDx;
    int dy = curDy;
    if (state == MOVING) {
      proj.getSelection().drawGhostsShifted(context, dx, dy);

      MoveGesture gesture = moveGesture;
      if (gesture != null && drawConnections && (dx != 0 || dy != 0)) {
        MoveResult result = gesture.findResult(dx, dy);
        if (result != null) {
          Collection<Wire> wiresToAdd = result.getWiresToAdd();
          Graphics g = context.getGraphics();
          GraphicsUtil.switchToWidth(g, 3);
          g.setColor(Color.GRAY);
          for (Wire w : wiresToAdd) {
            Location loc0 = w.getEnd0();
            Location loc1 = w.getEnd1();
            g.drawLine(loc0.getX(), loc0.getY(), loc1.getX(), loc1.getY());
          }
          GraphicsUtil.switchToWidth(g, 1);
          g.setColor(COLOR_UNMATCHED);
          for (Location conn : result.getUnconnectedLocations()) {
            int connX = conn.getX();
            int connY = conn.getY();
            g.fillOval(connX - 3, connY - 3, 6, 6);
            g.fillOval(connX + dx - 3, connY + dy - 3, 6, 6);
          }
        }
      }
    } else if (state == RECT_SELECT) {
      int left = start.getX();
      int right = left + dx;
      if (left > right) {
        int i = left;
        left = right;
        right = i;
      }
      int top = start.getY();
      int bot = top + dy;
      if (top > bot) {
        int i = top;
        top = bot;
        bot = i;
      }

      Graphics gBase = context.getGraphics();
      int w = right - left - 1;
      int h = bot - top - 1;
      if (w > 2 && h > 2) {
        gBase.setColor(BACKGROUND_RECT_SELECT);
        gBase.fillRect(left + 1, top + 1, w - 1, h - 1);
      }

      Circuit circ = canvas.getCircuit();
      Bounds bds = Bounds.create(left, top, right - left, bot - top);
      for (Component c : circ.getAllWithin(bds)) {
        Location cloc = c.getLocation();
        Graphics gDup = gBase.create();
        context.setGraphics(gDup);
        c.getFactory()
            .drawGhost(context, COLOR_RECT_SELECT, cloc.getX(), cloc.getY(), c.getAttributeSet());
        gDup.dispose();
      }

      gBase.setColor(COLOR_RECT_SELECT);
      GraphicsUtil.switchToWidth(gBase, 2);
      if (w < 0) w = 0;
      if (h < 0) h = 0;
      gBase.drawRect(left, top, w, h);
    }
  }