Package com.cburch.logisim.tools

Source Code of com.cburch.logisim.tools.WiringTool

/* 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.tools;

import java.awt.Cursor;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import javax.swing.Icon;

import com.cburch.logisim.circuit.CircuitMutation;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.gui.main.Canvas;
import com.cburch.logisim.prefs.AppPreferences;
import com.cburch.logisim.proj.Action;
import com.cburch.logisim.util.GraphicsUtil;
import com.cburch.logisim.util.Icons;
import com.cburch.logisim.util.StringGetter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;

public class WiringTool extends Tool {
  private static Cursor cursor
    = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
  private static final Icon toolIcon = Icons.getIcon("wiring.gif");
 
  private static final int HORIZONTAL = 1;
  private static final int VERTICAL = 2;

  private boolean exists = false;
  private boolean inCanvas = false;
  private Location start = Location.create(0, 0);
  private Location cur = Location.create(0, 0);
  private boolean hasDragged = false;
  private boolean startShortening = false;
  private Wire shortening = null;
  private Action lastAction = null;
  private int direction = 0;

  public WiringTool() {
    super.select(null);
  }
 
  @Override
  public void select(Canvas canvas) {
    super.select(canvas);
    lastAction = null;
    reset();
  }
 
  private void reset() {
    exists = false;
    inCanvas = false;
    start = Location.create(0, 0);
    cur = Location.create(0, 0);
    startShortening = false;
    shortening = null;
    direction = 0;
  }
 
  @Override
  public boolean equals(Object other) {
    return other instanceof WiringTool;
  }
 
  @Override
  public int hashCode() {
    return WiringTool.class.hashCode();
  }

  @Override
  public String getName() {
    return "Wiring Tool";
  }

  @Override
  public String getDisplayName() {
    return Strings.get("wiringTool");
  }

  @Override
  public String getDescription() {
    return Strings.get("wiringToolDesc");
  }
 
  private boolean computeMove(int newX, int newY) {
    if (cur.getX() == newX && cur.getY() == newY) return false;
    Location start = this.start;
    if (direction == 0) {
      if (newX != start.getX()) direction = HORIZONTAL;
      else if (newY != start.getY()) direction = VERTICAL;
    } else if (direction == HORIZONTAL && newX == start.getX()) {
      if (newY == start.getY()) direction = 0;
      else direction = VERTICAL;
    } else if (direction == VERTICAL && newY == start.getY()) {
      if (newX == start.getX()) direction = 0;
      else direction = HORIZONTAL;
    }
    return true;
  }
 
  @Override
  public Set<Component> getHiddenComponents(Canvas canvas) {
    Component shorten = willShorten(start, cur);
    if (shorten != null) {
      return Collections.singleton(shorten);
    } else {
      return null;
    }
  }

  @Override
  public void draw(Canvas canvas, ComponentDrawContext context) {
    Graphics g = context.getGraphics();
    if (exists) {
      Location e0 = start;
      Location e1 = cur;
      Wire shortenBefore = willShorten(start, cur);
      if (shortenBefore != null) {
        Wire shorten = getShortenResult(shortenBefore, start, cur);
        if (shorten == null) {
          return;
        } else {
          e0 = shorten.getEnd0();
          e1 = shorten.getEnd1();
        }
      }
      int x0 = e0.getX();
      int y0 = e0.getY();
      int x1 = e1.getX();
      int y1 = e1.getY();

      g.setColor(Color.BLACK);
      GraphicsUtil.switchToWidth(g, 3);
      if (direction == HORIZONTAL) {
        if (x0 != x1) g.drawLine(x0, y0, x1, y0);
        if (y0 != y1) g.drawLine(x1, y0, x1, y1);
      } else if (direction == VERTICAL) {
        if (y0 != y1) g.drawLine(x0, y0, x0, y1);
        if (x0 != x1) g.drawLine(x0, y1, x1, y1);
      }
    } else if (AppPreferences.ADD_SHOW_GHOSTS.getBoolean() && inCanvas) {
      g.setColor(Color.GRAY);
      g.fillOval(cur.getX() - 2, cur.getY() - 2, 5, 5);
    }
  }

  @Override
  public void mouseEntered(Canvas canvas, Graphics g,
      MouseEvent e) {
    inCanvas = true;
    canvas.getProject().repaintCanvas();
  }

  @Override
  public void mouseExited(Canvas canvas, Graphics g,
      MouseEvent e) {
    inCanvas = false;
    canvas.getProject().repaintCanvas();
  }

  @Override
  public void mouseMoved(Canvas canvas, Graphics g, MouseEvent e) {
    if (exists) {
      mouseDragged(canvas, g, e);
    } else {
      Canvas.snapToGrid(e);
      inCanvas = true;
      int curX = e.getX();
      int curY = e.getY();
      if (cur.getX() != curX || cur.getY() != curY) {
        cur = Location.create(curX, curY);
      }
      canvas.getProject().repaintCanvas();
    }
  }

  @Override
  public void mousePressed(Canvas canvas, Graphics g, MouseEvent e) {
    if (!canvas.getProject().getLogisimFile().contains(canvas.getCircuit())) {
      exists = false;
      canvas.setErrorMessage(Strings.getter("cannotModifyError"));
      return;
    }

    if (exists) {
      mouseDragged(canvas, g, e);
    } else {
      Canvas.snapToGrid(e);
      start = Location.create(e.getX(), e.getY());
      cur = start;
      exists = true;
      hasDragged = false;
     
      startShortening = !canvas.getCircuit().getWires(start).isEmpty();
      shortening = null;
 
      super.mousePressed(canvas, g, e);
      canvas.getProject().repaintCanvas();
    }
  }

  @Override
  public void mouseDragged(Canvas canvas, Graphics g, MouseEvent e) {
    if (exists) {
      Canvas.snapToGrid(e);
      int curX = e.getX();
      int curY = e.getY();
      if (!computeMove(curX, curY)) return;
      hasDragged = true;
 
      Rectangle rect = new Rectangle();
      rect.add(start.getX(), start.getY());
      rect.add(cur.getX(), cur.getY());
      rect.add(curX, curY);
      rect.grow(3, 3);
 
      cur = Location.create(curX, curY);
      super.mouseDragged(canvas, g, e);
     
      Wire shorten = null;
      if (startShortening) {
        for (Wire w : canvas.getCircuit().getWires(start)) {
          if (w.contains(cur)) { shorten = w; break; }
        }
      }
      if (shorten == null) {
        for (Wire w : canvas.getCircuit().getWires(cur)) {
          if (w.contains(start)) { shorten = w; break; }
        }
      }
      shortening = shorten;
 
      canvas.repaint(rect);
    }
  }
 
  void resetClick() {
    exists = false;
  }

  @Override
  public void mouseReleased(Canvas canvas, Graphics g, MouseEvent e) {
    if (!exists) return;

    Canvas.snapToGrid(e);
    int curX = e.getX();
    int curY = e.getY();
    if (computeMove(curX, curY)) {
      cur = Location.create(curX, curY);
    }
    if (hasDragged) {
      exists = false;
      super.mouseReleased(canvas, g, e);
 
      ArrayList<Wire> ws = new ArrayList<Wire>(2);
      if (cur.getY() == start.getY() || cur.getX() == start.getX()) {
        Wire w = Wire.create(cur, start);
        w = checkForRepairs(canvas, w, w.getEnd0());
        w = checkForRepairs(canvas, w, w.getEnd1());
        if (performShortening(canvas, start, cur)) {
          return;
        }
        if (w.getLength() > 0) ws.add(w);
      } else {
        Location m;
        if (direction == HORIZONTAL) {
          m = Location.create(cur.getX(), start.getY());
        } else {
          m = Location.create(start.getX(), cur.getY());
        }
        Wire w0 = Wire.create(start, m);
        Wire w1 = Wire.create(m, cur);
        w0 = checkForRepairs(canvas, w0, start);
        w1 = checkForRepairs(canvas, w1, cur);
        if (w0.getLength() > 0) ws.add(w0);
        if (w1.getLength() > 0) ws.add(w1);
      }
      if (ws.size() > 0) {
        CircuitMutation mutation = new CircuitMutation(canvas.getCircuit());
        mutation.addAll(ws);
        StringGetter desc;
        if (ws.size() == 1) desc = Strings.getter("addWireAction");
        else desc = Strings.getter("addWiresAction");
        Action act = mutation.toAction(desc);
        canvas.getProject().doAction(act);
        lastAction = act;
      }
    }
  }
 
  private Wire checkForRepairs(Canvas canvas, Wire w, Location end) {
    if (w.getLength() <= 10) return w; // don't repair a short wire to nothing
    if (!canvas.getCircuit().getNonWires(end).isEmpty()) return w;

    int delta = (end.equals(w.getEnd0()) ? 10 : -10);
    Location cand;
    if (w.isVertical()) {
      cand = Location.create(end.getX(), end.getY() + delta);
    } else {
      cand = Location.create(end.getX() + delta, end.getY());
    }

    for (Component comp : canvas.getCircuit().getNonWires(cand)) {
      if (comp.getBounds().contains(end)) {
        WireRepair repair = (WireRepair) comp.getFeature(WireRepair.class);
        if (repair != null && repair.shouldRepairWire(new WireRepairData(w, cand))) {
          w = Wire.create(w.getOtherEnd(end), cand);
          canvas.repaint(end.getX() - 13, end.getY() - 13, 26, 26);
          return w;
        }
      }
    }
    return w;
  }
 
  private Wire willShorten(Location drag0, Location drag1) {
    Wire shorten = shortening;
    if (shorten == null) {
      return null;
    } else if (shorten.endsAt(drag0) || shorten.endsAt(drag1)) {
      return shorten;
    } else {
      return null;
    }
  }
 
  private Wire getShortenResult(Wire shorten, Location drag0, Location drag1) {
    if (shorten == null) {
      return null;
    } else {
      Location e0;
      Location e1;
      if (shorten.endsAt(drag0)) {
        e0 = drag1;
        e1 = shorten.getOtherEnd(drag0);
      } else if (shorten.endsAt(drag1)) {
        e0 = drag0;
        e1 = shorten.getOtherEnd(drag1);
      } else {
        return null;
      }
      return e0.equals(e1) ? null : Wire.create(e0, e1);
    }
  }
 
  private boolean performShortening(Canvas canvas, Location drag0, Location drag1) {
    Wire shorten = willShorten(drag0, drag1);
    if (shorten == null) {
      return false;
    } else {
      CircuitMutation xn = new CircuitMutation(canvas.getCircuit());
      StringGetter actName;
      Wire result = getShortenResult(shorten, drag0, drag1);
      if (result == null) {
        xn.remove(shorten);
        actName = Strings.getter("removeComponentAction",
            shorten.getFactory().getDisplayGetter());
      } else {
        xn.replace(shorten, result);
        actName = Strings.getter("shortenWireAction");
      }
      canvas.getProject().doAction(xn.toAction(actName));
      return true;
    }
  }
 
  @Override
  public void keyPressed(Canvas canvas, KeyEvent event) {
    switch (event.getKeyCode()) {
    case KeyEvent.VK_BACK_SPACE:
      if (lastAction != null && canvas.getProject().getLastAction() == lastAction) {
        canvas.getProject().undoAction();
        lastAction = null;
      }
    }
  }

  @Override
  public void paintIcon(ComponentDrawContext c, int x, int y) {
    Graphics g = c.getGraphics();
    if (toolIcon != null) {
      toolIcon.paintIcon(c.getDestination(), g, x + 2, y + 2);
    } else {
      g.setColor(java.awt.Color.black);
      g.drawLine(x + 3, y + 13, x + 17, y + 7);
      g.fillOval(x + 1, y + 11, 5, 5);
      g.fillOval(x + 15, y + 5, 5, 5);
    }
  }

  @Override
  public Cursor getCursor() { return cursor; }
}
TOP

Related Classes of com.cburch.logisim.tools.WiringTool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.