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 }