1 /* 2 * Copyright (c) 1997, 2018, 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 javax.swing.plaf.basic; 27 28 import sun.swing.DefaultLookup; 29 import sun.swing.UIAction; 30 import javax.swing.*; 31 import javax.swing.event.*; 32 import java.awt.Color; 33 import java.awt.Component; 34 import java.awt.Container; 35 import java.awt.Dimension; 36 import java.awt.Graphics; 37 import java.awt.Insets; 38 import java.awt.Point; 39 import java.awt.Rectangle; 40 import java.awt.event.*; 41 import java.beans.PropertyChangeEvent; 42 import java.beans.PropertyChangeListener; 43 44 import javax.swing.border.*; 45 import javax.swing.plaf.*; 46 47 48 /** 49 * A default L&F implementation of MenuBarUI. This implementation 50 * is a "combined" view/controller. 51 * 52 * @author Georges Saab 53 * @author David Karlton 54 * @author Arnaud Weber 55 */ 56 public class BasicMenuBarUI extends MenuBarUI { 57 58 /** 59 * The instance of {@code JMenuBar}. 60 */ 61 protected JMenuBar menuBar = null; 62 63 /** 64 * The instance of {@code ContainerListener}. 65 */ 66 protected ContainerListener containerListener; 67 68 /** 69 * The instance of {@code ChangeListener}. 70 */ 71 protected ChangeListener changeListener; 72 private Handler handler; 73 74 /** 75 * Returns a new instance of {@code BasicMenuBarUI}. 76 * 77 * @param x a component 78 * @return a new instance of {@code BasicMenuBarUI} 79 */ 80 public static ComponentUI createUI(JComponent x) { 81 return new BasicMenuBarUI(); 82 } 83 84 static void loadActionMap(LazyActionMap map) { 85 map.put(new Actions(Actions.TAKE_FOCUS)); 86 } 87 88 public void installUI(JComponent c) { 89 menuBar = (JMenuBar) c; 90 91 installDefaults(); 92 installListeners(); 93 installKeyboardActions(); 94 95 } 96 97 /** 98 * Installs default properties. 99 */ 100 protected void installDefaults() { 101 if (menuBar.getLayout() == null || 102 menuBar.getLayout() instanceof UIResource) { 103 menuBar.setLayout(new DefaultMenuLayout(menuBar,BoxLayout.LINE_AXIS)); 104 } 105 106 LookAndFeel.installProperty(menuBar, "opaque", Boolean.TRUE); 107 LookAndFeel.installBorder(menuBar,"MenuBar.border"); 108 LookAndFeel.installColorsAndFont(menuBar, 109 "MenuBar.background", 110 "MenuBar.foreground", 111 "MenuBar.font"); 112 } 113 114 /** 115 * Registers listeners. 116 */ 117 protected void installListeners() { 118 containerListener = createContainerListener(); 119 changeListener = createChangeListener(); 120 121 for (int i = 0; i < menuBar.getMenuCount(); i++) { 122 JMenu menu = menuBar.getMenu(i); 123 if (menu!=null) 124 menu.getModel().addChangeListener(changeListener); 125 } 126 menuBar.addContainerListener(containerListener); 127 } 128 129 /** 130 * Registers keyboard actions. 131 */ 132 protected void installKeyboardActions() { 133 InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 134 135 SwingUtilities.replaceUIInputMap(menuBar, 136 JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap); 137 138 LazyActionMap.installLazyActionMap(menuBar, BasicMenuBarUI.class, 139 "MenuBar.actionMap"); 140 } 141 142 InputMap getInputMap(int condition) { 143 if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) { 144 Object[] bindings = (Object[])DefaultLookup.get 145 (menuBar, this, "MenuBar.windowBindings"); 146 if (bindings != null) { 147 return LookAndFeel.makeComponentInputMap(menuBar, bindings); 148 } 149 } 150 return null; 151 } 152 153 public void uninstallUI(JComponent c) { 154 uninstallDefaults(); 155 uninstallListeners(); 156 uninstallKeyboardActions(); 157 158 menuBar = null; 159 } 160 161 /** 162 * Uninstalls default properties. 163 */ 164 protected void uninstallDefaults() { 165 if (menuBar!=null) { 166 LookAndFeel.uninstallBorder(menuBar); 167 } 168 } 169 170 /** 171 * Unregisters listeners. 172 */ 173 protected void uninstallListeners() { 174 menuBar.removeContainerListener(containerListener); 175 176 for (int i = 0; i < menuBar.getMenuCount(); i++) { 177 JMenu menu = menuBar.getMenu(i); 178 if (menu !=null) 179 menu.getModel().removeChangeListener(changeListener); 180 } 181 182 containerListener = null; 183 changeListener = null; 184 handler = null; 185 } 186 187 /** 188 * Unregisters keyboard actions. 189 */ 190 protected void uninstallKeyboardActions() { 191 SwingUtilities.replaceUIInputMap(menuBar, JComponent. 192 WHEN_IN_FOCUSED_WINDOW, null); 193 SwingUtilities.replaceUIActionMap(menuBar, null); 194 } 195 196 /** 197 * Returns an instance of {@code ContainerListener}. 198 * 199 * @return an instance of {@code ContainerListener} 200 */ 201 protected ContainerListener createContainerListener() { 202 return getHandler(); 203 } 204 205 /** 206 * Returns an instance of {@code ChangeListener}. 207 * 208 * @return an instance of {@code ChangeListener} 209 */ 210 protected ChangeListener createChangeListener() { 211 return getHandler(); 212 } 213 214 private Handler getHandler() { 215 if (handler == null) { 216 handler = new Handler(); 217 } 218 return handler; 219 } 220 221 222 public Dimension getMinimumSize(JComponent c) { 223 return null; 224 } 225 226 public Dimension getMaximumSize(JComponent c) { 227 return null; 228 } 229 230 private class Handler implements ChangeListener, ContainerListener { 231 // 232 // ChangeListener 233 // 234 public void stateChanged(ChangeEvent e) { 235 int i,c; 236 for(i=0,c = menuBar.getMenuCount() ; i < c ; i++) { 237 JMenu menu = menuBar.getMenu(i); 238 if(menu !=null && menu.isSelected()) { 239 menuBar.getSelectionModel().setSelectedIndex(i); 240 break; 241 } 242 } 243 } 244 245 // 246 // ContainerListener 247 // 248 public void componentAdded(ContainerEvent e) { 249 Component c = e.getChild(); 250 if (c instanceof JMenu) 251 ((JMenu)c).getModel().addChangeListener(changeListener); 252 } 253 public void componentRemoved(ContainerEvent e) { 254 Component c = e.getChild(); 255 if (c instanceof JMenu) 256 ((JMenu)c).getModel().removeChangeListener(changeListener); 257 } 258 } 259 260 261 private static class Actions extends UIAction { 262 private static final String TAKE_FOCUS = "takeFocus"; 263 264 Actions(String key) { 265 super(key); 266 } 267 268 public void actionPerformed(ActionEvent e) { 269 // TAKE_FOCUS 270 JMenuBar menuBar = (JMenuBar)e.getSource(); 271 MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager(); 272 MenuElement[] me; 273 MenuElement[] subElements; 274 JMenu menu = menuBar.getMenu(0); 275 if (menu!=null) { 276 me = new MenuElement[3]; 277 me[0] = (MenuElement) menuBar; 278 me[1] = (MenuElement) menu; 279 me[2] = (MenuElement) menu.getPopupMenu(); 280 defaultManager.setSelectedPath(me); 281 } 282 } 283 } 284 }