Package com.cburch.draw.tools

Source Code of com.cburch.draw.tools.PolyTool

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

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Icon;

import com.cburch.draw.actions.ModelAddAction;
import com.cburch.draw.canvas.Canvas;
import com.cburch.draw.model.CanvasModel;
import com.cburch.draw.model.CanvasObject;
import com.cburch.draw.shapes.DrawAttr;
import com.cburch.draw.shapes.LineUtil;
import com.cburch.draw.shapes.Poly;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.util.Icons;

public class PolyTool extends AbstractTool {
  // how close we need to be to the start point to count as "closing the loop"
  private static final int CLOSE_TOLERANCE = 2;
 
  private boolean closed; // whether we are drawing polygons or polylines
  private DrawingAttributeSet attrs;
  private boolean active;
  private ArrayList<Location> locations;
  private boolean mouseDown;
  private int lastMouseX;
  private int lastMouseY;
 
  public PolyTool(boolean closed, DrawingAttributeSet attrs) {
    this.closed = closed;
    this.attrs = attrs;
    active = false;
    locations = new ArrayList<Location>();
  }
 
  @Override
  public Icon getIcon() {
    if (closed) {
      return Icons.getIcon("drawpoly.gif");
    } else {
      return Icons.getIcon("drawplin.gif");
    }
  }
 
  @Override
  public List<Attribute<?>> getAttributes() {
    return DrawAttr.getFillAttributes(attrs.getValue(DrawAttr.PAINT_TYPE));
  }

  @Override
  public Cursor getCursor(Canvas canvas) {
    return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
  }
 
  @Override
  public void toolDeselected(Canvas canvas) {
    CanvasObject add = commit(canvas);
    canvas.toolGestureComplete(this, add);
    repaintArea(canvas);
  }
 
  @Override
  public void mousePressed(Canvas canvas, MouseEvent e) {
    int mx = e.getX();
    int my = e.getY();
    lastMouseX = mx;
    lastMouseY = my;
    int mods = e.getModifiersEx();
    if ((mods & InputEvent.CTRL_DOWN_MASK) != 0) {
      mx = canvas.snapX(mx);
      my = canvas.snapY(my);
    }

    if (active && e.getClickCount() > 1) {
      CanvasObject add = commit(canvas);
      canvas.toolGestureComplete(this, add);
      return;
    }

    Location loc = Location.create(mx, my);
    ArrayList<Location> locs = locations;
    if (!active) { locs.clear(); locs.add(loc); }
    locs.add(loc);

    mouseDown = true;
    active = canvas.getModel() != null;
    repaintArea(canvas);
  }
 
  @Override
  public void mouseDragged(Canvas canvas, MouseEvent e) {
    updateMouse(canvas, e.getX(), e.getY(), e.getModifiersEx());
  }
 
  @Override
  public void mouseReleased(Canvas canvas, MouseEvent e) {
    if (active) {
      updateMouse(canvas, e.getX(), e.getY(), e.getModifiersEx());
      mouseDown = false;
      int size = locations.size();
      if (size >= 3) {
        Location first = locations.get(0);
        Location last = locations.get(size - 1);
        if (first.manhattanDistanceTo(last) <= CLOSE_TOLERANCE) {
          locations.remove(size - 1);
          CanvasObject add = commit(canvas);
          canvas.toolGestureComplete(this, add);
        }
      }
    }
  }
 
  @Override
  public void keyPressed(Canvas canvas, KeyEvent e) {
    int code = e.getKeyCode();
    if (active && mouseDown
        && (code == KeyEvent.VK_SHIFT || code == KeyEvent.VK_CONTROL)) {
      updateMouse(canvas, lastMouseX, lastMouseY, e.getModifiersEx());
    }
  }
 
  @Override
  public void keyReleased(Canvas canvas, KeyEvent e) {
    keyPressed(canvas, e);
  }

  @Override
  public void keyTyped(Canvas canvas, KeyEvent e) {
    if (active) {
      char ch = e.getKeyChar();
      if (ch == '\u001b') { // escape key
        active = false;
        locations.clear();
        repaintArea(canvas);
        canvas.toolGestureComplete(this, null);
      } else if (ch == '\n') { // enter key
        CanvasObject add = commit(canvas);
        canvas.toolGestureComplete(this, add);
      }
    }
  }
 
  private CanvasObject commit(Canvas canvas) {
    if (!active) return null;
    CanvasObject add = null;
    active = false;
    ArrayList<Location> locs = locations;
    for(int i = locs.size() - 2; i >= 0; i--) {
      if (locs.get(i).equals(locs.get(i + 1))) locs.remove(i);
    }
    if (locs.size() > 1) {
      CanvasModel model = canvas.getModel();
      add = new Poly(closed, locs);
      canvas.doAction(new ModelAddAction(model, add));
      repaintArea(canvas);
    }
    locs.clear();
    return add;
  }
 
  private void updateMouse(Canvas canvas, int mx, int my, int mods) {
    lastMouseX = mx;
    lastMouseY = my;
    if (active) {
      int index = locations.size() - 1;
      Location last = locations.get(index);
      Location newLast;
      if ((mods & MouseEvent.SHIFT_DOWN_MASK) != 0 && index > 0) {
        Location nextLast = locations.get(index - 1);
        newLast = LineUtil.snapTo8Cardinals(nextLast, mx, my);
      } else {
        newLast = Location.create(mx, my);
      }
      if ((mods & MouseEvent.CTRL_DOWN_MASK) != 0) {
        int lastX = newLast.getX();
        int lastY = newLast.getY();
        lastX = canvas.snapX(lastX);
        lastY = canvas.snapY(lastY);
        newLast = Location.create(lastX, lastY);
      }
     
      if (!newLast.equals(last)) {
        locations.set(index, newLast);
        repaintArea(canvas);
      }
    }
  }

  private void repaintArea(Canvas canvas) {
    canvas.repaint();
  }
 
  @Override
  public void draw(Canvas canvas, Graphics g) {
    if (active) {
      g.setColor(Color.GRAY);
      int size = locations.size();
      int[] xs = new int[size];
      int[] ys = new int[size];
      for(int i = 0; i < size; i++) {
        Location loc = locations.get(i);
        xs[i] = loc.getX();
        ys[i] = loc.getY();
      }
      g.drawPolyline(xs, ys, size);
      int lastX = xs[xs.length - 1];
      int lastY = ys[ys.length - 1];
      g.fillOval(lastX - 2, lastY - 2, 4, 4);
    }
  }
}
TOP

Related Classes of com.cburch.draw.tools.PolyTool

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.