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:
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85:
86:
89: public class BasicMenuItemUI extends MenuItemUI
90: {
91:
94: protected Font acceleratorFont;
95:
96:
99: protected Color acceleratorForeground;
100:
101:
105: protected Color acceleratorSelectionForeground;
106:
107:
111: protected Icon arrowIcon;
112:
113:
117: protected Icon checkIcon;
118:
119:
122: protected int defaultTextIconGap = 4;
123:
124:
127: protected Color disabledForeground;
128:
129:
132: protected MenuDragMouseListener menuDragMouseListener;
133:
134:
137: protected JMenuItem menuItem;
138:
139:
142: protected MenuKeyListener menuKeyListener;
143:
144:
147: protected MouseInputListener mouseInputListener;
148:
149:
152: protected boolean oldBorderPainted;
153:
154:
157: protected Color selectionBackground;
158:
159:
162: protected Color selectionForeground;
163:
164:
167: private String acceleratorDelimiter;
168:
169:
172: private ItemListener itemListener;
173:
174:
177: private int defaultAcceleratorLabelGap = 10;
178:
179:
182: private int MenuGap = 10;
183:
184:
185: PropertyChangeHandler propertyChangeListener;
186:
187:
191: class PropertyChangeHandler implements PropertyChangeListener
192: {
193:
200: public void propertyChange(PropertyChangeEvent e)
201: {
202: if (e.getPropertyName() == "accelerator")
203: {
204: InputMap map = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
205: if (map != null)
206: map.remove((KeyStroke)e.getOldValue());
207: else
208: map = new ComponentInputMapUIResource(menuItem);
209:
210: KeyStroke accelerator = (KeyStroke) e.getNewValue();
211: if (accelerator != null)
212: map.put(accelerator, "doClick");
213: }
214: }
215: }
216:
217:
223: class ClickAction extends AbstractAction
224: {
225:
229: public void actionPerformed(ActionEvent event)
230: {
231: doClick(MenuSelectionManager.defaultManager());
232: }
233: }
234:
235:
238: public BasicMenuItemUI()
239: {
240: mouseInputListener = createMouseInputListener(menuItem);
241: menuDragMouseListener = createMenuDragMouseListener(menuItem);
242: menuKeyListener = createMenuKeyListener(menuItem);
243: itemListener = new ItemHandler();
244: propertyChangeListener = new PropertyChangeHandler();
245: }
246:
247:
254: protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
255: {
256: return new MenuDragMouseHandler();
257: }
258:
259:
267: protected MenuKeyListener createMenuKeyListener(JComponent c)
268: {
269: return new MenuKeyHandler();
270: }
271:
272:
279: protected MouseInputListener createMouseInputListener(JComponent c)
280: {
281: return new MouseInputHandler();
282: }
283:
284:
292: public static ComponentUI createUI(JComponent c)
293: {
294: return new BasicMenuItemUI();
295: }
296:
297:
303: protected void doClick(MenuSelectionManager msm)
304: {
305: menuItem.doClick();
306: msm.clearSelectedPath();
307: }
308:
309:
316: public Dimension getMaximumSize(JComponent c)
317: {
318: return null;
319: }
320:
321:
328: public Dimension getMinimumSize(JComponent c)
329: {
330: return null;
331: }
332:
333:
339: public MenuElement[] getPath()
340: {
341: ArrayList path = new ArrayList();
342:
343:
344: if (menuItem instanceof JMenu)
345: path.add(((JMenu) menuItem).getPopupMenu());
346:
347: Component c = menuItem;
348: while (c instanceof MenuElement)
349: {
350: path.add(0, (MenuElement) c);
351:
352: if (c instanceof JPopupMenu)
353: c = ((JPopupMenu) c).getInvoker();
354: else
355: c = c.getParent();
356: }
357:
358: MenuElement[] pathArray = new MenuElement[path.size()];
359: path.toArray(pathArray);
360: return pathArray;
361: }
362:
363:
376: protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
377: Icon arrowIcon,
378: int defaultTextIconGap)
379: {
380: JMenuItem m = (JMenuItem) c;
381: Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m,
382: defaultTextIconGap);
383:
384:
385:
386: KeyStroke accelerator = m.getAccelerator();
387: Rectangle rect;
388:
389: if (accelerator != null)
390: {
391: rect = getAcceleratorRect(
392: accelerator,
393: m.getToolkit().getFontMetrics(acceleratorFont));
394:
395:
396: d.width += rect.width + defaultAcceleratorLabelGap;
397:
398:
399: if (d.height < rect.height)
400: d.height = rect.height;
401: }
402:
403: if (checkIcon != null)
404: {
405: d.width += checkIcon.getIconWidth() + defaultTextIconGap;
406:
407: if (checkIcon.getIconHeight() > d.height)
408: d.height = checkIcon.getIconHeight();
409: }
410:
411: if (arrowIcon != null && (c instanceof JMenu))
412: {
413: int pWidth = m.getParent().getWidth();
414: if (!((JMenu)c).isTopLevelMenu() && d.width < pWidth)
415: d.width = pWidth
416: - m.getInsets().left - m.getInsets().right;
417: else
418: d.width += arrowIcon.getIconWidth() + MenuGap;
419:
420: if (arrowIcon.getIconHeight() > d.height)
421: d.height = arrowIcon.getIconHeight();
422: }
423:
424: return d;
425: }
426:
427:
434: public Dimension getPreferredSize(JComponent c)
435: {
436: return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap);
437: }
438:
439:
444: protected String getPropertyPrefix()
445: {
446: return "MenuItem";
447: }
448:
449:
455: protected void installComponents(JMenuItem menuItem)
456: {
457:
458: }
459:
460:
464: protected void installDefaults()
465: {
466: String prefix = getPropertyPrefix();
467: LookAndFeel.installBorder(menuItem, prefix + ".border");
468: LookAndFeel.installColorsAndFont(menuItem, prefix + ".background",
469: prefix + ".foreground", prefix + ".font");
470: menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
471: acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont");
472: acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground");
473: acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground");
474: selectionBackground = UIManager.getColor(prefix + ".selectionBackground");
475: selectionForeground = UIManager.getColor(prefix + ".selectionForeground");
476: acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter");
477: checkIcon = UIManager.getIcon(prefix + ".checkIcon");
478:
479: menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
480: menuItem.setHorizontalAlignment(SwingConstants.LEADING);
481: }
482:
483:
486: protected void installKeyboardActions()
487: {
488: InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
489: if (focusedWindowMap == null)
490: focusedWindowMap = new ComponentInputMapUIResource(menuItem);
491: KeyStroke accelerator = menuItem.getAccelerator();
492: if (accelerator != null)
493: focusedWindowMap.put(accelerator, "doClick");
494: SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap);
495:
496: ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem);
497: if (UIActionMap == null)
498: UIActionMap = new ActionMapUIResource();
499: UIActionMap.put("doClick", new ClickAction());
500: SwingUtilities.replaceUIActionMap(menuItem, UIActionMap);
501: }
502:
503:
506: protected void installListeners()
507: {
508: menuItem.addMouseListener(mouseInputListener);
509: menuItem.addMouseMotionListener(mouseInputListener);
510: menuItem.addMenuDragMouseListener(menuDragMouseListener);
511: menuItem.addMenuKeyListener(menuKeyListener);
512: menuItem.addItemListener(itemListener);
513: menuItem.addPropertyChangeListener(propertyChangeListener);
514: }
515:
516:
524: public void installUI(JComponent c)
525: {
526: super.installUI(c);
527: menuItem = (JMenuItem) c;
528: installDefaults();
529: installComponents(menuItem);
530: installListeners();
531: installKeyboardActions();
532: }
533:
534:
542: public void paint(Graphics g, JComponent c)
543: {
544: paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(),
545: c.getForeground(), defaultTextIconGap);
546: }
547:
548:
558: protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
559: {
560:
561:
562: ButtonModel mod = menuItem.getModel();
563: if (menuItem.isContentAreaFilled())
564: {
565: if ((menuItem.isSelected() && checkIcon == null) || (mod != null &&
566: mod.isArmed())
567: && (menuItem.getParent() instanceof MenuElement))
568: g.setColor(selectionBackground);
569: else
570: g.setColor(bgColor);
571: g.fillRect(0, 0, menuItem.getWidth(), menuItem.getHeight());
572: }
573: }
574:
575:
593: protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
594: Icon arrowIcon, Color background,
595: Color foreground, int defaultTextIconGap)
596: {
597: JMenuItem m = (JMenuItem) c;
598: Rectangle tr = new Rectangle();
599: Rectangle ir = new Rectangle();
600: Rectangle vr = new Rectangle();
601: Rectangle br = new Rectangle();
602: Rectangle ar = new Rectangle();
603: Rectangle cr = new Rectangle();
604:
605: int vertAlign = m.getVerticalAlignment();
606: int horAlign = m.getHorizontalAlignment();
607: int vertTextPos = m.getVerticalTextPosition();
608: int horTextPos = m.getHorizontalTextPosition();
609:
610: Font f = m.getFont();
611: g.setFont(f);
612: FontMetrics fm = g.getFontMetrics(f);
613: SwingUtilities.calculateInnerArea(m, br);
614: SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
615: paintBackground(g, m, background);
616:
617:
621: Insets insets = m.getInsets();
622: br.x -= insets.left;
623: br.y -= insets.top;
624: br.width += insets.right + insets.left;
625: br.height += insets.top + insets.bottom;
626:
627:
628: if (checkIcon != null)
629: {
630: SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
631: horAlign, vertTextPos, horTextPos,
632: vr, cr, tr, defaultTextIconGap);
633: checkIcon.paintIcon(m, g, cr.x, cr.y);
634:
635:
636:
637:
638: vr.x = cr.x + cr.width + defaultTextIconGap;
639: }
640:
641:
642: if (arrowIcon != null && (c instanceof JMenu))
643: {
644: if (!((JMenu) c).isTopLevelMenu())
645: {
646: int width = arrowIcon.getIconWidth();
647: int height = arrowIcon.getIconHeight();
648: int offset = (vr.height - height) / 2;
649: arrowIcon.paintIcon(m, g, vr.width - width, vr.y + offset);
650: }
651: }
652:
653:
654: Icon i = m.getIcon();
655: SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, vertAlign,
656: horAlign, vertTextPos, horTextPos, vr,
657: ir, tr, defaultTextIconGap);
658: if (i != null)
659: i.paintIcon(c, g, ir.x, ir.y);
660: paintText(g, m, tr, m.getText());
661:
662:
663: String acceleratorText = "";
664:
665: if (m.getAccelerator() != null)
666: {
667: acceleratorText = getAcceleratorText(m.getAccelerator());
668: fm = g.getFontMetrics(acceleratorFont);
669: ar.width = fm.stringWidth(acceleratorText);
670: ar.x = br.width - ar.width;
671: vr.x = br.width - ar.width - defaultTextIconGap;
672:
673: SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
674: vertAlign, horAlign, vertTextPos,
675: horTextPos, vr, ir, ar,
676: defaultTextIconGap);
677:
678: paintAccelerator(g, m, ar, acceleratorText);
679: }
680: }
681:
682:
695: protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
696: String text)
697: {
698: Font f = menuItem.getFont();
699: g.setFont(f);
700: FontMetrics fm = g.getFontMetrics(f);
701:
702: if (text != null && !text.equals(""))
703: {
704: if (menuItem.isEnabled())
705: {
706:
707:
708: ButtonModel mod = menuItem.getModel();
709: if ((menuItem.isSelected() && checkIcon == null)
710: || (mod != null && mod.isArmed())
711: && (menuItem.getParent() instanceof MenuElement))
712: g.setColor(selectionForeground);
713: else
714: g.setColor(menuItem.getForeground());
715: }
716: else
717:
718:
719:
720:
721:
722: g.setColor(Color.gray);
723:
724: int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
725:
726: if (mnemonicIndex != -1)
727: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
728: textRect.x,
729: textRect.y
730: + fm.getAscent());
731: else
732: BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
733: textRect.y + fm.getAscent());
734: }
735: }
736:
737:
743: protected void uninstallComponents(JMenuItem menuItem)
744: {
745:
746: }
747:
748:
752: protected void uninstallDefaults()
753: {
754: menuItem.setForeground(null);
755: menuItem.setBackground(null);
756: menuItem.setBorder(null);
757: menuItem.setMargin(null);
758: menuItem.setBackground(null);
759: menuItem.setBorder(null);
760: menuItem.setFont(null);
761: menuItem.setForeground(null);
762: menuItem.setMargin(null);
763: acceleratorFont = null;
764: acceleratorForeground = null;
765: acceleratorSelectionForeground = null;
766: arrowIcon = null;
767: selectionBackground = null;
768: selectionForeground = null;
769: acceleratorDelimiter = null;
770: }
771:
772:
775: protected void uninstallKeyboardActions()
776: {
777: SwingUtilities.replaceUIInputMap(menuItem,
778: JComponent.WHEN_IN_FOCUSED_WINDOW, null);
779: }
780:
781:
784: protected void uninstallListeners()
785: {
786: menuItem.removeMouseListener(mouseInputListener);
787: menuItem.removeMenuDragMouseListener(menuDragMouseListener);
788: menuItem.removeMenuKeyListener(menuKeyListener);
789: menuItem.removeItemListener(itemListener);
790: menuItem.removePropertyChangeListener(propertyChangeListener);
791: }
792:
793:
801: public void uninstallUI(JComponent c)
802: {
803: uninstallListeners();
804: uninstallDefaults();
805: uninstallComponents(menuItem);
806: menuItem = null;
807: }
808:
809:
817: public void update(Graphics g, JComponent c)
818: {
819: paint(g, c);
820: }
821:
822:
829: private String getAcceleratorText(KeyStroke accelerator)
830: {
831:
832: String modifiersText = "";
833: int modifiers = accelerator.getModifiers();
834: char keyChar = accelerator.getKeyChar();
835: int keyCode = accelerator.getKeyCode();
836:
837: if (modifiers != 0)
838: modifiersText = KeyEvent.getKeyModifiersText(modifiers)
839: + acceleratorDelimiter;
840:
841: if (keyCode == KeyEvent.VK_UNDEFINED)
842: return modifiersText + keyChar;
843: else
844: return modifiersText + KeyEvent.getKeyText(keyCode);
845: }
846:
847:
856: private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
857: {
858: int width = fm.stringWidth(getAcceleratorText(accelerator));
859: int height = fm.getHeight();
860: return new Rectangle(0, 0, width, height);
861: }
862:
863:
876: private void paintAccelerator(Graphics g, JMenuItem menuItem,
877: Rectangle acceleratorRect,
878: String acceleratorText)
879: {
880: g.setFont(acceleratorFont);
881: FontMetrics fm = g.getFontMetrics(acceleratorFont);
882:
883: if (menuItem.isEnabled())
884: g.setColor(acceleratorForeground);
885: else
886:
887:
888: g.setColor(Color.gray);
889:
890: BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x,
891: acceleratorRect.y + fm.getAscent());
892: }
893:
894:
899: protected class MouseInputHandler implements MouseInputListener
900: {
901:
904: protected MouseInputHandler()
905: {
906:
907: }
908:
909:
916: public void mouseClicked(MouseEvent e)
917: {
918: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
919: manager.processMouseEvent(e);
920: }
921:
922:
929: public void mouseDragged(MouseEvent e)
930: {
931: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
932: manager.processMouseEvent(e);
933: }
934:
935:
944: public void mouseEntered(MouseEvent e)
945: {
946: Component source = (Component) e.getSource();
947: if (source.getParent() instanceof MenuElement)
948: {
949: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
950: manager.setSelectedPath(getPath());
951: manager.processMouseEvent(e);
952: }
953: }
954:
955:
962: public void mouseExited(MouseEvent e)
963: {
964: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
965: manager.processMouseEvent(e);
966: }
967:
968:
975: public void mouseMoved(MouseEvent e)
976: {
977: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
978: manager.processMouseEvent(e);
979: }
980:
981:
988: public void mousePressed(MouseEvent e)
989: {
990: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
991: manager.processMouseEvent(e);
992: }
993:
994:
1002: public void mouseReleased(MouseEvent e)
1003: {
1004: Rectangle size = menuItem.getBounds();
1005: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1006: if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
1007: && e.getY() < size.height)
1008: {
1009: manager.clearSelectedPath();
1010: menuItem.doClick();
1011: }
1012:
1013: else
1014: manager.processMouseEvent(e);
1015: }
1016: }
1017:
1018:
1021: private class MenuDragMouseHandler implements MenuDragMouseListener
1022: {
1023:
1029: public void menuDragMouseDragged(MenuDragMouseEvent e)
1030: {
1031: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1032: manager.setSelectedPath(e.getPath());
1033: }
1034:
1035:
1042: public void menuDragMouseEntered(MenuDragMouseEvent e)
1043: {
1044: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1045: manager.setSelectedPath(e.getPath());
1046: }
1047:
1048:
1054: public void menuDragMouseExited(MenuDragMouseEvent e)
1055: {
1056:
1057: }
1058:
1059:
1066: public void menuDragMouseReleased(MenuDragMouseEvent e)
1067: {
1068: MenuElement[] path = e.getPath();
1069:
1070: if (path[path.length - 1] instanceof JMenuItem)
1071: ((JMenuItem) path[path.length - 1]).doClick();
1072:
1073: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1074: manager.clearSelectedPath();
1075: }
1076: }
1077:
1078:
1082: private class MenuKeyHandler implements MenuKeyListener
1083: {
1084:
1090: public void menuKeyPressed(MenuKeyEvent e)
1091: {
1092:
1093: }
1094:
1095:
1101: public void menuKeyReleased(MenuKeyEvent e)
1102: {
1103:
1104: }
1105:
1106:
1113: public void menuKeyTyped(MenuKeyEvent e)
1114: {
1115:
1116: }
1117: }
1118:
1119:
1123: private class ItemHandler implements ItemListener
1124: {
1125:
1130: public void itemStateChanged(ItemEvent evt)
1131: {
1132: boolean state = false;
1133: if (menuItem instanceof JCheckBoxMenuItem)
1134: {
1135: if (evt.getStateChange() == ItemEvent.SELECTED)
1136: state = true;
1137: ((JCheckBoxMenuItem) menuItem).setState(state);
1138: }
1139: menuItem.revalidate();
1140: menuItem.repaint();
1141: }
1142: }
1143: }