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

org.jhotdraw8.fxcontrols.dock.TabPaneTrack Maven / Gradle / Ivy

The newest version!
/*
 * @(#)TabPaneTrack.java
 * Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
 */
package org.jhotdraw8.fxcontrols.dock;

import javafx.beans.property.BooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.Node;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.jhotdraw8.fxbase.binding.CustomBinding;
import org.jspecify.annotations.Nullable;

/**
 * This track stacks its children on the Z-axis into a tab pane.
 */
public class TabPaneTrack extends AbstractDockParent implements Track {

    private final TabPane tabPane = new TabPane();
    private final ResizePane resizePane = new ResizePane();

    static class MyTab extends Tab {
        private final DockableDragHandler dockableDragHandler;
        private final DockChild dockChild;

        MyTab(DockChild dockChild, @Nullable String text, @Nullable Node graphic) {
            super(text, graphic);
            this.dockChild = dockChild;
            if (dockChild instanceof Dockable) {
                dockableDragHandler = new DockableDragHandler((Dockable) dockChild);
            } else {
                dockableDragHandler = null;
            }
        }

        BooleanProperty showingProperty() {
            return dockChild.showingProperty();
        }

        void dispose() {
            if (dockableDragHandler != null) {
                dockableDragHandler.dispose();
            }
        }

        @Override
        public String toString() {
            return "MyTab@" + Integer.toHexString(hashCode()) + "{" +
                    dockChild +
                    '}';
        }
    }

    @SuppressWarnings("this-escape")
    public TabPaneTrack() {
        getChildren().add(resizePane);
        resizePane.setCenter(tabPane);
        SplitPane.setResizableWithParent(this, Boolean.FALSE);
        VBox.setVgrow(this, Priority.NEVER);
        HBox.setHgrow(this, Priority.NEVER);

        tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
        dockParentProperty().addListener(onParentChanged());
        CustomBinding.bindContentBidirectional(tabPane.getTabs(), getDockChildren(),
                this::makeTab, k -> ((MyTab) k).dispose(),
                tab -> ((MyTab) tab).dockChild, null);
        CustomBinding.bind(tabPane.getSelectionModel().selectedItemProperty(),
                t -> ((MyTab) t).showingProperty(), showingProperty(),
                false);
    }

    protected ChangeListener onParentChanged() {
        return (o, oldv, newv) -> {
            resizePane.setUserResizable(newv != null && !newv.isResizesDockChildren());
            resizePane.setResizeAxis(newv == null ? TrackAxis.Y : newv.getDockAxis());
        };
    }

    private MyTab makeTab(DockChild c) {
        if (c instanceof Dockable k) {
            MyTab tab = new MyTab(k, k.getText(), k.getNode());
            tab.graphicProperty().bind(CustomBinding.compute(k::getGraphic, k.graphicProperty(), editableProperty()));
            return tab;
        } else {
            return new MyTab(c, "-", c.getNode());
        }
    }


    @Override
    public TrackAxis getDockAxis() {
        return TrackAxis.Z;
    }

    @Override
    public boolean isResizesDockChildren() {
        return true;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy