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: map.put((KeyStroke)e.getNewValue(), "doClick");
210: }
211: }
212: }
213:
214:
220: class ClickAction extends AbstractAction
221: {
222:
226: public void actionPerformed(ActionEvent event)
227: {
228: doClick(MenuSelectionManager.defaultManager());
229: }
230: }
231:
232:
235: public BasicMenuItemUI()
236: {
237: mouseInputListener = createMouseInputListener(menuItem);
238: menuDragMouseListener = createMenuDragMouseListener(menuItem);
239: menuKeyListener = createMenuKeyListener(menuItem);
240: itemListener = new ItemHandler();
241: propertyChangeListener = new PropertyChangeHandler();
242: }
243:
244:
251: protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
252: {
253: return new MenuDragMouseHandler();
254: }
255:
256:
264: protected MenuKeyListener createMenuKeyListener(JComponent c)
265: {
266: return new MenuKeyHandler();
267: }
268:
269:
276: protected MouseInputListener createMouseInputListener(JComponent c)
277: {
278: return new MouseInputHandler();
279: }
280:
281:
289: public static ComponentUI createUI(JComponent c)
290: {
291: return new BasicMenuItemUI();
292: }
293:
294:
300: protected void doClick(MenuSelectionManager msm)
301: {
302: menuItem.doClick();
303: msm.clearSelectedPath();
304: }
305:
306:
313: public Dimension getMaximumSize(JComponent c)
314: {
315: return null;
316: }
317:
318:
325: public Dimension getMinimumSize(JComponent c)
326: {
327: return null;
328: }
329:
330:
336: public MenuElement[] getPath()
337: {
338: ArrayList path = new ArrayList();
339:
340:
341: if (menuItem instanceof JMenu)
342: path.add(((JMenu) menuItem).getPopupMenu());
343:
344: Component c = menuItem;
345: while (c instanceof MenuElement)
346: {
347: path.add(0, (MenuElement) c);
348:
349: if (c instanceof JPopupMenu)
350: c = ((JPopupMenu) c).getInvoker();
351: else
352: c = c.getParent();
353: }
354:
355: MenuElement[] pathArray = new MenuElement[path.size()];
356: path.toArray(pathArray);
357: return pathArray;
358: }
359:
360:
373: protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
374: Icon arrowIcon,
375: int defaultTextIconGap)
376: {
377: JMenuItem m = (JMenuItem) c;
378: Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m,
379: defaultTextIconGap);
380:
381:
382:
383: KeyStroke accelerator = m.getAccelerator();
384: Rectangle rect;
385:
386: if (accelerator != null)
387: {
388: rect = getAcceleratorRect(
389: accelerator,
390: m.getToolkit().getFontMetrics(acceleratorFont));
391:
392:
393: d.width += rect.width + defaultAcceleratorLabelGap;
394:
395:
396: if (d.height < rect.height)
397: d.height = rect.height;
398: }
399:
400: if (checkIcon != null)
401: {
402: d.width += checkIcon.getIconWidth() + defaultTextIconGap;
403:
404: if (checkIcon.getIconHeight() > d.height)
405: d.height = checkIcon.getIconHeight();
406: }
407:
408: if (arrowIcon != null && (c instanceof JMenu))
409: {
410: int pWidth = m.getParent().getWidth();
411: if (!((JMenu)c).isTopLevelMenu() && d.width < pWidth)
412: d.width = pWidth
413: - m.getInsets().left - m.getInsets().right;
414: else
415: d.width += arrowIcon.getIconWidth() + MenuGap;
416:
417: if (arrowIcon.getIconHeight() > d.height)
418: d.height = arrowIcon.getIconHeight();
419: }
420:
421: return d;
422: }
423:
424:
431: public Dimension getPreferredSize(JComponent c)
432: {
433: return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap);
434: }
435:
436:
441: protected String getPropertyPrefix()
442: {
443: return "MenuItem";
444: }
445:
446:
452: protected void installComponents(JMenuItem menuItem)
453: {
454:
455: }
456:
457:
461: protected void installDefaults()
462: {
463: String prefix = getPropertyPrefix();
464: LookAndFeel.installBorder(menuItem, prefix + ".border");
465: LookAndFeel.installColorsAndFont(menuItem, prefix + ".background",
466: prefix + ".foreground", prefix + ".font");
467: menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
468: acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont");
469: acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground");
470: acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground");
471: selectionBackground = UIManager.getColor(prefix + ".selectionBackground");
472: selectionForeground = UIManager.getColor(prefix + ".selectionForeground");
473: acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter");
474: checkIcon = UIManager.getIcon(prefix + ".checkIcon");
475:
476: menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
477: menuItem.setHorizontalAlignment(SwingConstants.LEADING);
478: }
479:
480:
483: protected void installKeyboardActions()
484: {
485: InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
486: if (focusedWindowMap == null)
487: focusedWindowMap = new ComponentInputMapUIResource(menuItem);
488: focusedWindowMap.put(menuItem.getAccelerator(), "doClick");
489: SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap);
490:
491: ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem);
492: if (UIActionMap == null)
493: UIActionMap = new ActionMapUIResource();
494: UIActionMap.put("doClick", new ClickAction());
495: SwingUtilities.replaceUIActionMap(menuItem, UIActionMap);
496: }
497:
498:
501: protected void installListeners()
502: {
503: menuItem.addMouseListener(mouseInputListener);
504: menuItem.addMouseMotionListener(mouseInputListener);
505: menuItem.addMenuDragMouseListener(menuDragMouseListener);
506: menuItem.addMenuKeyListener(menuKeyListener);
507: menuItem.addItemListener(itemListener);
508: menuItem.addPropertyChangeListener(propertyChangeListener);
509: }
510:
511:
519: public void installUI(JComponent c)
520: {
521: super.installUI(c);
522: menuItem = (JMenuItem) c;
523: installDefaults();
524: installComponents(menuItem);
525: installListeners();
526: installKeyboardActions();
527: }
528:
529:
537: public void paint(Graphics g, JComponent c)
538: {
539: paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(),
540: c.getForeground(), defaultTextIconGap);
541: }
542:
543:
553: protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
554: {
555:
556:
557: ButtonModel mod = menuItem.getModel();
558: if ((menuItem.isSelected() && checkIcon == null) || (mod != null &&
559: mod.isArmed())
560: && (menuItem.getParent() instanceof MenuElement))
561: {
562: if (menuItem.isContentAreaFilled())
563: {
564: g.setColor(selectionBackground);
565: g.fillRect(0, 0, menuItem.getWidth(), menuItem.getHeight());
566: }
567: }
568:
569: }
570:
571:
589: protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
590: Icon arrowIcon, Color background,
591: Color foreground, int defaultTextIconGap)
592: {
593: JMenuItem m = (JMenuItem) c;
594: Rectangle tr = new Rectangle();
595: Rectangle ir = new Rectangle();
596: Rectangle vr = new Rectangle();
597: Rectangle br = new Rectangle();
598: Rectangle ar = new Rectangle();
599: Rectangle cr = new Rectangle();
600:
601: int vertAlign = m.getVerticalAlignment();
602: int horAlign = m.getHorizontalAlignment();
603: int vertTextPos = m.getVerticalTextPosition();
604: int horTextPos = m.getHorizontalTextPosition();
605:
606: Font f = m.getFont();
607: g.setFont(f);
608: FontMetrics fm = g.getFontMetrics(f);
609: SwingUtilities.calculateInnerArea(m, br);
610: SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
611: paintBackground(g, m, m.getBackground());
612:
613:
617: Insets insets = m.getInsets();
618: br.x -= insets.left;
619: br.y -= insets.top;
620: br.width += insets.right + insets.left;
621: br.height += insets.top + insets.bottom;
622:
623:
624: if (checkIcon != null)
625: {
626: SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
627: horAlign, vertTextPos, horTextPos,
628: vr, cr, tr, defaultTextIconGap);
629: checkIcon.paintIcon(m, g, cr.x, cr.y);
630:
631:
632:
633:
634: vr.x = cr.x + cr.width + defaultTextIconGap;
635: }
636:
637:
638: if (arrowIcon != null && (c instanceof JMenu))
639: {
640: if (!((JMenu) c).isTopLevelMenu())
641: {
642: int width = arrowIcon.getIconWidth();
643: int height = arrowIcon.getIconHeight();
644: int offset = (vr.height - height) / 2;
645: arrowIcon.paintIcon(m, g, vr.width - width, vr.y + offset);
646: }
647: }
648:
649:
650: Icon i = m.getIcon();
651: SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, vertAlign,
652: horAlign, vertTextPos, horTextPos, vr,
653: ir, tr, defaultTextIconGap);
654: if (i != null)
655: i.paintIcon(c, g, ir.x, ir.y);
656: paintText(g, m, tr, m.getText());
657:
658:
659: String acceleratorText = "";
660:
661: if (m.getAccelerator() != null)
662: {
663: acceleratorText = getAcceleratorText(m.getAccelerator());
664: fm = g.getFontMetrics(acceleratorFont);
665: ar.width = fm.stringWidth(acceleratorText);
666: ar.x = br.width - ar.width;
667: vr.x = br.width - ar.width - defaultTextIconGap;
668:
669: SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
670: vertAlign, horAlign, vertTextPos,
671: horTextPos, vr, ir, ar,
672: defaultTextIconGap);
673:
674: paintAccelerator(g, m, ar, acceleratorText);
675: }
676: }
677:
678:
691: protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
692: String text)
693: {
694: Font f = menuItem.getFont();
695: g.setFont(f);
696: FontMetrics fm = g.getFontMetrics(f);
697:
698: if (text != null && !text.equals(""))
699: {
700: if (menuItem.isEnabled())
701: {
702:
703:
704: ButtonModel mod = menuItem.getModel();
705: if ((menuItem.isSelected() && checkIcon == null)
706: || (mod != null && mod.isArmed())
707: && (menuItem.getParent() instanceof MenuElement))
708: g.setColor(selectionForeground);
709: else
710: g.setColor(menuItem.getForeground());
711: }
712: else
713:
714:
715:
716:
717:
718: g.setColor(Color.gray);
719:
720: int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
721:
722: if (mnemonicIndex != -1)
723: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
724: textRect.x,
725: textRect.y
726: + fm.getAscent());
727: else
728: BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
729: textRect.y + fm.getAscent());
730: }
731: }
732:
733:
739: protected void uninstallComponents(JMenuItem menuItem)
740: {
741:
742: }
743:
744:
748: protected void uninstallDefaults()
749: {
750: menuItem.setForeground(null);
751: menuItem.setBackground(null);
752: menuItem.setBorder(null);
753: menuItem.setMargin(null);
754: menuItem.setBackground(null);
755: menuItem.setBorder(null);
756: menuItem.setFont(null);
757: menuItem.setForeground(null);
758: menuItem.setMargin(null);
759: acceleratorFont = null;
760: acceleratorForeground = null;
761: acceleratorSelectionForeground = null;
762: arrowIcon = null;
763: selectionBackground = null;
764: selectionForeground = null;
765: acceleratorDelimiter = null;
766: }
767:
768:
771: protected void uninstallKeyboardActions()
772: {
773: SwingUtilities.replaceUIInputMap(menuItem,
774: JComponent.WHEN_IN_FOCUSED_WINDOW, null);
775: }
776:
777:
780: protected void uninstallListeners()
781: {
782: menuItem.removeMouseListener(mouseInputListener);
783: menuItem.removeMenuDragMouseListener(menuDragMouseListener);
784: menuItem.removeMenuKeyListener(menuKeyListener);
785: menuItem.removeItemListener(itemListener);
786: menuItem.removePropertyChangeListener(propertyChangeListener);
787: }
788:
789:
797: public void uninstallUI(JComponent c)
798: {
799: uninstallListeners();
800: uninstallDefaults();
801: uninstallComponents(menuItem);
802: menuItem = null;
803: }
804:
805:
813: public void update(Graphics g, JComponent c)
814: {
815: paint(g, c);
816: }
817:
818:
825: private String getAcceleratorText(KeyStroke accelerator)
826: {
827:
828: String modifiersText = "";
829: int modifiers = accelerator.getModifiers();
830: char keyChar = accelerator.getKeyChar();
831: int keyCode = accelerator.getKeyCode();
832:
833: if (modifiers != 0)
834: modifiersText = KeyEvent.getKeyModifiersText(modifiers)
835: + acceleratorDelimiter;
836:
837: if (keyCode == KeyEvent.VK_UNDEFINED)
838: return modifiersText + keyChar;
839: else
840: return modifiersText + KeyEvent.getKeyText(keyCode);
841: }
842:
843:
852: private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
853: {
854: int width = fm.stringWidth(getAcceleratorText(accelerator));
855: int height = fm.getHeight();
856: return new Rectangle(0, 0, width, height);
857: }
858:
859:
872: private void paintAccelerator(Graphics g, JMenuItem menuItem,
873: Rectangle acceleratorRect,
874: String acceleratorText)
875: {
876: g.setFont(acceleratorFont);
877: FontMetrics fm = g.getFontMetrics(acceleratorFont);
878:
879: if (menuItem.isEnabled())
880: g.setColor(acceleratorForeground);
881: else
882:
883:
884: g.setColor(Color.gray);
885:
886: BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x,
887: acceleratorRect.y + fm.getAscent());
888: }
889:
890:
895: protected class MouseInputHandler implements MouseInputListener
896: {
897:
900: protected MouseInputHandler()
901: {
902:
903: }
904:
905:
912: public void mouseClicked(MouseEvent e)
913: {
914: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
915: manager.processMouseEvent(e);
916: }
917:
918:
925: public void mouseDragged(MouseEvent e)
926: {
927: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
928: manager.processMouseEvent(e);
929: }
930:
931:
940: public void mouseEntered(MouseEvent e)
941: {
942: Component source = (Component) e.getSource();
943: if (source.getParent() instanceof MenuElement)
944: {
945: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
946: manager.setSelectedPath(getPath());
947: manager.processMouseEvent(e);
948: }
949: }
950:
951:
958: public void mouseExited(MouseEvent e)
959: {
960: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
961: manager.processMouseEvent(e);
962: }
963:
964:
971: public void mouseMoved(MouseEvent e)
972: {
973: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
974: manager.processMouseEvent(e);
975: }
976:
977:
984: public void mousePressed(MouseEvent e)
985: {
986: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
987: manager.processMouseEvent(e);
988: }
989:
990:
998: public void mouseReleased(MouseEvent e)
999: {
1000: Rectangle size = menuItem.getBounds();
1001: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1002: if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
1003: && e.getY() < size.height)
1004: {
1005: manager.clearSelectedPath();
1006: menuItem.doClick();
1007: }
1008:
1009: else
1010: manager.processMouseEvent(e);
1011: }
1012: }
1013:
1014:
1017: private class MenuDragMouseHandler implements MenuDragMouseListener
1018: {
1019:
1025: public void menuDragMouseDragged(MenuDragMouseEvent e)
1026: {
1027: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1028: manager.setSelectedPath(e.getPath());
1029: }
1030:
1031:
1038: public void menuDragMouseEntered(MenuDragMouseEvent e)
1039: {
1040: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1041: manager.setSelectedPath(e.getPath());
1042: }
1043:
1044:
1050: public void menuDragMouseExited(MenuDragMouseEvent e)
1051: {
1052:
1053: }
1054:
1055:
1062: public void menuDragMouseReleased(MenuDragMouseEvent e)
1063: {
1064: MenuElement[] path = e.getPath();
1065:
1066: if (path[path.length - 1] instanceof JMenuItem)
1067: ((JMenuItem) path[path.length - 1]).doClick();
1068:
1069: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1070: manager.clearSelectedPath();
1071: }
1072: }
1073:
1074:
1078: private class MenuKeyHandler implements MenuKeyListener
1079: {
1080:
1086: public void menuKeyPressed(MenuKeyEvent e)
1087: {
1088:
1089: }
1090:
1091:
1097: public void menuKeyReleased(MenuKeyEvent e)
1098: {
1099:
1100: }
1101:
1102:
1109: public void menuKeyTyped(MenuKeyEvent e)
1110: {
1111:
1112: }
1113: }
1114:
1115:
1119: private class ItemHandler implements ItemListener
1120: {
1121:
1126: public void itemStateChanged(ItemEvent evt)
1127: {
1128: boolean state = false;
1129: if (menuItem instanceof JCheckBoxMenuItem)
1130: {
1131: if (evt.getStateChange() == ItemEvent.SELECTED)
1132: state = true;
1133: ((JCheckBoxMenuItem) menuItem).setState(state);
1134: }
1135: menuItem.revalidate();
1136: menuItem.repaint();
1137: }
1138: }
1139: }