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: import ;
75: import ;
76: import ;
77:
78:
81: public class BasicMenuItemUI extends MenuItemUI
82: {
83:
86: protected Font acceleratorFont;
87:
88:
91: protected Color acceleratorForeground;
92:
93:
97: protected Color acceleratorSelectionForeground;
98:
99:
103: protected Icon arrowIcon;
104:
105:
109: protected Icon checkIcon;
110:
111:
114: protected int defaultTextIconGap = 4;
115:
116:
119: protected Color disabledForeground;
120:
121:
124: protected MenuDragMouseListener menuDragMouseListener;
125:
126:
129: protected JMenuItem menuItem;
130:
131:
134: protected MenuKeyListener menuKeyListener;
135:
136:
139: protected MouseInputListener mouseInputListener;
140:
141:
144: protected boolean oldBorderPainted;
145:
146:
149: protected Color selectionBackground;
150:
151:
154: protected Color selectionForeground;
155:
156:
159: private String acceleratorDelimiter;
160:
161:
164: private ItemListener itemListener;
165:
166:
169: private int defaultAcceleratorLabelGap = 10;
170:
171:
174: private int defaultTextArrowIconGap = 10;
175:
176:
179: public BasicMenuItemUI()
180: {
181: mouseInputListener = createMouseInputListener(menuItem);
182: menuDragMouseListener = createMenuDragMouseListener(menuItem);
183: menuKeyListener = createMenuKeyListener(menuItem);
184: itemListener = new ItemHandler();
185: }
186:
187:
194: protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
195: {
196: return new MenuDragMouseHandler();
197: }
198:
199:
207: protected MenuKeyListener createMenuKeyListener(JComponent c)
208: {
209: return new MenuKeyHandler();
210: }
211:
212:
219: protected MouseInputListener createMouseInputListener(JComponent c)
220: {
221: return new MouseInputHandler();
222: }
223:
224:
232: public static ComponentUI createUI(JComponent c)
233: {
234: return new BasicMenuItemUI();
235: }
236:
237:
243: protected void doClick(MenuSelectionManager msm)
244: {
245: menuItem.doClick();
246: msm.clearSelectedPath();
247: }
248:
249:
256: public Dimension getMaximumSize(JComponent c)
257: {
258: return null;
259: }
260:
261:
268: public Dimension getMinimumSize(JComponent c)
269: {
270: return null;
271: }
272:
273:
279: public MenuElement[] getPath()
280: {
281: ArrayList path = new ArrayList();
282:
283:
284: if (menuItem instanceof JMenu)
285: path.add(((JMenu) menuItem).getPopupMenu());
286:
287: Component c = menuItem;
288: while (c instanceof MenuElement)
289: {
290: path.add(0, (MenuElement) c);
291:
292: if (c instanceof JPopupMenu)
293: c = ((JPopupMenu) c).getInvoker();
294: else
295: c = c.getParent();
296: }
297:
298: MenuElement[] pathArray = new MenuElement[path.size()];
299: path.toArray(pathArray);
300: return pathArray;
301: }
302:
303:
316: protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
317: Icon arrowIcon,
318: int defaultTextIconGap)
319: {
320: JMenuItem m = (JMenuItem) c;
321: Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m,
322: defaultTextIconGap);
323:
324:
325:
326: KeyStroke accelerator = m.getAccelerator();
327: Rectangle rect;
328:
329: if (accelerator != null)
330: {
331: rect = getAcceleratorRect(
332: accelerator,
333: m.getToolkit().getFontMetrics(acceleratorFont));
334:
335:
336: d.width += rect.width + defaultAcceleratorLabelGap;
337:
338:
339: if (d.height < rect.height)
340: d.height = rect.height;
341: }
342:
343: if (checkIcon != null)
344: {
345: d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap;
346:
347: if (checkIcon.getIconHeight() > d.height)
348: d.height = checkIcon.getIconHeight();
349: }
350:
351: if (arrowIcon != null && (c instanceof JMenu))
352: {
353: d.width = d.width + arrowIcon.getIconWidth() + defaultTextArrowIconGap;
354:
355: if (arrowIcon.getIconHeight() > d.height)
356: d.height = arrowIcon.getIconHeight();
357: }
358:
359: return d;
360: }
361:
362:
369: public Dimension getPreferredSize(JComponent c)
370: {
371: return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap);
372: }
373:
374:
379: protected String getPropertyPrefix()
380: {
381: return "MenuItem";
382: }
383:
384:
390: protected void installComponents(JMenuItem menuItem)
391: {
392:
393: }
394:
395:
399: protected void installDefaults()
400: {
401: String prefix = getPropertyPrefix();
402: LookAndFeel.installBorder(menuItem, prefix + ".border");
403: LookAndFeel.installColorsAndFont(menuItem, prefix + ".background",
404: prefix + ".foreground", prefix + ".font");
405: menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
406: acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont");
407: acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground");
408: acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground");
409: selectionBackground = UIManager.getColor(prefix + ".selectionBackground");
410: selectionForeground = UIManager.getColor(prefix + ".selectionForeground");
411: acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter");
412: checkIcon = UIManager.getIcon(prefix + ".checkIcon");
413:
414: menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
415: menuItem.setHorizontalAlignment(SwingConstants.LEADING);
416: menuItem.setOpaque(true);
417: }
418:
419:
422: protected void installKeyboardActions()
423: {
424:
425: }
426:
427:
430: protected void installListeners()
431: {
432: menuItem.addMouseListener(mouseInputListener);
433: menuItem.addMouseMotionListener(mouseInputListener);
434: menuItem.addMenuDragMouseListener(menuDragMouseListener);
435: menuItem.addMenuKeyListener(menuKeyListener);
436: menuItem.addItemListener(itemListener);
437: }
438:
439:
447: public void installUI(JComponent c)
448: {
449: super.installUI(c);
450: menuItem = (JMenuItem) c;
451: installDefaults();
452: installComponents(menuItem);
453: installListeners();
454: }
455:
456:
464: public void paint(Graphics g, JComponent c)
465: {
466: paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(),
467: c.getForeground(), defaultTextIconGap);
468: }
469:
470:
480: protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
481: {
482: Dimension size = getPreferredSize(menuItem);
483: Color foreground = g.getColor();
484: g.setColor(bgColor);
485: g.drawRect(0, 0, size.width, size.height);
486: g.setColor(foreground);
487: }
488:
489:
507: protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
508: Icon arrowIcon, Color background,
509: Color foreground, int defaultTextIconGap)
510: {
511: JMenuItem m = (JMenuItem) c;
512: Rectangle tr = new Rectangle();
513: Rectangle ir = new Rectangle();
514: Rectangle vr = new Rectangle();
515: Rectangle br = new Rectangle();
516: Rectangle ar = new Rectangle();
517: Rectangle cr = new Rectangle();
518:
519: int vertAlign = m.getVerticalAlignment();
520: int horAlign = m.getHorizontalAlignment();
521: int vertTextPos = m.getVerticalTextPosition();
522: int horTextPos = m.getHorizontalTextPosition();
523:
524: Font f = m.getFont();
525: g.setFont(f);
526: FontMetrics fm = g.getFontMetrics(f);
527: SwingUtilities.calculateInnerArea(m, br);
528: SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
529: paintBackground(g, m, m.getBackground());
530:
531:
535: Insets insets = m.getInsets();
536: br.x -= insets.left;
537: br.y -= insets.top;
538: br.width += insets.right + insets.left;
539: br.height += insets.top + insets.bottom;
540:
541:
542:
543: ButtonModel mod = m.getModel();
544: if ((m.isSelected() && checkIcon == null) || (mod != null &&
545: mod.isArmed())
546: && (m.getParent() instanceof MenuElement))
547: {
548: if (m.isContentAreaFilled())
549: {
550: g.setColor(selectionBackground);
551: g.fillRect(br.x, br.y, br.width, br.height);
552: }
553: }
554: else
555: {
556: if (m.isContentAreaFilled())
557: {
558: g.setColor(m.getBackground());
559: g.fillRect(br.x, br.y, br.width, br.height);
560: }
561: }
562:
563:
564: if (checkIcon != null)
565: {
566: SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
567: horAlign, vertTextPos, horTextPos,
568: vr, cr, tr, defaultTextIconGap);
569: checkIcon.paintIcon(m, g, cr.x, cr.y);
570:
571:
572:
573:
574: vr.x = cr.x + cr.width + defaultTextIconGap;
575: }
576:
577:
578: if (arrowIcon != null && (c instanceof JMenu))
579: {
580: if (!((JMenu) c).isTopLevelMenu())
581: {
582: int width = arrowIcon.getIconWidth();
583: int height = arrowIcon.getIconHeight();
584: int offset = (vr.height - height) / 2;
585: arrowIcon.paintIcon(m, g, vr.width - width, vr.y + offset);
586: }
587: }
588:
589:
590: Icon i = m.getIcon();
591: SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, vertAlign,
592: horAlign, vertTextPos, horTextPos, vr,
593: ir, tr, defaultTextIconGap);
594: if (i != null)
595: i.paintIcon(c, g, ir.x, ir.y);
596: paintText(g, m, tr, m.getText());
597:
598:
599: String acceleratorText = "";
600:
601: if (m.getAccelerator() != null)
602: {
603: acceleratorText = getAcceleratorText(m.getAccelerator());
604: fm = g.getFontMetrics(acceleratorFont);
605: ar.width = fm.stringWidth(acceleratorText);
606: ar.x = br.width - ar.width;
607: vr.x = br.width - ar.width - defaultTextIconGap;
608:
609: SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
610: vertAlign, horAlign, vertTextPos,
611: horTextPos, vr, ir, ar,
612: defaultTextIconGap);
613:
614: paintAccelerator(g, m, ar, acceleratorText);
615: }
616: }
617:
618:
631: protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
632: String text)
633: {
634: Font f = menuItem.getFont();
635: g.setFont(f);
636: FontMetrics fm = g.getFontMetrics(f);
637:
638: if (text != null && !text.equals(""))
639: {
640: if (menuItem.isEnabled())
641: {
642:
643:
644: ButtonModel mod = menuItem.getModel();
645: if ((menuItem.isSelected() && checkIcon == null)
646: || (mod != null && mod.isArmed())
647: && (menuItem.getParent() instanceof MenuElement))
648: g.setColor(selectionForeground);
649: else
650: g.setColor(menuItem.getForeground());
651: }
652: else
653:
654:
655:
656:
657:
658: g.setColor(Color.gray);
659:
660: int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
661:
662: if (mnemonicIndex != -1)
663: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
664: textRect.x,
665: textRect.y
666: + fm.getAscent());
667: else
668: BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
669: textRect.y + fm.getAscent());
670: }
671: }
672:
673:
679: protected void uninstallComponents(JMenuItem menuItem)
680: {
681:
682: }
683:
684:
688: protected void uninstallDefaults()
689: {
690: menuItem.setForeground(null);
691: menuItem.setBackground(null);
692: menuItem.setBorder(null);
693: menuItem.setMargin(null);
694: menuItem.setBackground(null);
695: menuItem.setBorder(null);
696: menuItem.setFont(null);
697: menuItem.setForeground(null);
698: menuItem.setMargin(null);
699: acceleratorFont = null;
700: acceleratorForeground = null;
701: acceleratorSelectionForeground = null;
702: arrowIcon = null;
703: selectionBackground = null;
704: selectionForeground = null;
705: acceleratorDelimiter = null;
706: }
707:
708:
711: protected void uninstallKeyboardActions()
712: {
713:
714: }
715:
716:
719: protected void uninstallListeners()
720: {
721: menuItem.removeMouseListener(mouseInputListener);
722: menuItem.removeMenuDragMouseListener(menuDragMouseListener);
723: menuItem.removeMenuKeyListener(menuKeyListener);
724: menuItem.removeItemListener(itemListener);
725: }
726:
727:
735: public void uninstallUI(JComponent c)
736: {
737: uninstallListeners();
738: uninstallDefaults();
739: uninstallComponents(menuItem);
740: menuItem = null;
741: }
742:
743:
751: public void update(Graphics g, JComponent c)
752: {
753: paint(g, c);
754: }
755:
756:
763: private String getAcceleratorText(KeyStroke accelerator)
764: {
765:
766: String modifiersText = "";
767: int modifiers = accelerator.getModifiers();
768: char keyChar = accelerator.getKeyChar();
769: int keyCode = accelerator.getKeyCode();
770:
771: if (modifiers != 0)
772: modifiersText = KeyEvent.getKeyModifiersText(modifiers)
773: + acceleratorDelimiter;
774:
775: if (keyCode == KeyEvent.VK_UNDEFINED)
776: return modifiersText + keyChar;
777: else
778: return modifiersText + KeyEvent.getKeyText(keyCode);
779: }
780:
781:
790: private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
791: {
792: int width = fm.stringWidth(getAcceleratorText(accelerator));
793: int height = fm.getHeight();
794: return new Rectangle(0, 0, width, height);
795: }
796:
797:
810: private void paintAccelerator(Graphics g, JMenuItem menuItem,
811: Rectangle acceleratorRect,
812: String acceleratorText)
813: {
814: g.setFont(acceleratorFont);
815: FontMetrics fm = g.getFontMetrics(acceleratorFont);
816:
817: if (menuItem.isEnabled())
818: g.setColor(acceleratorForeground);
819: else
820:
821:
822: g.setColor(Color.gray);
823:
824: BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x,
825: acceleratorRect.y + fm.getAscent());
826: }
827:
828:
833: protected class MouseInputHandler implements MouseInputListener
834: {
835:
838: protected MouseInputHandler()
839: {
840:
841: }
842:
843:
850: public void mouseClicked(MouseEvent e)
851: {
852: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
853: manager.processMouseEvent(e);
854: }
855:
856:
863: public void mouseDragged(MouseEvent e)
864: {
865: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
866: manager.processMouseEvent(e);
867: }
868:
869:
878: public void mouseEntered(MouseEvent e)
879: {
880: Component source = (Component) e.getSource();
881: if (source.getParent() instanceof MenuElement)
882: {
883: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
884: manager.setSelectedPath(getPath());
885: manager.processMouseEvent(e);
886: }
887: }
888:
889:
896: public void mouseExited(MouseEvent e)
897: {
898: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
899: manager.processMouseEvent(e);
900: }
901:
902:
909: public void mouseMoved(MouseEvent e)
910: {
911: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
912: manager.processMouseEvent(e);
913: }
914:
915:
922: public void mousePressed(MouseEvent e)
923: {
924: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
925: manager.processMouseEvent(e);
926: }
927:
928:
936: public void mouseReleased(MouseEvent e)
937: {
938: Rectangle size = menuItem.getBounds();
939: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
940: if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
941: && e.getY() < size.height)
942: {
943: manager.clearSelectedPath();
944: menuItem.doClick();
945: }
946:
947: else
948: manager.processMouseEvent(e);
949: }
950: }
951:
952:
955: private class MenuDragMouseHandler implements MenuDragMouseListener
956: {
957:
963: public void menuDragMouseDragged(MenuDragMouseEvent e)
964: {
965: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
966: manager.setSelectedPath(e.getPath());
967: }
968:
969:
976: public void menuDragMouseEntered(MenuDragMouseEvent e)
977: {
978: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
979: manager.setSelectedPath(e.getPath());
980: }
981:
982:
988: public void menuDragMouseExited(MenuDragMouseEvent e)
989: {
990:
991: }
992:
993:
1000: public void menuDragMouseReleased(MenuDragMouseEvent e)
1001: {
1002: MenuElement[] path = e.getPath();
1003:
1004: if (path[path.length - 1] instanceof JMenuItem)
1005: ((JMenuItem) path[path.length - 1]).doClick();
1006:
1007: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1008: manager.clearSelectedPath();
1009: }
1010: }
1011:
1012:
1016: private class MenuKeyHandler implements MenuKeyListener
1017: {
1018:
1024: public void menuKeyPressed(MenuKeyEvent e)
1025: {
1026:
1027: }
1028:
1029:
1035: public void menuKeyReleased(MenuKeyEvent e)
1036: {
1037:
1038: }
1039:
1040:
1047: public void menuKeyTyped(MenuKeyEvent e)
1048: {
1049:
1050: }
1051: }
1052:
1053:
1057: private class ItemHandler implements ItemListener
1058: {
1059:
1064: public void itemStateChanged(ItemEvent evt)
1065: {
1066: boolean state = false;
1067: if (menuItem instanceof JCheckBoxMenuItem)
1068: {
1069: if (evt.getStateChange() == ItemEvent.SELECTED)
1070: state = true;
1071: ((JCheckBoxMenuItem) menuItem).setState(state);
1072: }
1073: menuItem.revalidate();
1074: menuItem.repaint();
1075: }
1076: }
1077: }