/* * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javafx.scene.control; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import com.sun.javafx.collections.UnmodifiableListSet; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectPropertyBase; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.WritableValue; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.geometry.Side; import javafx.scene.AccessibleAttribute; import javafx.scene.AccessibleRole; import javafx.css.StyleableDoubleProperty; import javafx.css.CssMetaData; import javafx.css.PseudoClass; import javafx.css.converter.SizeConverter; import javafx.scene.control.skin.TabPaneSkin; import javafx.beans.DefaultProperty; import javafx.css.Styleable; import javafx.css.StyleableProperty; import javafx.scene.Node; /** *
A control that allows switching between a group of {@link Tab Tabs}. Only one tab * is visible at a time. Tabs are added to the TabPane by using the {@link #getTabs}.
* *Tabs in a TabPane can be positioned at any of the four sides by specifying the * {@link Side}.
* *A TabPane has two modes floating or recessed. Applying the styleclass STYLE_CLASS_FLOATING * will change the TabPane mode to floating.
* *The tabs width and height can be set to a specific size by * setting the min and max for height and width. TabPane default width will be * determined by the largest content width in the TabPane. This is the same for the height. * If a different size is desired the width and height of the TabPane can * be overridden by setting the min, pref and max size.
* *When the number of tabs do not fit the TabPane a menu button will appear on the right. * The menu button is used to select the tabs that are currently not visible. *
* *Example:
*
* TabPane tabPane = new TabPane();
* Tab tab = new Tab();
* tab.setText("new tab");
* tab.setContent(new Rectangle(200,200, Color.LIGHTSTEELBLUE));
* tabPane.getTabs().add(tab);
*
*
* @see Tab
* @since JavaFX 2.0
*/
@DefaultProperty("tabs")
public class TabPane extends Control {
private static final double DEFAULT_TAB_MIN_WIDTH = 0;
private static final double DEFAULT_TAB_MAX_WIDTH = Double.MAX_VALUE;
private static final double DEFAULT_TAB_MIN_HEIGHT = 0;
private static final double DEFAULT_TAB_MAX_HEIGHT = Double.MAX_VALUE;
/**
* TabPane mode will be changed to floating allowing the TabPane
* to be placed alongside other control.
*/
public static final String STYLE_CLASS_FLOATING = "floating";
/**
* Constructs a new TabPane.
*/
public TabPane() {
this((Tab[])null);
}
/**
* Constructs a new TabPane with the given tabs set to show.
*
* @param tabs The {@link Tab tabs} to display inside the TabPane.
* @since JavaFX 8u40
*/
public TabPane(Tab... tabs) {
getStyleClass().setAll("tab-pane");
setAccessibleRole(AccessibleRole.TAB_PANE);
setSelectionModel(new TabPaneSelectionModel(this));
this.tabs.addListener((ListChangeListenerThe tabs to display in this TabPane. Changing this ObservableList will * immediately result in the TabPane updating to display the new contents * of this ObservableList.
* *If the tabs ObservableList changes, the selected tab will remain the previously * selected tab, if it remains within this ObservableList. If the previously * selected tab is no longer in the tabs ObservableList, the selected tab will * become the first tab in the ObservableList.
* @return the list of tabs */ public final ObservableListSets the model used for tab selection. By changing the model you can alter * how the tabs are selected and which tabs are first or last.
* @param value the selection model */ public final void setSelectionModel(SingleSelectionModelGets the model used for tab selection.
* @return the model used for tab selection */ public final SingleSelectionModelThe position to place the tabs in this TabPane. Whenever this changes * the TabPane will immediately update the location of the tabs to reflect * this.
* * @param value the side */ public final void setSide(Side value) { sideProperty().set(value); } /** * The current position of the tabs in the TabPane. The default position * for the tabs is Side.Top. * * @return The current position of the tabs in the TabPane. */ public final Side getSide() { return side == null ? Side.TOP : side.get(); } /** * The position of the tabs in the TabPane. * @return the side property */ public final ObjectPropertySpecifies how the TabPane handles tab closing from an end-users * perspective. The options are:
* *Refer to the {@link TabClosingPolicy} enumeration for further details.
* * The default closing policy is TabClosingPolicy.SELECTED_TAB * @param value the closing policy */ public final void setTabClosingPolicy(TabClosingPolicy value) { tabClosingPolicyProperty().set(value); } /** * The closing policy for the tabs. * * @return The closing policy for the tabs. */ public final TabClosingPolicy getTabClosingPolicy() { return tabClosingPolicy == null ? TabClosingPolicy.SELECTED_TAB : tabClosingPolicy.get(); } /** * The closing policy for the tabs. * @return the closing policy property */ public final ObjectPropertySpecifies whether the graphic inside a Tab is rotated or not, such * that it is always upright, or rotated in the same way as the Tab text is.
* *By default rotateGraphic is set to false, to represent the fact that * the graphic isn't rotated, resulting in it always appearing upright. If * rotateGraphic is set to {@code true}, the graphic will rotate such that it * rotates with the tab text.
* * @param value a flag indicating whether to rotate the graphic */ public final void setRotateGraphic(boolean value) { rotateGraphicProperty().set(value); } /** * Returns {@code true} if the graphic inside a Tab is rotated. The * default is {@code false} * * @return the rotatedGraphic state. */ public final boolean isRotateGraphic() { return rotateGraphic == null ? false : rotateGraphic.get(); } /** * The rotateGraphic state of the tabs in the TabPane. * @return the rotateGraphic property */ public final BooleanProperty rotateGraphicProperty() { if (rotateGraphic == null) { rotateGraphic = new SimpleBooleanProperty(this, "rotateGraphic", false); } return rotateGraphic; } private DoubleProperty tabMinWidth; /** *The minimum width of the tabs in the TabPane. This can be used to limit * the length of text in tabs to prevent truncation. Setting the min equal * to the max will fix the width of the tab. By default the min equals to the max. * * This value can also be set via CSS using {@code -fx-tab-min-width} * *
* @param value the minimum width of the tabs */ public final void setTabMinWidth(double value) { tabMinWidthProperty().setValue(value); } /** * The minimum width of the tabs in the TabPane. * * @return The minimum width of the tabs */ public final double getTabMinWidth() { return tabMinWidth == null ? DEFAULT_TAB_MIN_WIDTH : tabMinWidth.getValue(); } /** * The minimum width of the tabs in the TabPane. * @return the minimum width property */ public final DoubleProperty tabMinWidthProperty() { if (tabMinWidth == null) { tabMinWidth = new StyleableDoubleProperty(DEFAULT_TAB_MIN_WIDTH) { @Override public CssMetaDataSpecifies the maximum width of a tab. This can be used to limit * the length of text in tabs. If the tab text is longer than the maximum * width the text will be truncated. Setting the max equal * to the min will fix the width of the tab. By default the min equals to the max * * This value can also be set via CSS using {@code -fx-tab-max-width}.
*/ private DoubleProperty tabMaxWidth; public final void setTabMaxWidth(double value) { tabMaxWidthProperty().setValue(value); } /** * The maximum width of the tabs in the TabPane. * * @return The maximum width of the tabs */ public final double getTabMaxWidth() { return tabMaxWidth == null ? DEFAULT_TAB_MAX_WIDTH : tabMaxWidth.getValue(); } /** * The maximum width of the tabs in the TabPane. * @return the maximum width property */ public final DoubleProperty tabMaxWidthProperty() { if (tabMaxWidth == null) { tabMaxWidth = new StyleableDoubleProperty(DEFAULT_TAB_MAX_WIDTH) { @Override public CssMetaDataThe minimum height of the tabs in the TabPane. This can be used to limit * the height in tabs. Setting the min equal to the max will fix the height * of the tab. By default the min equals to the max. * * This value can also be set via CSS using {@code -fx-tab-min-height} *
* @param value the minimum height of the tabs */ public final void setTabMinHeight(double value) { tabMinHeightProperty().setValue(value); } /** * The minimum height of the tabs in the TabPane. * * @return the minimum height of the tabs */ public final double getTabMinHeight() { return tabMinHeight == null ? DEFAULT_TAB_MIN_HEIGHT : tabMinHeight.getValue(); } /** * The minimum height of the tab. * @return the minimum height property */ public final DoubleProperty tabMinHeightProperty() { if (tabMinHeight == null) { tabMinHeight = new StyleableDoubleProperty(DEFAULT_TAB_MIN_HEIGHT) { @Override public CssMetaDataThe maximum height if the tabs in the TabPane. This can be used to limit * the height in tabs. Setting the max equal to the min will fix the height * of the tab. By default the min equals to the max. * * This value can also be set via CSS using -fx-tab-max-height *
*/ private DoubleProperty tabMaxHeight; public final void setTabMaxHeight(double value) { tabMaxHeightProperty().setValue(value); } /** * The maximum height of the tabs in the TabPane. * * @return The maximum height of the tabs */ public final double getTabMaxHeight() { return tabMaxHeight == null ? DEFAULT_TAB_MAX_HEIGHT : tabMaxHeight.getValue(); } /** *The maximum height of the tabs in the TabPane.
* @return the maximum height of the tabs */ public final DoubleProperty tabMaxHeightProperty() { if (tabMaxHeight == null) { tabMaxHeight = new StyleableDoubleProperty(DEFAULT_TAB_MAX_HEIGHT) { @Override public CssMetaDataThis specifies how the TabPane handles tab closing from an end-users * perspective. The options are:
* *