2 Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.awt
.Component
;
42 import java
.awt
.Graphics
;
43 import java
.awt
.Insets
;
44 import java
.awt
.event
.KeyEvent
;
45 import java
.awt
.event
.MouseEvent
;
47 import javax
.accessibility
.Accessible
;
48 import javax
.accessibility
.AccessibleContext
;
49 import javax
.accessibility
.AccessibleRole
;
50 import javax
.accessibility
.AccessibleSelection
;
51 import javax
.accessibility
.AccessibleStateSet
;
52 import javax
.swing
.plaf
.MenuBarUI
;
54 import javax
.swing
.border
.Border
;
57 * JMenuBar is a container for menu's. For a menu bar to be seen on the
58 * screen, at least one menu should be added to it. Just like adding
59 * components to container, one can use add() to add menu's to the menu bar.
60 * Menu's will be displayed in the menu bar in the order they were added.
61 * The JMenuBar uses selectionModel to keep track of selected menu index.
62 * JMenuBar's selectionModel will fire ChangeEvents to its registered
63 * listeners when the selected index changes.
65 public class JMenuBar
extends JComponent
implements Accessible
, MenuElement
68 * Provides accessibility support for <code>JMenuBar</code>.
70 * @author Roman Kennke (kennke@aicas.com)
72 protected class AccessibleJMenuBar
extends AccessibleJComponent
73 implements AccessibleSelection
77 * Returns the number of selected items in the menu bar. Possible values
78 * are <code>0</code> if nothing is selected, or <code>1</code> if one
81 * @return the number of selected items in the menu bar
83 public int getAccessibleSelectionCount()
86 if (getSelectionModel().getSelectedIndex() != -1)
92 * Returns the selected with index <code>i</code> menu, or
93 * <code>null</code> if the specified menu is not selected.
95 * @param i the index of the menu to return
97 * @return the selected with index <code>i</code> menu, or
98 * <code>null</code> if the specified menu is not selected
100 public Accessible
getAccessibleSelection(int i
)
102 if (getSelectionModel().getSelectedIndex() != i
)
108 * Returns <code>true</code> if the specified menu is selected,
109 * <code>false</code> otherwise.
111 * @param i the index of the menu to check
113 *@return <code>true</code> if the specified menu is selected,
114 * <code>false</code> otherwise
116 public boolean isAccessibleChildSelected(int i
)
118 return getSelectionModel().getSelectedIndex() == i
;
122 * Selects the menu with index <code>i</code>. If another menu is already
123 * selected, this will be deselected.
125 * @param i the menu to be selected
127 public void addAccessibleSelection(int i
)
129 getSelectionModel().setSelectedIndex(i
);
133 * Deselects the menu with index <code>i</code>.
135 * @param i the menu index to be deselected
137 public void removeAccessibleSelection(int i
)
139 if (getSelectionModel().getSelectedIndex() == i
)
140 getSelectionModel().clearSelection();
144 * Deselects all possibly selected menus.
146 public void clearAccessibleSelection()
148 getSelectionModel().clearSelection();
152 * In menu bars it is not possible to select all items, so this method
155 public void selectAllAccessibleSelection()
157 // In menu bars it is not possible to select all items, so this method
162 * Returns the accessible role of <code>JMenuBar</code>, which is
163 * {@link AccessibleRole#MENU_BAR}.
165 * @return the accessible role of <code>JMenuBar</code>, which is
166 * {@link AccessibleRole#MENU_BAR}
168 public AccessibleRole
getAccessibleRole()
170 return AccessibleRole
.MENU_BAR
;
174 * Returns the <code>AccessibleSelection</code> for this object. This
175 * method returns <code>this</code>, since the
176 * <code>AccessibleJMenuBar</code> manages its selection itself.
178 * @return the <code>AccessibleSelection</code> for this object
180 public AccessibleSelection
getAccessibleSelection()
186 * Returns the state of this <code>AccessibleJMenuBar</code>.
188 * @return the state of this <code>AccessibleJMenuBar</code>.
190 public AccessibleStateSet
getAccessibleStateSet()
192 AccessibleStateSet stateSet
= super.getAccessibleStateSet();
193 // TODO: Figure out what state must be added to the super state set.
198 private static final long serialVersionUID
= -8191026883931977036L;
200 /** JMenuBar's model. It keeps track of selected menu's index */
201 private transient SingleSelectionModel selectionModel
;
203 /* borderPainted property indicating if the menuBar's border will be painted*/
204 private boolean borderPainted
;
206 /* margin between menu bar's border and its menues*/
207 private Insets margin
;
210 * Creates a new JMenuBar object.
214 selectionModel
= new DefaultSingleSelectionModel();
215 borderPainted
= true;
220 * Adds menu to the menu bar
222 * @param c menu to add
224 * @return reference to the added menu
226 public JMenu
add(JMenu c
)
228 c
.setAlignmentX(Component
.LEFT_ALIGNMENT
);
234 * This method overrides addNotify() in the Container to register
235 * this menu bar with the current keyboard manager.
237 public void addNotify()
240 KeyboardManager
.getManager().registerJMenuBar(this);
243 public AccessibleContext
getAccessibleContext()
245 if (accessibleContext
== null)
246 accessibleContext
= new AccessibleJMenuBar();
247 return accessibleContext
;
251 * Returns reference to this menu bar
253 * @return reference to this menu bar
255 public Component
getComponent()
261 * Returns component at the specified index.
263 * @param i index of the component to get
265 * @return component at the specified index. Null is returned if
266 * component at the specified index doesn't exist.
267 * @deprecated Replaced by getComponent(int)
269 public Component
getComponentAtIndex(int i
)
271 return getComponent(i
);
275 * Returns index of the specified component
277 * @param c Component to search for
279 * @return index of the specified component. -1 is returned if
280 * specified component doesnt' exist in the menu bar.
282 public int getComponentIndex(Component c
)
284 Component
[] comps
= getComponents();
288 for (int i
= 0; i
< comps
.length
; i
++)
290 if (comps
[i
].equals(c
))
303 * @return DOCUMENT ME!
305 public JMenu
getHelpMenu()
311 * Returns margin betweeen menu bar's border and its menues
313 * @return margin between menu bar's border and its menues
315 public Insets
getMargin()
318 return new Insets(0, 0, 0, 0);
324 * Return menu at the specified index. If component at the
325 * specified index is not a menu, then null is returned.
327 * @param index index to look for the menu
329 * @return menu at specified index, or null if menu doesn't exist
330 * at the specified index.
332 public JMenu
getMenu(int index
)
334 if (getComponentAtIndex(index
) instanceof JMenu
)
335 return (JMenu
) getComponentAtIndex(index
);
341 * Returns number of menu's in this menu bar
343 * @return number of menu's in this menu bar
345 public int getMenuCount()
347 return getComponentCount();
351 * Returns selection model for this menu bar. SelectionModel
352 * keeps track of the selected menu in the menu bar. Whenever
353 * selected property of selectionModel changes, the ChangeEvent
354 * will be fired its ChangeListeners.
356 * @return selection model for this menu bar.
358 public SingleSelectionModel
getSelectionModel()
360 return selectionModel
;
364 * Method of MenuElement interface. It returns subcomponents
365 * of the menu bar, which are all the menues that it contains.
367 * @return MenuElement[] array containing menues in this menu bar
369 public MenuElement
[] getSubElements()
371 MenuElement
[] subElements
= new MenuElement
[getComponentCount()];
373 for (int i
= 0; i
< getComponentCount(); i
++)
374 subElements
[i
] = (MenuElement
) getMenu(i
);
380 * Set the "UI" property of the menu bar, which is a look and feel class
381 * responsible for handling the menuBar's input events and painting it.
383 * @return The current "UI" property
385 public MenuBarUI
getUI()
387 return (MenuBarUI
) ui
;
391 * This method returns a name to identify which look and feel class will be
392 * the UI delegate for the menu bar.
394 * @return The Look and Feel classID. "MenuBarUI"
396 public String
getUIClassID()
402 * Returns true if menu bar paints its border and false otherwise
404 * @return true if menu bar paints its border and false otherwise
406 public boolean isBorderPainted()
408 return borderPainted
;
412 * Returns true if some menu in menu bar is selected.
414 * @return true if some menu in menu bar is selected and false otherwise
416 public boolean isSelected()
418 return selectionModel
.isSelected();
422 * This method does nothing by default. This method is need for the
423 * MenuElement interface to be implemented.
425 * @param isIncluded true if menuBar is included in the selection
426 * and false otherwise
428 public void menuSelectionChanged(boolean isIncluded
)
430 // Do nothing - needed for implementation of MenuElement interface
434 * Paints border of the menu bar, if its borderPainted property is set to
437 * @param g The graphics context with which to paint the border
439 protected void paintBorder(Graphics g
)
443 Border border
= getBorder();
445 getBorder().paintBorder(this, g
, 0, 0, getSize(null).width
,
446 getSize(null).height
);
451 * A string that describes this JMenuBar. Normally only used
454 * @return A string describing this JMenuBar
456 protected String
paramString()
458 StringBuffer sb
= new StringBuffer();
459 sb
.append(super.paramString());
460 sb
.append(",margin=");
461 if (getMargin() != null)
462 sb
.append(getMargin());
463 sb
.append(",paintBorder=").append(isBorderPainted());
464 return sb
.toString();
468 * Process key events forwarded from MenuSelectionManager. This method
469 * doesn't do anything. It is here to conform to the MenuElement interface.
471 * @param e event forwarded from MenuSelectionManager
472 * @param path path to the menu element from which event was generated
473 * @param manager MenuSelectionManager for the current menu hierarchy
476 public void processKeyEvent(KeyEvent e
, MenuElement
[] path
,
477 MenuSelectionManager manager
)
479 // Do nothing - needed for implementation of MenuElement interface
483 * This method overrides JComponent.processKeyBinding to allow the
484 * JMenuBar to check all the child components (recursiveley) to see
485 * if they'll consume the event.
487 * @param ks the KeyStroke for the event
488 * @param e the KeyEvent for the event
489 * @param condition the focus condition for the binding
490 * @param pressed true if the key is pressed
492 protected boolean processKeyBinding(KeyStroke ks
, KeyEvent e
, int condition
,
495 // See if the regular JComponent behavior consumes the event
496 if (super.processKeyBinding(ks
, e
, condition
, pressed
))
499 // If not, have to recursively check all the child menu elements to see
501 MenuElement
[] children
= getSubElements();
502 for (int i
= 0; i
< children
.length
; i
++)
503 if (processKeyBindingHelper(children
[i
], ks
, e
, condition
, pressed
))
509 * This is a helper method to recursively check the children of this
510 * JMenuBar to see if they will consume a key event via key bindings.
511 * This is used for menu accelerators.
512 * @param menuElement the menuElement to check (and check all its children)
513 * @param ks the KeyStroke for the event
514 * @param e the KeyEvent that may be consumed
515 * @param condition the focus condition for the binding
516 * @param pressed true if the key was pressed
517 * @return true <code>menuElement</code> or one of its children consume
518 * the event (processKeyBinding returns true for menuElement or one of
521 static boolean processKeyBindingHelper(MenuElement menuElement
, KeyStroke ks
,
522 KeyEvent e
, int condition
,
525 // First check the menuElement itself, if it's a JComponent
526 if (menuElement
instanceof JComponent
527 && ((JComponent
) menuElement
).processKeyBinding(ks
, e
, condition
,
531 // If that didn't consume it, check all the children recursively
532 MenuElement
[] children
= menuElement
.getSubElements();
533 for (int i
= 0; i
< children
.length
; i
++)
534 if (processKeyBindingHelper(children
[i
], ks
, e
, condition
, pressed
))
540 * Process mouse events forwarded from MenuSelectionManager. This method
541 * doesn't do anything. It is here to conform to the MenuElement interface.
543 * @param event event forwarded from MenuSelectionManager
544 * @param path path to the menu element from which event was generated
545 * @param manager MenuSelectionManager for the current menu hierarchy
548 public void processMouseEvent(MouseEvent event
, MenuElement
[] path
,
549 MenuSelectionManager manager
)
551 // Do nothing - needed for implementation of MenuElement interface
555 * This method overrides removeNotify() in the Container to
556 * unregister this menu bar from the current keyboard manager.
558 public void removeNotify()
560 KeyboardManager
.getManager().unregisterJMenuBar(this);
561 super.removeNotify();
565 * Sets painting status of the border. If 'b' is true then menu bar's
566 * border will be painted, and it will not be painted otherwise.
568 * @param b indicates if menu bar's border should be painted.
570 public void setBorderPainted(boolean b
)
572 if (b
!= borderPainted
)
574 boolean old
= borderPainted
;
576 firePropertyChange("borderPainted", old
, b
);
583 * Sets help menu for this menu bar
585 * @param menu help menu
587 * @specnote The specification states that this method is not yet implemented
588 * and should throw an exception.
590 public void setHelpMenu(JMenu menu
)
592 // We throw an Error here, just as Sun's JDK does.
593 throw new Error("setHelpMenu() not yet implemented.");
597 * Sets the menu bar's "margin" bound property, which represents
598 * distance between the menubar's border and its menus.
599 * icon. When marging property is modified, PropertyChangeEvent will
600 * be fired to menuBar's PropertyChangeListener's.
602 * @param m distance between the menubar's border and its menus.
605 public void setMargin(Insets m
)
609 Insets oldMargin
= margin
;
611 firePropertyChange("margin", oldMargin
, margin
);
616 * Changes menu bar's selection to the specified menu.
617 * This method updates selected index of menu bar's selection model,
618 * which results in a model firing change event.
620 * @param sel menu to select
622 public void setSelected(Component sel
)
624 int index
= getComponentIndex(sel
);
625 selectionModel
.setSelectedIndex(index
);
629 * Sets menuBar's selection model to the one specified
631 * @param model SingleSelectionModel that needs to be set for this menu bar
633 public void setSelectionModel(SingleSelectionModel model
)
635 if (selectionModel
!= model
)
637 SingleSelectionModel oldModel
= selectionModel
;
638 selectionModel
= model
;
639 firePropertyChange("model", oldModel
, selectionModel
);
644 * Set the "UI" property of the menu bar, which is a look and feel class
645 * responsible for handling menuBar's input events and painting it.
647 * @param ui The new "UI" property
649 public void setUI(MenuBarUI ui
)
655 * Set the "UI" property to a class constructed, via the {@link
656 * UIManager}, from the current look and feel.
658 public void updateUI()
660 setUI((MenuBarUI
) UIManager
.getUI(this));