/*

 * 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.JaxoColor;
import japlot.jaxodraw.JaxoLoopOptionsPanel;

import java.awt.BasicStroke;
import java.awt.Color;
import org.freehep.graphics2d.VectorGraphics;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;


import japlot.jaxodraw.*;


/** A general loop object. */
public abstract class JaLoopObject extends JaObject {
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/** The stroke of this loop object. */
    private float stroke;

    /** The dash  size of the loop object
     * (only used for ghost and scalar loops).
     */
    private float dash;

    /** The frequency of the loop object
     * (only used for photon and gluon loops).
     */
    private float freq;

    /** A Boolean variable that indicates whether to draw an arrow on
     * this loop object or not (not used for photon and gluon loops).*/
    private boolean arrow;

    /** A boolean variable that indicates whether the arrow should be
     * flipped with respect to the initial orientation or not
     * (not used for photon and gluon loops).
     */
    private boolean flip;

    /** The amplitude for this loop object (only used for photon and
     * gluon loops).
     */
    private int amp;

    /** A boolean variable that indicates whether this object
     * should be drawn with double lines.
     */
    private boolean doubleLine;

    /** The separation of the double lines. */
    private float dlSeparation;

    /** Constructor: sets the width, height, relative width and height,
     * to a default value of JaObject.INIT_SIZE.
     */
    public JaLoopObject() {
        setRelw(INIT_SIZE);
        setRelh(INIT_SIZE);

        setAmp(JaxoPrefs.getIntPref(JaxoPrefs.PREF_AMPLITUDE));
        setFreq(20.0f);
        setColor(JaxoColor.getColor(JaxoPrefs.getPref(
                    JaxoPrefs.PREF_COLOR)));
        setStroke(JaxoPrefs.getFloatPref(JaxoPrefs.PREF_LINEWIDTH));
        setDoubleLine(false);
        setDLSeparation(JaxoPrefs.getFloatPref(JaxoPrefs.PREF_DLSEP));

    }

    /** Returns an exact copy of this JaxoLoop.
     * @param temp An instance of the loop to copy to (since this is an abstract
     *  class, we have to provide an instance of a sub-class).
     * @return A copy of this JaxoLoop.
     */
    public final JaObject copy(JaLoopObject temp) {
        temp.setX(getX());
        temp.setY(getY());
        temp.setColor(getColor());
        temp.setStroke(getStroke());
        temp.setDoubleLine(getDoubleLine());
        temp.setDLSeparation(getDLSeparation());
        temp.setSize(getWidth(), getHeight(), getRelw(), getRelh());
        temp.setBoundingBox(getBoundingBox());
        return temp;
    }

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

        if (comp instanceof JaLoopObject) {
            if ((comp.getX() == getX())
                    && (((JaLoopObject) comp).getY() == getY())
                    && ((JaLoopObject) comp).getColor().equals(getColor())
                    && (((JaLoopObject) comp).getStroke() == getStroke())
                    && (
                        ((JaLoopObject) comp).getDoubleLine() == getDoubleLine()
                    )
                    && (
                        ((JaLoopObject) comp).getDLSeparation() == getDLSeparation()
                    ) && (((JaLoopObject) comp).getRelw() == getRelw())
                    && (((JaLoopObject) comp).getRelh() == getRelh())) {
                isCopy = true;
            }
        }

        return isCopy;

    }

    ////
    // Bean getter and setter methods

    /** Returns the stroke property of this loop object.
     * @return The stroke property of this loop object.
     */
    public final float getStroke() {
        return stroke;
    }

    /** Sets the stroke property of this loop object.
     * @param newStroke The stroke property of this loop object.
     */
    public final void setStroke(float newStroke) {
        this.stroke = newStroke;
    }

    /** Returns the dash property of this loop object.
     * @return  The dash property of this loop object.
     */
    public final float getDash() {
        return dash;
    }

    /** Sets the dash property of this loop object.
     * @param newDash The dash property of this loop object.
     */
    public final void setDash(float newDash) {
        this.dash = newDash;
    }

    /** Returns the freq property of this loop object.
     * @return The freq property of this loop object.
     */
    public final float getFreq() {
        return freq;
    }

    /** Sets the freq property of this loop object.
     * @param newFreq The freq property of this loop object.
     */
    public final void setFreq(float newFreq) {
        this.freq = newFreq;
    }

    /** Returns the amp property of this loop object.
     * @return The amp property of this loop object.
     */
    public final int getAmp() {
        return amp;
    }

    /** Sets the amp property of this loop object.
     * @param newAmp The amp property of this loop object.
     */
    public final void setAmp(int newAmp) {
        this.amp = newAmp;
    }

    /** Determines whether the arrow property of this loop object is set or not.
     * @return The arrow property of this loop object.
     */
    public final boolean isArrow() {
        return arrow;
    }

    /** Returns the arrow property of this loop object.
     * @return The arrow property  of this loop object.
     */
    public final boolean getArrow() {
        return arrow;
    }

    /** Sets the arrow property of this loop object.
     * @param arr The arrow property  of this loop object.
     */
    public final void setArrow(boolean arr) {
        this.arrow = arr;
    }

    /**Determines whether the flip property of this loop object is set or not.
     * @return The flip property  of this loop object.
     */
    public final boolean isFlip() {
        return flip;
    }

    /** Returns the flip property  of this loop object.
     * @return The flip property of this loop object.
     */
    public final boolean getFlip() {
        return flip;
    }

    /** Sets the  flip property of this loop object.
     * @param newFlip The flip property of this loop object.
     */
    public final void setFlip(boolean newFlip) {
        this.flip = newFlip;
    }

    /** Sets the double line property.
     * @param dline The double line boolean variable.
     */
    public final void setDoubleLine(boolean dline) {
        this.doubleLine = dline;
    }

    /** Returns the double line property.
     * @return The double line boolean variable of this object.
     */
    public final boolean getDoubleLine() {
        return doubleLine;
    }

    /** Sets the double line property.
     * @param dlsep The double line property.
     */
    public final void setDLSeparation(float dlsep) {
        this.dlSeparation = dlsep;
    }

    /** Returns the double line property.
     * @return The double line boolean variable of this object.
     */
    public final float getDLSeparation() {
        return dlSeparation;
    }

    /** Draws a visual aid during the dragging of a loop object,
     *  which is a red cross at the center.
     * @param g2 The graphics context to draw to.
     */
    public final void drawVisualAid(VectorGraphics g2) {
        g2.setColor(JaxoColor.RED);
        g2.setStroke(new BasicStroke(1.3f));

        int lp4 = LENGTH + 4;
        int x = getX();
        int y = getY();
        int w = getWidth();
        int h = getHeight();

        if ((getRelw() > 0) && (getRelh() >= 0)) {
            g2.drawLine(x - lp4, y, x + lp4, y);
            g2.drawLine(x, y - lp4, x, y + lp4);
        } else if ((getRelw() <= 0) && (getRelh() > 0)) {
            g2.drawLine((x + w) - lp4, y, x + w + lp4, y);
            g2.drawLine(x + w, y - lp4, x + w, y + lp4);
        } else if ((getRelw() < 0) && (getRelh() <= 0)) {
            g2.drawLine(x + w, (y + h) - lp4, x + w, y + h + lp4);
            g2.drawLine((x + w) - lp4, y + h, x + w + lp4, y + h);
        } else { //if ((getRelw() >= 0) && (getRelh() < 0)) {
            g2.drawLine(x - lp4, y + h, x + lp4, y + h);
            g2.drawLine(x, (y + h) - lp4, x, y + h + lp4);
        }
    }

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

        if (((getRelw() > 0) && (getRelh() >= 0))
                || ((getRelw() < 0) && (getRelh() <= 0))) {
            g2.drawRect(getX() - (LENGTH / 2), getY() - (LENGTH / 2), LENGTH,
                LENGTH);
            g2.drawRect((getX() + getWidth()) - (LENGTH / 2),
                (getY() + getHeight()) - (LENGTH / 2), LENGTH, LENGTH);

            if (isMarked()) {
                g2.setColor(JaxoColor.GRAYSCALE150);
                g2.fillRect(getX() - (LENGTH / 2) + 1,
                    getY() - (LENGTH / 2) + 1, LENGTH - 1, LENGTH - 1);
                g2.fillRect((getX() + getWidth()) - (LENGTH / 2) + 1,
                    (getY() + getHeight()) - (LENGTH / 2) + 1, LENGTH - 1,
                    LENGTH - 1);
            }
        } else if (((getRelw() <= 0) && (getRelh() > 0))
                || ((getRelw() >= 0) && (getRelh() < 0))) {
            g2.drawRect(getX() - (LENGTH / 2),
                (getY() + getHeight()) - (LENGTH / 2), LENGTH, LENGTH);
            g2.drawRect((getX() + getWidth()) - (LENGTH / 2),
                getY() - (LENGTH / 2), LENGTH, LENGTH);

            if (isMarked()) {
                g2.setColor(JaxoColor.GRAYSCALE150);
                g2.fillRect(getX() - (LENGTH / 2) + 1,
                    (getY() + getHeight()) - (LENGTH / 2) + 1, LENGTH - 1,
                    LENGTH - 1);
                g2.fillRect((getX() + getWidth()) - (LENGTH / 2) + 1,
                    getY() - (LENGTH / 2) + 1, LENGTH - 1, LENGTH - 1);
            }
        }
    }

    /** Determines which handle the user has selected to move/resize/edit this
     *  loop.
     * @param clickX The x coordinate where the mouse click has ocurred.
     * @param clickY The y coordinate where the mouse click has ocurred.
     * @param editmode The current edit mode.
     * @return One of the static variables SELECT_* defined in JaObject
     *  that specifies the handle which the user has clicked.
     */
    public final int getGrabbedHandle(int clickX, int clickY, int editmode) {
        if ((editmode == MOVE) || (editmode == COPY)) {
            if ((getRelw() > 0) && (getRelh() >= 0)) {
                if ((clickX >= (getX() - (LENGTH / 2)))
                        && (clickX <= (getX() + (LENGTH / 2)))
                        && (clickY >= (getY() - (LENGTH / 2)))
                        && (clickY <= (getY() + (LENGTH / 2)))) {
                    return SELECT_BODY;
                }

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

            if ((getRelw() < 0) && (getRelh() <= 0)) {
                if ((clickX >= (getX() - (LENGTH / 2)))
                        && (clickX <= (getX() + (LENGTH / 2)))
                        && (clickY >= (getY() - (LENGTH / 2)))
                        && (clickY <= (getY() + (LENGTH / 2)))) {
                    return SELECT_BODY;
                }

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

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

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

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

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

            return SELECT_NONE;
        } else if (editmode == RESIZE) {
            if ((getRelw() > 0) && (getRelh() >= 0)) {
                if ((clickX >= ((getX() + getWidth()) - (LENGTH / 2)))
                        && (clickX <= (getX() + getWidth() + (LENGTH / 2)))
                        && (
                            clickY >= ((getY() + getHeight()) - (LENGTH / 2))
                        ) && (
                            clickY <= (getY() + getHeight() + (LENGTH / 2))
                        )) {
                    return SELECT_LR;
                }
            } else if ((getRelw() < 0) && (getRelh() <= 0)) {
                if ((clickX >= (getX() - (LENGTH / 2)))
                        && (clickX <= (getX() + (LENGTH / 2)))
                        && (clickY >= (getY() - (LENGTH / 2)))
                        && (clickY <= (getY() + (LENGTH / 2)))) {
                    return SELECT_UL;
                }
            } else if ((getRelw() >= 0) && (getRelh() < 0)) {
                if ((clickX >= ((getX() + getWidth()) - (LENGTH / 2)))
                        && (clickX <= (getX() + getWidth() + (LENGTH / 2)))
                        && (clickY >= (getY() - (LENGTH / 2)))
                        && (clickY <= (getY() + (LENGTH / 2)))) {
                    return SELECT_UR;
                }
            } else if ((getRelw() <= 0) && (getRelh() > 0)) {
                if ((clickX >= (getX() - (LENGTH / 2)))
                        && (clickX <= (getX() + (LENGTH / 2)))
                        && (
                            clickY >= ((getY() + getHeight()) - (LENGTH / 2))
                        ) && (
                            clickY <= (getY() + getHeight() + (LENGTH / 2))
                        )) {
                    return SELECT_LL;
                }
            }

            return SELECT_NONE;
        }

        return SELECT_NONE;
    }

    /** Translates the given general path to the current location of this
     * JaxoLoop, rotates it by an angle determined by the relative width and
     * height and scales it by the given scale factor.
     * @param gp The GeneralPath object to be transformed.
     * @param scale An overall scale factor.
     * @return The transformed GeneralPath object.
     */
    protected final GeneralPath transl(GeneralPath gp, double scale) {
        AffineTransform at = new AffineTransform();

        //         if ((getRelw() == 0) && (getRelh() > 0)) {
        //             double theta = Math.PI / 2;
        //         } else if ((getRelw() == 0) && (getRelh() < 0)) {
        //             double theta = (Math.PI * 3) / 2;
        //         }
        double theta =
            (double) Math.atan2((float) getRelh(), (float) getRelw());

        if ((getRelw() > 0) && (getRelh() >= 0)) {
            at.translate(getX() - getWidth(), getY() - getHeight());
            at.rotate(theta, 0.d, 0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        if ((getRelw() >= 0) && (getRelh() < 0)) {
            at.translate(getX() - getWidth(), getY() + (2 * getHeight()));
            at.rotate(theta, 0.d, 0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        if ((getRelw() < 0) && (getRelh() <= 0)) {
            at.translate(getX() + (2 * getWidth()), getY() + (
                    2 * getHeight()
                ));
            at.rotate(theta, 0.d, 0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        if ((getRelw() <= 0) && (getRelh() > 0)) {
            at.translate(getX() + (2 * getWidth()), getY() - getHeight());
            at.rotate(theta, 0.d, 0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        return gp;
    }

    /** Draws an arrow on this loop
     * @param g2 The graphics context
     * @param c The color of the arrow
     * @param length The radius of the loop
     * @param size The size of the arrow
     * @param fl The flip property of this loop
     * @return A GeneralPath object of the arrow
     */
    protected final GeneralPath loopArrow(VectorGraphics g2, Color c,
        double length, float size, boolean fl) {
        g2.setStroke(new BasicStroke(2.0f));

        GeneralPath gp = new GeneralPath();
        float arrowsize = (5.f * size) / 8.f;
        gp.moveTo((float) arrowsize, 0.f);
        gp.lineTo(-arrowsize, arrowsize / 1.5f);
        gp.lineTo(-arrowsize / 1.5f, 0.f);
        gp.lineTo(-arrowsize, -arrowsize / 1.5f);
        gp.closePath();

        AffineTransform at = new AffineTransform();
        at.translate(0, length);

        if (flip) {
            at.rotate(Math.toRadians(180), 0.f, 0.f);
        }

        gp.transform(at);

        gp = transar(gp, 1.f);

        g2.setPaint(c);
        g2.fill(gp);

        return gp;
    }

    /** Draws an arrow on a double loop
     * @param g2 The graphics context
     * @param c The color of the arrow
     * @param length The radius of the loop
     * @param size The size of the arrow
     * @param fl The flip property of this loop
     * @param dlSep The separation of the double loop
     * @return A GeneralPath object of the arrow
     */
    protected final GeneralPath dLoopArrow(VectorGraphics g2, Color c,
        double length, float size, boolean fl, float dlSep) {
        g2.setStroke(new BasicStroke(2.0f));

        GeneralPath gp = new GeneralPath();
        float arrowsize = (5.f * size) / 8.f;
        gp.moveTo((float) arrowsize, dlSep);
        gp.lineTo(-arrowsize, (arrowsize / 1.5f) + dlSep);
        gp.lineTo(-arrowsize / 1.5f, dlSep);
        gp.lineTo(-arrowsize, (-arrowsize / 1.5f) + dlSep);
        gp.closePath();

        AffineTransform at = new AffineTransform();
        at.translate(0, length);

        if (flip) {
            at.rotate(Math.toRadians(180), 0.f, 0.f);
        }

        gp.transform(at);

        gp = transar(gp, 1.f);

        g2.setPaint(c);
        g2.fill(gp);

        return gp;
    }

    private GeneralPath transar(GeneralPath gp, double scale) {
        int ampangle = 360;

        AffineTransform at = new AffineTransform();

        double theta =
            (double) Math.atan2((float) getRelh(), (float) getRelw());

        if ((getRelw() > 0) && (getRelh() >= 0)) {
            at.translate(getX(), getY());
            at.rotate(((Math.PI - Math.toRadians(ampangle)) / 2) + theta, 0.d,
                0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        if ((getRelw() >= 0) && (getRelh() < 0)) {
            at.translate(getX(), getY() + getHeight());
            at.rotate(((Math.PI - Math.toRadians(ampangle)) / 2) + theta, 0.d,
                0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        if ((getRelw() < 0) && (getRelh() <= 0)) {
            at.translate(getX() + getWidth(), getY() + getHeight());
            at.rotate(((Math.PI - Math.toRadians(ampangle)) / 2) + theta, 0.d,
                0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        if ((getRelw() <= 0) && (getRelh() > 0)) {
            at.translate(getX() + getWidth(), getY());
            at.rotate(((Math.PI - Math.toRadians(ampangle)) / 2) + theta, 0.d,
                0.d);
            at.scale(scale, scale);
            gp.transform(at);
        }

        return gp;
    }

    /** Rescales this JaxoLoop 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 newRelWidth = 0;
        int newRelHeight = 0;

        int oldWidth = this.getSize().width;
        int oldHeight = this.getSize().height;
        int oldRelWidth = this.getRelSize().width;
        int oldRelHeight = this.getRelSize().height;
        int newAmp = (int) (this.getAmp() * scale);

        double newLength =
            (double) Math.sqrt((oldWidth * oldWidth) + (
                    oldHeight * oldHeight
                )) * scale;

        int wiggleNumbers = 0;

        if (this instanceof JaGlLoop) {
            wiggleNumbers =
                (int) (
                    (
                        Math.sqrt((oldWidth * oldWidth)
                            + (oldHeight * oldHeight)) * 2 * Math.PI
                    ) / this.getFreq() / 0.6f
                );
        } else {
            wiggleNumbers =
                (int) (
                    (
                        Math.sqrt((oldWidth * oldWidth)
                            + (oldHeight * oldHeight)) * 2 * Math.PI
                    ) / this.getFreq()
                );
        }

        float newFreq = 0.f;

        if (this instanceof JaGlLoop) {
            newFreq =
                (float) ((newLength * 2 * Math.PI) / wiggleNumbers / 0.6f);
        } else {
            newFreq = (float) ((newLength * 2 * Math.PI) / wiggleNumbers);
        }

        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()));

        double theta = Math.atan2((float) oldRelHeight, (float) oldRelWidth);

        if ((oldRelWidth < 0) && (oldRelHeight <= 0)) {
            newRelHeight = (int) (newLength * Math.sin(theta)) - 1;
            newRelWidth = (int) (newLength * Math.cos(theta)) - 1;
        } else if ((oldRelWidth >= 0) && (oldRelHeight < 0)) {
            newRelHeight = (int) (newLength * Math.sin(theta)) - 1;
            newRelWidth = (int) (newLength * Math.cos(theta)) + 1;
        } else if ((oldRelWidth <= 0) && (oldRelHeight > 0)) {
            newRelHeight = (int) (newLength * Math.sin(theta)) + 1;
            newRelWidth = (int) (newLength * Math.cos(theta)) - 1;
        } else if ((oldRelWidth > 0) && (oldRelHeight >= 0)) {
            newRelHeight = (int) (newLength * Math.sin(theta)) + 1;
            newRelWidth = (int) (newLength * Math.cos(theta)) + 1;
        }

        this.setAmp(newAmp);
        this.setFreq(newFreq);
        //this.setWAndH(Math.abs(newRelWidth), Math.abs(newRelHeight));
        this.setRelWAndH(newRelWidth, newRelHeight);
    }

    /** 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() {
        JaxoLoopOptionsPanel loopop = new JaxoLoopOptionsPanel(this);

        return loopop.hasChanged();
    }

    /** The LaTeX command that sets the width for this Loop,
     *  using the axodraw.sty package.
     * @return The corresponding LaTeX command.
     */
    public final String latexWidth() {
        // a default getStroke() value of 1.0 corresponds to a
        // default width in axodraw of  0.5;
        String thisValue = Float.toString(getStroke() / 2.f);
        String base = "\\SetWidth{";
        String closing = "}";
        String lineWidth = base.concat(thisValue.concat(closing));

        return lineWidth;
    }

    /** Returns a center point which is used by the latexCommand method.
     * @param scaleFactor A scale factor.
     * @param canvasHeight The height of the current canvas.
     * @return A Point2D object holding the center point.
     */
    protected Point2D getLaTexCenter(float scaleFactor, int canvasHeight) {
        Point2D centerPoint = new Point2D.Float();
        float cx;
        float cy;

        if ((getRelw() > 0) && (getRelh() >= 0)) {
            cx = getX() / scaleFactor;
            cy = (canvasHeight - getY()) / scaleFactor;
            centerPoint.setLocation(cx, cy);
        } else if ((getRelw() >= 0) && (getRelh() < 0)) {
            cx = getX() / scaleFactor;
            cy = (canvasHeight - (getY() + getHeight())) / scaleFactor;
            centerPoint.setLocation(cx, cy);
        } else if ((getRelw() < 0) && (getRelh() <= 0)) {
            cx = (getX() + getWidth()) / scaleFactor;
            cy = (canvasHeight - (getY() + getHeight())) / scaleFactor;
            centerPoint.setLocation(cx, cy);
        } else if ((getRelw() <= 0) && (getRelh() > 0)) {
            cx = (getX() + getWidth()) / scaleFactor;
            cy = (canvasHeight - getY()) / scaleFactor;
            centerPoint.setLocation(cx, cy);
        }

        return centerPoint;
    }

    /** Returns a radius which is used by the latexCommand method.
     * @param scaleFactor A scale factor.
     * @return The latex radius.
     */
    protected float getLaTexRadius(float scaleFactor) {
        float length =
            (float) Math.sqrt(((double) getWidth() * (double) getWidth())
                + ((double) getHeight() * (double) getHeight()));

        length = length / scaleFactor;

        return length;
    }

    /** Returns an angle which is used by the latexCommand method.
     * @return The latex angle.
     */
    protected Point2D getLaTexAngles() {
        Point2D anglesPoint = new Point2D.Float();
        int sAngle;
        int eAngle;

        if (getRelw() == 0) {
            sAngle = 90;
        }

        sAngle =
            (int) Math.round((
                    Math.atan2((float) getRelh(), (float) getRelw()) * 180.f
                ) / Math.PI);

        sAngle = -sAngle + 180;
        eAngle = sAngle + 360;

        if (isFlip()) {
            anglesPoint.setLocation(eAngle, sAngle);
        } else {
            anglesPoint.setLocation(sAngle, eAngle);
        }

        return anglesPoint;
    }
}

 

Ads help maintain this website.