/* * (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.connectors.rpc; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.util.logging.Logger; import org.openflexo.fge.GraphicalRepresentation; import org.openflexo.fge.geom.FGEGeometricObject.SimplifiedCardinalDirection; import org.openflexo.fge.geom.FGEPoint; import org.openflexo.fge.geom.FGERectPolylin; import org.openflexo.fge.geom.FGESegment; import org.openflexo.fge.geom.area.FGEArea; import org.openflexo.fge.geom.area.FGEPlane; import org.openflexo.fge.geom.area.FGESubstractionArea; public class AdjustableFirstControlPoint extends RectPolylinAdjustableControlPoint { static final Logger logger = Logger.getLogger(AdjustableFirstControlPoint.class.getPackage().getName()); private SimplifiedCardinalDirection currentStartOrientation = null; public AdjustableFirstControlPoint(FGEPoint point, RectPolylinConnector connector) { super(point, connector); } @Override public FGEArea getDraggingAuthorizedArea() { AffineTransform at1 = GraphicalRepresentation.convertNormalizedCoordinatesAT(getGraphicalRepresentation().getStartObject(), getGraphicalRepresentation()); FGEArea startArea = getGraphicalRepresentation().getStartObject().getShape().getShape().transform(at1); return new FGESubstractionArea(new FGEPlane(), startArea, false); } @Override public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint, FGEPoint initialPoint, MouseEvent event) { FGEPoint pt = getNearestPointOnAuthorizedArea(newRelativePoint); if (pt == null) { logger.warning("Cannot nearest point for point " + newRelativePoint + " and area " + getDraggingAuthorizedArea()); return false; } // Following little hack is used here to prevent some equalities that may // lead to inconsistent orientations // pt.x += FGEPoint.EPSILON; // pt.y += FGEPoint.EPSILON; setPoint(pt); getPolylin().updatePointAt(1, pt); movedFirstCP(); getConnector()._connectorChanged(true); getGraphicalRepresentation().notifyConnectorChanged(); return true; } /** * This method is internally called when first control point has been detected to be moved. * */ private void movedFirstCP() { FGEArea startArea = getConnector().retrieveAllowedStartArea(false); if (getConnector().getIsStartingLocationFixed() && !getConnector().getIsStartingLocationDraggable()) { // If starting location is fixed and not draggable, // Then retrieve start area itself (which is here a single point) startArea = getConnector().retrieveStartArea(); } FGEPoint newFirstCPLocation = getPoint(); // polylin.getPointAt(1); FGEPoint nextCPLocation = initialPolylin.getPointAt(2); SimplifiedCardinalDirection initialStartOrientation = initialPolylin.getApproximatedOrientationOfSegment(0); SimplifiedCardinalDirection initialFirstOrientation = initialPolylin.getApproximatedOrientationOfSegment(1); SimplifiedCardinalDirection initialNextOrientation = initialPolylin.getSegmentNb() > 2 ? initialPolylin .getApproximatedOrientationOfSegment(2) : null; if (startArea.getOrthogonalPerspectiveArea(initialStartOrientation).containsPoint(newFirstCPLocation)) { // OK, the new location will not modify general structure of connector FGEPoint newStartPoint = startArea.nearestPointFrom(newFirstCPLocation, initialStartOrientation.getOpposite()); if (newStartPoint == null) { logger.warning("Could not find nearest point from " + newFirstCPLocation + " on " + startArea + " following orientation " + initialStartOrientation.getOpposite()); newStartPoint = startArea.getNearestPoint(newFirstCPLocation); } getPolylin().updatePointAt(0, newStartPoint); getConnector().getStartControlPoint().setPoint(newStartPoint); if (getConnector().getIsStartingLocationFixed()) { // Don't forget this !!! getConnector().setFixedStartLocation( GraphicalRepresentation.convertNormalizedPoint(getGraphicalRepresentation(), newStartPoint, getGraphicalRepresentation().getStartObject())); } if (initialPolylin.getSegmentNb() > 3) { FGESegment oppositeSegment = initialPolylin.getSegmentAt(2); FGERectPolylin appendingPath1 = new FGERectPolylin(newFirstCPLocation, initialFirstOrientation, oppositeSegment.getP2(), initialPolylin.getApproximatedOrientationOfSegment(2).getOpposite(), true, getConnector() .getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); FGERectPolylin appendingPath2 = new FGERectPolylin(newFirstCPLocation, initialFirstOrientation, oppositeSegment.getP2(), initialPolylin.getApproximatedOrientationOfSegment(2), true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); FGERectPolylin appendingPath = appendingPath1.getPointsNb() <= appendingPath2.getPointsNb() ? appendingPath1 : appendingPath2; // debugPolylin = appendingPath; FGERectPolylin mergedPolylin = getConnector().mergePolylins(getPolylin(), 0, 1, appendingPath, 1, appendingPath.getPointsNb() - 1); mergedPolylin = getConnector().mergePolylins(mergedPolylin, 0, mergedPolylin.getPointsNb() - 1, initialPolylin, 4, initialPolylin.getPointsNb() - 1); getConnector().updateWithNewPolylin(mergedPolylin, true); } else { // We go directely to end point, we have to preserve direction FGERectPolylin appendingPath = new FGERectPolylin(newFirstCPLocation, initialFirstOrientation, initialPolylin.getSegmentAt( 2).getP2(), initialNextOrientation.getOpposite(), true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); FGERectPolylin mergedPolylin = getConnector().mergePolylins(getPolylin(), 0, 1, appendingPath, 1, appendingPath.getPointsNb() - 1); getConnector().updateWithNewPolylin(mergedPolylin, true); } currentStartOrientation = initialStartOrientation; } else { // Try to find a cardinal direction in which it is possible to project // dragged control point SimplifiedCardinalDirection orientation = null; // SimplifiedCardinalDirection alternativeOrientation = null; for (SimplifiedCardinalDirection o : getConnector().getPrimitiveAllowedStartOrientations()) { if (startArea.getOrthogonalPerspectiveArea(o).containsPoint(newFirstCPLocation)) { orientation = o; } } if (orientation == null) { // Control point has just moved in an area which is not in any // orthogonal perspective area of starting shape. // I don't want to hide the thuth: this is NOT good... // We keep here initial start orientation if (currentStartOrientation == null) { currentStartOrientation = initialStartOrientation; } orientation = currentStartOrientation; if (!getConnector().getAllowedStartOrientations().contains(orientation) && getConnector().getAllowedStartOrientations().size() > 0) { orientation = getConnector().getAllowedStartOrientations().firstElement(); } /*if (startArea.containsPoint(newFirstCPLocation)) { orientation = currentStartOrientation; alternativeOrientation = currentStartOrientation; } else { CardinalQuadrant quadrant = FGEPoint.getCardinalQuadrant(getPolylin().getFirstPoint(),newFirstCPLocation); orientation = quadrant.getHorizonalComponent(); alternativeOrientation = quadrant.getVerticalComponent(); }*/ // CardinalQuadrant quadrant = FGEPoint.getCardinalQuadrant(getPolylin().getFirstPoint(),newFirstCPLocation); // orientation = currentStartOrientation; /*if (quadrant.getHorizonalComponent() == currentStartOrientation) { alternativeOrientation = quadrant.getVerticalComponent(); } else { alternativeOrientation = quadrant.getHorizonalComponent(); }*/ // System.out.println("orientation="+orientation+" alternativeOrientation="+alternativeOrientation); // Compute new start position by getting nearest point of dragged point // located on anchor area of start area regarding orientation FGEPoint newStartPosition = startArea.getAnchorAreaFrom(orientation).getNearestPoint(newFirstCPLocation); // Compute path to append FGERectPolylin appendingPath; /*FGERectPolylin appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint( newStartPosition, nextCPLocation, newFirstCPLocation, true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap(), SimplifiedCardinalDirection.allDirectionsExcept(orientation), SimplifiedCardinalDirection.allDirectionsExcept(initialNextOrientation.getOpposite()));*/ if (initialPolylin.getSegmentNb() > 3) { FGESegment oppositeSegment = initialPolylin.getSegmentAt(2); appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint(newStartPosition, oppositeSegment.getP2(), newFirstCPLocation, orientation, initialNextOrientation.getOpposite(), true, getConnector() .getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); } else { appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint(newStartPosition, nextCPLocation, newFirstCPLocation, orientation, initialNextOrientation.getOpposite(), true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); } // Merge polylin FGERectPolylin mergedPolylin = getConnector().mergePolylins(appendingPath, 0, appendingPath.getPointsNb() - 1, initialPolylin, 3, initialPolylin.getPointsNb() - 1); // System.out.println("mergedPolylin="+mergedPolylin); // System.out.println("L'orientation est: "+mergedPolylin.getSegmentAt(0).getApproximatedOrientation()); // Update with this new polylin getConnector().updateWithNewPolylin(mergedPolylin, true); } else { // OK, we have found a cardinal direction in which it is possible to // project dragged control point // Compute new start position by projecting dragged control point // related to orientation FGEPoint newStartPosition = startArea.nearestPointFrom(newFirstCPLocation, orientation.getOpposite()); if (newStartPosition == null) { logger.warning("Could not find nearest point from " + newFirstCPLocation + " on " + startArea + " following orientation " + initialStartOrientation.getOpposite()); newStartPosition = startArea.getNearestPoint(newFirstCPLocation); } getPolylin().updatePointAt(0, newStartPosition); getConnector().getStartControlPoint().setPoint(newStartPosition); if (getConnector().getIsStartingLocationFixed()) { // Don't forget this !!! getConnector().setFixedStartLocation( GraphicalRepresentation.convertNormalizedPoint(getGraphicalRepresentation(), newStartPosition, getGraphicalRepresentation().getStartObject())); } // FGEPoint newStartPosition = startArea.getAnchorAreaFrom(orientation).getNearestPoint(newFirstCPLocation); // Compute path to append FGERectPolylin appendingPath; if (initialPolylin.getSegmentNb() > 3) { FGESegment oppositeSegment = initialPolylin.getSegmentAt(2); appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint(newStartPosition, oppositeSegment.getP2(), newFirstCPLocation, orientation, initialNextOrientation.getOpposite(), true, getConnector() .getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); } else { appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint(newStartPosition, nextCPLocation, newFirstCPLocation, orientation, initialNextOrientation.getOpposite(), true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); } // getConnector().debugPolylin = appendingPath; // Merge polylin FGERectPolylin mergedPolylin = getConnector().mergePolylins(appendingPath, 0, appendingPath.getPointsNb() - 1, initialPolylin, 3, initialPolylin.getPointsNb() - 1); // Update with this new polylin getConnector().updateWithNewPolylin(mergedPolylin, true); currentStartOrientation = orientation; } } } /** * This method is internally called when first control point has been detected to be moved. * */ /*private void movedFirstCP() { AffineTransform at1 = GraphicalRepresentation.convertNormalizedCoordinatesAT( getConnector().getStartObject(), getGraphicalRepresentation()); FGEArea startArea = getConnector().getStartObject().getShape().getOutline().transform(at1); FGEPoint firstCPLocation = getPoint(); //polylin.getPointAt(1); FGEPoint nextCPLocation = initialPolylin.getPointAt(2); SimplifiedCardinalDirection initialStartOrientation = initialPolylin.getApproximatedOrientationOfSegment(0); SimplifiedCardinalDirection initialFirstOrientation = initialPolylin.getApproximatedOrientationOfSegment(1); SimplifiedCardinalDirection initialNextOrientation = (initialPolylin.getSegmentNb() > 2 ? initialPolylin.getApproximatedOrientationOfSegment(2) : null); if (startArea.getOrthogonalPerspectiveArea(initialStartOrientation).containsPoint(firstCPLocation)) { // OK, the new location will not modify general structure of connector FGEPoint newPoint = new FGEPoint(getPolylin().getPointAt(0)); if (initialStartOrientation.isHorizontal()) { newPoint.setY(firstCPLocation.y); } else if (initialStartOrientation.isVertical()) { newPoint.setX(firstCPLocation.x); } getPolylin().updatePointAt(0, newPoint); getConnector().getStartControlPoint().setPoint(newPoint); if (initialPolylin.getSegmentNb() > 3) { FGESegment oppositeSegment = initialPolylin.getSegmentAt(2); FGERectPolylin appendingPath1 = new FGERectPolylin( firstCPLocation,initialFirstOrientation, oppositeSegment.getP2(),initialPolylin.getApproximatedOrientationOfSegment(2).getOpposite(), true,getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); FGERectPolylin appendingPath2 = new FGERectPolylin( firstCPLocation,initialFirstOrientation, oppositeSegment.getP2(),initialPolylin.getApproximatedOrientationOfSegment(2), true,getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); FGERectPolylin appendingPath = (appendingPath1.getPointsNb() <= appendingPath2.getPointsNb() ? appendingPath1 : appendingPath2); //debugPolylin = appendingPath; FGERectPolylin mergedPolylin = getConnector().mergePolylins(getPolylin(), 0, 1, appendingPath, 1, appendingPath.getPointsNb()-1); mergedPolylin = getConnector().mergePolylins( mergedPolylin, 0, mergedPolylin.getPointsNb()-1, initialPolylin, 4, initialPolylin.getPointsNb()-1); getConnector().updateWithNewPolylin(mergedPolylin); } else { // We go directely to end point, we have to preserve direction FGERectPolylin appendingPath = new FGERectPolylin( firstCPLocation,initialFirstOrientation, initialPolylin.getSegmentAt(2).getP2(),initialNextOrientation.getOpposite(), true,getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); FGERectPolylin mergedPolylin = getConnector().mergePolylins(getPolylin(), 0, 1, appendingPath, 1, appendingPath.getPointsNb()-1); getConnector().updateWithNewPolylin(mergedPolylin); } currentStartOrientation = initialStartOrientation; } else { // Try to find a cardinal direction in which it is possible to project // dragged control point SimplifiedCardinalDirection orientation = null; SimplifiedCardinalDirection alternativeOrientation = null; for (SimplifiedCardinalDirection o : SimplifiedCardinalDirection.values()) { if (startArea.getOrthogonalPerspectiveArea(o).containsPoint(firstCPLocation)) { orientation = o; } } if (orientation == null) { // Control point has just moved in an area which is not in any // orthogonal perspective area of starting shape. // We keep here initial start orientation if (currentStartOrientation == null) currentStartOrientation = initialStartOrientation; orientation = currentStartOrientation; if (startArea.containsPoint(firstCPLocation)) { orientation = currentStartOrientation; alternativeOrientation = currentStartOrientation; } else { CardinalQuadrant quadrant = FGEPoint.getCardinalQuadrant(getPolylin().getFirstPoint(),firstCPLocation); orientation = quadrant.getHorizonalComponent(); alternativeOrientation = quadrant.getVerticalComponent(); } // Compute new start position by getting nearest point of dragged point // located on anchor area of start area regarding orientation FGEPoint newStartPosition = startArea.getAnchorAreaFrom(orientation).getNearestPoint(firstCPLocation); // Compute path to append FGERectPolylin appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint( newStartPosition, nextCPLocation, firstCPLocation, true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap(), SimplifiedCardinalDirection.allDirectionsExcept(orientation,alternativeOrientation), SimplifiedCardinalDirection.allDirectionsExcept(initialNextOrientation.getOpposite())); // Merge polylin FGERectPolylin mergedPolylin = getConnector().mergePolylins(appendingPath, 0, appendingPath.getPointsNb()-1, initialPolylin, 3, initialPolylin.getPointsNb()-1); // Update with this new polylin getConnector().updateWithNewPolylin(mergedPolylin); } else { // OK, we have found a cardinal direction in which it is possible to // project dragged control point // Compute new start position by projecting dragged control point // related to orientation FGEPoint newStartPosition = startArea.getAnchorAreaFrom(orientation).getNearestPoint(firstCPLocation); // Compute path to append FGERectPolylin appendingPath = FGERectPolylin.makeRectPolylinCrossingPoint( newStartPosition, nextCPLocation, firstCPLocation, orientation, initialNextOrientation.getOpposite(), true, getConnector().getOverlapXResultingFromPixelOverlap(), getConnector().getOverlapYResultingFromPixelOverlap()); // Merge polylin FGERectPolylin mergedPolylin = getConnector().mergePolylins(appendingPath, 0, appendingPath.getPointsNb()-1, initialPolylin, 3, initialPolylin.getPointsNb()-1); // Update with this new polylin getConnector().updateWithNewPolylin(mergedPolylin); currentStartOrientation = orientation; } } }*/ }