1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58:
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68:
69:
81: public class JMenu extends JMenuItem implements Accessible, MenuElement
82: {
83:
87: private class MenuChangeListener
88: implements ChangeListener
89: {
90:
93: private boolean selected;
94:
95:
98: public void stateChanged(ChangeEvent ev)
99: {
100: ButtonModel m = (ButtonModel) ev.getSource();
101: boolean s = m.isSelected();
102: if (s != selected)
103: {
104: if (s)
105: fireMenuSelected();
106: else
107: fireMenuDeselected();
108: selected = s;
109: }
110: }
111: }
112:
113: private static final long serialVersionUID = 4227225638931828014L;
114:
115:
116: private JPopupMenu popupMenu = null;
117:
118:
120: private MenuEvent menuEvent = new MenuEvent(this);
121:
122:
124: private int delay;
125:
126:
127: protected WinListener popupListener;
128:
129:
133: private Point menuLocation;
134:
135:
140: private ChangeListener menuChangeListener;
141:
142:
145: public JMenu()
146: {
147: super();
148: setOpaque(false);
149: }
150:
151:
156: public JMenu(String text)
157: {
158: super(text);
159: popupMenu = new JPopupMenu();
160: popupMenu.setInvoker(this);
161: setOpaque(false);
162: }
163:
164:
170: public JMenu(Action action)
171: {
172: super(action);
173: createActionChangeListener(this);
174: popupMenu = new JPopupMenu();
175: popupMenu.setInvoker(this);
176: setOpaque(false);
177: }
178:
179:
186: public JMenu(String text, boolean tearoff)
187: {
188:
189: this(text);
190: }
191:
192:
199: public JMenuItem add(JMenuItem item)
200: {
201: return getPopupMenu().add(item);
202: }
203:
204:
211: public Component add(Component component)
212: {
213: getPopupMenu().insert(component, -1);
214: return component;
215: }
216:
217:
225: public Component add(Component component, int index)
226: {
227: return getPopupMenu().add(component, index);
228: }
229:
230:
237: public JMenuItem add(String text)
238: {
239: return add(new JMenuItem(text));
240: }
241:
242:
249: public JMenuItem add(Action action)
250: {
251: JMenuItem i = createActionComponent(action);
252: i.setAction(action);
253: add(i);
254: return i;
255: }
256:
257:
263: public void remove(JMenuItem item)
264: {
265: getPopupMenu().remove(item);
266: }
267:
268:
273: public void remove(int index)
274: {
275: if (index < 0 || (index > 0 && getMenuComponentCount() == 0))
276: throw new IllegalArgumentException();
277:
278: if (getMenuComponentCount() > 0)
279: popupMenu.remove(index);
280: }
281:
282:
287: public void remove(Component component)
288: {
289: int index = getPopupMenu().getComponentIndex(component);
290: if (index >= 0)
291: getPopupMenu().remove(index);
292: }
293:
294:
297: public void removeAll()
298: {
299: if (popupMenu != null)
300: popupMenu.removeAll();
301: }
302:
303:
310: public void insert(String text, int index)
311: {
312: this.insert(new JMenuItem(text), index);
313: }
314:
315:
324: public JMenuItem insert(JMenuItem item, int index)
325: {
326: if (index < 0)
327: throw new IllegalArgumentException("index less than zero");
328:
329: getPopupMenu().insert(item, index);
330: return item;
331: }
332:
333:
342: public JMenuItem insert(Action action, int index)
343: {
344: JMenuItem item = new JMenuItem(action);
345: this.insert(item, index);
346:
347: return item;
348: }
349:
350:
354: public void updateUI()
355: {
356: setUI((MenuItemUI) UIManager.getUI(this));
357: }
358:
359:
365: public String getUIClassID()
366: {
367: return "MenuUI";
368: }
369:
370:
375: public void setModel(ButtonModel model)
376: {
377: ButtonModel oldModel = getModel();
378: if (oldModel != null && menuChangeListener != null)
379: oldModel.removeChangeListener(menuChangeListener);
380:
381: super.setModel(model);
382:
383: if (model != null)
384: {
385: if (menuChangeListener == null)
386: menuChangeListener = new MenuChangeListener();
387: model.addChangeListener(menuChangeListener);
388: }
389: }
390:
391:
396: public boolean isSelected()
397: {
398: return super.isSelected();
399: }
400:
401:
407: public void setSelected(boolean selected)
408: {
409: ButtonModel m = getModel();
410: if (selected != m.isSelected())
411: m.setSelected(selected);
412: }
413:
414:
420: public boolean isPopupMenuVisible()
421: {
422: return getPopupMenu().isVisible();
423: }
424:
425:
430: public void setPopupMenuVisible(boolean popup)
431: {
432: if (popup != isPopupMenuVisible() && (isEnabled() || ! popup))
433: {
434: if (popup && isShowing())
435: {
436:
437: Point loc = menuLocation == null ? getPopupMenuOrigin()
438: : menuLocation;
439: getPopupMenu().show(this, loc.x, loc.y);
440: }
441: else
442: getPopupMenu().setVisible(false);
443: }
444: }
445:
446:
452: protected Point getPopupMenuOrigin()
453: {
454:
455: Point screenLoc = getLocationOnScreen();
456: Dimension size = getSize();
457:
458:
459: JPopupMenu popup = getPopupMenu();
460: Dimension popupSize = popup.getSize();
461: if (popupSize.width == 0 || popupSize.height == 0)
462: popupSize = popup.getPreferredSize();
463:
464:
465: Toolkit tk = Toolkit.getDefaultToolkit();
466: Rectangle screenBounds = new Rectangle(tk.getScreenSize());
467: GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
468: GraphicsDevice gd = ge.getDefaultScreenDevice();
469: GraphicsConfiguration gc = gd.getDefaultConfiguration();
470: Insets screenInsets = tk.getScreenInsets(gc);
471: screenBounds.x -= screenInsets.left;
472: screenBounds.width -= screenInsets.left + screenInsets.right;
473: screenBounds.y -= screenInsets.top;
474: screenBounds.height -= screenInsets.top + screenInsets.bottom;
475: screenLoc.x -= screenInsets.left;
476: screenLoc.y -= screenInsets.top;
477:
478: Point point = new Point();
479: if (isTopLevelMenu())
480: {
481:
482: int xOffset = UIManager.getInt("Menu.menuPopupOffsetX");
483: int yOffset = UIManager.getInt("Menu.menuPopupOffsetY");
484:
485: if (getComponentOrientation().isLeftToRight())
486: {
487:
488: point.x = xOffset;
489:
490: if (screenLoc.x + point.x + popupSize.width
491: > screenBounds.width + screenBounds.width
492: && screenBounds.width - size.width
493: < 2 * (screenLoc.x - screenBounds.x))
494:
495: point.x = size.width - xOffset - popupSize.width;
496: }
497: else
498: {
499:
500: point.x = size.width - xOffset - popupSize.width;
501: if (screenLoc.x + point.x < screenBounds.x
502: && screenBounds.width - size.width
503: > 2 * (screenLoc.x - screenBounds.x))
504:
505: point.x = xOffset;
506: }
507:
508: point.y = size.height + yOffset;
509: if (screenLoc.y + point.y + popupSize.height >= screenBounds.height
510: && screenBounds.height - size.height
511: < 2 * (screenLoc.y - screenBounds.y))
512:
513: point.y = - yOffset - popupSize.height;
514: }
515: else
516: {
517:
518: int xOffset = UIManager.getInt("Menu.submenuPopupOffsetX");
519: int yOffset = UIManager.getInt("Menu.submenuPopupOffsetY");
520:
521: if (getComponentOrientation().isLeftToRight())
522: {
523:
524: point.x = size.width + xOffset;
525: if (screenLoc.x + point.x + popupSize.width
526: >= screenBounds.x + screenBounds.width
527: && screenBounds.width - size.width
528: < 2 * (screenLoc.x - screenBounds.x))
529:
530: point.x = - xOffset - popupSize.width;
531: }
532: else
533: {
534:
535: point.x = - xOffset - popupSize.width;
536: if (screenLoc.x + point.x < screenBounds.x
537: && screenBounds.width - size.width
538: > 2 * (screenLoc.x - screenBounds.x))
539:
540: point.x = size.width + xOffset;
541: }
542:
543: point.y = yOffset;
544: if (screenLoc.y + point.y + popupSize.height
545: >= screenBounds.y + screenBounds.height
546: && screenBounds.height - size.height
547: < 2 * (screenLoc.y - screenBounds.y))
548:
549: point.y = size.height - yOffset - popupSize.height;
550: }
551: return point;
552: }
553:
554:
561: public int getDelay()
562: {
563: return delay;
564: }
565:
566:
574: public void setDelay(int delay)
575: {
576: if (delay < 0)
577: throw new IllegalArgumentException("delay less than 0");
578: this.delay = delay;
579: }
580:
581:
588: public void setMenuLocation(int x, int y)
589: {
590: menuLocation = new Point(x, y);
591: if (popupMenu != null)
592: popupMenu.setLocation(x, y);
593: }
594:
595:
602: protected JMenuItem createActionComponent(Action action)
603: {
604: return new JMenuItem(action);
605: }
606:
607:
615: protected PropertyChangeListener createActionChangeListener(JMenuItem item)
616: {
617: return new ActionChangedListener(item);
618: }
619:
620:
623: public void addSeparator()
624: {
625: getPopupMenu().addSeparator();
626: }
627:
628:
633: public void insertSeparator(int index)
634: {
635: if (index < 0)
636: throw new IllegalArgumentException("index less than 0");
637:
638: getPopupMenu().insert(new JPopupMenu.Separator(), index);
639: }
640:
641:
648: public JMenuItem getItem(int index)
649: {
650: if (index < 0)
651: throw new IllegalArgumentException("index less than 0");
652:
653: if (getItemCount() == 0)
654: return null;
655:
656: Component c = popupMenu.getComponentAtIndex(index);
657:
658: if (c instanceof JMenuItem)
659: return (JMenuItem) c;
660: else
661: return null;
662: }
663:
664:
671: public int getItemCount()
672: {
673: return getMenuComponentCount();
674: }
675:
676:
681: public boolean isTearOff()
682: {
683:
684: throw new Error("The method isTearOff() has not yet been implemented.");
685: }
686:
687:
692: public int getMenuComponentCount()
693: {
694: return getPopupMenu().getComponentCount();
695: }
696:
697:
705: public Component getMenuComponent(int index)
706: {
707: if (getPopupMenu() == null || getMenuComponentCount() == 0)
708: return null;
709:
710: return popupMenu.getComponentAtIndex(index);
711: }
712:
713:
718: public Component[] getMenuComponents()
719: {
720: return getPopupMenu().getComponents();
721: }
722:
723:
730: public boolean isTopLevelMenu()
731: {
732: return getParent() instanceof JMenuBar;
733: }
734:
735:
743: public boolean isMenuComponent(Component component)
744: {
745: return false;
746: }
747:
748:
753: public JPopupMenu getPopupMenu()
754: {
755: if (popupMenu == null)
756: {
757: popupMenu = new JPopupMenu();
758: popupMenu.setInvoker(this);
759: }
760: return popupMenu;
761: }
762:
763:
768: public void addMenuListener(MenuListener listener)
769: {
770: listenerList.add(MenuListener.class, listener);
771: }
772:
773:
778: public void removeMenuListener(MenuListener listener)
779: {
780: listenerList.remove(MenuListener.class, listener);
781: }
782:
783:
790: public MenuListener[] getMenuListeners()
791: {
792: return (MenuListener[]) listenerList.getListeners(MenuListener.class);
793: }
794:
795:
800: protected void fireMenuSelected()
801: {
802: MenuListener[] listeners = getMenuListeners();
803:
804: for (int index = 0; index < listeners.length; ++index)
805: listeners[index].menuSelected(menuEvent);
806: }
807:
808:
813: protected void fireMenuDeselected()
814: {
815: EventListener[] ll = listenerList.getListeners(MenuListener.class);
816:
817: for (int i = 0; i < ll.length; i++)
818: ((MenuListener) ll[i]).menuDeselected(menuEvent);
819: }
820:
821:
826: protected void fireMenuCanceled()
827: {
828: EventListener[] ll = listenerList.getListeners(MenuListener.class);
829:
830: for (int i = 0; i < ll.length; i++)
831: ((MenuListener) ll[i]).menuCanceled(menuEvent);
832: }
833:
834:
841: protected WinListener createWinListener(JPopupMenu popup)
842: {
843: return new WinListener(popup);
844: }
845:
846:
854: public void menuSelectionChanged(boolean changed)
855: {
856:
857:
858: setSelected(changed);
859: }
860:
861:
867: public MenuElement[] getSubElements()
868: {
869: return new MenuElement[] { popupMenu };
870: }
871:
872:
875: public Component getComponent()
876: {
877: return this;
878: }
879:
880:
887: public void setAccelerator(KeyStroke keystroke)
888: {
889: throw new Error("setAccelerator() is not defined for JMenu. Use setMnemonic() instead.");
890: }
891:
892:
897: protected void processKeyEvent(KeyEvent event)
898: {
899: MenuSelectionManager.defaultManager().processKeyEvent(event);
900: }
901:
902:
907: public void doClick(int time)
908: {
909: getModel().setArmed(true);
910: getModel().setPressed(true);
911: try
912: {
913: java.lang.Thread.sleep(time);
914: }
915: catch (java.lang.InterruptedException e)
916: {
917:
918: }
919:
920: getModel().setPressed(false);
921: getModel().setArmed(false);
922: popupMenu.show(this, this.getWidth(), 0);
923: }
924:
925:
931: protected String paramString()
932: {
933: return super.paramString();
934: }
935:
936: public AccessibleContext getAccessibleContext()
937: {
938: if (accessibleContext == null)
939: accessibleContext = new AccessibleJMenu();
940:
941: return accessibleContext;
942: }
943:
944:
947: protected class AccessibleJMenu extends AccessibleJMenuItem
948: implements AccessibleSelection
949: {
950: private static final long serialVersionUID = -8131864021059524309L;
951:
952: protected AccessibleJMenu()
953: {
954:
955: }
956:
957:
962: public int getAccessibleChildrenCount()
963: {
964: Component[] children = getMenuComponents();
965: int count = 0;
966: for (int i = 0; i < children.length; i++)
967: {
968: if (children[i] instanceof Accessible)
969: count++;
970: }
971: return count;
972: }
973:
974:
981: public Accessible getAccessibleChild(int index)
982: {
983: Component[] children = getMenuComponents();
984: int count = 0;
985: Accessible found = null;
986: for (int i = 0; i < children.length; i++)
987: {
988: if (children[i] instanceof Accessible)
989: {
990: if (count == index)
991: {
992: found = (Accessible) children[i];
993: break;
994: }
995: count++;
996: }
997: }
998: return found;
999: }
1000:
1001:
1007: public AccessibleSelection getAccessibleSelection()
1008: {
1009: return this;
1010: }
1011:
1012:
1021: public Accessible getAccessibleSelection(int index)
1022: {
1023: Accessible selected = null;
1024:
1025: if (index == 0)
1026: {
1027: MenuSelectionManager msm = MenuSelectionManager.defaultManager();
1028: MenuElement[] me = msm.getSelectedPath();
1029: if (me != null)
1030: {
1031: for (int i = 0; i < me.length; i++)
1032: {
1033: if (me[i] == JMenu.this)
1034: {
1035:
1036:
1037: do
1038: {
1039: if (me[i] instanceof Accessible)
1040: {
1041: selected = (Accessible) me[i];
1042: break;
1043: }
1044: i++;
1045: } while (i < me.length);
1046: }
1047: if (selected != null)
1048: break;
1049: }
1050: }
1051: }
1052: return selected;
1053: }
1054:
1055:
1064: public boolean isAccessibleChildSelected(int index)
1065: {
1066: boolean selected = false;
1067: MenuSelectionManager msm = MenuSelectionManager.defaultManager();
1068: MenuElement[] me = msm.getSelectedPath();
1069: if (me != null)
1070: {
1071: Accessible toBeFound = getAccessibleChild(index);
1072: for (int i = 0; i < me.length; i++)
1073: {
1074: if (me[i] == toBeFound)
1075: {
1076: selected = true;
1077: break;
1078: }
1079: }
1080: }
1081: return selected;
1082: }
1083:
1084:
1090: public AccessibleRole getAccessibleRole()
1091: {
1092: return AccessibleRole.MENU;
1093: }
1094:
1095:
1102: public int getAccessibleSelectionCount()
1103: {
1104: int count = 0;
1105: MenuSelectionManager msm = MenuSelectionManager.defaultManager();
1106: MenuElement[] me = msm.getSelectedPath();
1107: if (me != null)
1108: {
1109: for (int i = 0; i < me.length; i++)
1110: {
1111: if (me[i] == JMenu.this)
1112: {
1113: if (i + 1 < me.length)
1114: {
1115: count = 1;
1116: break;
1117: }
1118: }
1119: }
1120: }
1121: return count;
1122: }
1123:
1124:
1129: public void addAccessibleSelection(int index)
1130: {
1131: Accessible child = getAccessibleChild(index);
1132: if (child != null && child instanceof JMenuItem)
1133: {
1134: JMenuItem mi = (JMenuItem) child;
1135: MenuSelectionManager msm = MenuSelectionManager.defaultManager();
1136: msm.setSelectedPath(createPath(JMenu.this));
1137: }
1138: }
1139:
1140:
1145: public void removeAccessibleSelection(int index)
1146: {
1147: Accessible child = getAccessibleChild(index);
1148: if (child != null)
1149: {
1150: MenuSelectionManager msm = MenuSelectionManager.defaultManager();
1151: MenuElement[] oldSelection = msm.getSelectedPath();
1152: for (int i = 0; i < oldSelection.length; i++)
1153: {
1154: if (oldSelection[i] == child)
1155: {
1156:
1157:
1158: MenuElement[] newSel = new MenuElement[i - 1];
1159: System.arraycopy(oldSelection, 0, newSel, 0, i - 1);
1160: msm.setSelectedPath(newSel);
1161: break;
1162: }
1163: }
1164: }
1165: }
1166:
1167:
1171: public void clearAccessibleSelection()
1172: {
1173: MenuSelectionManager msm = MenuSelectionManager.defaultManager();
1174: MenuElement[] oldSelection = msm.getSelectedPath();
1175: for (int i = 0; i < oldSelection.length; i++)
1176: {
1177: if (oldSelection[i] == JMenu.this)
1178: {
1179:
1180:
1181: MenuElement[] newSel = new MenuElement[i];
1182: System.arraycopy(oldSelection, 0, newSel, 0, i);
1183: msm.setSelectedPath(newSel);
1184: break;
1185: }
1186: }
1187: }
1188:
1189:
1193: public void selectAllAccessibleSelection()
1194: {
1195:
1196: }
1197: }
1198:
1199: protected class WinListener extends WindowAdapter implements Serializable
1200: {
1201: private static final long serialVersionUID = -6415815570638474823L;
1202:
1203:
1208: public WinListener(JPopupMenu popup)
1209: {
1210:
1211: }
1212:
1213:
1219: public void windowClosing(WindowEvent event)
1220: {
1221: setSelected(false);
1222: }
1223: }
1224:
1225:
1228: private class ActionChangedListener implements PropertyChangeListener
1229: {
1230:
1231: private JMenuItem menuItem;
1232:
1233:
1234: public ActionChangedListener(JMenuItem menuItem)
1235: {
1236: this.menuItem = menuItem;
1237:
1238: Action a = menuItem.getAction();
1239: if (a != null)
1240: a.addPropertyChangeListener(this);
1241: }
1242:
1243:
1244: public void propertyChange(PropertyChangeEvent evt)
1245: {
1246:
1247: }
1248: }
1249:
1250:
1260: MenuElement[] createPath(JMenu leaf)
1261: {
1262: ArrayList path = new ArrayList();
1263: MenuElement[] array = null;
1264: Component current = leaf.getPopupMenu();
1265: while (true)
1266: {
1267: if (current instanceof JPopupMenu)
1268: {
1269: JPopupMenu popupMenu = (JPopupMenu) current;
1270: path.add(0, popupMenu);
1271: current = popupMenu.getInvoker();
1272: }
1273: else if (current instanceof JMenu)
1274: {
1275: JMenu menu = (JMenu) current;
1276: path.add(0, menu);
1277: current = menu.getParent();
1278: }
1279: else if (current instanceof JMenuBar)
1280: {
1281: JMenuBar menuBar = (JMenuBar) current;
1282: path.add(0, menuBar);
1283: array = new MenuElement[path.size()];
1284: array = (MenuElement[]) path.toArray(array);
1285: break;
1286: }
1287: }
1288: return array;
1289: }
1290: }