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:
55: import ;
56: import ;
57: import ;
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:
75:
78: public class BasicMenuItemUI extends MenuItemUI
79: {
80:
83: protected Font acceleratorFont;
84:
85:
88: protected Color acceleratorForeground;
89:
90:
94: protected Color acceleratorSelectionForeground;
95:
96:
100: protected Icon arrowIcon;
101:
102:
106: protected Icon checkIcon;
107:
108:
111: protected int defaultTextIconGap = 4;
112:
113:
116: protected Color disabledForeground;
117:
118:
121: protected MenuDragMouseListener menuDragMouseListener;
122:
123:
126: protected JMenuItem menuItem;
127:
128:
131: protected MenuKeyListener menuKeyListener;
132:
133:
136: protected MouseInputListener mouseInputListener;
137:
138:
141: protected boolean oldBorderPainted;
142:
143:
146: protected Color selectionBackground;
147:
148:
151: protected Color selectionForeground;
152:
153:
156: private String acceleratorDelimiter;
157:
158:
161: private PropertyChangeListener propertyChangeListener;
162:
163:
166: private int defaultAcceleratorLabelGap = 4;
167:
168:
171: public BasicMenuItemUI()
172: {
173: mouseInputListener = createMouseInputListener(menuItem);
174: menuDragMouseListener = createMenuDragMouseListener(menuItem);
175: menuKeyListener = createMenuKeyListener(menuItem);
176: propertyChangeListener = new PropertyChangeHandler();
177: }
178:
179:
186: protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
187: {
188: return new MenuDragMouseHandler();
189: }
190:
191:
199: protected MenuKeyListener createMenuKeyListener(JComponent c)
200: {
201: return new MenuKeyHandler();
202: }
203:
204:
211: protected MouseInputListener createMouseInputListener(JComponent c)
212: {
213: return new MouseInputHandler();
214: }
215:
216:
224: public static ComponentUI createUI(JComponent c)
225: {
226: return new BasicMenuItemUI();
227: }
228:
229:
234: protected void doClick(MenuSelectionManager msm)
235: {
236: menuItem.doClick();
237: msm.clearSelectedPath();
238: }
239:
240:
247: public Dimension getMaximumSize(JComponent c)
248: {
249: return null;
250: }
251:
252:
259: public Dimension getMinimumSize(JComponent c)
260: {
261: return null;
262: }
263:
264:
270: public MenuElement[] getPath()
271: {
272: ArrayList path = new ArrayList();
273:
274:
275: if (menuItem instanceof JMenu)
276: path.add(((JMenu) menuItem).getPopupMenu());
277:
278: Component c = menuItem;
279: while (c instanceof MenuElement)
280: {
281: path.add(0, (MenuElement) c);
282:
283: if (c instanceof JPopupMenu)
284: c = ((JPopupMenu) c).getInvoker();
285: else
286: c = c.getParent();
287: }
288:
289: MenuElement[] pathArray = new MenuElement[path.size()];
290: path.toArray(pathArray);
291: return pathArray;
292: }
293:
294:
304: protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
305: Icon arrowIcon,
306: int defaultTextIconGap)
307: {
308: JMenuItem m = (JMenuItem) c;
309: Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m,
310: defaultTextIconGap);
311:
312:
313:
314: KeyStroke accelerator = m.getAccelerator();
315: Rectangle rect;
316:
317: if (accelerator != null)
318: {
319: rect = getAcceleratorRect(accelerator,
320: m.getToolkit().getFontMetrics(acceleratorFont));
321:
322:
323: d.width = d.width + rect.width + defaultAcceleratorLabelGap;
324:
325:
326: if (d.height < rect.height)
327: d.height = rect.height;
328: }
329:
330: if (checkIcon != null)
331: {
332: d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap;
333:
334: if (checkIcon.getIconHeight() > d.height)
335: d.height = checkIcon.getIconHeight();
336: }
337:
338: if (arrowIcon != null && (c instanceof JMenu))
339: {
340: d.width = d.width + arrowIcon.getIconWidth() + defaultTextIconGap;
341:
342: if (arrowIcon.getIconHeight() > d.height)
343: d.height = arrowIcon.getIconHeight();
344: }
345:
346: return d;
347: }
348:
349:
356: public Dimension getPreferredSize(JComponent c)
357: {
358: return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap);
359: }
360:
361: protected String getPropertyPrefix()
362: {
363: return null;
364: }
365:
366:
371: protected void installComponents(JMenuItem menuItem)
372: {
373:
374: }
375:
376:
380: protected void installDefaults()
381: {
382: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
383:
384: menuItem.setBackground(defaults.getColor("MenuItem.background"));
385: menuItem.setBorder(defaults.getBorder("MenuItem.border"));
386: menuItem.setFont(defaults.getFont("MenuItem.font"));
387: menuItem.setForeground(defaults.getColor("MenuItem.foreground"));
388: menuItem.setMargin(defaults.getInsets("MenuItem.margin"));
389: menuItem.setOpaque(true);
390: acceleratorFont = defaults.getFont("MenuItem.acceleratorFont");
391: acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground");
392: acceleratorSelectionForeground = defaults.getColor("MenuItem.acceleratorSelectionForeground");
393: selectionBackground = defaults.getColor("MenuItem.selectionBackground");
394: selectionForeground = defaults.getColor("MenuItem.selectionForeground");
395: acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter");
396:
397: menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
398: menuItem.setHorizontalAlignment(SwingConstants.LEADING);
399: }
400:
401:
404: protected void installKeyboardActions()
405: {
406:
407: }
408:
409:
412: protected void installListeners()
413: {
414: menuItem.addMouseListener(mouseInputListener);
415: menuItem.addMouseMotionListener(mouseInputListener);
416: menuItem.addMenuDragMouseListener(menuDragMouseListener);
417: menuItem.addMenuKeyListener(menuKeyListener);
418: menuItem.addPropertyChangeListener(propertyChangeListener);
419: }
420:
421:
428: public void installUI(JComponent c)
429: {
430: super.installUI(c);
431: menuItem = (JMenuItem) c;
432: installDefaults();
433: installComponents(menuItem);
434: installListeners();
435: }
436:
437:
443: public void paint(Graphics g, JComponent c)
444: {
445: paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(),
446: c.getForeground(), defaultTextIconGap);
447: }
448:
449:
456: protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
457: {
458: Dimension size = getPreferredSize(menuItem);
459: Color foreground = g.getColor();
460: g.setColor(bgColor);
461: g.drawRect(0, 0, size.width, size.height);
462: g.setColor(foreground);
463: }
464:
465:
477: protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
478: Icon arrowIcon, Color background,
479: Color foreground, int defaultTextIconGap)
480: {
481: JMenuItem m = (JMenuItem) c;
482: Rectangle tr = new Rectangle();
483: Rectangle ir = new Rectangle();
484: Rectangle vr = new Rectangle();
485: Rectangle br = new Rectangle();
486: Rectangle ar = new Rectangle();
487: Rectangle cr = new Rectangle();
488:
489: int vertAlign = m.getVerticalAlignment();
490: int horAlign = m.getHorizontalAlignment();
491: int vertTextPos = m.getVerticalTextPosition();
492: int horTextPos = m.getHorizontalTextPosition();
493:
494: Font f = m.getFont();
495: g.setFont(f);
496: FontMetrics fm = g.getFontMetrics(f);
497: SwingUtilities.calculateInnerArea(m, br);
498: SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
499: paintBackground(g, m, m.getBackground());
500:
501:
503: Insets insets = m.getInsets();
504: br.x -= insets.left;
505: br.y -= insets.top;
506: br.width += insets.right + insets.left;
507: br.height += insets.top + insets.bottom;
508:
509:
510: if (m.isSelected() || m.getModel().isArmed() &&
511: (m.getParent() instanceof MenuElement))
512: {
513: if (m.isContentAreaFilled())
514: {
515: g.setColor(selectionBackground);
516: g.fillRect(br.x, br.y, br.width, br.height);
517: }
518: }
519: else
520: {
521: if (m.isContentAreaFilled())
522: {
523: g.setColor(m.getBackground());
524: g.fillRect(br.x, br.y, br.width, br.height);
525: }
526: }
527:
528:
529: if (checkIcon != null)
530: {
531: SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
532: horAlign, vertTextPos, horTextPos,
533: vr, cr, tr, defaultTextIconGap);
534: checkIcon.paintIcon(m, g, cr.x, cr.y);
535:
536:
537:
538:
539:
540: vr.x = cr.x + cr.width + defaultTextIconGap;
541: }
542:
543:
544: if (arrowIcon != null && (c instanceof JMenu))
545: {
546: if (! ((JMenu) c).isTopLevelMenu())
547: {
548: int width = arrowIcon.getIconWidth();
549: int height = arrowIcon.getIconHeight();
550:
551: arrowIcon.paintIcon(m, g, vr.width - width + defaultTextIconGap,
552: vr.y + 2);
553: }
554: }
555:
556:
557: Icon i = m.getIcon();
558: SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i,
559: vertAlign, horAlign, vertTextPos,
560: horTextPos, vr, ir, tr,
561: defaultTextIconGap);
562: if (i != null)
563: i.paintIcon(c, g, ir.x, ir.y);
564:
565: paintText(g, m, tr, m.getText());
566:
567:
568: String acceleratorText = "";
569:
570: if (m.getAccelerator() != null)
571: {
572: acceleratorText = getAcceleratorText(m.getAccelerator());
573: fm = g.getFontMetrics(acceleratorFont);
574: ar.width = fm.stringWidth(acceleratorText);
575: ar.x = br.width - ar.width;
576: vr.x = br.width - ar.width;
577:
578: SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
579: vertAlign, horAlign, vertTextPos,
580: horTextPos, vr, ir, ar,
581: defaultTextIconGap);
582:
583: paintAccelerator(g, m, ar, acceleratorText);
584: }
585: }
586:
587:
596: protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
597: String text)
598: {
599: Font f = menuItem.getFont();
600: g.setFont(f);
601: FontMetrics fm = g.getFontMetrics(f);
602:
603: if (text != null && ! text.equals(""))
604: {
605: if (menuItem.isEnabled())
606: {
607:
608: if (menuItem.isSelected() || menuItem.getModel().isArmed() &&
609: (menuItem.getParent() instanceof MenuElement))
610: g.setColor(selectionForeground);
611: else
612: g.setColor(menuItem.getForeground());
613: }
614: else
615:
616:
617:
618:
619:
620: g.setColor(Color.gray);
621:
622: int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
623:
624: if (mnemonicIndex != -1)
625: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
626: textRect.x,
627: textRect.y
628: + fm.getAscent());
629: else
630: BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
631: textRect.y + fm.getAscent());
632: }
633: }
634:
635:
640: protected void uninstallComponents(JMenuItem menuItem)
641: {
642:
643: }
644:
645:
649: protected void uninstallDefaults()
650: {
651: menuItem.setForeground(null);
652: menuItem.setBackground(null);
653: menuItem.setBorder(null);
654: menuItem.setMargin(null);
655: menuItem.setBackground(null);
656: menuItem.setBorder(null);
657: menuItem.setFont(null);
658: menuItem.setForeground(null);
659: menuItem.setMargin(null);
660: acceleratorFont = null;
661: acceleratorForeground = null;
662: acceleratorSelectionForeground = null;
663: arrowIcon = null;
664: selectionBackground = null;
665: selectionForeground = null;
666: acceleratorDelimiter = null;
667: }
668:
669:
672: protected void uninstallKeyboardActions()
673: {
674:
675: }
676:
677:
680: protected void uninstallListeners()
681: {
682: menuItem.removeMouseListener(mouseInputListener);
683: menuItem.removeMenuDragMouseListener(menuDragMouseListener);
684: menuItem.removeMenuKeyListener(menuKeyListener);
685: menuItem.removePropertyChangeListener(propertyChangeListener);
686: }
687:
688:
695: public void uninstallUI(JComponent c)
696: {
697: uninstallListeners();
698: uninstallDefaults();
699: uninstallComponents(menuItem);
700: menuItem = null;
701: }
702:
703:
709: public void update(Graphics g, JComponent c)
710: {
711: paint(g, c);
712: }
713:
714:
721: private String getAcceleratorText(KeyStroke accelerator)
722: {
723:
724: String modifiersText = "";
725: int modifiers = accelerator.getModifiers();
726: char keyChar = accelerator.getKeyChar();
727: int keyCode = accelerator.getKeyCode();
728:
729: if (modifiers != 0)
730: modifiersText = KeyEvent.getKeyModifiersText(modifiers)
731: + acceleratorDelimiter;
732:
733: if (keyCode == KeyEvent.VK_UNDEFINED)
734: return modifiersText + keyChar;
735: else
736: return modifiersText + KeyEvent.getKeyText(keyCode);
737: }
738:
739:
747: private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
748: {
749: int width = fm.stringWidth(getAcceleratorText(accelerator));
750: int height = fm.getHeight();
751: return new Rectangle(0, 0, width, height);
752: }
753:
754:
763: private void paintAccelerator(Graphics g, JMenuItem menuItem,
764: Rectangle acceleratorRect,
765: String acceleratorText)
766: {
767: g.setFont(acceleratorFont);
768: FontMetrics fm = g.getFontMetrics(acceleratorFont);
769:
770: if (menuItem.isEnabled())
771: g.setColor(acceleratorForeground);
772: else
773:
774:
775: g.setColor(Color.gray);
776:
777: BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x,
778: acceleratorRect.y + fm.getAscent());
779: }
780:
781:
787: protected class MouseInputHandler implements MouseInputListener
788: {
789:
792: protected MouseInputHandler()
793: {
794: }
795:
796:
802: public void mouseClicked(MouseEvent e)
803: {
804: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
805: manager.processMouseEvent(e);
806: }
807:
808:
814: public void mouseDragged(MouseEvent e)
815: {
816: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
817: manager.processMouseEvent(e);
818: }
819:
820:
828: public void mouseEntered(MouseEvent e)
829: {
830: Component source = (Component) e.getSource();
831: if (source.getParent() instanceof MenuElement)
832: {
833: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
834: manager.setSelectedPath(getPath());
835: manager.processMouseEvent(e);
836: }
837: }
838:
839:
845: public void mouseExited(MouseEvent e)
846: {
847: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
848: manager.processMouseEvent(e);
849: }
850:
851:
857: public void mouseMoved(MouseEvent e)
858: {
859: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
860: manager.processMouseEvent(e);
861: }
862:
863:
869: public void mousePressed(MouseEvent e)
870: {
871: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
872: manager.processMouseEvent(e);
873: }
874:
875:
882: public void mouseReleased(MouseEvent e)
883: {
884: Rectangle size = menuItem.getBounds();
885: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
886: if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
887: && e.getY() < size.height)
888: {
889: manager.clearSelectedPath();
890: menuItem.doClick();
891: }
892:
893: else
894: manager.processMouseEvent(e);
895: }
896: }
897:
898:
901: protected class MenuDragMouseHandler implements MenuDragMouseListener
902: {
903:
908: public void menuDragMouseDragged(MenuDragMouseEvent e)
909: {
910: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
911: manager.setSelectedPath(e.getPath());
912: }
913:
914:
920: public void menuDragMouseEntered(MenuDragMouseEvent e)
921: {
922: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
923: manager.setSelectedPath(e.getPath());
924: }
925:
926:
932: public void menuDragMouseExited(MenuDragMouseEvent e)
933: {
934: }
935:
936:
942: public void menuDragMouseReleased(MenuDragMouseEvent e)
943: {
944: MenuElement[] path = e.getPath();
945:
946: if (path[path.length - 1] instanceof JMenuItem)
947: ((JMenuItem) path[path.length - 1]).doClick();
948:
949: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
950: manager.clearSelectedPath();
951: }
952: }
953:
954:
958: protected class MenuKeyHandler implements MenuKeyListener
959: {
960:
965: public void menuKeyPressed(MenuKeyEvent e)
966: {
967: }
968:
969:
974: public void menuKeyReleased(MenuKeyEvent e)
975: {
976: }
977:
978:
984: public void menuKeyTyped(MenuKeyEvent e)
985: {
986: }
987: }
988:
989:
993: protected class PropertyChangeHandler implements PropertyChangeListener
994: {
995:
1000: public void propertyChange(PropertyChangeEvent evt)
1001: {
1002: menuItem.revalidate();
1003: menuItem.repaint();
1004: }
1005: }
1006: }