/*******************************************************************************
* Copyright (c) 2015, 2016 itemis AG and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Matthias Wienand (itemis AG) - initial API and implementation
*
*******************************************************************************/
package org.eclipse.gef.fx.examples;
import org.eclipse.gef.fx.anchors.AnchorKey;
import org.eclipse.gef.fx.anchors.DynamicAnchor;
import org.eclipse.gef.fx.anchors.DynamicAnchor.AnchoredReferencePoint;
import org.eclipse.gef.fx.nodes.InfiniteCanvas;
import org.eclipse.gef.geometry.planar.Point;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.MapChangeListener;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.Circle;
import javafx.scene.shape.ClosePath;
import javafx.scene.shape.CubicCurve;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.QuadCurve;
import javafx.scene.shape.QuadCurveTo;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
public class DynamicAnchorShapeSnippet extends AbstractFxExample {
public static void main(String[] args) {
launch();
}
private Circle refPoint;
private Line anchorLine;
private DynamicAnchor anchor;
private AnchorKey anchorKey;
private MapChangeListener<AnchorKey, Point> anchorPositionChangeListener = new MapChangeListener<AnchorKey, Point>() {
@Override
public void onChanged(
javafx.collections.MapChangeListener.Change<? extends AnchorKey, ? extends Point> change) {
if (change.getKey() == anchorKey) {
Point anchorPoint = change.getValueAdded();
if (anchorPoint != null) {
anchorLine.setStartX(anchorPoint.x);
anchorLine.setStartY(anchorPoint.y);
}
}
}
};
public DynamicAnchorShapeSnippet() {
super("DynamicAnchor for JavaFX Shape");
}
@Override
public Scene createScene() {
InfiniteCanvas root = new InfiniteCanvas();
Scene scene = new Scene(root, 500, 400);
// create choice box to select shape
ChoiceBox<String> shapeChoiceBox = new ChoiceBox<>();
shapeChoiceBox.getItems().addAll("Arc", "Circle", "CubicCurve",
"Ellipse", "Line", "Path", "Polygon", "Polyline", "QuadCurve",
"Rectangle", "Star Polygon");
shapeChoiceBox.setLayoutX(10);
shapeChoiceBox.setLayoutY(10);
root.getContentGroup().getChildren().add(shapeChoiceBox);
// create group containing the selected shape
final Group selectedShapeGroup = new Group();
selectedShapeGroup.setLayoutX(150);
selectedShapeGroup.setLayoutY(150);
selectedShapeGroup.setScaleX(3);
selectedShapeGroup.setScaleY(3);
root.getContentGroup().getChildren().add(selectedShapeGroup);
// create reference point
refPoint = new Circle(3.5);
refPoint.setStroke(Color.BLACK);
refPoint.setFill(Color.RED);
root.getContentGroup().getChildren().add(refPoint);
// create group containing the anchor line
anchorLine = new Line();
anchorLine.setStroke(Color.RED);
anchorLine.setStrokeWidth(1.5);
anchorLine.setFill(null);
root.getContentGroup().getChildren().add(anchorLine);
// register for ref point changes
anchorKey = new AnchorKey(anchorLine, "ref");
refPoint.boundsInParentProperty()
.addListener(new ChangeListener<Bounds>() {
@Override
public void changed(
javafx.beans.value.ObservableValue<? extends Bounds> observable,
Bounds oldValue, Bounds newValue) {
Point2D refInScene = refPoint.localToScene(
refPoint.getCenterX(), refPoint.getCenterY());
Point2D refInLocal = anchorLine
.sceneToLocal(refInScene);
if (anchor != null) {
anchor.getComputationParameter(anchorKey,
AnchoredReferencePoint.class)
.set(new Point(refInLocal.getX(),
refInLocal.getY()));
}
anchorLine.setEndX(refInLocal.getX());
anchorLine.setEndY(refInLocal.getY());
}
});
refPoint.relocate(300, 300);
// register relocate on drag for refPoint
refPoint.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Point2D positionInParent = refPoint.getParent()
.sceneToLocal(event.getSceneX(), event.getSceneY());
refPoint.relocate(positionInParent.getX(),
positionInParent.getY());
}
});
// register for choice changes
shapeChoiceBox.valueProperty()
.addListener(new ChangeListener<String>() {
@Override
public void changed(
ObservableValue<? extends String> observable,
String oldValue, String newValue) {
showShape(selectedShapeGroup, newValue);
}
});
// display initial shape
shapeChoiceBox.setValue("Star Polygon");
return scene;
}
protected void showShape(Group selectedShapeGroup, String item) {
// unregister anchor
if (anchor != null) {
anchor.positionsUnmodifiableProperty()
.removeListener(anchorPositionChangeListener);
anchor.detach(anchorKey);
anchor = null;
}
// clear shape box
selectedShapeGroup.getChildren().clear();
// determine shape geometry
Shape shape = null;
if ("Arc".equals(item)) {
shape = new Arc(50, 50, 20, 20, 15, 135);
} else if ("Circle".equals(item)) {
shape = new Circle(50, 50, 20);
} else if ("CubicCurve".equals(item)) {
shape = new CubicCurve(10, 80, 10, 10, 80, 10, 80, 80);
} else if ("Ellipse".equals(item)) {
shape = new Ellipse(50, 50, 30, 15);
} else if ("Line".equals(item)) {
shape = new Line(10, 10, 80, 80);
} else if ("Path".equals(item)) {
shape = new Path(new MoveTo(10, 10), new LineTo(80, 10),
new QuadCurveTo(50, 50, 80, 80),
new CubicCurveTo(50, 50, 30, 100, 10, 80), new ClosePath());
} else if ("Polygon".equals(item)) {
shape = new Polygon(10, 10, 80, 50, 10, 80);
} else if ("Polyline".equals(item)) {
shape = new Polyline(10, 10, 80, 50, 10, 80);
} else if ("QuadCurve".equals(item)) {
shape = new QuadCurve(10, 80, 50, 10, 80, 80);
} else if ("Rectangle".equals(item)) {
shape = new Rectangle(10, 10, 70, 40);
} else if ("Star Polygon".equals(item)) {
shape = new Polygon(50, 10, 60, 40, 90, 50, 60, 60, 50, 90, 40, 60,
10, 50, 40, 40);
} else {
throw new IllegalStateException(
"Unsupported selection: <" + item + ">.");
}
// apply shape style
shape.setStrokeWidth(3.5);
shape.setStroke(Color.BLACK);
shape.setFill(Color.GREY);
// add to content group
selectedShapeGroup.getChildren().add(shape);
// create anchor
anchor = new DynamicAnchor(shape);
Point2D refInScene = refPoint.localToScene(refPoint.getCenterX(),
refPoint.getCenterY());
Point2D refInLocal = anchorLine.sceneToLocal(refInScene);
anchor.getComputationParameter(anchorKey,
AnchoredReferencePoint.class)
.set(new Point(refInLocal.getX(), refInLocal.getY()));
anchor.positionsUnmodifiableProperty()
.addListener(anchorPositionChangeListener);
anchor.attach(anchorKey);
}
}