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 */ 140 public final ObservableList<Node> getItems() { return items; } 141 142 private final ObservableList<Node> items = FXCollections.<Node>observableArrayList(); 143 144 /** 145 * The orientation of the {@code ToolBar} - this can either be horizontal 146 * or vertical. 147 */ 148 private ObjectProperty<Orientation> orientation; 149 public final void setOrientation(Orientation value) { 150 orientationProperty().set(value); 151 }; 152 public final Orientation getOrientation() { 153 return orientation == null ? Orientation.HORIZONTAL : orientation.get(); 154 } 155 public final ObjectProperty<Orientation> orientationProperty() { 156 if (orientation == null) { 157 orientation = new StyleableObjectProperty<Orientation>(Orientation.HORIZONTAL) { 158 @Override public void invalidated() { 159 final boolean isVertical = (get() == Orientation.VERTICAL); 160 pseudoClassStateChanged(VERTICAL_PSEUDOCLASS_STATE, isVertical); 161 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, !isVertical); 162 } 163 164 @Override 165 public Object getBean() { 166 return ToolBar.this; 167 } 168 169 @Override 170 public String getName() { 171 return "orientation"; 172 } 173 174 @Override 175 public CssMetaData<ToolBar,Orientation> getCssMetaData() { 176 return StyleableProperties.ORIENTATION; 177 } 178 }; 179 } 180 return orientation; 181 } 182 183 /*************************************************************************** 184 * * 185 * Methods * 186 * * 187 **************************************************************************/ 188 189 /** {@inheritDoc} */ 190 @Override protected Skin<?> createDefaultSkin() { 191 return new ToolBarSkin(this); 192 } 193 194 /*************************************************************************** 195 * * 196 * Stylesheet Handling * 197 * * 198 **************************************************************************/ 199 200 private static final String DEFAULT_STYLE_CLASS = "tool-bar"; 201 202 private static class StyleableProperties { 203 private static final CssMetaData<ToolBar,Orientation> ORIENTATION = 204 new CssMetaData<ToolBar,Orientation>("-fx-orientation", 205 new EnumConverter<Orientation>(Orientation.class), 206 Orientation.HORIZONTAL) { 207 208 @Override 209 public Orientation getInitialValue(ToolBar node) { 210 // A vertical ToolBar should remain vertical 211 return node.getOrientation(); 212 } 213 214 @Override 215 public boolean isSettable(ToolBar n) { 216 return n.orientation == null || !n.orientation.isBound(); 217 } 218 219 @Override 220 public StyleableProperty<Orientation> getStyleableProperty(ToolBar n) { 221 return (StyleableProperty<Orientation>)(WritableValue<Orientation>)n.orientationProperty(); 222 } 223 }; 224 225 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 226 static { 227 final List<CssMetaData<? extends Styleable, ?>> styleables = 228 new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData()); 229 styleables.add(ORIENTATION); 230 STYLEABLES = Collections.unmodifiableList(styleables); 231 } 232 } 233 234 /** 235 * @return The CssMetaData associated with this class, which may include the 236 * CssMetaData of its superclasses. 237 * @since JavaFX 8.0 238 */ 239 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 240 return StyleableProperties.STYLEABLES; 241 } 242 243 /** 244 * {@inheritDoc} 245 * @since JavaFX 8.0 246 */ 247 @Override 248 public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { 249 return getClassCssMetaData(); 250 } 251 252 private static final PseudoClass VERTICAL_PSEUDOCLASS_STATE = PseudoClass.getPseudoClass("vertical"); 253 private static final PseudoClass HORIZONTAL_PSEUDOCLASS_STATE = PseudoClass.getPseudoClass("horizontal"); 254 255 /** 256 * Returns the initial focus traversable state of this control, for use 257 * by the JavaFX CSS engine to correctly set its initial value. This method 258 * is overridden as by default UI controls have focus traversable set to true, 259 * but that is not appropriate for this control. 260 * 261 * @since 9 262 */ 263 @Override protected Boolean getInitialFocusTraversable() { 264 return Boolean.FALSE; 265 } 266 }