/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fge;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.logging.Logger;
import org.openflexo.fge.controller.DrawingController;
import org.openflexo.fge.controller.MouseClickControl;
import org.openflexo.fge.controller.MouseClickControlAction.MouseClickControlActionType;
import org.openflexo.fge.controller.MouseControl.MouseButton;
import org.openflexo.fge.cp.ControlPoint;
import org.openflexo.fge.cp.GeometryAdjustingControlPoint;
import org.openflexo.fge.geom.FGEAbstractLine;
import org.openflexo.fge.geom.FGECircle;
import org.openflexo.fge.geom.FGECubicCurve;
import org.openflexo.fge.geom.FGEEllips;
import org.openflexo.fge.geom.FGEGeneralShape;
import org.openflexo.fge.geom.FGEGeneralShape.GeneralShapePathElement;
import org.openflexo.fge.geom.FGEGeometricObject.CardinalQuadrant;
import org.openflexo.fge.geom.FGEGeometricObject.Filling;
import org.openflexo.fge.geom.FGELine;
import org.openflexo.fge.geom.FGEPoint;
import org.openflexo.fge.geom.FGEPolygon;
import org.openflexo.fge.geom.FGEPolylin;
import org.openflexo.fge.geom.FGEQuadCurve;
import org.openflexo.fge.geom.FGERectangle;
import org.openflexo.fge.geom.FGERoundRectangle;
import org.openflexo.fge.geom.FGESegment;
import org.openflexo.fge.geom.FGEShape;
import org.openflexo.fge.geom.area.FGEArea;
import org.openflexo.fge.geom.area.FGEPlane;
import org.openflexo.fge.geom.area.FGEQuarterPlane;
import org.openflexo.fge.graphics.BackgroundStyle;
import org.openflexo.fge.graphics.BackgroundStyle.BackgroundStyleType;
import org.openflexo.fge.graphics.FGEGeometricGraphics;
import org.openflexo.fge.graphics.ForegroundStyle;
import org.openflexo.fge.notifications.FGENotification;
import org.openflexo.fge.notifications.GeometryModified;
import org.openflexo.toolbox.ToolBox;
public class GeometricGraphicalRepresentation<O> extends GraphicalRepresentation<O> implements Observer {
private static final Logger logger = Logger.getLogger(GeometricGraphicalRepresentation.class.getPackage().getName());
// *******************************************************************************
// * Parameters *
// *******************************************************************************
public static enum Parameters implements GRParameter {
foreground, background, layer, geometricObject
}
// *******************************************************************************
// * Inner classes *
// *******************************************************************************
// *******************************************************************************
// * Fields *
// *******************************************************************************
private int layer = FGEConstants.DEFAULT_OBJECT_LAYER;
private ForegroundStyle foreground;
private BackgroundStyle background;
protected FGEGeometricGraphics graphics;
private FGEArea geometricObject;
// *******************************************************************************
// * Constructor *
// *******************************************************************************
public GeometricGraphicalRepresentation(FGEArea anObject, O aDrawable, Drawing<?> aDrawing) {
super(aDrawable, aDrawing);
foreground = ForegroundStyle.makeStyle(Color.BLACK);
// foreground.setGraphicalRepresentation(this);
foreground.addObserver(this);
background = BackgroundStyle.makeColoredBackground(Color.WHITE);
// background.setGraphicalRepresentation(this);
background.addObserver(this);
geometricObject = anObject;
rebuildControlPoints();
graphics = new FGEGeometricGraphics(this);
addToMouseClickControls(MouseClickControl.makeMouseClickControl("Selection", MouseButton.LEFT, 1,
MouseClickControlActionType.SELECTION));
if (ToolBox.getPLATFORM() == ToolBox.MACOS) {
addToMouseClickControls(MouseClickControl.makeMouseMetaClickControl("Multiple selection", MouseButton.LEFT, 1,
MouseClickControlActionType.MULTIPLE_SELECTION));
} else {
addToMouseClickControls(MouseClickControl.makeMouseControlClickControl("Multiple selection", MouseButton.LEFT, 1,
MouseClickControlActionType.MULTIPLE_SELECTION));
}
}
@Override
public Vector<GRParameter> getAllParameters() {
Vector<GRParameter> returned = super.getAllParameters();
Parameters[] allParams = Parameters.values();
for (int i = 0; i < allParams.length; i++) {
returned.add(allParams[i]);
}
return returned;
}
// ***************************************************************************
// * Deletion *
// ***************************************************************************
@Override
public void delete() {
if (background != null) {
background.deleteObserver(this);
}
if (foreground != null) {
foreground.deleteObserver(this);
}
super.delete();
}
// *******************************************************************************
// * Accessors *
// *******************************************************************************
public ForegroundStyle getForeground() {
return foreground;
}
public void setForeground(ForegroundStyle aForeground) {
FGENotification notification = requireChange(Parameters.foreground, aForeground);
if (notification != null) {
if (foreground != null) {
foreground.deleteObserver(this);
}
foreground = aForeground;
if (aForeground != null) {
aForeground.addObserver(this);
}
hasChanged(notification);
}
}
public boolean getNoStroke() {
return foreground.getNoStroke();
}
public void setNoStroke(boolean noStroke) {
foreground.setNoStroke(noStroke);
}
public BackgroundStyle getBackground() {
return background;
}
public void setBackground(BackgroundStyle aBackground) {
FGENotification notification = requireChange(Parameters.background, aBackground);
if (notification != null) {
// background = aBackground.clone();
if (background != null) {
background.deleteObserver(this);
}
background = aBackground;
// background.setGraphicalRepresentation(this);
if (aBackground != null) {
aBackground.addObserver(this);
}
hasChanged(notification);
}
}
public BackgroundStyleType getBackgroundType() {
return background.getBackgroundStyleType();
}
public void setBackgroundType(BackgroundStyleType backgroundType) {
if (backgroundType != getBackgroundType()) {
setBackground(BackgroundStyle.makeBackground(backgroundType));
}
}
@Override
public int getLayer() {
return layer;
}
@Override
public void setLayer(int layer) {
FGENotification notification = requireChange(Parameters.layer, layer);
if (notification != null) {
this.layer = layer;
hasChanged(notification);
}
}
@Override
public int getViewX(double scale) {
return getViewBounds(scale).x;
}
@Override
public int getViewY(double scale) {
return getViewBounds(scale).y;
}
@Override
public int getViewWidth(double scale) {
return getViewBounds(scale).width;
}
@Override
public int getViewHeight(double scale) {
return getViewBounds(scale).height;
}
@Override
public Rectangle getViewBounds(double scale) {
return getBounds(scale);
}
public Rectangle getBounds(double scale) {
return getContainerGraphicalRepresentation().getViewBounds(scale);
// return new Rectangle(0,0,1,1);
}
@Override
public FGERectangle getNormalizedBounds() {
Rectangle bounds = getBounds(1);
return new FGERectangle(0, 0, bounds.width, bounds.height, Filling.FILLED);
}
@Override
public boolean isContainedInSelection(Rectangle drawingViewSelection, double scale) {
FGERectangle drawingViewBounds = new FGERectangle(drawingViewSelection.getX(), drawingViewSelection.getY(),
drawingViewSelection.getWidth(), drawingViewSelection.getHeight(), Filling.FILLED);
boolean isFullyContained = true;
/* for (ControlPoint cp : getConnector().getControlPoints()) {
Point cpInContainerView = convertLocalNormalizedPointToRemoteViewCoordinates(
cp.getPoint(),
getDrawingGraphicalRepresentation(),
scale);
FGEPoint preciseCPInContainerView = new FGEPoint(cpInContainerView.x,cpInContainerView.y);
if (!drawingViewBounds.containsPoint(preciseCPInContainerView)) {
//System.out.println("Going outside: point="+preciseCPInContainerView+" bounds="+containerViewBounds);
isFullyContained = false;
}
}*/
return isFullyContained;
}
@Override
public AffineTransform convertNormalizedPointToViewCoordinatesAT(double scale) {
return AffineTransform.getScaleInstance(scale, scale);
/*double width = getContainerGraphicalRepresentation().getViewWidth(scale);
double height = getContainerGraphicalRepresentation().getViewHeight(scale);
AffineTransform returned = AffineTransform.getScaleInstance(width,height);
if (scale != 1) {
returned.preConcatenate(AffineTransform.getScaleInstance(scale,scale));
}
return returned;*/
}
@Override
public AffineTransform convertViewCoordinatesToNormalizedPointAT(double scale) {
return AffineTransform.getScaleInstance(1 / scale, 1 / scale);
/*double width = getContainerGraphicalRepresentation().getViewWidth(scale);
double height = getContainerGraphicalRepresentation().getViewHeight(scale);
AffineTransform returned = new AffineTransform();
if (scale != 1) returned = AffineTransform.getScaleInstance(1/scale, 1/scale);
returned.preConcatenate(AffineTransform.getScaleInstance(1/width,1/height));
return returned;*/
}
// *******************************************************************************
// * Methods *
// *******************************************************************************
public void paintGeometricObject(FGEGeometricGraphics graphics) {
getGeometricObject().paint(graphics);
}
@Override
public void paint(Graphics g, DrawingController<?> controller) {
if (!isRegistered()) {
setRegistered(true);
}
super.paint(g, controller);
Graphics2D g2 = (Graphics2D) g;
graphics.createGraphics(g2, controller);
graphics.setDefaultBackground(getBackground());
graphics.setDefaultForeground(getForeground());
graphics.setDefaultTextStyle(getTextStyle());
if (getIsSelected() || getIsFocused()) {
ForegroundStyle style = getForeground().clone();
if (getIsSelected()) {
style.setColorNoNotification(getDrawingGraphicalRepresentation().getSelectionColor());
} else if (getIsFocused()) {
style.setColorNoNotification(getDrawingGraphicalRepresentation().getFocusColor());
}
graphics.setDefaultForeground(style);
}
paintGeometricObject(graphics);
if (getIsSelected() || getIsFocused()) {
Color color = null;
if (getIsSelected()) {
color = getDrawingGraphicalRepresentation().getSelectionColor();
} else if (getIsFocused()) {
color = getDrawingGraphicalRepresentation().getFocusColor();
}
for (ControlPoint cp : getControlPoints()) {
cp.paint(graphics);
}
}
if (hasFloatingLabel()) {
graphics.useTextStyle(getTextStyle());
graphics.drawString(getText(), new FGEPoint(getLabelRelativePosition().x + getAbsoluteTextX(), getLabelRelativePosition().y
+ getAbsoluteTextY()), getHorizontalTextAlignment());
}
graphics.releaseGraphics();
}
protected FGEPoint getLabelRelativePosition() {
if (getGeometricObject() instanceof FGEPoint) {
return (FGEPoint) getGeometricObject();
} else if (getGeometricObject() instanceof FGEAbstractLine) {
FGEAbstractLine line = (FGEAbstractLine) getGeometricObject();
return new FGESegment(line.getP1(), line.getP2()).getMiddle();
} else if (getGeometricObject() instanceof FGEShape) {
return ((FGEShape) getGeometricObject()).getCenter();
}
return new FGEPoint(0, 0);
}
@Override
public boolean hasFloatingLabel() {
return hasText();
}
@Override
public String getInspectorName() {
return "GeometricGraphicalRepresentation.inspector";
}
@Override
public void update(Observable observable, Object notification) {
super.update(observable, notification);
if (observable instanceof BackgroundStyle) {
notifyAttributeChange(Parameters.background);
}
if (observable instanceof ForegroundStyle) {
notifyAttributeChange(Parameters.foreground);
}
}
public FGEArea getGeometricObject() {
return geometricObject;
}
public void setGeometricObject(FGEArea geometricObject) {
FGENotification notification = requireChange(Parameters.geometricObject, geometricObject);
if (notification != null) {
this.geometricObject = geometricObject;
rebuildControlPoints();
hasChanged(notification);
}
}
protected Vector<ControlPoint> _controlPoints;
public List<ControlPoint> getControlPoints() {
if (_controlPoints == null) {
rebuildControlPoints();
}
return _controlPoints;
}
/*protected final void notifyCPDragged(String name, FGEPoint newLocation)
{
notifyGeometryChanged();
rebuildControlPoints();
}*/
protected List<ControlPoint> buildControlPointsForPoint(FGEPoint point) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
returned.add(new GeometryAdjustingControlPoint<FGEPoint>(this, "point", point.clone()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGEPoint) getGeometricObject()).x = newAbsolutePoint.x;
((FGEPoint) getGeometricObject()).y = newAbsolutePoint.y;
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEPoint geometricObject) {
setPoint(geometricObject);
}
});
return returned;
}
protected List<ControlPoint> buildControlPointsForLine(FGEAbstractLine line) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
returned.add(new GeometryAdjustingControlPoint<FGELine>(this, "p1", line.getP1()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGELine) getGeometricObject()).setP1(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGELine geometricObject) {
setPoint(geometricObject.getP1());
}
});
returned.add(new GeometryAdjustingControlPoint<FGELine>(this, "p2", line.getP2()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGELine) getGeometricObject()).setP2(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGELine geometricObject) {
setPoint(geometricObject.getP2());
}
});
return returned;
}
protected List<ControlPoint> buildControlPointsForCurve(FGEQuadCurve curve) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
returned.add(new GeometryAdjustingControlPoint<FGEQuadCurve>(this, "p1", curve.getP1()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGEQuadCurve) getGeometricObject()).setP1(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEQuadCurve geometricObject) {
setPoint(geometricObject.getP1());
}
});
returned.add(new GeometryAdjustingControlPoint<FGEQuadCurve>(this, "cp", curve.getCtrlPoint()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGEQuadCurve) getGeometricObject()).setCtrlPoint(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEQuadCurve geometricObject) {
setPoint(geometricObject.getCtrlPoint());
}
});
returned.add(new GeometryAdjustingControlPoint<FGEQuadCurve>(this, "p3", curve.getP3()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGEQuadCurve) getGeometricObject()).setP3(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEQuadCurve geometricObject) {
setPoint(geometricObject.getP3());
}
});
returned.add(new GeometryAdjustingControlPoint<FGEQuadCurve>(this, "p2", curve.getP2()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGEQuadCurve) getGeometricObject()).setP2(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEQuadCurve geometricObject) {
setPoint(geometricObject.getP2());
}
});
return returned;
}
protected List<ControlPoint> buildControlPointsForCurve(FGECubicCurve curve) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
returned.add(new GeometryAdjustingControlPoint<FGECubicCurve>(this, "p1", curve.getP1()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGECubicCurve) getGeometricObject()).setP1(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGECubicCurve geometricObject) {
setPoint(geometricObject.getP1());
}
});
returned.add(new GeometryAdjustingControlPoint<FGECubicCurve>(this, "cp1", curve.getCtrlP1()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGECubicCurve) getGeometricObject()).setCtrlP1(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGECubicCurve geometricObject) {
setPoint(geometricObject.getCtrlP1());
}
});
returned.add(new GeometryAdjustingControlPoint<FGECubicCurve>(this, "cp2", curve.getCtrlP2()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGECubicCurve) getGeometricObject()).setCtrlP2(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGECubicCurve geometricObject) {
setPoint(geometricObject.getCtrlP2());
}
});
returned.add(new GeometryAdjustingControlPoint<FGECubicCurve>(this, "p2", curve.getP2()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
((FGECubicCurve) getGeometricObject()).setP2(newAbsolutePoint);
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGECubicCurve geometricObject) {
setPoint(geometricObject.getP2());
}
});
return returned;
}
protected List<ControlPoint> buildControlPointsForPolygon(FGEPolygon polygon) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
for (int i = 0; i < polygon.getPointsNb(); i++) {
final int index = i;
returned.add(new GeometryAdjustingControlPoint<FGEPolygon>(this, "p" + i, polygon.getPointAt(i)) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration,
FGEPoint newAbsolutePoint, FGEPoint initialPoint, MouseEvent event) {
FGEPoint p = ((FGEPolygon) getGeometricObject()).getPointAt(index);
p.x = newAbsolutePoint.x;
p.y = newAbsolutePoint.y;
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEPolygon geometricObject) {
setPoint(geometricObject.getPointAt(index));
}
});
}
return returned;
}
protected List<ControlPoint> buildControlPointsForPolylin(FGEPolylin polylin) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
for (int i = 0; i < polylin.getPointsNb(); i++) {
final int index = i;
returned.add(new GeometryAdjustingControlPoint<FGEPolylin>(this, "p" + i, polylin.getPointAt(i)) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration,
FGEPoint newAbsolutePoint, FGEPoint initialPoint, MouseEvent event) {
FGEPoint p = ((FGEPolylin) getGeometricObject()).getPointAt(index);
p.x = newAbsolutePoint.x;
p.y = newAbsolutePoint.y;
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEPolylin geometricObject) {
setPoint(geometricObject.getPointAt(index));
}
});
}
return returned;
}
protected List<ControlPoint> buildControlPointsForEllips(FGEEllips ellips) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
// TODO
return returned;
}
protected List<ControlPoint> buildControlPointsForRectangle(FGERectangle rectangle) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
returned.add(new GeometryAdjustingControlPoint<FGERectangle>(this, "northWest", rectangle.getNorthWestPt()) {
private double initialWidth;
private double initialHeight;
@Override
public void startDragging(DrawingController<?> controller, FGEPoint startPoint) {
initialWidth = ((FGERectangle) getGeometricObject()).width;
initialHeight = ((FGERectangle) getGeometricObject()).height;
setDraggingAuthorizedArea(FGEQuarterPlane.makeFGEQuarterPlane(((FGERectangle) getGeometricObject()).getSouthEastPt(),
CardinalQuadrant.NORTH_WEST));
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
FGEPoint pt = getNearestPointOnAuthorizedArea(newAbsolutePoint);
setPoint(pt);
((FGERectangle) getGeometricObject()).x = pt.x;
((FGERectangle) getGeometricObject()).y = pt.y;
((FGERectangle) getGeometricObject()).width = -pt.x + initialPoint.x + initialWidth;
((FGERectangle) getGeometricObject()).height = -pt.y + initialPoint.y + initialHeight;
notifyGeometryChanged();
return true;
}
@Override
public void update(FGERectangle geometricObject) {
setPoint(geometricObject.getNorthWestPt());
}
});
returned.add(new GeometryAdjustingControlPoint<FGERectangle>(this, "northEast", rectangle.getNorthEastPt()) {
private double initialWidth;
private double initialHeight;
@Override
public void startDragging(DrawingController<?> controller, FGEPoint startPoint) {
initialWidth = ((FGERectangle) getGeometricObject()).width;
initialHeight = ((FGERectangle) getGeometricObject()).height;
setDraggingAuthorizedArea(FGEQuarterPlane.makeFGEQuarterPlane(((FGERectangle) getGeometricObject()).getSouthWestPt(),
CardinalQuadrant.NORTH_EAST));
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
FGEPoint pt = getNearestPointOnAuthorizedArea(newAbsolutePoint);
setPoint(pt);
((FGERectangle) getGeometricObject()).y = pt.y;
((FGERectangle) getGeometricObject()).width = pt.x - initialPoint.x + initialWidth;
((FGERectangle) getGeometricObject()).height = -pt.y + initialPoint.y + initialHeight;
notifyGeometryChanged();
return true;
}
@Override
public void update(FGERectangle geometricObject) {
setPoint(geometricObject.getNorthEastPt());
}
});
returned.add(new GeometryAdjustingControlPoint<FGERectangle>(this, "southWest", rectangle.getSouthWestPt()) {
private double initialWidth;
private double initialHeight;
@Override
public void startDragging(DrawingController<?> controller, FGEPoint startPoint) {
initialWidth = ((FGERectangle) getGeometricObject()).width;
initialHeight = ((FGERectangle) getGeometricObject()).height;
setDraggingAuthorizedArea(FGEQuarterPlane.makeFGEQuarterPlane(((FGERectangle) getGeometricObject()).getNorthEastPt(),
CardinalQuadrant.SOUTH_WEST));
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
FGEPoint pt = getNearestPointOnAuthorizedArea(newAbsolutePoint);
setPoint(pt);
((FGERectangle) getGeometricObject()).x = pt.x;
((FGERectangle) getGeometricObject()).width = -pt.x + initialPoint.x + initialWidth;
((FGERectangle) getGeometricObject()).height = pt.y - initialPoint.y + initialHeight;
notifyGeometryChanged();
return true;
}
@Override
public void update(FGERectangle geometricObject) {
setPoint(geometricObject.getSouthWestPt());
}
});
returned.add(new GeometryAdjustingControlPoint<FGERectangle>(this, "southEast", rectangle.getSouthEastPt()) {
private double initialWidth;
private double initialHeight;
@Override
public void startDragging(DrawingController<?> controller, FGEPoint startPoint) {
initialWidth = ((FGERectangle) getGeometricObject()).width;
initialHeight = ((FGERectangle) getGeometricObject()).height;
setDraggingAuthorizedArea(FGEQuarterPlane.makeFGEQuarterPlane(((FGERectangle) getGeometricObject()).getNorthWestPt(),
CardinalQuadrant.SOUTH_EAST));
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
FGEPoint pt = getNearestPointOnAuthorizedArea(newAbsolutePoint);
setPoint(pt);
((FGERectangle) getGeometricObject()).width = pt.x - initialPoint.x + initialWidth;
((FGERectangle) getGeometricObject()).height = pt.y - initialPoint.y + initialHeight;
notifyGeometryChanged();
return true;
}
@Override
public void update(FGERectangle geometricObject) {
setPoint(geometricObject.getSouthEastPt());
}
});
return returned;
}
protected List<ControlPoint> buildControlPointsForGeneralShape(FGEGeneralShape shape) {
Vector<ControlPoint> returned = new Vector<ControlPoint>();
returned.add(new GeometryAdjustingControlPoint<FGEGeneralShape>(this, "p0", shape.getPathElements().firstElement().getP1()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
FGEPoint p = ((FGEGeneralShape) getGeometricObject()).getPathElements().firstElement().getP1();
p.x = newAbsolutePoint.x;
p.y = newAbsolutePoint.y;
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEGeneralShape geometricObject) {
setPoint(geometricObject.getPathElements().firstElement().getP1());
}
});
for (int i = 0; i < shape.getPathElements().size(); i++) {
final int index = i;
GeneralShapePathElement<?> element = shape.getPathElements().get(i);
returned.add(new GeometryAdjustingControlPoint<FGEGeneralShape>(this, "p" + i, element.getP2()) {
@Override
public FGEArea getDraggingAuthorizedArea() {
return new FGEPlane();
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration,
FGEPoint newAbsolutePoint, FGEPoint initialPoint, MouseEvent event) {
FGEPoint p = ((FGEGeneralShape) getGeometricObject()).getPathElements().get(index).getP2();
p.x = newAbsolutePoint.x;
p.y = newAbsolutePoint.y;
((FGEGeneralShape) getGeometricObject()).refresh();
setPoint(newAbsolutePoint);
notifyGeometryChanged();
return true;
}
@Override
public void update(FGEGeneralShape geometricObject) {
setPoint(geometricObject.getPathElements().get(index).getP2());
}
});
}
return returned;
}
private void updateControlPoints() {
boolean cpNeedsToBeRebuilt = false;
for (ControlPoint cp : _controlPoints) {
if (cp instanceof GeometryAdjustingControlPoint) {
((GeometryAdjustingControlPoint) cp).update(getGeometricObject());
} else {
cpNeedsToBeRebuilt = true;
}
}
if (cpNeedsToBeRebuilt) {
rebuildControlPoints();
}
}
public List<ControlPoint> rebuildControlPoints() {
if (_controlPoints == null) {
_controlPoints = new Vector<ControlPoint>();
}
_controlPoints.clear();
if (getGeometricObject() == null) {
return _controlPoints;
}
if (getGeometricObject() instanceof FGEPoint) {
_controlPoints.addAll(buildControlPointsForPoint((FGEPoint) getGeometricObject()));
} else if (getGeometricObject() instanceof FGEAbstractLine) {
_controlPoints.addAll(buildControlPointsForLine((FGEAbstractLine) getGeometricObject()));
} else if (getGeometricObject() instanceof FGERectangle) {
_controlPoints.addAll(buildControlPointsForRectangle((FGERectangle) getGeometricObject()));
} else if (getGeometricObject() instanceof FGERoundRectangle) {
_controlPoints.addAll(buildControlPointsForRectangle(((FGERoundRectangle) getGeometricObject()).getBoundingBox()));
} else if (getGeometricObject() instanceof FGEEllips) {
_controlPoints.addAll(buildControlPointsForEllips((FGEEllips) getGeometricObject()));
} else if (getGeometricObject() instanceof FGEPolygon) {
_controlPoints.addAll(buildControlPointsForPolygon((FGEPolygon) getGeometricObject()));
} else if (getGeometricObject() instanceof FGEPolylin) {
_controlPoints.addAll(buildControlPointsForPolylin((FGEPolylin) getGeometricObject()));
} else if (getGeometricObject() instanceof FGEQuadCurve) {
_controlPoints.addAll(buildControlPointsForCurve((FGEQuadCurve) getGeometricObject()));
} else if (getGeometricObject() instanceof FGECubicCurve) {
_controlPoints.addAll(buildControlPointsForCurve((FGECubicCurve) getGeometricObject()));
} else if (getGeometricObject() instanceof FGEGeneralShape) {
_controlPoints.addAll(buildControlPointsForGeneralShape((FGEGeneralShape) getGeometricObject()));
}
return _controlPoints;
}
public void notifyGeometryChanged() {
updateControlPoints();
setChanged();
notifyObservers(new GeometryModified());
if (getGeometricObject() instanceof FGEPoint) {
notifyChange("drawable.x");
notifyChange("drawable.y");
} else if (getGeometricObject() instanceof FGELine) {
notifyChange("drawable.x1");
notifyChange("drawable.y1");
notifyChange("drawable.x2");
notifyChange("drawable.y2");
} else if (getGeometricObject() instanceof FGERectangle) {
notifyChange("drawable.x");
notifyChange("drawable.y");
notifyChange("drawable.width");
notifyChange("drawable.height");
} else if (getGeometricObject() instanceof FGECircle) {
notifyChange("drawable.centerX");
notifyChange("drawable.centerY");
notifyChange("drawable.radius");
} else if (getGeometricObject() instanceof FGEEllips) {
notifyChange("drawable.x");
notifyChange("drawable.y");
notifyChange("drawable.width");
notifyChange("drawable.height");
}
}
// Hack: for the inspector !!!
private void notifyChange(final String string) {
notify(new FGENotification(string, null, null));
}
}