/* * Copyright (c) 2014 tabletoptool.com team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * rptools.com team - initial implementation * tabletoptool.com team - further development */ package com.t3.model.drawing; import java.awt.AlphaComposite; import java.awt.Composite; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Line2D; import com.t3.model.Zone; import com.t3.model.ZonePoint; import com.t3.util.guidreference.NullHelper; import com.t3.util.guidreference.ZoneReference; import com.t3.xstreamversioned.version.SerializationVersion; /** * Base class for the radius, line, and cone templates. * * @author jgorrell * @version $Revision: 5945 $ $Date: 2013-06-02 21:05:50 +0200 (Sun, 02 Jun 2013) $ $Author: azhrei_fje $ */ @SerializationVersion(0) public abstract class AbstractTemplate extends AbstractDrawing { /*--------------------------------------------------------------------------------------------- * Instance Variables *-------------------------------------------------------------------------------------------*/ /** * The current width of this template in squares. */ private int radius; /** * The location of the vertex where painting starts. */ private ZonePoint vertex = new ZonePoint(0, 0); /** * The zone where this drawable is painted. */ private ZoneReference zone; /*--------------------------------------------------------------------------------------------- * Class Variables *-------------------------------------------------------------------------------------------*/ /** * Maximum radius value allowed. */ public static final int MAX_RADIUS = 30; /** * Minimum radius value allowed. */ public static final int MIN_RADIUS = 1; /** * Extra padding added to insure the wide lines do not get clipped. */ public static final int BOUNDS_PADDING = 10; /** * The alpha forced on all background fills. */ public static final float DEFAULT_BG_ALPHA = 0.20f; /** * The directions that can be drawn. All is for a radius and the other values are for cones. */ @SerializationVersion(0) public static enum Direction { /** Draw a Radius */ ALL, // Draw a cone in the indicated direction. Order is important! /** Draw a cone directly to the west (left) of the selection point. */ WEST, /** Draw a cone directly to the north west (upper left quadrant) of the selection point. */ NORTH_WEST, /** Draw a cone directly to the north (up) of the selection point. */ NORTH, /** Draw a cone directly to the north east (upper right quadrant) of the selection point. */ NORTH_EAST, /** Draw a cone directly to the east (right) of the selection point. */ EAST, /** Draw a cone directly to the south east (lower right quadrant) of the selection point. */ SOUTH_EAST, /** Draw a cone directly to the south (down) of the selection point. */ SOUTH, /** Draw a cone directly to the south west (lower left quadrant) of the selection point. */ SOUTH_WEST; /** * Find the direction to draw a cone from two points. The first point would be the mouse location and the second * would be the vertex of the cone. * * @param x1 * Mouse X coordinate. * @param y1 * Mouse Y coordinate. * @param x2 * Vertex X coordinate. * @param y2 * Vertex Y coordinate. * @return The direction from the vertex (point 2) to the mouse (point 1). */ public static Direction findDirection(int x1, int y1, int x2, int y2) { double dX = x1 - x2; double dY = y1 - y2; double angle = Math.atan2(dY, dX); int value = (int) Math.floor(((angle / Math.PI + 1.0) / 2.0) * 16.0); if (value >= 15) value = 0; return values()[((value + 1) / 2) + 1]; } } /** * The quadrants for drawing. */ @SerializationVersion(0) public static enum Quadrant { /** Draw in the north east (upper right) quadrant. */ NORTH_EAST, /** Draw in the north west (upper left) quadrant. */ NORTH_WEST, /** Draw in the south east (lower right) quadrant. */ SOUTH_EAST, /** Draw in the south west (lower left) quadrant. */ SOUTH_WEST } /*--------------------------------------------------------------------------------------------- * Instance Methods *-------------------------------------------------------------------------------------------*/ /** * Set the radius of the template in squares. * * @param squares * The number of squares in the radius for this template. */ public void setRadius(int squares) { if (squares > MAX_RADIUS) squares = MAX_RADIUS; radius = squares; } /** * Get the radius for this RadiusTemplate. * * @return Returns the current value of radius in squares. */ public int getRadius() { return radius; } /** * Get the vertex for this RadiusTemplate. * * @return Returns the current value of vertex. */ public ZonePoint getVertex() { return vertex; } /** * Set the value of vertex for this RadiusTemplate. * * @param vertex * The vertex to set. */ public void setVertex(ZonePoint vertex) { this.vertex = vertex; } /** * Get the zoneId for this RadiusTemplate. * * @return Returns the current value of zone. */ public ZoneReference getZoneReference() { return zone; } /** * Set the value of zone for this RadiusTemplate. * * @param zone * The zone to set or null. */ public void setZone(Zone zone) { this.zone = NullHelper.referenceZone(zone); } /** * Paint the border or area of the template * * @param g * Where to paint * @param border * Paint the border? * @param area * Paint the area? */ protected void paint(Graphics2D g, boolean border, boolean area) { if (radius == 0 || zone==null) return; // Find the proper distance int gridSize = zone.value().getGrid().getSize(); for (int y = 0; y < radius; y++) { for (int x = 0; x < radius; x++) { // Get the offset to the corner of the square int xOff = x * gridSize; int yOff = y * gridSize; // Template specific painting if (border) paintBorder(g, x, y, xOff, yOff, gridSize, getDistance(x, y)); if (area) paintArea(g, x, y, xOff, yOff, gridSize, getDistance(x, y)); } // endfor } // endfor } /** * Paint the close horizontal line of a cell's border. All directions are relevant to the vertex. * * @param g * The painter. * @param xOff * X Offset to cell from vertex in screen coordinates. * @param yOff * Y Offset to cell from vertex in screen coordinates. * @param gridSize * Size of a cell in screen coordinates. * @param q * The quadrant the cell is in relative to the vertex. */ protected void paintCloseHorizontalBorder(Graphics2D g, int xOff, int yOff, int gridSize, Quadrant q) { int x = vertex.x + getXMult(q) * xOff; int y = vertex.y + getYMult(q) * yOff; Line2D l = new Line2D.Double(x, y, x + getXMult(q) * gridSize, y); g.draw(l); } /** * Paint the close vertical line of a cell's border. All directions are relevant to the vertex. * * @param g * The painter. * @param xOff * X Offset to cell from vertex in screen coordinates. * @param yOff * Y Offset to cell from vertex in screen coordinates. * @param gridSize * Size of a cell in screen coordinates. * @param q * The quadrant the cell is in relative to the vertex. */ protected void paintCloseVerticalBorder(Graphics2D g, int xOff, int yOff, int gridSize, Quadrant q) { int x = vertex.x + getXMult(q) * xOff; int y = vertex.y + getYMult(q) * yOff; Line2D l = new Line2D.Double(x, y, x, y + getYMult(q) * gridSize); g.draw(l); } /** * Fill the area of a cell. * * @param g * The painter. * @param xOff * X Offset to cell from vertex in screen coordinates. * @param yOff * Y Offset to cell from vertex in screen coordinates. * @param gridSize * Size of a cell in screen coordinates. * @param q * The quadrant the cell is in relative to the vertex. */ protected void paintArea(Graphics2D g, int xOff, int yOff, int gridSize, Quadrant q) { int x = vertex.x + getXMult(q) * xOff + ((getXMult(q) - 1) / 2) * gridSize; int y = vertex.y + getYMult(q) * yOff + ((getYMult(q) - 1) / 2) * gridSize; g.fill(new Rectangle(x, y, gridSize, gridSize)); } /** * Paint the far horizontal line of a cell's border. All directions are relevant to the vertex. * * @param g * The painter. * @param xOff * X Offset to cell from vertex in screen coordinates. * @param yOff * Y Offset to cell from vertex in screen coordinates. * @param gridSize * Size of a cell in screen coordinates. * @param q * The quadrant the cell is in relative to the vertex. */ protected void paintFarHorizontalBorder(Graphics2D g, int xOff, int yOff, int gridSize, Quadrant q) { int x = vertex.x + getXMult(q) * xOff; int y = vertex.y + getYMult(q) * yOff + getYMult(q) * gridSize; Line2D l = new Line2D.Double(x, y, x + getXMult(q) * gridSize, y); g.draw(l); } /** * Paint the far vertical line of a cell's border. All directions are relevant to the vertex. * * @param g * The painter. * @param xOff * X Offset to cell from vertex in screen coordinates. * @param yOff * Y Offset to cell from vertex in screen coordinates. * @param gridSize * Size of a cell in screen coordinates. * @param q * The quadrant the cell is in relative to the vertex. */ protected void paintFarVerticalBorder(Graphics2D g, int xOff, int yOff, int gridSize, Quadrant q) { int x = vertex.x + getXMult(q) * xOff + getXMult(q) * gridSize; int y = vertex.y + getYMult(q) * yOff; Line2D l = new Line2D.Double(x, y, x, y + getYMult(q) * gridSize); g.draw(l); } /** * Get the multiplier in the X direction. * * @param q * Quadrant being accessed * @return -1 for west and +1 for east */ protected int getXMult(Quadrant q) { return ((q == Quadrant.NORTH_WEST || q == Quadrant.SOUTH_WEST) ? -1 : +1); } /** * Get the multiplier in the X direction. * * @param q * Quadrant being accessed * @return -1 for north and +1 for south */ protected int getYMult(Quadrant q) { return ((q == Quadrant.NORTH_WEST || q == Quadrant.NORTH_EAST) ? -1 : +1); } /** * Get the distance to a specific coordinate. * * @param x * delta-X of the coordinate. * @param y * delta-Y of the coordinate. * @return Number of cells to the passed coordinate. */ public int getDistance(int x, int y) { if (x > y) return x + (y / 2) + 1 + (y & 1); return y + (x / 2) + 1 + (x & 1); } /*--------------------------------------------------------------------------------------------- * Overridden AbstractDrawing Methods *-------------------------------------------------------------------------------------------*/ /** * @see com.t3.model.drawing.AbstractDrawing#draw(java.awt.Graphics2D) */ @Override protected void draw(Graphics2D g) { paint(g, true, false); } /** * @see com.t3.model.drawing.AbstractDrawing#drawBackground(java.awt.Graphics2D) */ @Override protected void drawBackground(Graphics2D g) { // Adjust alpha automatically Composite old = g.getComposite(); if (old != AlphaComposite.Clear) g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, DEFAULT_BG_ALPHA)); paint(g, false, true); g.setComposite(old); } /*--------------------------------------------------------------------------------------------- * Abstract Methods *-------------------------------------------------------------------------------------------*/ /** * Paint the border of the template. Note that all coordinates are for the south east quadrant, just change the * signs of the x/y and xOff/yOff offsets to get to the other quadrants. * * @param g * Where to paint * @param x * Distance from vertex along X axis in cell coordinates. * @param y * Distance from vertex along Y axis in cell coordinates. * @param xOff * Distance from vertex along X axis in screen coordinates. * @param yOff * Distance from vertex along Y axis in screen coordinates. * @param gridSize * The size of one side of the grid in screen coordinates. * @param distance * The distance in cells from the vertex to the cell which is offset from the vertex by <code>x</code> & * <code>y</code>. */ protected abstract void paintBorder(Graphics2D g, int x, int y, int xOff, int yOff, int gridSize, int distance); /** * Paint the border of the template. Note that all coordinates are for the south east quadrant, just change the * signs of the x/y and xOff/yOff offsets to get to the other quadrants. * * @param g * Where to paint * @param x * Distance from vertex along X axis in cell coordinates. * @param y * Distance from vertex along Y axis in cell coordinates. * @param xOff * Distance from vertex along X axis in screen coordinates. * @param yOff * Distance from vertex along Y axis in screen coordinates. * @param gridSize * The size of one side of the grid in screen coordinates. * @param distance * The distance in cells from the vertex to the cell which is offset from the vertex by <code>x</code> & * <code>y</code>. */ protected abstract void paintArea(Graphics2D g, int x, int y, int xOff, int yOff, int gridSize, int distance); }