/*******************************************************************************
* Copyright (c) 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.mvc.fx.parts;
import org.eclipse.gef.fx.nodes.Connection;
import org.eclipse.gef.geometry.euclidean.Angle;
import org.eclipse.gef.geometry.euclidean.Vector;
import org.eclipse.gef.geometry.planar.BezierCurve;
import org.eclipse.gef.geometry.planar.Point;
import com.google.common.collect.SetMultimap;
import javafx.scene.Node;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;
/**
* An {@link AbstractSegmentHandlePart} with a rectangular
* {@link javafx.scene.shape.Rectangle} visual.
*
* @author mwienand
*
*/
public class RectangleSegmentHandlePart
extends AbstractSegmentHandlePart<javafx.scene.shape.Rectangle> {
/**
* The default width for this part's visualization.
*/
protected static final double DEFAULT_WIDTH = 4;
/**
* The default length for this part's visualization.
*/
protected static final double DEFAULT_LENGTH = 8;
@Override
protected javafx.scene.shape.Rectangle doCreateVisual() {
javafx.scene.shape.Rectangle visual = new javafx.scene.shape.Rectangle();
visual.setTranslateX(-DEFAULT_LENGTH / 2);
visual.setTranslateY(-DEFAULT_WIDTH / 2);
visual.setFill(getMoveFill());
visual.setStroke(getStroke());
visual.setWidth(DEFAULT_LENGTH);
visual.setHeight(DEFAULT_WIDTH);
visual.setStrokeWidth(1);
visual.setStrokeType(StrokeType.OUTSIDE);
return visual;
}
@Override
public void doRefreshVisual(Rectangle visual) {
super.doRefreshVisual(visual);
updateColor();
}
/**
* Updates the color of this part's visualization. If this handle part
* represents a way or end point of an {@link Connection}, it's color will
* be set to indicate whether the handle is connected to another part or
* not.
*/
protected void updateColor() {
// only update when bound to anchorage
SetMultimap<IVisualPart<? extends Node>, String> anchorages = getAnchoragesUnmodifiable();
if (getRoot() == null || anchorages.keySet().size() != 1) {
return;
}
Rectangle visual = getVisual();
// no need to update the color if we are invisible
if (!visual.isVisible()) {
return;
}
if (getSegmentParameter() == 0.5) {
// move handle in the middle of a segment
visual.setFill(getMoveFill());
} else if (getSegmentParameter() != 0.0
&& getSegmentParameter() != 1.0) {
// quarter handles (creation)
visual.setFill(getInsertFill());
visual.setWidth(DEFAULT_LENGTH * 4d / 5d);
visual.setHeight(DEFAULT_WIDTH * 4d / 5d);
visual.setTranslateX(-DEFAULT_LENGTH / 2d + DEFAULT_LENGTH / 10d);
visual.setTranslateY(-DEFAULT_WIDTH / 2d + DEFAULT_WIDTH / 10d);
} else {
visual.setTranslateX(-DEFAULT_LENGTH / 2);
visual.setTranslateY(-DEFAULT_WIDTH / 2);
visual.setWidth(DEFAULT_LENGTH);
visual.setHeight(DEFAULT_WIDTH);
// end point handles
boolean connected = false;
IVisualPart<? extends Node> targetPart = anchorages.keySet()
.iterator().next();
if (targetPart.getVisual() instanceof Connection) {
Connection connection = (Connection) targetPart.getVisual();
if (getSegmentIndex() + getSegmentParameter() == 0.0) {
// handle at start point
connected = connection.isStartConnected();
} else if (getSegmentParameter()
+ getSegmentIndex() == getSegmentsInScene().length) {
// handle at end point
connected = connection.isEndConnected();
}
}
// update color according to connected state
if (connected) {
visual.setFill(getConnectedFill());
} else {
visual.setFill(getMoveFill());
}
}
}
@Override
protected void updateLocation(Rectangle visual) {
super.updateLocation(visual);
BezierCurve bezierSegmentInParent = getBezierSegmentInParent();
if (bezierSegmentInParent == null) {
return;
}
Point direction = bezierSegmentInParent.getDerivative()
.get(getSegmentParameter());
Vector directionVector = new Vector(direction.x, direction.y);
if (directionVector.isNull()) {
return;
}
Vector xVector = new Vector(1, 0);
Angle angleCcw = xVector.getAngleCCW(directionVector);
visual.setRotate(angleCcw.deg());
}
}