1 /* 2 * Copyright (c) 2010, 2014, 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 javafx.css.converter.BooleanConverter; 29 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.List; 33 34 import javafx.beans.DefaultProperty; 35 import javafx.beans.property.BooleanProperty; 36 import javafx.beans.value.ObservableValue; 37 import javafx.beans.value.WritableValue; 38 import javafx.collections.FXCollections; 39 import javafx.collections.ObservableList; 40 import javafx.css.CssMetaData; 41 import javafx.css.StyleableBooleanProperty; 42 43 import javafx.scene.control.skin.MenuBarSkin; 44 45 import javafx.css.Styleable; 46 import javafx.css.StyleableProperty; 47 import javafx.scene.AccessibleRole; 48 49 /** 50 * <p> 51 * A MenuBar control traditionally is placed at the very top of the user 52 * interface, and embedded within it are {@link Menu Menus}. To add a menu to 53 * a menubar, you add it to the {@link #getMenus() menus} ObservableList. 54 * By default, for each menu added to the menubar, it will be 55 * represented as a button with the Menu {@link MenuItem#textProperty() text} value displayed. 56 * <p> 57 * MenuBar sets focusTraversable to false. 58 * </p> 59 * 60 * To create and populate a {@code MenuBar}, you may do what is shown below. 61 * Please refer to the {@link Menu} API page for more information on how to 62 * configure it. 63 * <pre><code> 64 * final Menu menu1 = new Menu("File"); 65 * final Menu menu2 = new Menu("Options"); 66 * final Menu menu3 = new Menu("Help"); 67 * 68 * MenuBar menuBar = new MenuBar(); 69 * menuBar.getMenus().addAll(menu1, menu2, menu3); 70 * </code></pre> 71 * 72 * @see Menu 73 * @see MenuItem 74 * @since JavaFX 2.0 75 */ 76 @DefaultProperty("menus") 77 public class MenuBar extends Control { 78 79 /*************************************************************************** 80 * * 81 * Constructors * 82 * * 83 **************************************************************************/ 84 85 /** 86 * Creates a new empty MenuBar. 87 */ 88 public MenuBar() { 89 this((Menu[])null); 90 } 91 92 /** 93 * Creates a new MenuBar populated with the given menus. 94 * 95 * @param menus The menus to place inside the MenuBar 96 * @since JavaFX 8u40 97 */ 98 public MenuBar(Menu... menus) { 99 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 100 setAccessibleRole(AccessibleRole.MENU_BAR); 101 102 if (menus != null) { 103 getMenus().addAll(menus); 104 } 105 106 // focusTraversable is styleable through css. Calling setFocusTraversable 107 // makes it look to css like the user set the value and css will not 108 // override. Initializing focusTraversable by calling applyStyle with null 109 // StyleOrigin ensures that css will be able to override the value. 110 ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE); 111 } 112 113 114 115 /*************************************************************************** 116 * * 117 * Instance variables * 118 * * 119 **************************************************************************/ 120 private ObservableList<Menu> menus = FXCollections.<Menu>observableArrayList(); 121 122 123 /*************************************************************************** 124 * * 125 * Properties * 126 * * 127 **************************************************************************/ 128 129 /** 130 * Use the system menu bar if the current platform supports it. 131 * 132 * This should not be set on more than one MenuBar instance per 133 * Stage. If this property is set to true on more than one 134 * MenuBar in the same Stage, then the last menu set is allowed 135 * to modify the system menu bar, and if there is an existing installed 136 * system menu it is unset and removed from the system menu bar. 137 * 138 * Note that trying to uni-directionally bind to this property 139 * will throw a RuntimeException. Please use 140 * bi-directional binding to this property instead. 141 * 142 * @since JavaFX 2.1 143 */ 144 public final BooleanProperty useSystemMenuBarProperty() { 145 if (useSystemMenuBar == null) { 146 useSystemMenuBar = new StyleableBooleanProperty() { 147 148 @Override 149 public CssMetaData<MenuBar,Boolean> getCssMetaData() { 150 return StyleableProperties.USE_SYSTEM_MENU_BAR; 151 } 152 153 @Override 154 public Object getBean() { 155 return MenuBar.this; 156 } 157 158 @Override 159 public String getName() { 160 return "useSystemMenuBar"; 161 } 162 163 @Override 164 public void bind(final ObservableValue<? extends Boolean> rawObservable) { 165 throw new RuntimeException(BIND_MSG); 166 } 167 168 }; 169 } 170 return useSystemMenuBar; 171 } 172 private String BIND_MSG = 173 "cannot uni-directionally bind to the system menu bar - use bindBidrectional instead"; 174 175 private BooleanProperty useSystemMenuBar; 176 public final void setUseSystemMenuBar(boolean value) { 177 useSystemMenuBarProperty().setValue(value); 178 } 179 public final boolean isUseSystemMenuBar() { 180 return useSystemMenuBar == null ? false : useSystemMenuBar.getValue(); 181 } 182 183 184 /*************************************************************************** 185 * * 186 * Public API * 187 * * 188 **************************************************************************/ 189 190 /** 191 * The menus to show within this MenuBar. If this ObservableList is modified at 192 * runtime, the MenuBar will update as expected. 193 * @see Menu 194 */ 195 public final ObservableList<Menu> getMenus() { 196 return menus; 197 } 198 199 /** {@inheritDoc} */ 200 @Override protected Skin<?> createDefaultSkin() { 201 return new MenuBarSkin(this); 202 } 203 204 /*************************************************************************** 205 * * 206 * Stylesheet Handling * 207 * * 208 **************************************************************************/ 209 210 private static final String DEFAULT_STYLE_CLASS = "menu-bar"; 211 212 private static class StyleableProperties { 213 private static final CssMetaData<MenuBar, Boolean> USE_SYSTEM_MENU_BAR = 214 new CssMetaData<MenuBar, Boolean>("-fx-use-system-menu-bar", 215 BooleanConverter.getInstance(), 216 false) { 217 @Override public boolean isSettable(MenuBar n) { 218 return n.useSystemMenuBar == null || !n.useSystemMenuBar.isBound(); 219 } 220 221 @Override public StyleableProperty<Boolean> getStyleableProperty(MenuBar n) { 222 return (StyleableProperty<Boolean>)(WritableValue<Boolean>)n.useSystemMenuBarProperty(); 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(USE_SYSTEM_MENU_BAR); 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 super classes. 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 /** 254 * Most Controls return true for focusTraversable, so Control overrides 255 * this method to return true, but MenuBar returns false for 256 * focusTraversable's initial value; hence the override of the override. 257 * This method is called from CSS code to get the correct initial value. 258 * @treatAsPrivate implementation detail 259 */ 260 @Deprecated @Override 261 protected /*do not make final*/ Boolean impl_cssGetFocusTraversableInitialValue() { 262 return Boolean.FALSE; 263 } 264 265 } 266