Java source code of 'jhplot.jadraw.JaBox'

/*

 * Title: japlot.jaxodraw
 * Description: Graphical user interface for drawing Feynman diagrams
 * @author Daniele Binosi 
 * @author Lukas Theussl  

 Copyright (C) 2003-2006,  Daniele Binosi and Lukas Theussl

 See the file LICENSE in the source distribution home directory
 for a full copy of the GPL (GNU General Public License).

    This file is part of japlot.jaxodraw.

    japlot.jaxodraw is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    japlot.jaxodraw is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 */
package jhplot.jadraw;

import japlot.jaxodraw.JaxoBoxOptionsPanel;
import japlot.jaxodraw.JaxoColor;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.BasicStroke;
import java.awt.Composite;
import java.awt.Dimension;
import org.freehep.graphics2d.VectorGraphics;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

/** A box object. */
public class JaBox extends JaFillObject {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private float transp;
	private boolean fill;

	/**
	 * Constructor: sets the width, height, getRelw() and getRelh() to a default
	 * value of 25.
	 */
	public JaBox() {
		setColor(Color.black);
		setFillColor(Color.white);
		setRelw(INIT_SIZE);
		setRelh(INIT_SIZE);
		transp = 1.0f;
		fill = true;
	}

	/**
	 * Build a box.
	 * 
	 * @param x1
	 *            starting x
	 * @param y1
	 *            starting y
	 * @param x2
	 *            end of x
	 * @param y2
	 *            end of y
	 * @param what
	 *            if "NDC", coordinate in NDC (from 0 to 1), if "USER"
	 *            coordinates are in the user system given by the axes.
	 */
	public JaBox(double x1, double y1, double x2, double y2, String what) {

		setColor(Color.black);
		setFillColor(Color.white);

		transp = 1.0f;
		fill = true;

		setLocation(x1, y1, what);
		setRelWH(x2, y2, what);

	}

	/**
	 * Get coordinates of the box
	 * 
	 * @param x
	 * @param y
	 * @param relw
	 * @param relh
	 * @return
	 */
	public int[] getXYCoord(int x, int y, int relw, int relh) {

		int[] co = new int[4];

		if (((relw > 0) && (relh >= 0)) || ((relw < 0) && (relh <= 0))) {
			co[0] = x;
			co[1] = y;
			co[2] = x + Math.abs(relw);
			co[3] = y + Math.abs(relh);
		}

		if (((relw >= 0) && (relh < 0)) || ((relw <= 0) && (relh > 0))) {
			co[0] = x;
			co[1] = y + Math.abs(relh);
			co[2] = x + Math.abs(relw);
			co[3] = y;
		}

		return co;
	}

	/**
	 * Set box location in pixel coordinates
	 * 
	 * @param xin
	 *            min x
	 * @param yin
	 *            max x
	 * @param xfin
	 *            min y
	 * @param yfin
	 *            max y
	 */

	public void setLocationXY(int xin, int yin, int xfin, int yfin) {

		int newWidth = Math.abs(xfin - xin);
		int newHeight = Math.abs(yfin - yin);
		int newRelWidth = xfin - xin;
		int newRelHeight = yfin - yin;
		int newXin = xin;
		int newYin = yin;

		if ((newRelWidth > 0) && (newRelHeight >= 0)) {
			newXin = xin;
			newYin = yin;
		}

		if ((newRelWidth < 0) && (newRelHeight <= 0)) {
			newXin = xfin;
			newYin = yfin;
		}

		if ((newRelWidth >= 0) && (newRelHeight < 0)) {
			newXin = xin;
			newYin = yin + newRelHeight;
		}

		if ((newRelWidth <= 0) && (newRelHeight > 0)) {
			newXin = xin + newRelWidth;
			newYin = yin;
		}

		setRelWAndH(newWidth, newHeight);
		setLocation(newXin, newYin);

	}

	/**
	 * Fill or not the object
	 * 
	 * @param fill
	 *            true is filled
	 */
	public void setFilled(boolean fill) {
		this.fill = fill;
	}

	/**
	 * Get the filled style
	 * 
	 * @return
	 */

	public boolean isFilled() {
		return fill;
	}

	/**
	 * Set transparency of this object
	 * 
	 * @param transp
	 *            transparency from 0 to 1
	 */
	public void setTransparency(float transp) {
		this.transp = transp;
	}

	/**
	 * Get the transparency of it
	 * 
	 * @return transparency
	 */
	public float getTransparency() {
		return transp;
	}

	/**
	 * Returns an exact copy of this Label.
	 * 
	 * @return A copy of this Label.
	 */
	public final JaObject copy() {
		JaBox temp = new JaBox();
		temp.setX(getX());
		temp.setY(getY());
		temp.setColor(getColor());
		temp.setFilled(isFilled());
		temp.setTransparency(getTransparency());
		temp.setFillColor(getFillColor());
		temp.setStroke(getStroke());
		temp.setSize(getWidth(), getHeight(), getRelw(), getRelh());
		temp.setBoundingBox(getBoundingBox());

		return temp;
	}

	/**
	 * Returns true if all serializable variables of this JaObject and those of
	 * the specified one are equal.
	 * 
	 * @param comp
	 *            A JaObject to compare with.
	 * @return True if the objects are equal, false otherwise.
	 */
	public final boolean isCopy(JaObject comp) {
		boolean isCopy = false;

		if (comp instanceof JaBox) {
			JaBox temp = (JaBox) comp;
			if ((temp.getX() == getX()) && (temp.getY() == getY())
					&& (temp.getColor().equals(getColor()))
					&& (temp.getFillColor().equals(getFillColor()))
					&& (temp.getStroke() == getStroke())
					&& (temp.getRelw() == getRelw())
					&& (temp.isFilled() == isFilled())
					&& (temp.getRelh() == getRelh())) {
				isCopy = true;
			}
		}

		return isCopy;

	}

	/**
	 * Determines where on this JaObject a mouse click has ocurred.
	 * 
	 * @param clickX
	 *            The x position of the point where the mouse click ocurred.
	 * @param clickY
	 *            The y position of the point where the mouse click ocurred.
	 * @param editmode
	 *            The current edit mode as defined in JaxoMainPanel.
	 * @return An integer specifying whether the click ocurred on one of the
	 *         handles and if yes, on which.
	 */
	public final int getGrabbedHandle(int clickX, int clickY, int editmode) {
		if ((editmode == MOVE) || (editmode == COPY)) {
			if ((clickX >= (getX() + getWidth()))
					&& (clickX <= (getX() + getWidth() + LENGTH))
					&& (clickY >= (getY() + getHeight()))
					&& (clickY <= (getY() + getHeight() + LENGTH))) {
				return SELECT_BODY;
			}

			if ((clickX >= (getX() - LENGTH)) && (clickX <= getX())
					&& (clickY >= (getY() + getHeight()))
					&& (clickY <= (getY() + getHeight() + LENGTH))) {
				return SELECT_BODY;
			}

			if ((clickX >= (getX() + getWidth()))
					&& (clickX <= (getX() + getWidth() + LENGTH))
					&& (clickY >= (getY() - LENGTH)) && (clickY <= getY())) {
				return SELECT_BODY;
			}

			if ((clickX >= (getX() - LENGTH)) && (clickX <= getX())
					&& (clickY >= (getY() - LENGTH)) && (clickY <= getY())) {
				return SELECT_BODY;
			}

			return SELECT_NONE;
		}

		if (editmode == RESIZE) {
			if ((clickX >= (getX() + getWidth()))
					&& (clickX <= (getX() + getWidth() + LENGTH))
					&& (clickY >= (getY() + getHeight()))
					&& (clickY <= (getY() + getHeight() + LENGTH))) {
				return SELECT_LR;
			}

			if ((clickX >= (getX() - LENGTH)) && (clickX <= getX())
					&& (clickY >= (getY() + getHeight()))
					&& (clickY <= (getY() + getHeight() + LENGTH))) {
				return SELECT_LL;
			}

			if ((clickX >= (getX() + getWidth()))
					&& (clickX <= (getX() + getWidth() + LENGTH))
					&& (clickY >= (getY() - LENGTH)) && (clickY <= getY())) {
				return SELECT_UR;
			}

			if ((clickX >= (getX() - LENGTH)) && (clickX <= getX())
					&& (clickY >= (getY() - LENGTH)) && (clickY <= getY())) {
				return SELECT_UL;
			}

			return SELECT_NONE;
		}

		return SELECT_NONE;
	}

	/**
	 * Draws the handles of this box object.
	 * 
	 * @param g2
	 *            The current graphics context.
	 */
	public final void drawHandles(VectorGraphics g2) {
		g2.setColor(JaxoColor.RED);
		g2.setStroke(new BasicStroke(1.0f));

		int x = getX();
		int y = getY();
		int width = getWidth();
		int height = getHeight();

		g2.drawRect(x - LENGTH, y - LENGTH, LENGTH, LENGTH);
		g2.drawRect(x - LENGTH, y + height, LENGTH, LENGTH);
		g2.drawRect(x + width, y - LENGTH, LENGTH, LENGTH);
		g2.drawRect(x + width, y + height, LENGTH, LENGTH);

		if (this.isMarked()) {
			g2.setColor(JaxoColor.GRAYSCALE150);
			g2.fillRect(x - LENGTH + 1, y - LENGTH + 1, LENGTH - 1, LENGTH - 1);
			g2.fillRect(x - LENGTH + 1, y + height + 1, LENGTH - 1, LENGTH - 1);
			g2.fillRect(x + width + 1, y - LENGTH + 1, LENGTH - 1, LENGTH - 1);
			g2.fillRect(x + width + 1, y + height + 1, LENGTH - 1, LENGTH - 1);
		}
	}

	/**
	 * The method that draws this Label.
	 * 
	 * @param g2
	 *            The graphics context where the Label has to be drawn.
	 * @param drawToScreen
	 *            A boolean variable that indicates whether the drawing is done
	 *            on the screen or somewhere else. This is used for
	 *            exporting/printing, where the object handles should not be
	 *            painted, even if they are visible on the screen.
	 */
	public final void jaxoDraw(VectorGraphics g2, boolean drawToScreen) {
		GeneralPath gp = getGeneralPath();
		gp.reset();

		Rectangle2D box = new Rectangle2D.Float();
		box.setFrame(getX(), getY(), getWidth(), getHeight());
		gp.append(box, false);
		g2.setColor(getFillColor());
		g2.setStroke(new BasicStroke(1.0f));

		Composite cold = g2.getComposite();
		Composite c = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
				transp);
		g2.setComposite(c);

		if (isFilled())
			g2.fill(gp);
		gp.reset();
		gp.append(box, false);
		g2.setColor(getColor());
		g2.setStroke(new BasicStroke(getStroke()));
		g2.draw(gp);

		Rectangle2D bb = gp.getBounds2D();
		double[] bbox = { bb.getMinX(), bb.getMinY(), bb.getMaxX(),
				bb.getMaxY() };
		setBoundingBox(bbox);

		g2.setComposite(cold);
	}

	/**
	 * The LaTeX command that is necessary to draw the given Label using the
	 * axodraw.sty package.
	 * 
	 * @param scale
	 *            A scale factor to translate Java coordinates to LaTeX
	 *            coordinates.
	 * @param canvasDim
	 *            The current dimension of the canvas.
	 * @return The corresponding axodraw LaTeX command.
	 */
	public final String latexCommand(float scale, Dimension canvasDim) {
		int canvasHeight = canvasDim.height;

		Point2D lowerCorner = getLaTexLowerCorner(scale, canvasHeight);
		Point2D upperCorner = getLaTexUpperCorner(scale, canvasHeight);

		String command = "";

		if (((int) lowerCorner.getX() == (int) upperCorner.getX())
				&& ((int) lowerCorner.getY() == (int) upperCorner.getY())) {
			command = "%";
		} else {
			if (JaxoColor.isGrayScale(getFillColor())) {
				String grayScale = JaxoColor.getGreyScale(getFillColor());

				command = "\\GBox" + "(" + D_FORMAT.format(lowerCorner.getX())
						+ "," + D_FORMAT.format(lowerCorner.getY()) + ")" + "("
						+ D_FORMAT.format(upperCorner.getX()) + ","
						+ D_FORMAT.format(upperCorner.getY()) + ")" + "{"
						+ grayScale + "}";
			} else {
				String tlc = JaxoColor.getColorName(getColor());
				String tfc = JaxoColor.getColorName(getFillColor());

				command = "\\CBox" + "(" + D_FORMAT.format(lowerCorner.getX())
						+ "," + D_FORMAT.format(lowerCorner.getY()) + ")" + "("
						+ D_FORMAT.format(upperCorner.getX()) + ","
						+ D_FORMAT.format(upperCorner.getY()) + ")" + "{" + tlc
						+ "}" + "{" + tfc + "}";
			}
		}

		return command;
	}

	/**
	 * Rescales this Label by the scale factor scale, keeping the point (orx,
	 * ory) fixed.
	 * 
	 * @param orx
	 *            The x - coordinate of the fixed point
	 * @param ory
	 *            The y - coordinate of the fixed point
	 * @param scale
	 *            The scale parameter
	 */
	public final void rescaleObject(int orx, int ory, float scale) {
		// int oldWidth = this.getSize().width;
		// int oldHeight = this.getSize().height;
		// int newWidth = (int) Math.round(oldWidth * scale);
		// int newHeight = (int) Math.round(oldHeight * scale);
		int newRelWidth = (int) Math.round(this.getRelSize().width * scale);
		int newRelHeight = (int) Math.round(this.getRelSize().height * scale);

		Point2D newP = this.scalePoint(orx, ory, scale, this.getX(), this
				.getY());

		this.setX((int) Math.round(newP.getX()));
		this.setY((int) Math.round(newP.getY()));

		// this.setWAndH(newWidth, newHeight);
		this.setRelWAndH(newRelWidth, newRelHeight);
	}

	// ///////////////////////////////////////////////////////////////////////
	//
	// private auxiliary methods //
	//
	// ///////////////////////////////////////////////////////////////////////
	private Point2D getLaTexLowerCorner(float scaleFactor, int canvasHeight) {
		Point2D lowerCornerVec = new Point2D.Float();
		float x1;
		float y1;

		x1 = getX();
		y1 = getY() + getHeight();

		lowerCornerVec.setLocation(x1 / scaleFactor, (canvasHeight - y1)
				/ scaleFactor);

		return lowerCornerVec;
	}

	private Point2D getLaTexUpperCorner(float scaleFactor, int canvasHeight) {
		Point2D upperCornerVec = new Point2D.Float();
		float x1;
		float y1;

		x1 = getX() + getWidth();
		y1 = getY();

		upperCornerVec.setLocation(x1 / scaleFactor, (canvasHeight - y1)
				/ scaleFactor);

		return upperCornerVec;
	}

	/**
	 * Brings up the edit panel that allows to change the parameters of this
	 * object.
	 * 
	 * @return True if the editing actually changed the object, false if the
	 *         object has not been changed.
	 */
	public final boolean editPanel() {
		JaxoBoxOptionsPanel boxop = new JaxoBoxOptionsPanel(this);

		return boxop.hasChanged();
	}
}