354 }
355 }
356 }
357
358 /**
359 * Computes the origin for the <code>JMenu</code>'s popup menu.
360 * This method uses Look and Feel properties named
361 * <code>Menu.menuPopupOffsetX</code>,
362 * <code>Menu.menuPopupOffsetY</code>,
363 * <code>Menu.submenuPopupOffsetX</code>, and
364 * <code>Menu.submenuPopupOffsetY</code>
365 * to adjust the exact location of popup.
366 *
367 * @return a <code>Point</code> in the coordinate space of the
368 * menu which should be used as the origin
369 * of the <code>JMenu</code>'s popup menu
370 *
371 * @since 1.3
372 */
373 protected Point getPopupMenuOrigin() {
374 int x = 0;
375 int y = 0;
376 JPopupMenu pm = getPopupMenu();
377 // Figure out the sizes needed to caclulate the menu position
378 Dimension s = getSize();
379 Dimension pmSize = pm.getSize();
380 // For the first time the menu is popped up,
381 // the size has not yet been initiated
382 if (pmSize.width==0) {
383 pmSize = pm.getPreferredSize();
384 }
385 Point position = getLocationOnScreen();
386 Toolkit toolkit = Toolkit.getDefaultToolkit();
387 GraphicsConfiguration gc = getGraphicsConfiguration();
388 Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
389 GraphicsEnvironment ge =
390 GraphicsEnvironment.getLocalGraphicsEnvironment();
391 GraphicsDevice[] gd = ge.getScreenDevices();
392 for(int i = 0; i < gd.length; i++) {
393 if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
394 GraphicsConfiguration dgc =
395 gd[i].getDefaultConfiguration();
883 *
884 * @return an array of <code>Component</code>s or an empty array
885 * if there is no popup menu
886 */
887 public Component[] getMenuComponents() {
888 if (popupMenu != null)
889 return popupMenu.getComponents();
890
891 return new Component[0];
892 }
893
894 /**
895 * Returns true if the menu is a 'top-level menu', that is, if it is
896 * the direct child of a menubar.
897 *
898 * @return true if the menu is activated from the menu bar;
899 * false if the menu is activated from a menu item
900 * on another menu
901 */
902 public boolean isTopLevelMenu() {
903 if (getParent() instanceof JMenuBar)
904 return true;
905
906 return false;
907 }
908
909 /**
910 * Returns true if the specified component exists in the
911 * submenu hierarchy.
912 *
913 * @param c the <code>Component</code> to be tested
914 * @return true if the <code>Component</code> exists, false otherwise
915 */
916 public boolean isMenuComponent(Component c) {
917 // Are we in the MenuItem part of the menu
918 if (c == this)
919 return true;
920 // Are we in the PopupMenu?
921 if (c instanceof JPopupMenu) {
922 JPopupMenu comp = (JPopupMenu) c;
923 if (comp == this.getPopupMenu())
924 return true;
925 }
926 // Are we in a Component on the PopupMenu
998 }
999
1000 /**
1001 * Removes a listener for menu events.
1002 *
1003 * @param l the listener to be removed
1004 */
1005 public void removeMenuListener(MenuListener l) {
1006 listenerList.remove(MenuListener.class, l);
1007 }
1008
1009 /**
1010 * Returns an array of all the <code>MenuListener</code>s added
1011 * to this JMenu with addMenuListener().
1012 *
1013 * @return all of the <code>MenuListener</code>s added or an empty
1014 * array if no listeners have been added
1015 * @since 1.4
1016 */
1017 public MenuListener[] getMenuListeners() {
1018 return (MenuListener[])listenerList.getListeners(MenuListener.class);
1019 }
1020
1021 /**
1022 * Notifies all listeners that have registered interest for
1023 * notification on this event type. The event instance
1024 * is created lazily.
1025 *
1026 * @exception Error if there is a <code>null</code> listener
1027 * @see EventListenerList
1028 */
1029 protected void fireMenuSelected() {
1030 if (DEBUG) {
1031 System.out.println("In JMenu.fireMenuSelected");
1032 }
1033 // Guaranteed to return a non-null array
1034 Object[] listeners = listenerList.getListenerList();
1035 // Process the listeners last to first, notifying
1036 // those that are interested in this event
1037 for (int i = listeners.length-2; i>=0; i-=2) {
1038 if (listeners[i]==MenuListener.class) {
1288 }
1289
1290 /**
1291 * Programmatically performs a "click". This overrides the method
1292 * <code>AbstractButton.doClick</code> in order to make the menu pop up.
1293 * @param pressTime indicates the number of milliseconds the
1294 * button was pressed for
1295 */
1296 public void doClick(int pressTime) {
1297 MenuElement me[] = buildMenuElementArray(this);
1298 MenuSelectionManager.defaultManager().setSelectedPath(me);
1299 }
1300
1301 /*
1302 * Build an array of menu elements - from <code>PopupMenu</code> to
1303 * the root <code>JMenuBar</code>.
1304 * @param leaf the leaf node from which to start building up the array
1305 * @return the array of menu items
1306 */
1307 private MenuElement[] buildMenuElementArray(JMenu leaf) {
1308 Vector elements = new Vector();
1309 Component current = leaf.getPopupMenu();
1310 JPopupMenu pop;
1311 JMenu menu;
1312 JMenuBar bar;
1313
1314 while (true) {
1315 if (current instanceof JPopupMenu) {
1316 pop = (JPopupMenu) current;
1317 elements.insertElementAt(pop, 0);
1318 current = pop.getInvoker();
1319 } else if (current instanceof JMenu) {
1320 menu = (JMenu) current;
1321 elements.insertElementAt(menu, 0);
1322 current = menu.getParent();
1323 } else if (current instanceof JMenuBar) {
1324 bar = (JMenuBar) current;
1325 elements.insertElementAt(bar, 0);
1326 MenuElement me[] = new MenuElement[elements.size()];
1327 elements.copyInto(me);
1328 return me;
1392 * future Swing releases. The current serialization support is
1393 * appropriate for short term storage or RMI between applications running
1394 * the same version of Swing. As of 1.4, support for long term storage
1395 * of all JavaBeans<sup><font size="-2">TM</font></sup>
1396 * has been added to the <code>java.beans</code> package.
1397 * Please see {@link java.beans.XMLEncoder}.
1398 */
1399 protected class AccessibleJMenu extends AccessibleJMenuItem
1400 implements AccessibleSelection {
1401
1402 /**
1403 * Returns the number of accessible children in the object. If all
1404 * of the children of this object implement Accessible, than this
1405 * method should return the number of children of this object.
1406 *
1407 * @return the number of accessible children in the object.
1408 */
1409 public int getAccessibleChildrenCount() {
1410 Component[] children = getMenuComponents();
1411 int count = 0;
1412 for (int j = 0; j < children.length; j++) {
1413 if (children[j] instanceof Accessible) {
1414 count++;
1415 }
1416 }
1417 return count;
1418 }
1419
1420 /**
1421 * Returns the nth Accessible child of the object.
1422 *
1423 * @param i zero-based index of child
1424 * @return the nth Accessible child of the object
1425 */
1426 public Accessible getAccessibleChild(int i) {
1427 Component[] children = getMenuComponents();
1428 int count = 0;
1429 for (int j = 0; j < children.length; j++) {
1430 if (children[j] instanceof Accessible) {
1431 if (count == i) {
1432 if (children[j] instanceof JComponent) {
1433 // FIXME: [[[WDW - probably should set this when
1434 // the component is added to the menu. I tried
1435 // to do this in most cases, but the separators
1436 // added by addSeparator are hard to get to.]]]
1437 AccessibleContext ac = ((Accessible) children[j]).getAccessibleContext();
1438 ac.setAccessibleParent(JMenu.this);
1439 }
1440 return (Accessible) children[j];
1441 } else {
1442 count++;
1443 }
1444 }
1445 }
1446 return null;
1447 }
1448
1449 /**
1450 * Get the role of this object.
1451 *
1452 * @return an instance of AccessibleRole describing the role of the
1453 * object
1454 * @see AccessibleRole
1455 */
1456 public AccessibleRole getAccessibleRole() {
1457 return AccessibleRole.MENU;
1458 }
1459
1460 /**
1564 MenuSelectionManager.defaultManager().setSelectedPath(me);
1565 } else {
1566 MenuSelectionManager.defaultManager().setSelectedPath(null);
1567 }
1568 }
1569 }
1570
1571 /**
1572 * Removes the nth item from the selection. In general, menus
1573 * can only have one item within them selected at a time
1574 * (e.g. one sub-menu popped open).
1575 *
1576 * @param i the zero-based index of the selected item
1577 */
1578 public void removeAccessibleSelection(int i) {
1579 if (i < 0 || i >= getItemCount()) {
1580 return;
1581 }
1582 JMenuItem mi = getItem(i);
1583 if (mi != null && mi instanceof JMenu) {
1584 if (((JMenu) mi).isSelected()) {
1585 MenuElement old[] =
1586 MenuSelectionManager.defaultManager().getSelectedPath();
1587 MenuElement me[] = new MenuElement[old.length-2];
1588 for (int j = 0; j < old.length -2; j++) {
1589 me[j] = old[j];
1590 }
1591 MenuSelectionManager.defaultManager().setSelectedPath(me);
1592 }
1593 }
1594 }
1595
1596 /**
1597 * Clears the selection in the object, so that nothing in the
1598 * object is selected. This will close any open sub-menu.
1599 */
1600 public void clearAccessibleSelection() {
1601 // if this menu is selected, reset selection to only go
1602 // to this menu; else do nothing
1603 MenuElement old[] =
1604 MenuSelectionManager.defaultManager().getSelectedPath();
|
354 }
355 }
356 }
357
358 /**
359 * Computes the origin for the <code>JMenu</code>'s popup menu.
360 * This method uses Look and Feel properties named
361 * <code>Menu.menuPopupOffsetX</code>,
362 * <code>Menu.menuPopupOffsetY</code>,
363 * <code>Menu.submenuPopupOffsetX</code>, and
364 * <code>Menu.submenuPopupOffsetY</code>
365 * to adjust the exact location of popup.
366 *
367 * @return a <code>Point</code> in the coordinate space of the
368 * menu which should be used as the origin
369 * of the <code>JMenu</code>'s popup menu
370 *
371 * @since 1.3
372 */
373 protected Point getPopupMenuOrigin() {
374 int x;
375 int y;
376 JPopupMenu pm = getPopupMenu();
377 // Figure out the sizes needed to caclulate the menu position
378 Dimension s = getSize();
379 Dimension pmSize = pm.getSize();
380 // For the first time the menu is popped up,
381 // the size has not yet been initiated
382 if (pmSize.width==0) {
383 pmSize = pm.getPreferredSize();
384 }
385 Point position = getLocationOnScreen();
386 Toolkit toolkit = Toolkit.getDefaultToolkit();
387 GraphicsConfiguration gc = getGraphicsConfiguration();
388 Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
389 GraphicsEnvironment ge =
390 GraphicsEnvironment.getLocalGraphicsEnvironment();
391 GraphicsDevice[] gd = ge.getScreenDevices();
392 for(int i = 0; i < gd.length; i++) {
393 if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
394 GraphicsConfiguration dgc =
395 gd[i].getDefaultConfiguration();
883 *
884 * @return an array of <code>Component</code>s or an empty array
885 * if there is no popup menu
886 */
887 public Component[] getMenuComponents() {
888 if (popupMenu != null)
889 return popupMenu.getComponents();
890
891 return new Component[0];
892 }
893
894 /**
895 * Returns true if the menu is a 'top-level menu', that is, if it is
896 * the direct child of a menubar.
897 *
898 * @return true if the menu is activated from the menu bar;
899 * false if the menu is activated from a menu item
900 * on another menu
901 */
902 public boolean isTopLevelMenu() {
903 return getParent() instanceof JMenuBar;
904
905 }
906
907 /**
908 * Returns true if the specified component exists in the
909 * submenu hierarchy.
910 *
911 * @param c the <code>Component</code> to be tested
912 * @return true if the <code>Component</code> exists, false otherwise
913 */
914 public boolean isMenuComponent(Component c) {
915 // Are we in the MenuItem part of the menu
916 if (c == this)
917 return true;
918 // Are we in the PopupMenu?
919 if (c instanceof JPopupMenu) {
920 JPopupMenu comp = (JPopupMenu) c;
921 if (comp == this.getPopupMenu())
922 return true;
923 }
924 // Are we in a Component on the PopupMenu
996 }
997
998 /**
999 * Removes a listener for menu events.
1000 *
1001 * @param l the listener to be removed
1002 */
1003 public void removeMenuListener(MenuListener l) {
1004 listenerList.remove(MenuListener.class, l);
1005 }
1006
1007 /**
1008 * Returns an array of all the <code>MenuListener</code>s added
1009 * to this JMenu with addMenuListener().
1010 *
1011 * @return all of the <code>MenuListener</code>s added or an empty
1012 * array if no listeners have been added
1013 * @since 1.4
1014 */
1015 public MenuListener[] getMenuListeners() {
1016 return listenerList.getListeners(MenuListener.class);
1017 }
1018
1019 /**
1020 * Notifies all listeners that have registered interest for
1021 * notification on this event type. The event instance
1022 * is created lazily.
1023 *
1024 * @exception Error if there is a <code>null</code> listener
1025 * @see EventListenerList
1026 */
1027 protected void fireMenuSelected() {
1028 if (DEBUG) {
1029 System.out.println("In JMenu.fireMenuSelected");
1030 }
1031 // Guaranteed to return a non-null array
1032 Object[] listeners = listenerList.getListenerList();
1033 // Process the listeners last to first, notifying
1034 // those that are interested in this event
1035 for (int i = listeners.length-2; i>=0; i-=2) {
1036 if (listeners[i]==MenuListener.class) {
1286 }
1287
1288 /**
1289 * Programmatically performs a "click". This overrides the method
1290 * <code>AbstractButton.doClick</code> in order to make the menu pop up.
1291 * @param pressTime indicates the number of milliseconds the
1292 * button was pressed for
1293 */
1294 public void doClick(int pressTime) {
1295 MenuElement me[] = buildMenuElementArray(this);
1296 MenuSelectionManager.defaultManager().setSelectedPath(me);
1297 }
1298
1299 /*
1300 * Build an array of menu elements - from <code>PopupMenu</code> to
1301 * the root <code>JMenuBar</code>.
1302 * @param leaf the leaf node from which to start building up the array
1303 * @return the array of menu items
1304 */
1305 private MenuElement[] buildMenuElementArray(JMenu leaf) {
1306 Vector<MenuElement> elements = new Vector<MenuElement>();
1307 Component current = leaf.getPopupMenu();
1308 JPopupMenu pop;
1309 JMenu menu;
1310 JMenuBar bar;
1311
1312 while (true) {
1313 if (current instanceof JPopupMenu) {
1314 pop = (JPopupMenu) current;
1315 elements.insertElementAt(pop, 0);
1316 current = pop.getInvoker();
1317 } else if (current instanceof JMenu) {
1318 menu = (JMenu) current;
1319 elements.insertElementAt(menu, 0);
1320 current = menu.getParent();
1321 } else if (current instanceof JMenuBar) {
1322 bar = (JMenuBar) current;
1323 elements.insertElementAt(bar, 0);
1324 MenuElement me[] = new MenuElement[elements.size()];
1325 elements.copyInto(me);
1326 return me;
1390 * future Swing releases. The current serialization support is
1391 * appropriate for short term storage or RMI between applications running
1392 * the same version of Swing. As of 1.4, support for long term storage
1393 * of all JavaBeans<sup><font size="-2">TM</font></sup>
1394 * has been added to the <code>java.beans</code> package.
1395 * Please see {@link java.beans.XMLEncoder}.
1396 */
1397 protected class AccessibleJMenu extends AccessibleJMenuItem
1398 implements AccessibleSelection {
1399
1400 /**
1401 * Returns the number of accessible children in the object. If all
1402 * of the children of this object implement Accessible, than this
1403 * method should return the number of children of this object.
1404 *
1405 * @return the number of accessible children in the object.
1406 */
1407 public int getAccessibleChildrenCount() {
1408 Component[] children = getMenuComponents();
1409 int count = 0;
1410 for (Component child : children) {
1411 if (child instanceof Accessible) {
1412 count++;
1413 }
1414 }
1415 return count;
1416 }
1417
1418 /**
1419 * Returns the nth Accessible child of the object.
1420 *
1421 * @param i zero-based index of child
1422 * @return the nth Accessible child of the object
1423 */
1424 public Accessible getAccessibleChild(int i) {
1425 Component[] children = getMenuComponents();
1426 int count = 0;
1427 for (Component child : children) {
1428 if (child instanceof Accessible) {
1429 if (count == i) {
1430 if (child instanceof JComponent) {
1431 // FIXME: [[[WDW - probably should set this when
1432 // the component is added to the menu. I tried
1433 // to do this in most cases, but the separators
1434 // added by addSeparator are hard to get to.]]]
1435 AccessibleContext ac = child.getAccessibleContext();
1436 ac.setAccessibleParent(JMenu.this);
1437 }
1438 return (Accessible) child;
1439 } else {
1440 count++;
1441 }
1442 }
1443 }
1444 return null;
1445 }
1446
1447 /**
1448 * Get the role of this object.
1449 *
1450 * @return an instance of AccessibleRole describing the role of the
1451 * object
1452 * @see AccessibleRole
1453 */
1454 public AccessibleRole getAccessibleRole() {
1455 return AccessibleRole.MENU;
1456 }
1457
1458 /**
1562 MenuSelectionManager.defaultManager().setSelectedPath(me);
1563 } else {
1564 MenuSelectionManager.defaultManager().setSelectedPath(null);
1565 }
1566 }
1567 }
1568
1569 /**
1570 * Removes the nth item from the selection. In general, menus
1571 * can only have one item within them selected at a time
1572 * (e.g. one sub-menu popped open).
1573 *
1574 * @param i the zero-based index of the selected item
1575 */
1576 public void removeAccessibleSelection(int i) {
1577 if (i < 0 || i >= getItemCount()) {
1578 return;
1579 }
1580 JMenuItem mi = getItem(i);
1581 if (mi != null && mi instanceof JMenu) {
1582 if (mi.isSelected()) {
1583 MenuElement old[] =
1584 MenuSelectionManager.defaultManager().getSelectedPath();
1585 MenuElement me[] = new MenuElement[old.length-2];
1586 for (int j = 0; j < old.length -2; j++) {
1587 me[j] = old[j];
1588 }
1589 MenuSelectionManager.defaultManager().setSelectedPath(me);
1590 }
1591 }
1592 }
1593
1594 /**
1595 * Clears the selection in the object, so that nothing in the
1596 * object is selected. This will close any open sub-menu.
1597 */
1598 public void clearAccessibleSelection() {
1599 // if this menu is selected, reset selection to only go
1600 // to this menu; else do nothing
1601 MenuElement old[] =
1602 MenuSelectionManager.defaultManager().getSelectedPath();
|