1 /* 2 * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.control; 27 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.List; 31 32 import javafx.beans.DefaultProperty; 33 import javafx.beans.property.ObjectProperty; 34 import javafx.beans.value.WritableValue; 35 import javafx.collections.FXCollections; 36 import javafx.collections.ObservableList; 37 import javafx.geometry.Orientation; 38 import javafx.scene.AccessibleRole; 39 import javafx.scene.Node; 40 import javafx.css.StyleableObjectProperty; 41 import javafx.css.CssMetaData; 42 import javafx.css.PseudoClass; 43 44 import javafx.css.converter.EnumConverter; 45 import javafx.scene.control.skin.ToolBarSkin; 46 47 import javafx.css.Styleable; 48 import javafx.css.StyleableProperty; 49 50 /** 51 * <p> 52 * A ToolBar is a control which displays items horizontally 53 * or vertically. The most common items to place within a {@code ToolBar} 54 * are {@link Button Buttons}, {@link ToggleButton ToggleButtons} and 55 * {@link Separator Separators}, but you are not restricted to just these, and 56 * can insert any {@link Node} into them. 57 * </p> 58 * 59 * <p>If there are too many items to fit in the ToolBar an overflow button will appear. 60 * The overflow button allows you to select items that are not currently visible in the toolbar. 61 * </p> 62 * <p> 63 * ToolBar sets focusTraversable to false. 64 * </p> 65 * 66 * <p> 67 * Example of a horizontal ToolBar with eight buttons separated with two vertical separators. 68 * </p> 69 * <pre><code> 70 * ToolBar toolBar = new ToolBar( 71 * new Button("New"), 72 * new Button("Open"), 73 * new Button("Save"), 74 * new Separator(true), 75 * new Button("Clean"), 76 * new Button("Compile"), 77 * new Button("Run"), 78 * new Separator(true), 79 * new Button("Debug"), 80 * new Button("Profile") 81 * ); 82 * </code></pre> 83 * 84 * @since JavaFX 2.0 85 */ 86 @DefaultProperty("items") 87 public class ToolBar extends Control { 88 89 /*************************************************************************** 90 * * 91 * Constructors * 92 * * 93 **************************************************************************/ 94 95 /** 96 * Creates an empty tool bar. 97 */ 98 public ToolBar() { 99 initialize(); 100 } 101 102 /** 103 * Creates a tool bar populated with the specified nodes. None of the items 104 * can be null. 105 * 106 * @param items the items to add 107 */ 108 public ToolBar(Node... items) { 109 initialize(); 110 this.items.addAll(items); 111 } 112 113 private void initialize() { 114 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 115 setAccessibleRole(AccessibleRole.TOOL_BAR); 116 // focusTraversable is styleable through css. Calling setFocusTraversable 117 // makes it look to css like the user set the value and css will not 118 // override. Initializing focusTraversable by calling set on the 119 // CssMetaData ensures that css will be able to override the value. 120 ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE); 121 122 // initialize css pseudo-class state 123 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, true); 124 125 } 126 127 /*************************************************************************** 128 * * 129 * Properties * 130 * * 131 **************************************************************************/ 132 133 /** 134 * The items contained in the {@code ToolBar}. Typical use case for a 135 * {@code ToolBar} suggest that the most common items to place within it 136 * are {@link Button Buttons}, {@link ToggleButton ToggleButtons}, and {@link Separator Separators}, 137 * but you are not restricted to just these, and can insert any {@link Node}. 138 * The items added must not be null. 139 * @return the list of items 140 */ 141 public final ObservableList<Node> getItems() { return items; } 142 143 private final ObservableList<Node> items = FXCollections.<Node>observableArrayList(); 144 145 /** 146 * The orientation of the {@code ToolBar} - this can either be horizontal 147 * or vertical. 148 */ 149 private ObjectProperty<Orientation> orientation; 150 public final void setOrientation(Orientation value) { 151 orientationProperty().set(value); 152 }; 153 public final Orientation getOrientation() { 154 return orientation == null ? Orientation.HORIZONTAL : orientation.get(); 155 } 156 public final ObjectProperty<Orientation> orientationProperty() { 157 if (orientation == null) { 158 orientation = new StyleableObjectProperty<Orientation>(Orientation.HORIZONTAL) { 159 @Override public void invalidated() { 160 final boolean isVertical = (get() == Orientation.VERTICAL); 161 pseudoClassStateChanged(VERTICAL_PSEUDOCLASS_STATE, isVertical); 162 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, !isVertical); 163 } 164 165 @Override 166 public Object getBean() { 167 return ToolBar.this; 168 } 169 170 @Override 171 public String getName() { 172 return "orientation"; 173 } 174 175 @Override 176 public CssMetaData<ToolBar,Orientation> getCssMetaData() { 177 return StyleableProperties.ORIENTATION; 178 } 179 }; 180 } 181 return orientation; 182 } 183 184 /*************************************************************************** 185 * * 186 * Methods * 187 * * 188 **************************************************************************/ 189 190 /** {@inheritDoc} */ 191 @Override protected Skin<?> createDefaultSkin() { 192 return new ToolBarSkin(this); 193 } 194 195 /*************************************************************************** 196 * * 197 * Stylesheet Handling * 198 * * 199 **************************************************************************/ 200 201 private static final String DEFAULT_STYLE_CLASS = "tool-bar"; 202 203 private static class StyleableProperties { 204 private static final CssMetaData<ToolBar,Orientation> ORIENTATION = 205 new CssMetaData<ToolBar,Orientation>("-fx-orientation", 206 new EnumConverter<Orientation>(Orientation.class), 207 Orientation.HORIZONTAL) { 208 209 @Override 210 public Orientation getInitialValue(ToolBar node) { 211 // A vertical ToolBar should remain vertical 212 return node.getOrientation(); 213 } 214 215 @Override 216 public boolean isSettable(ToolBar n) { 217 return n.orientation == null || !n.orientation.isBound(); 218 } 219 220 @Override 221 public StyleableProperty<Orientation> getStyleableProperty(ToolBar n) { 222 return (StyleableProperty<Orientation>)(WritableValue<Orientation>)n.orientationProperty(); 223 } 224 }; 225 226 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 227 static { 228 final List<CssMetaData<? extends Styleable, ?>> styleables = 229 new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData()); 230 styleables.add(ORIENTATION); 231 STYLEABLES = Collections.unmodifiableList(styleables); 232 } 233 } 234 235 /** 236 * @return The CssMetaData associated with this class, which may include the 237 * CssMetaData of its superclasses. 238 * @since JavaFX 8.0 239 */ 240 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 241 return StyleableProperties.STYLEABLES; 242 } 243 244 /** 245 * {@inheritDoc} 246 * @since JavaFX 8.0 247 */ 248 @Override 249 public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { 250 return getClassCssMetaData(); 251 } 252 253 private static final PseudoClass VERTICAL_PSEUDOCLASS_STATE = PseudoClass.getPseudoClass("vertical"); 254 private static final PseudoClass HORIZONTAL_PSEUDOCLASS_STATE = PseudoClass.getPseudoClass("horizontal"); 255 256 /** 257 * Returns the initial focus traversable state of this control, for use 258 * by the JavaFX CSS engine to correctly set its initial value. This method 259 * is overridden as by default UI controls have focus traversable set to true, 260 * but that is not appropriate for this control. 261 * 262 * @since 9 263 */ 264 @Override protected Boolean getInitialFocusTraversable() { 265 return Boolean.FALSE; 266 } 267 }