Package com.cburch.draw.shapes

Source Code of com.cburch.draw.shapes.Rectangular

/* 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.Graphics;
import java.util.List;

import com.cburch.draw.model.CanvasObject;
import com.cburch.draw.model.Handle;
import com.cburch.draw.model.HandleGesture;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.util.UnmodifiableList;

abstract class Rectangular extends FillableCanvasObject {
  private Bounds bounds; // excluding the stroke's width
 
  public Rectangular(int x, int y, int w, int h) {
    bounds = Bounds.create(x, y, w, h);
  }
 
  @Override
  public boolean matches(CanvasObject other) {
    if (other instanceof Rectangular) {
      Rectangular that = (Rectangular) other;
      return this.bounds.equals(that.bounds)
        && super.matches(that);
    } else {
      return false;
    }
  }

  @Override
  public int matchesHashCode() {
    return bounds.hashCode() * 31 + super.matchesHashCode();
  }
 
  public int getX() {
    return bounds.getX();
  }
 
  public int getY() {
    return bounds.getY();
  }
 
  public int getWidth() {
    return bounds.getWidth();
  }
 
  public int getHeight() {
    return bounds.getHeight();
  }
 
  @Override
  public Bounds getBounds() {
    int wid = getStrokeWidth();
    Object type = getPaintType();
    if (wid < 2 || type == DrawAttr.PAINT_FILL) {
      return bounds;
    } else {
      return bounds.expand(wid / 2);
    }
  }
 
  @Override
  public void translate(int dx, int dy) {
    bounds = bounds.translate(dx, dy);
  }
 
  @Override
  public List<Handle> getHandles(HandleGesture gesture) {
    return UnmodifiableList.create(getHandleArray(gesture));
  }
   
  private Handle[] getHandleArray(HandleGesture gesture) {
    Bounds bds = bounds;
    int x0 = bds.getX();
    int y0 = bds.getY();
    int x1 = x0 + bds.getWidth();
    int y1 = y0 + bds.getHeight();
    if (gesture == null) {
      return new Handle[] { new Handle(this, x0, y0),
          new Handle(this, x1, y0), new Handle(this, x1, y1),
          new Handle(this, x0, y1) };
    } else {
      int hx = gesture.getHandle().getX();
      int hy = gesture.getHandle().getY();
      int dx = gesture.getDeltaX();
      int dy = gesture.getDeltaY();
      int newX0 = x0 == hx ? x0 + dx : x0;
      int newY0 = y0 == hy ? y0 + dy : y0;
      int newX1 = x1 == hx ? x1 + dx : x1;
      int newY1 = y1 == hy ? y1 + dy : y1;
      if (gesture.isShiftDown()) {
        if (gesture.isAltDown()) {
          if (x0 == hx) newX1 -= dx;
          if (x1 == hx) newX0 -= dx;
          if (y0 == hy) newY1 -= dy;
          if (y1 == hy) newY0 -= dy;

          int w = Math.abs(newX1 - newX0);
          int h = Math.abs(newY1 - newY0);
          if (w > h) { // reduce width to h
            int dw = (w - h) / 2;
            newX0 -= (newX0 > newX1 ? 1 : -1) * dw;
            newX1 -= (newX1 > newX0 ? 1 : -1) * dw;
          } else {
            int dh = (h - w) / 2;
            newY0 -= (newY0 > newY1 ? 1 : -1) * dh;
            newY1 -= (newY1 > newY0 ? 1 : -1) * dh;
          }
        } else {
          int w = Math.abs(newX1 - newX0);
          int h = Math.abs(newY1 - newY0);
          if (w > h) { // reduce width to h
            if (x0 == hx) {
              newX0 = newX1 + (newX0 > newX1 ? 1 : -1) * h;
            }
            if (x1 == hx) {
              newX1 = newX0 + (newX1 > newX0 ? 1 : -1) * h;
            }
          } else { // reduce height to w
            if (y0 == hy) {
              newY0 = newY1 + (newY0 > newY1 ? 1 : -1) * w;
            }
            if (y1 == hy) {
              newY1 = newY0 + (newY1 > newY0 ? 1 : -1) * w;
            }
          }
        }
      } else {
        if (gesture.isAltDown()) {
          if (x0 == hx) newX1 -= dx;
          if (x1 == hx) newX0 -= dx;
          if (y0 == hy) newY1 -= dy;
          if (y1 == hy) newY0 -= dy;
        } else {
          ; // already handled
        }
      }
      return new Handle[] { new Handle(this, newX0, newY0),
        new Handle(this, newX1, newY0), new Handle(this, newX1, newY1),
        new Handle(this, newX0, newY1) };
    }
  }
 
  @Override
  public boolean canMoveHandle(Handle handle) {
    return true;
  }

  @Override
  public Handle moveHandle(HandleGesture gesture) {
    Handle[] oldHandles = getHandleArray(null);
    Handle[] newHandles = getHandleArray(gesture);
    Handle moved = gesture == null ? null : gesture.getHandle();
    Handle result = null;
    int x0 = Integer.MAX_VALUE;
    int x1 = Integer.MIN_VALUE;
    int y0 = Integer.MAX_VALUE;
    int y1 = Integer.MIN_VALUE;
    int i = -1;
    for (Handle h : newHandles) {
      i++;
      if (oldHandles[i].equals(moved)) {
        result = h;
      }
      int hx = h.getX();
      int hy = h.getY();
      if (hx < x0) x0 = hx;
      if (hx > x1) x1 = hx;
      if (hy < y0) y0 = hy;
      if (hy > y1) y1 = hy;
    }
    bounds = Bounds.create(x0, y0, x1 - x0, y1 - y0);
    return result;
  }
 
  @Override
  public void paint(Graphics g, HandleGesture gesture) {
    if (gesture == null) {
      Bounds bds = bounds;
      draw(g, bds.getX(), bds.getY(), bds.getWidth(), bds.getHeight());
    } else {
      Handle[] handles = getHandleArray(gesture);
      Handle p0 = handles[0];
      Handle p1 = handles[2];
      int x0 = p0.getX();
      int y0 = p0.getY();
      int x1 = p1.getX();
      int y1 = p1.getY();
      if (x1 < x0) { int t = x0; x0 = x1; x1 = t; }
      if (y1 < y0) { int t = y0; y0 = y1; y1 = t; }
 
      draw(g, x0, y0, x1 - x0, y1 - y0);
    }
  }
 
  @Override
  public boolean contains(Location loc, boolean assumeFilled) {
    Object type = getPaintType();
    if (assumeFilled && type == DrawAttr.PAINT_STROKE) {
      type = DrawAttr.PAINT_STROKE_FILL;
    }
    Bounds b = bounds;
    int x = b.getX();
    int y = b.getY();
    int w = b.getWidth();
    int h = b.getHeight();
    int qx = loc.getX();
    int qy = loc.getY();
    if (type == DrawAttr.PAINT_FILL) {
      return isInRect(qx, qy, x, y, w, h) && contains(x, y, w, h, loc);
    } else if (type == DrawAttr.PAINT_STROKE) {
      int stroke = getStrokeWidth();
      int tol2 = Math.max(2 * Line.ON_LINE_THRESH, stroke);
      int tol = tol2 / 2;
      return isInRect(qx, qy, x - tol, y - tol, w + tol2, h + tol2)
          && contains(x - tol, y - tol, w + tol2, h + tol2, loc)
          && !contains(x + tol, y + tol, w - tol2, h - tol2, loc);
    } else if (type == DrawAttr.PAINT_STROKE_FILL) {
      int stroke = getStrokeWidth();
      int tol2 = stroke;
      int tol = tol2 / 2;
      return isInRect(qx, qy, x - tol, y - tol, w + tol2, h + tol2)
        && contains(x - tol, y - tol, w + tol2, h + tol2, loc);
    } else {
      return false;
    }
  }
 
  boolean isInRect(int qx, int qy, int x0, int y0, int w, int h) {
    return qx >= x0 && qx < x0 + w && qy >= y0 && qy < y0 + h;
  }
 
  protected abstract boolean contains(int x, int y, int w, int h, Location q);
  protected abstract void draw(Graphics g, int x, int y, int w, int h);
}
TOP

Related Classes of com.cburch.draw.shapes.Rectangular

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.