All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.gsi.chart.ui.TilingPane Maven / Gradle / Ivy

package de.gsi.chart.ui;

import java.util.ArrayList;
import java.util.List;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener;
import javafx.scene.Node;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;

import org.kordamp.ikonli.javafx.FontIcon;

/**
 * TilingPane that to mimics HBox-, VBox-, or TilePane layout while consistently maximising it's children and
 * following layout constraints from its parent
 *
 * @author rstein
 */
public class TilingPane extends GridPane {
    protected static final String FONT_AWESOME = "FontAwesome";
    protected static final int FONT_SIZE = 20;
    private final ObjectProperty layout = new SimpleObjectProperty<>(this, "layout", Layout.GRID) {
        @Override
        public void set(final Layout newLayout) {
            if (newLayout == null) {
                throw new IllegalArgumentException("layout must not be null");
            }
            super.set(newLayout);
        }
    };

    public TilingPane() {
        this(Layout.GRID);
    }

    public TilingPane(final Layout layout) {
        this(layout, (Node[]) null);
    }

    public TilingPane(final Layout layout, Node... nodes) {
        super();
        this.layout.set(layout);
        VBox.setVgrow(this, Priority.ALWAYS);
        getChildren().addListener((ListChangeListener) change -> {
            while (change.next()) {
                layoutNormal();
            }
        });

        this.layout.addListener((ch, o, n) -> layoutNormal());

        if (nodes != null) {
            getChildren().addAll(nodes);
        }
    }

    public Layout getLayout() {
        return layoutProperty().get();
    }

    public ObjectProperty layoutProperty() {
        return layout;
    }

    public void setLayout(final Layout value) {
        layoutProperty().set(value);
    }

    @Override
    public String toString() {
        return TilingPane.class.getSimpleName() + "('" + getLayout() + "0')";
    }

    protected int getColumnsCount() {
        final int childCount = getChildren().size();
        if (childCount == 0) {
            return 1;
        }
        switch (getLayout()) {
        case HBOX:
            return childCount;
        case MAXIMISE:
        case VBOX:
            return 1;
        case GRID:
        default:
            if (childCount < 4) {
                return 2;
            }

            return (int) Math.ceil(Math.sqrt(childCount)); // n-columns
        }
    }

    protected void layoutNormal() {
        if (getChildren().isEmpty()) {
            return;
        }
        final int colsCount = getColumnsCount();

        if (getColumnConstraints().size() != colsCount) {
            final List colConstraintList = new ArrayList<>();
            for (int i = 0; i < colsCount; i++) {
                final ColumnConstraints colConstraints = new ColumnConstraints(); // NOPMD
                colConstraints.setPercentWidth(100.0 / colsCount);
                colConstraints.setFillWidth(true);
                colConstraintList.add(colConstraints);
            }
            getColumnConstraints().setAll(colConstraintList);
        }

        int rowIndex = 0;
        int colIndex = 0;
        int childCount = 0;
        final int nChildren = getChildren().size();
        int nColSpan = Math.max(1, colsCount / (nChildren - childCount));
        for (final Node child : getChildren()) {
            GridPane.setFillWidth(child, true);
            GridPane.setFillHeight(child, true);
            GridPane.setColumnIndex(child, colIndex);
            GridPane.setRowIndex(child, rowIndex);

            if ((colIndex == 0) && ((nChildren - childCount) < colsCount)) {
                nColSpan = Math.max(1, colsCount / (nChildren - childCount));
            }
            // last window fills up row
            if (((nChildren - childCount) == 1) && (colIndex < colsCount)) {
                nColSpan = colsCount - colIndex;
            }

            GridPane.setColumnSpan(child, nColSpan);

            colIndex += nColSpan;
            if (colIndex >= colsCount) {
                colIndex = 0;
                rowIndex++;
            }
            childCount++;
        }
    }

    public enum Layout {
        HBOX("HBox", "fas-arrows-alt-h:" + FONT_SIZE),
        VBOX("VBox", "fas-arrows-alt-v:" + FONT_SIZE),
        GRID("Grid", "fas-th:" + FONT_SIZE),
        MAXIMISE("Maximise", "fas-window-maximize:" + FONT_SIZE);

        private final String name;
        private final String iconCode;

        Layout(final String name, final String iconCode) {
            this.name = name;
            this.iconCode = iconCode;
        }

        public Node getIcon() {
            return new FontIcon(iconCode);
        }

        public String getName() {
            return name;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy