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,
359: defaultTextIconGap);
360: }
361:
362:
367: protected String getPropertyPrefix()
368: {
369: return "MenuItem";
370: }
371:
372:
377: protected void installComponents(JMenuItem menuItem)
378: {
379:
380: }
381:
382:
386: protected void installDefaults()
387: {
388: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
389:
390: menuItem.setBackground(defaults.getColor("MenuItem.background"));
391: menuItem.setBorder(defaults.getBorder("MenuItem.border"));
392: menuItem.setFont(defaults.getFont("MenuItem.font"));
393: menuItem.setForeground(defaults.getColor("MenuItem.foreground"));
394: menuItem.setMargin(defaults.getInsets("MenuItem.margin"));
395: menuItem.setOpaque(true);
396: acceleratorFont = defaults.getFont("MenuItem.acceleratorFont");
397: acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground");
398: acceleratorSelectionForeground = defaults.getColor("MenuItem.acceleratorSelectionForeground");
399: selectionBackground = defaults.getColor("MenuItem.selectionBackground");
400: selectionForeground = defaults.getColor("MenuItem.selectionForeground");
401: acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter");
402:
403: menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
404: menuItem.setHorizontalAlignment(SwingConstants.LEADING);
405: }
406:
407:
410: protected void installKeyboardActions()
411: {
412:
413: }
414:
415:
418: protected void installListeners()
419: {
420: menuItem.addMouseListener(mouseInputListener);
421: menuItem.addMouseMotionListener(mouseInputListener);
422: menuItem.addMenuDragMouseListener(menuDragMouseListener);
423: menuItem.addMenuKeyListener(menuKeyListener);
424: menuItem.addPropertyChangeListener(propertyChangeListener);
425: }
426:
427:
434: public void installUI(JComponent c)
435: {
436: super.installUI(c);
437: menuItem = (JMenuItem) c;
438: installDefaults();
439: installComponents(menuItem);
440: installListeners();
441: }
442:
443:
449: public void paint(Graphics g, JComponent c)
450: {
451: paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(),
452: c.getForeground(), defaultTextIconGap);
453: }
454:
455:
462: protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
463: {
464: Dimension size = getPreferredSize(menuItem);
465: Color foreground = g.getColor();
466: g.setColor(bgColor);
467: g.drawRect(0, 0, size.width, size.height);
468: g.setColor(foreground);
469: }
470:
471:
483: protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
484: Icon arrowIcon, Color background,
485: Color foreground, int defaultTextIconGap)
486: {
487: JMenuItem m = (JMenuItem) c;
488: Rectangle tr = new Rectangle();
489: Rectangle ir = new Rectangle();
490: Rectangle vr = new Rectangle();
491: Rectangle br = new Rectangle();
492: Rectangle ar = new Rectangle();
493: Rectangle cr = new Rectangle();
494:
495: int vertAlign = m.getVerticalAlignment();
496: int horAlign = m.getHorizontalAlignment();
497: int vertTextPos = m.getVerticalTextPosition();
498: int horTextPos = m.getHorizontalTextPosition();
499:
500: Font f = m.getFont();
501: g.setFont(f);
502: FontMetrics fm = g.getFontMetrics(f);
503: SwingUtilities.calculateInnerArea(m, br);
504: SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
505: paintBackground(g, m, m.getBackground());
506:
507:
509: Insets insets = m.getInsets();
510: br.x -= insets.left;
511: br.y -= insets.top;
512: br.width += insets.right + insets.left;
513: br.height += insets.top + insets.bottom;
514:
515:
516:
517: if ((m.isSelected() && checkIcon == null) || m.getModel().isArmed() &&
518: (m.getParent() instanceof MenuElement))
519: {
520: if (m.isContentAreaFilled())
521: {
522: g.setColor(selectionBackground);
523: g.fillRect(br.x, br.y, br.width, br.height);
524: }
525: }
526: else
527: {
528: if (m.isContentAreaFilled())
529: {
530: g.setColor(m.getBackground());
531: g.fillRect(br.x, br.y, br.width, br.height);
532: }
533: }
534:
535:
536: if (checkIcon != null)
537: {
538: SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
539: horAlign, vertTextPos, horTextPos,
540: vr, cr, tr, defaultTextIconGap);
541: checkIcon.paintIcon(m, g, cr.x, cr.y);
542:
543:
544:
545:
546: vr.x = cr.x + cr.width + defaultTextIconGap;
547: }
548:
549:
550: if (arrowIcon != null && (c instanceof JMenu))
551: {
552: if (! ((JMenu) c).isTopLevelMenu())
553: {
554: int width = arrowIcon.getIconWidth();
555: int height = arrowIcon.getIconHeight();
556:
557: arrowIcon.paintIcon(m, g, vr.width - width + defaultTextIconGap,
558: vr.y + 2);
559: }
560: }
561:
562:
563: Icon i = m.getIcon();
564: SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i,
565: vertAlign, horAlign, vertTextPos,
566: horTextPos, vr, ir, tr,
567: defaultTextIconGap);
568: if (i != null)
569: i.paintIcon(c, g, ir.x, ir.y);
570: paintText(g, m, tr, m.getText());
571:
572:
573: String acceleratorText = "";
574:
575: if (m.getAccelerator() != null)
576: {
577: acceleratorText = getAcceleratorText(m.getAccelerator());
578: fm = g.getFontMetrics(acceleratorFont);
579: ar.width = fm.stringWidth(acceleratorText);
580: ar.x = br.width - ar.width;
581: vr.x = br.width - ar.width;
582:
583: SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
584: vertAlign, horAlign, vertTextPos,
585: horTextPos, vr, ir, ar,
586: defaultTextIconGap);
587:
588: paintAccelerator(g, m, ar, acceleratorText);
589: }
590: }
591:
592:
601: protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
602: String text)
603: {
604: Font f = menuItem.getFont();
605: g.setFont(f);
606: FontMetrics fm = g.getFontMetrics(f);
607:
608: if (text != null && ! text.equals(""))
609: {
610: if (menuItem.isEnabled())
611: {
612:
613:
614: if ((menuItem.isSelected() && checkIcon == null) || menuItem.getModel().isArmed() &&
615: (menuItem.getParent() instanceof MenuElement))
616: g.setColor(selectionForeground);
617: else
618: g.setColor(menuItem.getForeground());
619: }
620: else
621:
622:
623:
624:
625:
626: g.setColor(Color.gray);
627:
628: int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
629:
630: if (mnemonicIndex != -1)
631: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
632: textRect.x,
633: textRect.y
634: + fm.getAscent());
635: else
636: BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
637: textRect.y + fm.getAscent());
638: }
639: }
640:
641:
646: protected void uninstallComponents(JMenuItem menuItem)
647: {
648:
649: }
650:
651:
655: protected void uninstallDefaults()
656: {
657: menuItem.setForeground(null);
658: menuItem.setBackground(null);
659: menuItem.setBorder(null);
660: menuItem.setMargin(null);
661: menuItem.setBackground(null);
662: menuItem.setBorder(null);
663: menuItem.setFont(null);
664: menuItem.setForeground(null);
665: menuItem.setMargin(null);
666: acceleratorFont = null;
667: acceleratorForeground = null;
668: acceleratorSelectionForeground = null;
669: arrowIcon = null;
670: selectionBackground = null;
671: selectionForeground = null;
672: acceleratorDelimiter = null;
673: }
674:
675:
678: protected void uninstallKeyboardActions()
679: {
680:
681: }
682:
683:
686: protected void uninstallListeners()
687: {
688: menuItem.removeMouseListener(mouseInputListener);
689: menuItem.removeMenuDragMouseListener(menuDragMouseListener);
690: menuItem.removeMenuKeyListener(menuKeyListener);
691: menuItem.removePropertyChangeListener(propertyChangeListener);
692: }
693:
694:
701: public void uninstallUI(JComponent c)
702: {
703: uninstallListeners();
704: uninstallDefaults();
705: uninstallComponents(menuItem);
706: menuItem = null;
707: }
708:
709:
715: public void update(Graphics g, JComponent c)
716: {
717: paint(g, c);
718: }
719:
720:
727: private String getAcceleratorText(KeyStroke accelerator)
728: {
729:
730: String modifiersText = "";
731: int modifiers = accelerator.getModifiers();
732: char keyChar = accelerator.getKeyChar();
733: int keyCode = accelerator.getKeyCode();
734:
735: if (modifiers != 0)
736: modifiersText = KeyEvent.getKeyModifiersText(modifiers)
737: + acceleratorDelimiter;
738:
739: if (keyCode == KeyEvent.VK_UNDEFINED)
740: return modifiersText + keyChar;
741: else
742: return modifiersText + KeyEvent.getKeyText(keyCode);
743: }
744:
745:
753: private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
754: {
755: int width = fm.stringWidth(getAcceleratorText(accelerator));
756: int height = fm.getHeight();
757: return new Rectangle(0, 0, width, height);
758: }
759:
760:
769: private void paintAccelerator(Graphics g, JMenuItem menuItem,
770: Rectangle acceleratorRect,
771: String acceleratorText)
772: {
773: g.setFont(acceleratorFont);
774: FontMetrics fm = g.getFontMetrics(acceleratorFont);
775:
776: if (menuItem.isEnabled())
777: g.setColor(acceleratorForeground);
778: else
779:
780:
781: g.setColor(Color.gray);
782:
783: BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x,
784: acceleratorRect.y + fm.getAscent());
785: }
786:
787:
793: protected class MouseInputHandler implements MouseInputListener
794: {
795:
798: protected MouseInputHandler()
799: {
800: }
801:
802:
808: public void mouseClicked(MouseEvent e)
809: {
810: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
811: manager.processMouseEvent(e);
812: }
813:
814:
820: public void mouseDragged(MouseEvent e)
821: {
822: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
823: manager.processMouseEvent(e);
824: }
825:
826:
834: public void mouseEntered(MouseEvent e)
835: {
836: Component source = (Component) e.getSource();
837: if (source.getParent() instanceof MenuElement)
838: {
839: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
840: manager.setSelectedPath(getPath());
841: manager.processMouseEvent(e);
842: }
843: }
844:
845:
851: public void mouseExited(MouseEvent e)
852: {
853: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
854: manager.processMouseEvent(e);
855: }
856:
857:
863: public void mouseMoved(MouseEvent e)
864: {
865: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
866: manager.processMouseEvent(e);
867: }
868:
869:
875: public void mousePressed(MouseEvent e)
876: {
877: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
878: manager.processMouseEvent(e);
879: }
880:
881:
888: public void mouseReleased(MouseEvent e)
889: {
890: Rectangle size = menuItem.getBounds();
891: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
892: if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
893: && e.getY() < size.height)
894: {
895: manager.clearSelectedPath();
896: menuItem.doClick();
897: }
898:
899: else
900: manager.processMouseEvent(e);
901: }
902: }
903:
904:
907: protected class MenuDragMouseHandler implements MenuDragMouseListener
908: {
909:
914: public void menuDragMouseDragged(MenuDragMouseEvent e)
915: {
916: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
917: manager.setSelectedPath(e.getPath());
918: }
919:
920:
926: public void menuDragMouseEntered(MenuDragMouseEvent e)
927: {
928: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
929: manager.setSelectedPath(e.getPath());
930: }
931:
932:
938: public void menuDragMouseExited(MenuDragMouseEvent e)
939: {
940: }
941:
942:
948: public void menuDragMouseReleased(MenuDragMouseEvent e)
949: {
950: MenuElement[] path = e.getPath();
951:
952: if (path[path.length - 1] instanceof JMenuItem)
953: ((JMenuItem) path[path.length - 1]).doClick();
954:
955: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
956: manager.clearSelectedPath();
957: }
958: }
959:
960:
964: protected class MenuKeyHandler implements MenuKeyListener
965: {
966:
971: public void menuKeyPressed(MenuKeyEvent e)
972: {
973: }
974:
975:
980: public void menuKeyReleased(MenuKeyEvent e)
981: {
982: }
983:
984:
990: public void menuKeyTyped(MenuKeyEvent e)
991: {
992: }
993: }
994:
995:
999: protected class PropertyChangeHandler implements PropertyChangeListener
1000: {
1001:
1006: public void propertyChange(PropertyChangeEvent evt)
1007: {
1008: menuItem.revalidate();
1009: menuItem.repaint();
1010: }
1011: }
1012: }