package de.gsi.chart.ui; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.value.ChangeListener; import javafx.collections.ListChangeListener; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; import javafx.scene.layout.CornerRadii; import javafx.scene.layout.FlowPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import de.gsi.chart.Chart; /** * tool bar for plugins to add their controls (if necessary) * * @author rstein */ public class ToolBarFlowPane extends FlowPane { private static final int DEFAULT_TOOLBAR_HEIGHT = 28; private static final double CORNER_SPACE_PADDING_FACTOR = 1.8; private Color defaultColour = Color.web("#f4f4f4", 0.85).deriveColor(0, 1.0, .94, 1.0); private Color selectedColour = Color.web("#f4f4f4", 0.85).deriveColor(0, 1.0, .92, 1.0); private Insets toolBarPadding = new Insets(1, 12.5, 5, 12.5); private final DoubleProperty cornerRadius = new SimpleDoubleProperty(this, "cornerRadius", 25.0); private final Chart chart; /** * @param chart the associated chart pane */ public ToolBarFlowPane(final Chart chart) { super(); this.chart = chart; this.setId(this.getClass().getSimpleName() + "(Chart)"); // N.B. not a unique name but for testing this suffices StackPane.setAlignment(this, Pos.TOP_CENTER); this.setPrefHeight(USE_COMPUTED_SIZE); this.setBackground(new Background(new BackgroundFill(defaultColour, CornerRadii.EMPTY, Insets.EMPTY))); this.setMinHeight(0); this.setShape(ToolBarShapeHelper.getToolBarShape(this.getWidth(), this.getHeight(), cornerRadius.get())); this.setAlignment(Pos.TOP_CENTER); this.setMinWidth(0); setPadding(calculateInsets()); // NOPMD HBox.setHgrow(this, Priority.NEVER); ChangeListener<Number> toolBarSizeListener = (ch, o, n) -> { if (n.equals(o)) { return; } adjustToolBarWidth(); }; this.widthProperty().addListener(toolBarSizeListener); this.heightProperty().addListener(toolBarSizeListener); chart.getCanvas().widthProperty().addListener(toolBarSizeListener); cornerRadius.addListener(toolBarSizeListener); } private void adjustToolBarWidth() { final double maxLength = 0.60 * chart.getWidth(); double length = 0.0; for (Node node : this.getChildren()) { length += node.prefWidth(DEFAULT_TOOLBAR_HEIGHT); } length += 4 * cornerRadius.get(); final double wrapLength = Math.min(maxLength, Math.max(length, 50)); this.setPrefWrapLength(wrapLength); this.setMaxWidth(wrapLength); this.setWidth(maxLength); final int height = (int) Math.max(getHeight(), Math.max(getBoundsInParent().getHeight(), getBoundsInLocal().getHeight())); this.setMinHeight(height); this.setShape(ToolBarShapeHelper.getToolBarShape(wrapLength, height, cornerRadius.get())); } /** * Calculate the tool bar insets. It is called on tool bar width or it's contents changes and on corner radius * changes. * * @return Insets for the tool bar pane */ protected Insets calculateInsets() { final double roundCornerSpace = CORNER_SPACE_PADDING_FACTOR * cornerRadius.get(); final double sidePaddingRight = Math.max(roundCornerSpace, toolBarPadding.getRight()); final double sidePaddingLeft = Math.max(roundCornerSpace, toolBarPadding.getLeft()); return new Insets(toolBarPadding.getTop(), sidePaddingRight, toolBarPadding.getBottom(), sidePaddingLeft); } public DoubleProperty cornerRadiusProperty() { return cornerRadius; } public Color getToolBarDefaultColor() { return this.defaultColour; } public Insets getToolBarInsets() { return toolBarPadding; } public Color getToolBarSelectedColor() { return this.selectedColour; } public void registerListener() { this.getChildren().addListener((ListChangeListener.Change<? extends Node> c) -> adjustToolBarWidth()); setOnMouseClicked(mevt -> { if (chart.toolBarPinnedProperty().isBound()) { return; } chart.setToolBarPinned(!chart.isToolBarPinned()); }); chart.toolBarPinnedProperty().addListener((obj, valOld, valNew) -> { if (valNew) { chart.setPinnedSide(javafx.geometry.Side.TOP); this.setBackground(new Background(new BackgroundFill(selectedColour, CornerRadii.EMPTY, Insets.EMPTY))); } else { chart.setPinnedSide(null); this.setBackground(new Background(new BackgroundFill(defaultColour, CornerRadii.EMPTY, Insets.EMPTY))); } chart.requestLayout(); }); } public void setToolBarDefaultColor(final Color color) { this.defaultColour = color; } public void setToolBarInsets(final Insets padding) { toolBarPadding = padding; this.setPadding(toolBarPadding); } public void setToolBarSelectedColor(final Color color) { this.selectedColour = color; } }