/******************************************************************************* * Copyright (c) 2015 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.snippets; import java.util.Arrays; import java.util.List; import org.eclipse.gef.fx.nodes.GeometryNode; import org.eclipse.gef.fx.nodes.InfiniteCanvas; import org.eclipse.gef.geometry.planar.RoundedRectangle; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; import javafx.geometry.Bounds; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Slider; import javafx.scene.control.TextField; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Rectangle; import javafx.scene.shape.StrokeType; import javafx.scene.text.Text; import javafx.stage.Stage; public class RoundedRectangleSnippet extends Application { static class RectData { public double arcWidthPercentage; public double arcHeightPercentage; public RectData(double aw, double ah) { arcWidthPercentage = aw; arcHeightPercentage = ah; } } public static void main(String[] args) { launch(); } private List<RectData> getRectData() { return Arrays.asList( new RectData[] { new RectData(0, 0), new RectData(0.125, 0), new RectData(0, 0.125), new RectData(0.125, 0.125), new RectData(0.25, 0.25), new RectData(0.5, 0.5), new RectData(0.75, 0.75), new RectData(1, 1), new RectData(1.5, 1.5), new RectData(2, 2) }); } @Override public void start(Stage primaryStage) throws Exception { InfiniteCanvas root = new InfiniteCanvas(); Scene scene = new Scene(root, 600, 500); final int PAD = 20; final int HEIGHT = 100; // create width slider Slider widthSlider = new Slider(50, 200, 100); widthSlider.setPrefWidth(200); // create entry for width slider value TextField widthSliderText = new TextField(); widthSliderText.textProperty() .bind(widthSlider.valueProperty().asString()); widthSliderText.setPrefWidth(50); // layout slider and textfield in a box HBox hBox = new HBox(); hBox.setStyle( "-fx-background-color: white; -fx-border-color: black; -fx-border-width: 1px;"); hBox.getChildren().addAll(new Text("Width: "), widthSlider, widthSliderText); root.getOverlayGroup().getChildren().add(hBox); final double x = PAD; double y = PAD; ObservableList<Node> contents = root.getContentGroup().getChildren(); for (RectData rd : getRectData()) { // create half transparent background rect Rectangle bgRect = new Rectangle(x, y, 100, HEIGHT); bgRect.widthProperty().bind(widthSlider.valueProperty()); bgRect.setStroke(null); bgRect.setFill(new Color(1.0, 0, 0, 0.5)); contents.add(bgRect); // create rectangle with arcs and inside stroke final Rectangle rect = new Rectangle(x, y, 100, HEIGHT); rect.widthProperty().bind(widthSlider.valueProperty()); rect.arcWidthProperty().bind(widthSlider.valueProperty() .multiply(rd.arcWidthPercentage)); rect.setArcHeight(rd.arcHeightPercentage * HEIGHT); rect.setStroke(Color.BLACK); rect.setStrokeType(StrokeType.INSIDE); rect.setFill(Color.BROWN); contents.add(rect); // create vertices if (rd.arcHeightPercentage > 0 && rd.arcWidthPercentage > 0) { double awp = rd.arcWidthPercentage > 1 ? 1 : rd.arcWidthPercentage; double ah = rect.getArcHeight() > rect.getHeight() ? rect.getHeight() : rect.getArcHeight(); contents.add(new Circle(x, y + rect.getHeight() - ah / 2, 2.5, Color.CYAN)); contents.add(new Circle(x, y + rect.getHeight() / 2, 2.5, Color.CYAN)); contents.add(new Circle(x, y + ah / 2, 2.5, Color.CYAN)); Circle dot = new Circle(x + rect.getWidth() / 2, y, 2.5, Color.CYAN); dot.centerXProperty() .bind(widthSlider.valueProperty().divide(2).add(x)); contents.add(dot); dot = new Circle(x, y, 2.5, Color.CYAN); dot.centerXProperty().bind(widthSlider.valueProperty() .multiply(awp).divide(2).add(x)); contents.add(dot); dot = new Circle(x, y, 2.5, Color.CYAN); dot.centerXProperty() .bind(widthSlider.valueProperty().add(x) .subtract(widthSlider.valueProperty() .multiply(awp).divide(2))); contents.add(dot); } // create geometry node containing a rounded rectangle for // comparison RoundedRectangle rr = new RoundedRectangle( rect.getX() + rect.getWidth() + PAD * 2, rect.getY(), rect.getWidth(), rect.getHeight(), rect.getArcWidth(), rect.getArcHeight()); final GeometryNode<RoundedRectangle> geometryNode = new GeometryNode<>( rr); geometryNode.setStrokeType(StrokeType.INSIDE); geometryNode.setStroke(Color.BLACK); geometryNode.setFill(Color.BROWN); contents.add(geometryNode); rect.layoutBoundsProperty() .addListener(new ChangeListener<Bounds>() { @Override public void changed( ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) { RoundedRectangle newGeometry = geometryNode .getGeometry().getCopy() .setX(rect.getX() + rect.getWidth() + PAD * 2) .setWidth(rect.getWidth()) .setHeight(rect.getHeight()) .setArcWidth(rect.getArcWidth()) .setArcHeight(rect.getArcHeight()); geometryNode.setGeometry(newGeometry); } }); // create labels showing the stats Text arcWidthLabel = new Text( "arc-width: " + (rd.arcWidthPercentage * 100) + "%"); Text arcHeightLabel = new Text( "arc-height: " + (rd.arcHeightPercentage * 100) + "%"); VBox vBox = new VBox(); vBox.getChildren().addAll(arcWidthLabel, arcHeightLabel); vBox.layoutXProperty() .bind(widthSlider.valueProperty().multiply(2).add(PAD * 4)); vBox.setLayoutY(y); contents.add(vBox); // increase y coord y += HEIGHT + PAD; } primaryStage.setScene(scene); primaryStage.sizeToScene(); primaryStage.setTitle( "JavaFX Rectangle vs. GeometryNode<RoundedRectangle>"); primaryStage.show(); } }