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 }