/*
* (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.wkf.processeditor.gr;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import org.openflexo.fge.GraphicalRepresentation;
import org.openflexo.fge.ShapeGraphicalRepresentation.ShapeBorder;
import org.openflexo.fge.connectors.Connector;
import org.openflexo.fge.connectors.Connector.ConnectorType;
import org.openflexo.fge.connectors.ConnectorSymbol.EndSymbolType;
import org.openflexo.fge.connectors.ConnectorSymbol.MiddleSymbolType;
import org.openflexo.fge.connectors.ConnectorSymbol.StartSymbolType;
import org.openflexo.fge.connectors.CurveConnector;
import org.openflexo.fge.connectors.rpc.RectPolylinConnector;
import org.openflexo.fge.connectors.rpc.RectPolylinConnector.RectPolylinAdjustability;
import org.openflexo.fge.connectors.rpc.RectPolylinConnector.RectPolylinConstraints;
import org.openflexo.fge.controller.CustomClickControlAction;
import org.openflexo.fge.controller.DrawingController;
import org.openflexo.fge.controller.MouseClickControl;
import org.openflexo.fge.geom.FGEDimension;
import org.openflexo.fge.geom.FGEGeometricObject.Filling;
import org.openflexo.fge.geom.FGEGeometricObject.SimplifiedCardinalDirection;
import org.openflexo.fge.geom.FGEPoint;
import org.openflexo.fge.geom.FGERectPolylin;
import org.openflexo.fge.geom.FGERectangle;
import org.openflexo.fge.graphics.ForegroundStyle;
import org.openflexo.fge.graphics.TextStyle;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.NameChanged;
import org.openflexo.foundation.RepresentableFlexoModelObject;
import org.openflexo.foundation.utils.FlexoFont;
import org.openflexo.foundation.wkf.WKFObject;
import org.openflexo.foundation.wkf.dm.PostInserted;
import org.openflexo.foundation.wkf.dm.PostRemoved;
import org.openflexo.foundation.wkf.dm.WKFAttributeDataModification;
import org.openflexo.foundation.wkf.edge.FlexoPostCondition;
import org.openflexo.foundation.wkf.edge.WKFEdge;
import org.openflexo.foundation.wkf.node.ActionNode;
import org.openflexo.foundation.wkf.node.FlexoPreCondition;
import org.openflexo.foundation.wkf.node.IFOperator;
import org.openflexo.foundation.wkf.node.PetriGraphNode;
import org.openflexo.inspector.HasIcon;
import org.openflexo.toolbox.ToolBox;
import org.openflexo.wkf.WKFCst;
import org.openflexo.wkf.WKFPreferences;
import org.openflexo.wkf.processeditor.ProcessEditorConstants;
import org.openflexo.wkf.processeditor.ProcessEditorController;
import org.openflexo.wkf.processeditor.ProcessRepresentation;
public abstract class EdgeGR<O extends WKFEdge<?, ?>> extends WKFConnectorGR<O> implements ProcessEditorConstants {
protected static final Logger logger = Logger.getLogger(EdgeGR.class.getPackage().getName());
private final boolean isInduced;
public EdgeGR(O edge, WKFObject startObject, WKFObject endObject, ProcessRepresentation aDrawing) {
super(ConnectorType.RECT_POLYLIN, aDrawing.getFirstVisibleObject(getRepresentedStartObject(edge.getStartNode(), aDrawing)),
aDrawing.getFirstVisibleObject(getRepresentedEndObject(edge.getEndNode(), aDrawing)), edge, aDrawing);
if (startObject == null) {
logger.warning("Edge: " + edge + " first visible object for " + edge.getStartNode() + " is null !");
}
if (endObject == null) {
logger.warning("Edge: " + edge + " first visible object for " + edge.getEndNode() + " is null !");
}
edge.addObserver(this);
isInduced = aDrawing.getFirstVisibleObject(edge.getStartNode()) != edge.getStartNode()
|| aDrawing.getFirstVisibleObject(edge.getEndNode()) != edge.getEndNode();
setForeground(ForegroundStyle.makeStyle(WKFCst.EDGE_COLOR, 1.0f));
setMiddleSymbol(MiddleSymbolType.NONE);
setEndSymbol(EndSymbolType.FILLED_ARROW);
addToMouseClickControls(new ResetLayout(), true);
addToMouseClickControls(new ProcessEditorController.ShowContextualMenuControl(false));
if (ToolBox.getPLATFORM() != ToolBox.MACOS) {
addToMouseClickControls(new ProcessEditorController.ShowContextualMenuControl(true));
}
setIsMultilineAllowed(true);
updatePropertiesFromWKFPreferences();
}
@Override
public final void delete() {
if (getDrawable() != null) {
getDrawable().deleteObserver(this);
}
super.delete();
}
protected static WKFObject getRepresentedStartObject(WKFObject declaredStartObject, ProcessRepresentation aDrawing) {
return declaredStartObject;
}
protected static WKFObject getRepresentedEndObject(WKFObject declaredEndObject, ProcessRepresentation aDrawing) {
if (declaredEndObject instanceof FlexoPreCondition && ((FlexoPreCondition) declaredEndObject).getAttachedBeginNode() != null
&& aDrawing.isVisible(((FlexoPreCondition) declaredEndObject).getAttachedBeginNode())) {
return ((FlexoPreCondition) declaredEndObject).getAttachedBeginNode();
}
return declaredEndObject;
}
protected Connector makeConnector(ConnectorType connectorType) {
Connector returned = Connector.makeConnector(connectorType, this);
ensurePolylinConverterIsRegistered();
ensurePointConverterIsRegistered();
if (returned instanceof RectPolylinConnector) {
RectPolylinConnector connector = (RectPolylinConnector) returned;
// connector.setAdjustability(RectPolylinAdjustability.FULLY_ADJUSTABLE);
connector.setAdjustability(WKFPreferences.getConnectorAdjustability());
// logger.info("Post: "+getPostCondition().getName()+" hasGraphicalPropertyForKey("+getStoredPolylinKey()+"): "+getPostCondition().hasGraphicalPropertyForKey(getStoredPolylinKey()));
if (getEdge().hasGraphicalPropertyForKey(getOldStoredPolylinKey())) {
getEdge()._setGraphicalPropertyForKey(getEdge()._graphicalPropertyForKey(getOldStoredPolylinKey()), getStoredPolylinKey());
getEdge()._removeGraphicalPropertyWithKey(getOldStoredPolylinKey());
}
if (getEdge().hasGraphicalPropertyForKey(getStoredPolylinKey())) {
polylinIWillBeAdustedTo = (FGERectPolylin) getEdge()._graphicalPropertyForKey(getStoredPolylinKey());
connector.setWasManuallyAdjusted(true);
}
if (getEdge().getEndNode() instanceof FlexoPreCondition
&& !getEdge().hasGraphicalPropertyForKey(getPreConditionLayoutTransformFlagKey())
&& getEdge().hasGraphicalPropertyForKey(
getRelativeMiddleSymbolLocationKey(getContext(startObject, getEdge().getEndNode(), false)))) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
convertOldLayout((RectPolylinConnector) getConnector());
}
});
} else {
if (getEdge().hasGraphicalPropertyForKey(getOldCrossedCPKey())) {
getEdge()._setGraphicalPropertyForKey(getEdge()._graphicalPropertyForKey(getOldCrossedCPKey()), getCrossedCPKey());
getEdge()._removeGraphicalPropertyWithKey(getOldCrossedCPKey());
}
if (getEdge().hasGraphicalPropertyForKey(getCrossedCPKey())) {
connector.setCrossedControlPoint((FGEPoint) getEdge()._graphicalPropertyForKey(getCrossedCPKey()));
}
if (getEdge().hasGraphicalPropertyForKey(getOldFixedStartLocationKey())) {
getEdge()._setGraphicalPropertyForKey(getEdge()._graphicalPropertyForKey(getOldFixedStartLocationKey()),
getFixedStartLocationKey());
getEdge()._removeGraphicalPropertyWithKey(getOldFixedStartLocationKey());
}
if (getEdge().hasGraphicalPropertyForKey(getFixedStartLocationKey())) {
connector.setFixedStartLocation((FGEPoint) getEdge()._graphicalPropertyForKey(getFixedStartLocationKey()));
}
if (getEdge().hasGraphicalPropertyForKey(getOldFixedEndLocationKey())) {
getEdge()._setGraphicalPropertyForKey(getEdge()._graphicalPropertyForKey(getOldFixedEndLocationKey()),
getFixedEndLocationKey());
getEdge()._removeGraphicalPropertyWithKey(getOldFixedEndLocationKey());
}
if (getEdge().hasGraphicalPropertyForKey(getFixedEndLocationKey())) {
connector.setFixedEndLocation((FGEPoint) getEdge()._graphicalPropertyForKey(getFixedEndLocationKey()));
}
}
connector.setStraightLineWhenPossible(true);
connector.setRectPolylinConstraints(RectPolylinConstraints.NONE);
connector.setIsRounded(true);
connector.setIsStartingLocationDraggable(true);
connector.setIsEndingLocationDraggable(true);
} else if (returned instanceof CurveConnector) {
CurveConnector connector = (CurveConnector) returned;
if (getEdge().hasGraphicalPropertyForKey(getOldStoredCurveCPKey())) {
getEdge()._setGraphicalPropertyForKey(getEdge()._graphicalPropertyForKey(getOldStoredCurveCPKey()), getStoredCurveCPKey());
getEdge()._removeGraphicalPropertyWithKey(getOldStoredCurveCPKey());
}
// Default value is 0.5 / 0.55: the exact middle of the arc (that will look straight)
if (!getEdge().hasGraphicalPropertyForKey(getStoredCurveCPKey())) {
getEdge()._setGraphicalPropertyForKey(new FGEPoint(0.5, 0.55), getStoredCurveCPKey());
}
connector._setCpPosition((FGEPoint) getEdge()._graphicalPropertyForKey(getStoredCurveCPKey()));
}
return returned;
}
protected void convertOldLayout(RectPolylinConnector connector) {
if (getEdge().hasGraphicalPropertyForKey(getPreConditionLayoutTransformFlagKey()) || isDeleted()) {
return;
}
double relativeLocation = (Double) getEdge()._graphicalPropertyForKey(
getRelativeMiddleSymbolLocationKey(getContext(startObject, getEdge().getEndNode(), false)));
setRelativeMiddleSymbolLocation(relativeLocation);
Rectangle normalizedBounds = getNormalizedBounds(1.0);
String oldContext = getContext(startObject, getEdge().getEndNode(), false);
AffineTransform startToDrawingAT = convertFromDrawableToDrawingAT(getStartObject(), 1.0);
AffineTransform endToDrawingAT = convertFromDrawableToDrawingAT(getEndObject(), 1.0);
double posx = ((FlexoPreCondition) getEdge().getEndNode()).getX(ProcessEditorConstants.BASIC_PROCESS_EDITOR);
double posy = ((FlexoPreCondition) getEdge().getEndNode()).getY(ProcessEditorConstants.BASIC_PROCESS_EDITOR);
FGEPoint startLocationInDrawing = new FGEPoint();
FGEPoint endLocationInDrawing = new FGEPoint();
startToDrawingAT.transform(startLocationInDrawing, startLocationInDrawing);
ShapeBorder startBorder = getStartObject().getBorder();
startLocationInDrawing.x -= startBorder.left;
startLocationInDrawing.y -= startBorder.top;
// Start object bounds in drawing coordinates
FGEDimension startSize = getStartObject().getSize();
startSize.width += startBorder.right + startBorder.left;
startSize.height += startBorder.bottom + startBorder.top;
FGERectangle startObjectRect = new FGERectangle(startLocationInDrawing, startSize, Filling.FILLED);
// Compute the precondition location into the drawing coordinates
endToDrawingAT.transform(new FGEPoint(posx, posy), endLocationInDrawing);
/*endLocationInDrawing.x += getEndObject().getBorder().left;
endLocationInDrawing.y += getEndObject().getBorder().top;*/
// Pre condition bounds in drawing coordinates
FGERectangle preConditionRect = new FGERectangle(endLocationInDrawing, new FGEDimension(PreConditionGR.PRECONDITION_SIZE,
PreConditionGR.PRECONDITION_SIZE), Filling.FILLED);
// Compute previous connector bounds (since before, end object was the precondition)
FGERectangle connectorRectWithPreConditionInDrawing = preConditionRect.rectangleUnion(startObjectRect);
FGEPoint oldCrossedPoint = (FGEPoint) getEdge()._graphicalPropertyForKey(getCrossedCPKey(oldContext));
if (oldCrossedPoint != null) {
getEdge()._removeGraphicalPropertyWithKey(getCrossedCPKey(oldContext));
FGEPoint crossedPointInDrawing = new FGEPoint(connectorRectWithPreConditionInDrawing.x
+ connectorRectWithPreConditionInDrawing.width * oldCrossedPoint.x, connectorRectWithPreConditionInDrawing.y
+ connectorRectWithPreConditionInDrawing.height * oldCrossedPoint.y);
FGEPoint crossedPointInConnector = new FGEPoint();
convertFromDrawingToDrawableAT(this, 1.0).transform(crossedPointInDrawing, crossedPointInConnector);
crossedPointInConnector.x /= normalizedBounds.width;
crossedPointInConnector.y /= normalizedBounds.height;
connector.setCrossedControlPoint(crossedPointInConnector);
}
Point2D labelLocation = getEdge().getLabelLocation(oldContext);
if (labelLocation != null) {
setAbsoluteTextX(labelLocation.getX());
setAbsoluteTextY(labelLocation.getY());
}
if (getEdge().hasGraphicalPropertyForKey(getFixedStartLocationKey(oldContext))) {
connector.setFixedStartLocation((FGEPoint) getEdge()._graphicalPropertyForKey(getFixedStartLocationKey(oldContext)));
getEdge()._removeGraphicalPropertyWithKey(getFixedStartLocationKey(oldContext));
}
ShapeBorder border = getEndObject().getBorder();
FGEPoint endLocation = new FGEPoint(posx / (getEndObject().getWidth() + border.left), posy
/ (getEndObject().getHeight() + border.top));
connector.setFixedEndLocation(endLocation);
getEdge()._removeGraphicalPropertyWithKey(getFixedEndLocationKey(oldContext));
getEdge()._removeGraphicalPropertyWithKey(
getRelativeMiddleSymbolLocationKey(getContext(startObject, getEdge().getEndNode(), false)));
getEdge()._setGraphicalPropertyForKey(Boolean.TRUE, getPreConditionLayoutTransformFlagKey());
}
private FGERectPolylin polylinIWillBeAdustedTo;
@Override
public void notifyObjectHierarchyWillBeUpdated() {
super.notifyObjectHierarchyWillBeUpdated();
if (getDrawing().getFirstVisibleObject(getRepresentedStartObject(getEdge().getStartNode(), getDrawing())) != startObject
|| getDrawing().getFirstVisibleObject(getRepresentedEndObject(getEdge().getEndNode(), getDrawing())) != endObject) {
dismissGraphicalRepresentation();
}
}
@Override
public void notifyObjectHierarchyHasBeenUpdated() {
super.notifyObjectHierarchyHasBeenUpdated();
if (polylinIWillBeAdustedTo != null && getConnector() instanceof RectPolylinConnector && !getEdge().isDeleted()) {
// logger.info("Post: "+getPostCondition().getName()+" manuallySetPolylin to "+polylinIWillBeAdustedTo);
((RectPolylinConnector) getConnector()).manuallySetPolylin(polylinIWillBeAdustedTo);
polylinIWillBeAdustedTo = null;
refreshConnector();
}
}
@Override
public boolean getIsVisible() {
return true;
}
@Override
public String getText() {
return getEdge().getName();
}
@Override
public void setTextNoNotification(String aName) {
getEdge().setName(aName);
}
public WKFEdge<?, ?> getEdge() {
return getDrawable();
}
public FlexoPostCondition<?, ?> getPostCondition() {
if (getEdge() instanceof FlexoPostCondition) {
return (FlexoPostCondition<?, ?>) getEdge();
}
return null;
}
@Override
public String toString() {
return "EdgeGR of " + getDrawable();
}
@Override
public StartSymbolType getStartSymbol() {
if (getPostCondition() != null) {
if (getPostCondition().startOperatorIsIfNode()) {
IFOperator ifOperator = (IFOperator) getPostCondition().getStartNode();
if (ifOperator.isNegativeEvaluationPostcondition(getPostCondition())) {
return StartSymbolType.PLAIN_CIRCLE;
}
}
if (getPostCondition().getIsDefaultFlow()) {
return StartSymbolType.DEFAULT_FLOW;
} else if (getPostCondition().getIsConditional()) {
if (!getPostCondition().getStartNode().isOperatorNode()) {
return StartSymbolType.PLAIN_LONG_DIAMOND;
}
} else {
if (isInduced()) {
return StartSymbolType.NONE;
} else {
return StartSymbolType.FILLED_CIRCLE;
}
}
}
return StartSymbolType.NONE;
}
@Override
public double getStartSymbolSize() {
if (getPostCondition() != null) {
if (getPostCondition().startOperatorIsIfNode()) {
IFOperator ifOperator = (IFOperator) getEdge().getStartNode();
if (ifOperator.isNegativeEvaluationPostcondition(getPostCondition())) {
return 5;
}
}
if (getPostCondition().getIsDefaultFlow()) {
return 15;
} else if (getPostCondition().getIsConditional()) {
return 10;
} else {
return 5;
}
}
return 0;
}
@Override
public double getAbsoluteTextX() {
if (getEdge().hasLabelLocationForContext(getOldContext())) {
getEdge().setLabelX(getEdge().getLabelX(getOldContext(), getDefaultLabelX()), getContext());
getEdge()._removeGraphicalPropertyWithKey(getEdge().getLabelXKeyForContext(getOldContext()));
}
if (!getEdge().hasLabelLocationForContext(getContext())) {
getEdge().getLabelX(getContext(), getDefaultLabelX());
}
return getEdge().getLabelX(getContext());
}
@Override
public void setAbsoluteTextXNoNotification(double posX) {
getEdge().setLabelX(posX, getContext());
}
@Override
public double getAbsoluteTextY() {
if (getEdge().hasLabelLocationForContext(getOldContext())) {
getEdge().setLabelY(getEdge().getLabelY(getOldContext(), getDefaultLabelY()), getContext());
getEdge()._removeGraphicalPropertyWithKey(getEdge().getLabelYKeyForContext(getOldContext()));
}
if (!getEdge().hasLabelLocationForContext(getContext())) {
getEdge().getLabelY(getContext(), getDefaultLabelY());
}
return getEdge().getLabelY(getContext());
}
@Override
public void setAbsoluteTextYNoNotification(double posY) {
getEdge().setLabelY(posY, getContext());
}
public void resetLayout() {
if (getConnector() instanceof RectPolylinConnector) {
getEdge().setLocationConstraintFlag(true);
((RectPolylinConnector) getConnector()).setIsStartingLocationFixed(false);
((RectPolylinConnector) getConnector()).setIsEndingLocationFixed(false);
if (WKFPreferences.getConnectorAdjustability() == RectPolylinAdjustability.FULLY_ADJUSTABLE) {
((RectPolylinConnector) getConnector()).setWasManuallyAdjusted(false);
} else if (WKFPreferences.getConnectorAdjustability() == RectPolylinAdjustability.BASICALLY_ADJUSTABLE) {
((RectPolylinConnector) getConnector()).setCrossedControlPoint(null);
refreshConnector();
}
}
}
@Override
public void refreshConnector() {
if (!isConnectorConsistent()) {
// Dont' go further for connector that are inconsistent (this may happen
// during big model restructurations (for example during a multiple delete)
return;
}
if (getConnector() instanceof RectPolylinConnector && getEndObject() instanceof PreConditionGR) {
PreConditionGR preGR = (PreConditionGR) getEndObject();
AbstractNodeGR<?> nodeGR = (AbstractNodeGR<?>) preGR.getContainerGraphicalRepresentation();
FGEPoint preLocationInNode = GraphicalRepresentation.convertNormalizedPoint(preGR, new FGEPoint(0.5, 0.5), nodeGR);
SimplifiedCardinalDirection orientation = FGEPoint.getSimplifiedOrientation(new FGEPoint(0.5, 0.5), preLocationInNode);
endOrientationFixed = true;
newEndOrientation = orientation;
/*
* if (connector.getRectPolylinConstraints() == RectPolylinConstraints.START_ORIENTATION_FIXED) {
* connector.setRectPolylinConstraints(RectPolylinConstraints.ORIENTATIONS_FIXED,connector.getStartOrientation(),orientation); }
* else { connector.setRectPolylinConstraints(RectPolylinConstraints.END_ORIENTATION_FIXED,null,orientation); }
* connector.setIsEndingLocationFixed(true); connector.setIsEndingLocationDraggable(false); connector.setFixedEndLocation(new
* FGEPoint(0.5+0.5*Math.cos(orientation.getRadians()),0.5-0.5*Math.sin(orientation.getRadians())));
*/
}
if (getConnector() instanceof RectPolylinConnector) {
if (getStartObject() instanceof AnnotationGR) {
startOrientationFixed = ((AnnotationGR) getStartObject()).getModel().isAnnotation();
double d = getStartObject().getLocationInDrawing().x + getStartObject().getWidth() / 2;
double e = getEndObject().getLocationInDrawing().x + getEndObject().getWidth() / 2;
if (d > e) {
newStartOrientation = SimplifiedCardinalDirection.WEST;
} else {
newStartOrientation = SimplifiedCardinalDirection.EAST;
}
}
if (getEndObject() instanceof AnnotationGR) {
endOrientationFixed = ((AnnotationGR) getEndObject()).getModel().isAnnotation();
double d = getStartObject().getLocationInDrawing().x + getStartObject().getWidth() / 2;
double e = getEndObject().getLocationInDrawing().x + getEndObject().getWidth() / 2;
if (d < e) {
newEndOrientation = SimplifiedCardinalDirection.WEST;
} else {
newEndOrientation = SimplifiedCardinalDirection.EAST;
}
}
}
if (getConnector() instanceof RectPolylinConnector) {
RectPolylinConnector connector = (RectPolylinConnector) getConnector();
if (endOrientationFixed) {
if (startOrientationFixed) {
connector.setRectPolylinConstraints(RectPolylinConstraints.ORIENTATIONS_FIXED, newStartOrientation, newEndOrientation);
} else {
connector.setRectPolylinConstraints(RectPolylinConstraints.END_ORIENTATION_FIXED, null, newEndOrientation);
}
} else {
if (startOrientationFixed) {
connector.setRectPolylinConstraints(RectPolylinConstraints.START_ORIENTATION_FIXED, newStartOrientation, null);
} else {
connector.setRectPolylinConstraints(RectPolylinConstraints.NONE);
}
}
if (startOrientationFixed) {
connector.setIsStartingLocationFixed(true);
connector.setIsStartingLocationDraggable(false);
if (newStartOrientation != null) {
connector.setFixedStartLocation(new FGEPoint(0.5 + 0.5 * Math.cos(newStartOrientation.getRadians()), 0.5 - 0.5 * Math
.sin(newStartOrientation.getRadians())));
}
}
if (endOrientationFixed) {
connector.setIsEndingLocationFixed(true);
connector.setIsEndingLocationDraggable(false);
if (newEndOrientation != null) {
connector.setFixedEndLocation(new FGEPoint(0.5 + 0.5 * Math.cos(newEndOrientation.getRadians()), 0.5 - 0.5 * Math
.sin(newEndOrientation.getRadians())));
}
}
/*
* if (newOrientationConstraints == RectPolylinConstraints.START_ORIENTATION_FIXED) { newOrientationConstraints =
* RectPolylinConstraints.ORIENTATIONS_FIXED; } else { newOrientationConstraints = RectPolylinConstraints.END_ORIENTATION_FIXED;
* }
*
*
* switch (newOrientationConstraints) { case ORIENTATIONS_FIXED:
* connector.setRectPolylinConstraints(RectPolylinConstraints.ORIENTATIONS_FIXED,newStartOrientation,newEndOrientation); break;
* case START_ORIENTATION_FIXED:
* connector.setRectPolylinConstraints(RectPolylinConstraints.START_ORIENTATION_FIXED,newStartOrientation,null); break; case
* END_ORIENTATION_FIXED:
* connector.setRectPolylinConstraints(RectPolylinConstraints.END_ORIENTATION_FIXED,null,newEndOrientation); break; default:
* break; }
*
* connector.setRectPolylinConstraints(newOrientationConstraints,newStartOrientation,newEndOrientation);
*/
}
super.refreshConnector();
storeNewLayout();
}
protected boolean startOrientationFixed;
protected boolean endOrientationFixed;
protected SimplifiedCardinalDirection newStartOrientation;
protected SimplifiedCardinalDirection newEndOrientation;
private String context;
@Override
public void notifyConnectorChanged() {
super.notifyConnectorChanged();
storeNewLayout();
}
private String getContext() {
if (context == null) {
return getContext(startObject, endObject, true);
}
return context;
}
private String getContext(WKFObject start, WKFObject end, boolean storeContext) {
StringBuilder sb = new StringBuilder(BASIC_PROCESS_EDITOR);
if (start instanceof PetriGraphNode) {
sb.append(((PetriGraphNode) start).getDepth());
} else {
if (start != null) {
sb.append(start.getClass().getSimpleName());
} else {
sb.append("???");
storeContext = false;
}
}
sb.append('_');
if (end instanceof PetriGraphNode) {
sb.append(((PetriGraphNode) end).getDepth());
} else {
if (end != null) {
sb.append(end.getClass().getSimpleName());
} else {
sb.append("???");
storeContext = false;
}
}
if (storeContext) {
return context = sb.toString();
} else {
return sb.toString();
}
}
private String getPreConditionLayoutTransformFlagKey() {
return "pcl_transform_" + getContext();
}
private String getStoredPolylinKey() {
return getStoredPolylinKey(getContext());
}
private String getStoredCurveCPKey() {
return getStoredCurveCPKey(getContext());
}
private String getCrossedCPKey() {
return getCrossedCPKey(getContext());
}
private String getFixedStartLocationKey() {
return getFixedStartLocationKey(getContext());
}
private String getFixedEndLocationKey() {
return getFixedEndLocationKey(getContext());
}
private String getRelativeMiddleSymbolLocationKey() {
return getRelativeMiddleSymbolLocationKey(getContext());
}
private String getStoredPolylinKey(String context) {
return "polylin_" + context;
}
private String getStoredCurveCPKey(String context) {
return "curve_cp_" + context;
}
private String getCrossedCPKey(String context) {
return "crossed_cp_" + context;
}
private String getFixedStartLocationKey(String context) {
return "fixed_start_location_" + context;
}
private String getFixedEndLocationKey(String context) {
return "fixed_end_location_" + context;
}
private String getRelativeMiddleSymbolLocationKey(String context) {
return "middle_symbol_location_" + context;
}
private String getOldContext() {
return BASIC_PROCESS_EDITOR + "_" + (startObject != null ? startObject.getFlexoID() : "???") + "_"
+ (endObject != null ? endObject.getFlexoID() : "???");
}
private String getOldStoredPolylinKey() {
return "polylin_" + getOldContext();
}
private String getOldStoredCurveCPKey() {
return "curve_cp_" + getOldContext();
}
private String getOldCrossedCPKey() {
return "crossed_cp_" + getOldContext();
}
private String getOldFixedStartLocationKey() {
return "fixed_start_location_" + getOldContext();
}
private String getOldFixedEndLocationKey() {
return "fixed_end_location_" + getOldContext();
}
private String getOldRelativeMiddleSymbolLocationKey() {
return "middle_symbol_location_" + getOldContext();
}
public boolean startLocationManuallyAdjusted() {
return getConnector() instanceof RectPolylinConnector && ((RectPolylinConnector) getConnector()).getIsStartingLocationFixed();
}
public boolean endLocationManuallyAdjusted() {
return getConnector() instanceof RectPolylinConnector && ((RectPolylinConnector) getConnector()).getIsEndingLocationFixed();
}
private void storeNewLayout() {
/*
* boolean debug = false; if (getDrawable().getName() != null && getDrawable().getName().equals("B")) debug= true;
*
* if (debug) { logger.info("storeNewLayout() for "+getDrawable()); logger.info("getStoredPolylinKey() = "+getStoredPolylinKey());
* logger.info("isRegistered() = "+isRegistered()); }
*/
if (getConnector() instanceof RectPolylinConnector && isRegistered()) {
RectPolylinConnector connector = (RectPolylinConnector) getConnector();
if (connector.getAdjustability() == RectPolylinAdjustability.FULLY_ADJUSTABLE) {
ensurePolylinConverterIsRegistered();
if (connector.getWasManuallyAdjusted() && connector._getPolylin() != null) {
if (polylinIWillBeAdustedTo == null) { // Store this layout only in no other layout is beeing registering
if (logger.isLoggable(Level.FINE)) {
logger.fine("Edge " + getPostCondition().getName() + ": store new layout for " + getStoredPolylinKey() + " to "
+ connector._getPolylin());
}
getEdge()._setGraphicalPropertyForKey(connector._getPolylin(), getStoredPolylinKey());
}
} else {
if (getEdge().hasGraphicalPropertyForKey(getStoredPolylinKey())) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Edge " + getPostCondition().getName() + ": remove layout for " + getStoredPolylinKey());
}
getEdge()._removeGraphicalPropertyWithKey(getStoredPolylinKey());
}
}
} else if (connector.getAdjustability() == RectPolylinAdjustability.BASICALLY_ADJUSTABLE) {
ensurePointConverterIsRegistered();
if (connector.getCrossedControlPoint() != null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Edge " + getPostCondition().getName() + ": store new ccp for " + getCrossedCPKey() + " to "
+ connector.getCrossedControlPoint());
}
getEdge()._setGraphicalPropertyForKey(connector.getCrossedControlPoint(), getCrossedCPKey());
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Edge " + getPostCondition().getName() + ": remove layout for " + getCrossedCPKey());
}
getEdge()._removeGraphicalPropertyWithKey(getCrossedCPKey());
}
}
if (connector.getIsStartingLocationFixed()) {
ensurePointConverterIsRegistered();
getEdge()._setGraphicalPropertyForKey(connector.getFixedStartLocation(), getFixedStartLocationKey());
} else {
if (getEdge().hasGraphicalPropertyForKey(getFixedStartLocationKey())) {
getEdge()._removeGraphicalPropertyWithKey(getFixedStartLocationKey());
}
}
if (connector.getIsEndingLocationFixed()) {
ensurePointConverterIsRegistered();
getEdge()._setGraphicalPropertyForKey(connector.getFixedEndLocation(), getFixedEndLocationKey());
} else {
if (getEdge().hasGraphicalPropertyForKey(getFixedEndLocationKey())) {
getEdge()._removeGraphicalPropertyWithKey(getFixedEndLocationKey());
}
}
} else if (getConnector() instanceof CurveConnector && isRegistered()) {
CurveConnector connector = (CurveConnector) getConnector();
ensurePointConverterIsRegistered();
getEdge()._setGraphicalPropertyForKey(connector._getCpPosition(), getStoredCurveCPKey());
if (connector.getAreBoundsAdjustable()) {
ensurePointConverterIsRegistered();
getEdge()._setGraphicalPropertyForKey(connector._getCp1RelativeToStartObject(), getFixedStartLocationKey());
getEdge()._setGraphicalPropertyForKey(connector._getCp2RelativeToEndObject(), getFixedEndLocationKey());
} else {
if (getEdge().hasGraphicalPropertyForKey(getFixedStartLocationKey())) {
getEdge()._removeGraphicalPropertyWithKey(getFixedStartLocationKey());
}
if (getEdge().hasGraphicalPropertyForKey(getFixedEndLocationKey())) {
getEdge()._removeGraphicalPropertyWithKey(getFixedEndLocationKey());
}
}
}
}
@Override
public double getRelativeMiddleSymbolLocation() {
double defaultValue = 1.0;
/*
* if (!getEdge().hasGraphicalPropertyForKey(getRelativeMiddleSymbolLocationKey())) { if (getConnector() instanceof
* RectPolylinConnector) { // GPO: does not always work because polylin is modified when pre-condition is relocated. FGERectPolylin
* polylin = ((RectPolylinConnector)getConnector()).getCurrentPolylin(); defaultValue =
* polylin.getRelativeLocation(polylin.getBiggestSegment().getMiddle());
* System.err.println(defaultValue+" "+polylin.getSegmentNb()); } }
*/
if (getEdge().hasGraphicalPropertyForKey(getOldRelativeMiddleSymbolLocationKey())) {
defaultValue = getEdge()._doubleGraphicalPropertyForKey(getOldRelativeMiddleSymbolLocationKey(), defaultValue);
getEdge()._removeGraphicalPropertyWithKey(getOldRelativeMiddleSymbolLocationKey());
}
return getEdge()._doubleGraphicalPropertyForKey(getRelativeMiddleSymbolLocationKey(), defaultValue);
}
@Override
public void setRelativeMiddleSymbolLocation(double relativeMiddleSymbolLocation) {
getEdge()._setGraphicalPropertyForKey(relativeMiddleSymbolLocation, getRelativeMiddleSymbolLocationKey());
}
private boolean isPolylinConverterRegistered = false;
private void ensurePolylinConverterIsRegistered() {
if (!isPolylinConverterRegistered) {
if (getEdge().getProject().getStringEncoder()._converterForClass(FGERectPolylin.class) == null) {
getEdge().getProject().getStringEncoder()._addConverter(RECT_POLYLIN_CONVERTER);
}
isPolylinConverterRegistered = true;
}
}
private boolean isPointConverterRegistered = false;
private void ensurePointConverterIsRegistered() {
if (!isPointConverterRegistered) {
if (getEdge().getProject().getStringEncoder()._converterForClass(FGEPoint.class) == null) {
getEdge().getProject().getStringEncoder()._addConverter(POINT_CONVERTER);
}
isPointConverterRegistered = true;
}
}
public class ResetLayout extends MouseClickControl {
public ResetLayout() {
super("ResetLayout", MouseButton.LEFT, 2, new CustomClickControlAction() {
@Override
public boolean handleClick(GraphicalRepresentation<?> graphicalRepresentation, DrawingController<?> controller,
java.awt.event.MouseEvent event) {
// logger.info("Reset layout for edge");
resetLayout();
return true;
}
}, false, false, false, false);
}
}
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
// logger.info(">>>>>>>>>>> Notified "+dataModification+" for "+observable);
if (observable == getModel()) {
if (dataModification instanceof PostInserted || dataModification instanceof PostRemoved) {
getDrawing().updateGraphicalObjectsHierarchy();
} else if (dataModification instanceof WKFAttributeDataModification) {
String propertyName = ((WKFAttributeDataModification) dataModification).propertyName();
if (FlexoPostCondition.EDGE_REPRESENTATION.equals(propertyName)) {
updatePropertiesFromWKFPreferences();
refreshConnector();
} else if ("isConditional".equals(propertyName)) {
refreshConnector(true);
} else if ("isDefaultFlow".equals(((WKFAttributeDataModification) dataModification).propertyName())) {
refreshConnector(true);
} else if (WKFEdge.LOCATION_CONSTRAINT_FLAG.equals(propertyName) && (Boolean) dataModification.newValue()) {
refreshConnector(true);
}
} else if (dataModification instanceof NameChanged) {
notifyAttributeChange(org.openflexo.fge.GraphicalRepresentation.Parameters.text);
} else if ("hideWhenInduced".equals(dataModification.propertyName())) {
getDrawing().updateGraphicalObjectsHierarchy();
} else if (RepresentableFlexoModelObject.getBgColorKeyForContext(BASIC_PROCESS_EDITOR).equals(dataModification.propertyName())
|| RepresentableFlexoModelObject.getTextColorKeyForContext(BASIC_PROCESS_EDITOR)
.equals(dataModification.propertyName())) {
updatePropertiesFromWKFPreferences();
}
}
}
public boolean isInduced() {
return isInduced;
}
public boolean isInsideSameActionPetriGraph() {
return getPostCondition() != null
&& getPostCondition().getStartNode() instanceof ActionNode
&& getPostCondition().getNextNode() instanceof ActionNode
&& ((ActionNode) getPostCondition().getStartNode()).getParentPetriGraph() == ((ActionNode) getPostCondition().getNextNode())
.getParentPetriGraph();
}
@Override
public void updatePropertiesFromWKFPreferences() {
EdgeRepresentation type = (EdgeRepresentation) getEdge().getWorkflow().getConnectorRepresentation(
WKFPreferences.getConnectorRepresentation());
if (isInsideSameActionPetriGraph()) {
type = EdgeRepresentation.CURVE;
}
context = null;
TextStyle ts = TextStyle.makeTextStyle(getDrawable().getTextColor(BASIC_PROCESS_EDITOR, Color.BLACK), getEdgeFont().getFont());
ts.setBackgroundColor(getDrawable().getBgColor(BASIC_PROCESS_EDITOR, Color.WHITE));
ts.setIsBackgroundColored(true);
setTextStyle(ts);
setConnector(makeConnector(type.getConnectorType()));
}
private FlexoFont getEdgeFont() {
if (getDrawable().getWorkflow() != null) {
return getDrawable().getWorkflow().getEdgeFont(WKFPreferences.getEdgeFont());
} else {
return WKFPreferences.getEdgeFont();
}
}
public static enum EdgeRepresentation implements HasIcon {
RECT_POLYLIN, CURVE, LINE;
@Override
public ImageIcon getIcon() {
if (this == RECT_POLYLIN) {
return org.openflexo.fge.FGEIconLibrary.RECT_POLYLIN_CONNECTOR_ICON;
} else if (this == CURVE) {
return org.openflexo.fge.FGEIconLibrary.CURVE_CONNECTOR_ICON;
} else if (this == LINE) {
return org.openflexo.fge.FGEIconLibrary.LINE_CONNECTOR_ICON;
}
return null;
}
public ConnectorType getConnectorType() {
if (this == RECT_POLYLIN) {
return ConnectorType.RECT_POLYLIN;
} else if (this == CURVE) {
return ConnectorType.CURVE;
} else if (this == LINE) {
return ConnectorType.LINE;
}
return null;
}
}
// Override to implement default automatic layout
public double getDefaultLabelX() {
if (getConnector() instanceof RectPolylinConnector) {
return Math.sin(((RectPolylinConnector) getConnector()).getMiddleSymbolAngle()) * 15;
}
return 0;
}
// Override to implement default automatic layout
public double getDefaultLabelY() {
if (getConnector() instanceof RectPolylinConnector) {
return Math.cos(((RectPolylinConnector) getConnector()).getMiddleSymbolAngle()) * 15;
}
return 0;
}
}