blob: d93ef3f1ef5849749c9b816a98179dc5a0cf78d6 [file] [log] [blame]
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.jdesktop.swingx.designer;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
/**
* RectangleShape
*
* @author Created by Jasper Potts (May 22, 2007)
*/
public class RectangleShape extends PaintedShape {
private DoubleBean x1 = new DoubleBean();
private DoubleBean x2 = new DoubleBean();
private DoubleBean y1 = new DoubleBean();
private DoubleBean y2 = new DoubleBean();
private ControlPoint tl = new ControlPoint(x1, y1);
private ControlPoint tr = new ControlPoint(x2, y1);
private ControlPoint bl = new ControlPoint(x1, y2);
private ControlPoint br = new ControlPoint(x2, y2);
private DoubleBean roundingX = new DoubleBean() {
public void setValue(double value) {
// contrain y = y1 and x is between x1+1 and (x2-x1)/2
boolean x1isLess = x1.getValue() < x2.getValue();
double min = x1isLess ? x1.getValue() + 1 : x1.getValue() - 1;
double max = x1isLess ? x1.getValue() + ((x2.getValue() - x1.getValue()) / 2) :
x2.getValue() + ((x1.getValue() - x2.getValue()) / 2);
double newX = value;
if (newX < min) newX = min;
if (newX > max) newX = max;
super.setValue(newX);
}
};
private ControlPoint rounding = new ControlPoint(roundingX, y1) {
public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) {
double size = pixelSize * 3d;
Shape s = new Ellipse2D.Double(getX() - size, getY() - size,
size * 2, size * 2);
g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_FILL);
g2.fill(s);
g2.setColor(GraphicsHelper.BEZIER_CONTROL_POINT_LINE);
g2.draw(s);
}
public void setPosition(Point2D position) {
// only alow X to change
x.setValue(position.getX());
}
};
// =================================================================================================================
// Constructors
/** private noargs constructor for JIBX */
private RectangleShape() {
this(null);
}
public RectangleShape(UIDefaults canvasUiDefaults) {
super(canvasUiDefaults);
x1.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
// keep rounding point in sync
roundingX.setValue(roundingX.getValue() +
((Double) evt.getNewValue() - (Double) evt.getOldValue()));
firePropertyChange("bounds", null, getBounds(0));
}
});
x2.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
// keep rounding point in sync
double distanceFromX1 = Math.abs(roundingX.getValue() - x1.getValue());
roundingX.setValue(
(x1.getValue() < x2.getValue()) ? x1.getValue() + distanceFromX1 :
x1.getValue() - distanceFromX1
);
firePropertyChange("bounds", null, getBounds(0));
}
});
PropertyChangeListener listener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange("bounds", null, getBounds(0));
}
};
y1.addPropertyChangeListener(listener);
y2.addPropertyChangeListener(listener);
rounding.addPropertyChangeListener(listener);
}
public RectangleShape(double x, double y, double w, double h) {
this();
x1.setValue(x);
y1.setValue(y);
x2.setValue(x + w);
y2.setValue(y + h);
}
public Shape getShape() {
double rounding = getRounding();
double left = Math.min(x1.getValue(), x2.getValue());
double right = Math.max(x1.getValue(), x2.getValue());
double top = Math.min(y1.getValue(), y2.getValue());
double bottom = Math.max(y1.getValue(), y2.getValue());
if (rounding > 0) {
return new RoundRectangle2D.Double(
left, top, right - left, bottom - top, rounding, rounding
);
} else {
return new Rectangle2D.Double(left, top, right - left, bottom - top);
}
}
public double getRounding() {
double rounding = Math.abs(roundingX.getValue() - x1.getValue()) * 2;
return rounding > 2 ? rounding : 0;
}
public void setRounding(double rounding) {
if (rounding > 0 && rounding < 2) rounding = 0;
roundingX.setValue((rounding / 2d) + x1.getValue());
}
public boolean isRounded() {
return getRounding() > 0;
}
public double getX1() {
return x1.getValue();
}
public void setX1(double x1) {
this.x1.setValue(x1);
}
public double getX2() {
return x2.getValue();
}
public void setX2(double x2) {
this.x2.setValue(x2);
}
public double getY1() {
return y1.getValue();
}
public void setY1(double y1) {
this.y1.setValue(y1);
}
public double getY2() {
return y2.getValue();
}
public void setY2(double y2) {
this.y2.setValue(y2);
}
// =================================================================================================================
// SimpleShape Methods
public Rectangle2D getBounds(double pixelSize) {
double left = Math.min(x1.getValue(), x2.getValue());
double right = Math.max(x1.getValue(), x2.getValue());
double top = Math.min(y1.getValue(), y2.getValue());
double bottom = Math.max(y1.getValue(), y2.getValue());
return new Rectangle2D.Double(left, top, right - left, bottom - top);
}
public boolean isHit(Point2D p, double pixelSize) {
return getShape().contains(p);
}
public void paint(Graphics2D g2, double pixelSize) {
g2.setPaint(getPaint());
g2.fill(getShape());
}
public void setFrame(double x1, double y1, double x2, double y2) {
this.x1.setValue(x1);
this.y1.setValue(y1);
this.x2.setValue(x2);
this.y2.setValue(y2);
}
@Override
public String toString() {
Rectangle2D bounds = getBounds(0);
if (isRounded()) {
return "ROUND RECT { x=" + bounds.getX() + ", y=" + bounds.getY() + ", w=" + bounds.getWidth() + ", h=" + bounds.getHeight() + ", rounding=" + getRounding() + " }";
} else {
return "ROUND RECT { x=" + bounds.getX() + ", y=" + bounds.getY() + ", w=" + bounds.getWidth() + ", h=" + bounds.getHeight() + " }";
}
}
public List<ControlPoint> getControlPoints() {
List<ControlPoint> points = new ArrayList<ControlPoint>();
points.addAll(super.getControlPoints());
points.add(tl);
points.add(tr);
points.add(bl);
points.add(br);
points.add(rounding);
return points;
}
public void paintControls(Graphics2D g2, double pixelSize, boolean paintControlLines) {
if (paintControlLines) {
g2.setStroke(new BasicStroke((float) pixelSize));
g2.setColor(GraphicsHelper.CONTROL_LINE);
g2.draw(getShape());
}
tl.paintControls(g2, pixelSize, true);
tr.paintControls(g2, pixelSize, true);
bl.paintControls(g2, pixelSize, true);
br.paintControls(g2, pixelSize, true);
rounding.paintControls(g2, pixelSize, true);
}
public void move(double moveX, double moveY, boolean snapPixels) {
if (snapPixels) {
x1.setValue(Math.round(x1.getValue() + moveX));
x2.setValue(Math.round(x2.getValue() + moveX));
y1.setValue(Math.round(y1.getValue() + moveY));
y2.setValue(Math.round(y2.getValue() + moveY));
} else {
x1.setValue(x1.getValue() + moveX);
x2.setValue(x2.getValue() + moveX);
y1.setValue(y1.getValue() + moveY);
y2.setValue(y2.getValue() + moveY);
}
}
}