001: /*
002: * @(#)vsnetMenuUI.java
003: *
004: * Copyright 2002 JIDE Software Inc. All rights reserved.
005: */
006:
007: package com.jidesoft.plaf.eclipse;
008:
009: import com.jidesoft.plaf.UIDefaultsLookup;
010: import com.jidesoft.swing.JideSwingUtilities;
011: import com.sun.java.swing.plaf.windows.WindowsGraphicsUtils;
012: import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
013:
014: import javax.swing.*;
015: import javax.swing.border.Border;
016: import javax.swing.event.*;
017: import javax.swing.plaf.ComponentUI;
018: import java.awt.*;
019: import java.awt.event.ActionEvent;
020: import java.awt.event.MouseEvent;
021: import java.awt.event.MouseMotionListener;
022: import java.beans.PropertyChangeEvent;
023: import java.beans.PropertyChangeListener;
024: import java.util.ArrayList;
025: import java.util.Arrays;
026:
027: /**
028: * Menu UI implementation
029: */
030: public class EclipseMenuUI extends EclipseMenuItemUI {
031: protected ChangeListener changeListener;
032: protected PropertyChangeListener propertyChangeListener;
033: protected MenuListener menuListener;
034:
035: private int lastMnemonic = 0;
036:
037: /* diagnostic aids -- should be false for production builds. */
038: // private static final boolean TRACE = false; // trace creates and disposes
039: // private static final boolean VERBOSE = false; // show reuse hits/misses
040: // private static final boolean DEBUG = false; // show bad params, misc.
041: private static boolean crossMenuMnemonic = true;
042:
043: private boolean isMouseOver = false;
044:
045: public static ComponentUI createUI(JComponent x) {
046: return new EclipseMenuUI();
047: }
048:
049: @Override
050: protected void installDefaults() {
051: super .installDefaults();
052: ((JMenu) menuItem).setDelay(200);
053: crossMenuMnemonic = UIDefaultsLookup
054: .getBoolean("Menu.crossMenuMnemonic");
055: }
056:
057: @Override
058: protected String getPropertyPrefix() {
059: return "Menu";
060: }
061:
062: /**
063: * Draws the background of the menu item.
064: *
065: * @param g the paint graphics
066: * @param menuItem menu item to be painted
067: * @param bgColor selection background color
068: * @since 1.4
069: */
070: @Override
071: protected void paintBackground(Graphics g, JMenuItem menuItem,
072: Color bgColor) {
073: if (!(menuItem instanceof JMenu)
074: || !((JMenu) menuItem).isTopLevelMenu()) {
075: super .paintBackground(g, menuItem, bgColor);
076: return;
077: }
078:
079: ButtonModel model = menuItem.getModel();
080: Color oldColor = g.getColor();
081: int menuWidth = 0;
082: int menuHeight = 0;
083: if (JideSwingUtilities.getOrientationOf(menuItem) == SwingConstants.HORIZONTAL) {
084: menuWidth = menuItem.getWidth();
085: menuHeight = menuItem.getHeight();
086: } else {
087: menuWidth = menuItem.getHeight();
088: menuHeight = menuItem.getWidth();
089: }
090:
091: UIDefaults table = UIManager.getLookAndFeelDefaults();
092: Color darkShadow = table.getColor("controlDkShadow");
093: Color mouseHoverBackground = table
094: .getColor("Menu.mouseHoverBackground");
095: Border mouseHoverBorder = table
096: .getBorder("Menu.mouseHoverBorder");
097: Border mouseSelectedBorder = table
098: .getBorder("Menu.mouseSelectedBorder");
099:
100: if (menuItem.isOpaque()) {
101: if (menuItem.getParent() != null) {
102: g.setColor(menuItem.getParent().getBackground());
103: } else {
104: g.setColor(menuItem.getBackground());
105: }
106: g.fillRect(0, 0, menuWidth, menuHeight);
107: }
108:
109: // if (menuItem.isOpaque()) {
110: if (model.isArmed()
111: || (menuItem instanceof JMenu && model.isSelected())) {
112: // Draw a dark shadow border without bottom
113: if (mouseSelectedBorder != null) {
114: mouseSelectedBorder.paintBorder(menuItem, g, 0, 0,
115: menuWidth - 1, menuHeight);
116: }
117: g.setColor(mouseHoverBackground);
118: g.fillRect(1, 1, menuWidth - 3, menuHeight - 2);
119: } else {
120: if (isMouseOver() && model.isEnabled()) {
121: // Draw a line border with background
122: if (mouseHoverBorder != null) {
123: mouseHoverBorder.paintBorder(menuItem, g, 0, 0,
124: menuWidth - 1, menuHeight);
125: }
126: g.setColor(mouseHoverBackground);
127: g.fillRect(1, 1, menuWidth - 3, menuHeight - 2);
128: } else {
129: // normal menu without mouse hovering over
130: // g.setColor(menuItem.getBackground());
131: // g.fillRect(0, 0, menuWidth, menuHeight);
132: }
133: }
134: // }
135:
136: if (isDownArrowVisible(menuItem.getParent())) {
137: int middle = menuWidth - 9;
138: if (model.isSelected() || model.isArmed()
139: || model.isPressed() || isMouseOver()) {
140: JideSwingUtilities.paintArrow(g, selectionForeground,
141: middle - 2, menuHeight / 2 - 1, 5,
142: SwingConstants.HORIZONTAL);
143: } else {
144: JideSwingUtilities.paintArrow(g, menuItem
145: .getForeground(), middle - 2,
146: menuHeight / 2 - 1, 5,
147: SwingConstants.HORIZONTAL);
148: }
149: }
150: g.setColor(oldColor);
151: }
152:
153: @Override
154: protected void installListeners() {
155: super .installListeners();
156:
157: if (changeListener == null)
158: changeListener = createChangeListener(menuItem);
159:
160: if (changeListener != null)
161: menuItem.addChangeListener(changeListener);
162:
163: if (propertyChangeListener == null)
164: propertyChangeListener = createPropertyChangeListener(menuItem);
165:
166: if (propertyChangeListener != null)
167: menuItem.addPropertyChangeListener(propertyChangeListener);
168:
169: if (menuListener == null)
170: menuListener = createMenuListener(menuItem);
171:
172: if (menuListener != null)
173: ((JMenu) menuItem).addMenuListener(menuListener);
174: }
175:
176: @Override
177: protected void installKeyboardActions() {
178: super .installKeyboardActions();
179: updateMnemonicBinding();
180: }
181:
182: void updateMnemonicBinding() {
183: int mnemonic = menuItem.getModel().getMnemonic();
184: int[] shortcutKeys = (int[]) UIDefaultsLookup
185: .get("Menu.shortcutKeys");
186: if (mnemonic == lastMnemonic || shortcutKeys == null) {
187: return;
188: }
189: if (lastMnemonic != 0 && windowInputMap != null) {
190: for (int i = 0; i < shortcutKeys.length; i++) {
191: windowInputMap.remove(KeyStroke.getKeyStroke(
192: lastMnemonic, shortcutKeys[i], false));
193: }
194: }
195: if (mnemonic != 0) {
196: if (windowInputMap == null) {
197: windowInputMap = createInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
198: SwingUtilities.replaceUIInputMap(menuItem,
199: JComponent.WHEN_IN_FOCUSED_WINDOW,
200: windowInputMap);
201: }
202: for (int i = 0; i < shortcutKeys.length; i++) {
203: windowInputMap.put(KeyStroke.getKeyStroke(mnemonic,
204: shortcutKeys[i], false), "selectMenu");
205: }
206: }
207: lastMnemonic = mnemonic;
208: }
209:
210: @Override
211: protected void uninstallKeyboardActions() {
212: super .uninstallKeyboardActions();
213: }
214:
215: /**
216: * The ActionMap for BasicMenUI can not be shared, this is subclassed
217: * to create a new one for each invocation.
218: */
219: @Override
220: ActionMap getActionMap() {
221: return createActionMap();
222: }
223:
224: /**
225: * Invoked to create the ActionMap.
226: */
227: @Override
228: ActionMap createActionMap() {
229: ActionMap am = super .createActionMap();
230: if (am != null) {
231: am
232: .put("selectMenu", new PostAction((JMenu) menuItem,
233: true));
234: }
235: return am;
236: }
237:
238: @Override
239: protected MouseInputListener createMouseInputListener(JComponent c) {
240: return new MouseInputHandler();
241: }
242:
243: protected MenuListener createMenuListener(JComponent c) {
244: return new MenuHandler();
245: }
246:
247: protected ChangeListener createChangeListener(JComponent c) {
248: return null;
249: }
250:
251: protected PropertyChangeListener createPropertyChangeListener(
252: JComponent c) {
253: return new PropertyChangeHandler();
254: }
255:
256: @Override
257: protected void uninstallDefaults() {
258: menuItem.setArmed(false);
259: menuItem.setSelected(false);
260: menuItem.resetKeyboardActions();
261: super .uninstallDefaults();
262: }
263:
264: @Override
265: protected void uninstallListeners() {
266: super .uninstallListeners();
267:
268: if (changeListener != null)
269: menuItem.removeChangeListener(changeListener);
270:
271: if (propertyChangeListener != null)
272: menuItem
273: .removePropertyChangeListener(propertyChangeListener);
274:
275: if (menuListener != null)
276: ((JMenu) menuItem).removeMenuListener(menuListener);
277:
278: changeListener = null;
279: propertyChangeListener = null;
280: menuListener = null;
281: }
282:
283: @Override
284: protected MenuDragMouseListener createMenuDragMouseListener(
285: JComponent c) {
286: return new MenuDragMouseHandler();
287: }
288:
289: @Override
290: protected MenuKeyListener createMenuKeyListener(JComponent c) {
291: return new MenuKeyHandler();
292: }
293:
294: @Override
295: public Dimension getMaximumSize(JComponent c) {
296: if (((JMenu) menuItem).isTopLevelMenu() == true) {
297: Dimension d = c.getPreferredSize();
298: return new Dimension(d.width, Short.MAX_VALUE);
299: }
300: return null;
301: }
302:
303: public static void setupPostTimer(JMenu menu) {
304: Timer timer = new Timer(menu.getDelay(), new PostAction(menu,
305: false));
306: timer.setRepeats(false);
307: timer.start();
308: }
309:
310: protected static void appendPath(MenuElement[] path,
311: MenuElement elem) {
312: MenuElement newPath[] = new MenuElement[path.length + 1];
313: System.arraycopy(path, 0, newPath, 0, path.length);
314: newPath[path.length] = elem;
315: MenuSelectionManager.defaultManager().setSelectedPath(newPath);
316: }
317:
318: private static class PostAction extends AbstractAction {
319: JMenu menu;
320: boolean force = false;
321:
322: PostAction(JMenu menu, boolean shouldForce) {
323: this .menu = menu;
324: this .force = shouldForce;
325: }
326:
327: public void actionPerformed(ActionEvent e) {
328: if (!crossMenuMnemonic) {
329: JPopupMenu pm = getActivePopupMenu();
330: if (pm != null && pm != menu.getParent()) {
331: return;
332: }
333: }
334:
335: final MenuSelectionManager defaultManager = MenuSelectionManager
336: .defaultManager();
337: if (force) {
338: Container cnt = menu.getParent();
339: if (cnt != null && cnt instanceof JMenuBar) {
340: MenuElement me[];
341: MenuElement subElements[];
342:
343: subElements = menu.getPopupMenu().getSubElements();
344: if (subElements.length > 0) {
345: me = new MenuElement[4];
346: me[0] = (MenuElement) cnt;
347: me[1] = menu;
348: me[2] = menu.getPopupMenu();
349: me[3] = subElements[0];
350: } else {
351: me = new MenuElement[3];
352: me[0] = (MenuElement) cnt;
353: me[1] = menu;
354: me[2] = menu.getPopupMenu();
355: }
356: defaultManager.setSelectedPath(me);
357: }
358: } else {
359: MenuElement path[] = defaultManager.getSelectedPath();
360: if (path.length > 0 && path[path.length - 1] == menu) {
361: appendPath(path, menu.getPopupMenu());
362: }
363: }
364: }
365:
366: @Override
367: public boolean isEnabled() {
368: return menu.getModel().isEnabled();
369: }
370: }
371:
372: private class PropertyChangeHandler implements
373: PropertyChangeListener {
374: public void propertyChange(PropertyChangeEvent e) {
375: String prop = e.getPropertyName();
376: if (prop.equals(AbstractButton.MNEMONIC_CHANGED_PROPERTY)) {
377: updateMnemonicBinding();
378: }
379: }
380: }
381:
382: /**
383: * Instantiated and used by a menu item to handle the current menu selection
384: * from mouse events. A MouseInputHandler processes and forwards all mouse events
385: * to a shared instance of the MenuSelectionManager.
386: * <p/>
387: * This class is protected so that it can be subclassed by other look and
388: * feels to implement their own mouse handling behavior. All overridden
389: * methods should call the parent methods so that the menu selection
390: * is correct.
391: *
392: * @see MenuSelectionManager
393: * @since 1.4
394: */
395: protected class MouseInputHandler implements MouseInputListener {
396: public void mouseClicked(MouseEvent e) {
397: }
398:
399: /**
400: * Invoked when the mouse has been clicked on the menu. This
401: * method clears or sets the selection path of the
402: * MenuSelectionManager.
403: *
404: * @param e the mouse event
405: */
406: public void mousePressed(MouseEvent e) {
407: if (!(menuItem instanceof JMenu)) {
408: return;
409: }
410:
411: JMenu menu = (JMenu) menuItem;
412: if (!menu.isEnabled())
413: return;
414:
415: MenuSelectionManager manager = MenuSelectionManager
416: .defaultManager();
417: if (menu.isTopLevelMenu()) {
418: if (menu.isSelected()) {
419: manager.clearSelectedPath();
420: } else {
421: Container cnt = menu.getParent();
422: if (cnt != null
423: && cnt.getParent() instanceof MenuElement) {
424: MenuElement me[] = new MenuElement[3];
425: me[0] = (MenuElement) cnt.getParent();
426: me[1] = ((MenuElement) cnt);
427: me[2] = menu;
428: manager.setSelectedPath(me);
429: } else if (cnt != null
430: && cnt instanceof MenuElement) {
431: MenuElement me[] = new MenuElement[2];
432: me[0] = (MenuElement) cnt;
433: me[1] = menu;
434: manager.setSelectedPath(me);
435: }
436: }
437: }
438:
439: MenuElement selectedPath[] = manager.getSelectedPath();
440: if (selectedPath.length > 0
441: && selectedPath[selectedPath.length - 1] != menu
442: .getPopupMenu()) {
443:
444: if (menu.isTopLevelMenu() || menu.getDelay() == 0) {
445: appendPath(selectedPath, menu.getPopupMenu());
446: } else {
447: setupPostTimer(menu);
448: }
449: }
450: }
451:
452: /**
453: * Invoked when the mouse has been released on the menu. Delegates the
454: * mouse event to the MenuSelectionManager.
455: *
456: * @param e the mouse event
457: */
458: public void mouseReleased(MouseEvent e) {
459: if (!(menuItem instanceof JMenu)) {
460: return;
461: }
462:
463: JMenu menu = (JMenu) menuItem;
464: if (!menu.isEnabled())
465: return;
466: MenuSelectionManager manager = MenuSelectionManager
467: .defaultManager();
468: manager.processMouseEvent(e);
469: if (!e.isConsumed())
470: manager.clearSelectedPath();
471: }
472:
473: /**
474: * Invoked when the cursor enters the menu. This method sets the selected
475: * path for the MenuSelectionManager and handles the case
476: * in which a menu item is used to pop up an additional menu, as in a
477: * hierarchical menu system.
478: *
479: * @param e the mouse event; not used
480: */
481: public void mouseEntered(MouseEvent e) {
482: if (!(menuItem instanceof JMenu)) {
483: return;
484: }
485: JMenu menu = (JMenu) menuItem;
486: if (!menu.isEnabled())
487: return;
488:
489: MenuSelectionManager manager = MenuSelectionManager
490: .defaultManager();
491: MenuElement selectedPath[] = manager.getSelectedPath();
492: if (!menu.isTopLevelMenu()) {
493: if (!(selectedPath.length > 0 && selectedPath[selectedPath.length - 1] == menu
494: .getPopupMenu())) {
495: if (menu.getDelay() == 0) {
496: appendPath(getPath(), menu.getPopupMenu());
497: } else {
498: manager.setSelectedPath(getPath());
499: setupPostTimer(menu);
500: }
501: }
502: } else {
503: if (selectedPath.length > 0
504: && selectedPath[0] == menu.getParent()) {
505: MenuElement newPath[] = new MenuElement[3];
506: // A top level menu's parent is by definition
507: // a JMenuBar
508: newPath[0] = (MenuElement) menu.getParent();
509: newPath[1] = menu;
510: newPath[2] = menu.getPopupMenu();
511: manager.setSelectedPath(newPath);
512: }
513: }
514:
515: setMouseOver(true);
516: menuItem.repaint();
517: }
518:
519: public void mouseExited(MouseEvent e) {
520: setMouseOver(false);
521: menuItem.repaint();
522: }
523:
524: /**
525: * Invoked when a mouse button is pressed on the menu and then dragged.
526: * Delegates the mouse event to the MenuSelectionManager.
527: *
528: * @param e the mouse event
529: * @see MouseMotionListener#mouseDragged
530: */
531: public void mouseDragged(MouseEvent e) {
532: if (!(menuItem instanceof JMenu)) {
533: return;
534: }
535: JMenu menu = (JMenu) menuItem;
536: if (!menu.isEnabled())
537: return;
538: MenuSelectionManager.defaultManager().processMouseEvent(e);
539: }
540:
541: public void mouseMoved(MouseEvent e) {
542: }
543: }
544:
545: private static class MenuHandler implements MenuListener {
546: public void menuSelected(MenuEvent e) {
547: }
548:
549: public void menuDeselected(MenuEvent e) {
550: }
551:
552: public void menuCanceled(MenuEvent e) {
553: JMenu m = (JMenu) e.getSource();
554: MenuSelectionManager manager = MenuSelectionManager
555: .defaultManager();
556: if (manager.isComponentPartOfCurrentMenu(m))
557: MenuSelectionManager.defaultManager()
558: .clearSelectedPath();
559: }
560:
561: }
562:
563: /**
564: * As of Java 2 platform 1.4, this previously undocumented class
565: * is now obsolete. KeyBindings are now managed by the popup menu.
566: */
567: public class ChangeHandler implements ChangeListener {
568: public JMenu menu;
569: public EclipseMenuUI ui;
570: public boolean isSelected = false;
571: public Component wasFocused;
572:
573: public ChangeHandler(JMenu m, EclipseMenuUI ui) {
574: menu = m;
575: this .ui = ui;
576: }
577:
578: public void stateChanged(ChangeEvent e) {
579: }
580: }
581:
582: private class MenuDragMouseHandler implements MenuDragMouseListener {
583: public void menuDragMouseEntered(MenuDragMouseEvent e) {
584: }
585:
586: public void menuDragMouseDragged(MenuDragMouseEvent e) {
587: if (!(menuItem instanceof JMenu)) {
588: return;
589: }
590: if (menuItem.isEnabled() == false)
591: return;
592:
593: MenuSelectionManager manager = e.getMenuSelectionManager();
594: MenuElement path[] = e.getPath();
595:
596: Point p = e.getPoint();
597: if (p.x >= 0 && p.x < menuItem.getWidth() && p.y >= 0
598: && p.y < menuItem.getHeight()) {
599: JMenu menu = (JMenu) menuItem;
600: MenuElement selectedPath[] = manager.getSelectedPath();
601: if (!(selectedPath.length > 0 && selectedPath[selectedPath.length - 1] == menu
602: .getPopupMenu())) {
603: if (menu.isTopLevelMenu() || menu.getDelay() == 0
604: || e.getID() == MouseEvent.MOUSE_DRAGGED) {
605: appendPath(path, menu.getPopupMenu());
606: } else {
607: manager.setSelectedPath(path);
608: setupPostTimer(menu);
609: }
610: }
611: } else if (e.getID() == MouseEvent.MOUSE_RELEASED) {
612: Component comp = manager.componentForPoint(e
613: .getComponent(), e.getPoint());
614: if (comp == null)
615: manager.clearSelectedPath();
616: }
617:
618: }
619:
620: public void menuDragMouseExited(MenuDragMouseEvent e) {
621: }
622:
623: public void menuDragMouseReleased(MenuDragMouseEvent e) {
624: }
625: }
626:
627: static JPopupMenu getActivePopupMenu() {
628: MenuElement[] path = MenuSelectionManager.defaultManager()
629: .getSelectedPath();
630: for (int i = path.length - 1; i >= 0; i--) {
631: MenuElement elem = path[i];
632: if (elem instanceof JPopupMenu) {
633: return (JPopupMenu) elem;
634: }
635: }
636: return null;
637: }
638:
639: /**
640: * Handles the mnemonic handling for the JMenu and JMenuItems.
641: */
642: private class MenuKeyHandler implements MenuKeyListener {
643:
644: /**
645: * Opens the SubMenu
646: */
647: public void menuKeyTyped(MenuKeyEvent e) {
648: // if (DEBUG) {
649: // System.out.println("in BasicMenuUI.menuKeyTyped for " + menuItem.getText());
650: // }
651: if (!crossMenuMnemonic) {
652: JPopupMenu pm = getActivePopupMenu();
653: if (pm != null && pm != menuItem.getParent()) {
654: return;
655: }
656: }
657:
658: int key = menuItem.getMnemonic();
659: if (key == 0)
660: return;
661: MenuElement path[] = e.getPath();
662: if (lower((char) key) == lower(e.getKeyChar())) {
663: JPopupMenu popupMenu = ((JMenu) menuItem)
664: .getPopupMenu();
665: ArrayList newList = new ArrayList(Arrays.asList(path));
666: newList.add(popupMenu);
667: MenuElement sub[] = popupMenu.getSubElements();
668: if (sub.length > 0) {
669: newList.add(sub[0]);
670: }
671: MenuSelectionManager manager = e
672: .getMenuSelectionManager();
673: MenuElement newPath[] = new MenuElement[0];
674: newPath = (MenuElement[]) newList.toArray(newPath);
675: manager.setSelectedPath(newPath);
676: e.consume();
677: }
678: }
679:
680: /**
681: * Handles the mnemonics for the menu items. Will also handle duplicate mnemonics.
682: * Perhaps this should be moved into BasicPopupMenuUI. See 4670831
683: */
684: public void menuKeyPressed(MenuKeyEvent e) {
685: // if (DEBUG) {
686: // System.out.println("in BasicMenuUI.menuKeyPressed for " + menuItem.getText());
687: // }
688: // Handle the case for Escape or Enter...
689: char keyChar = e.getKeyChar();
690: if (!Character.isLetterOrDigit(keyChar))
691: return;
692:
693: MenuSelectionManager manager = e.getMenuSelectionManager();
694: MenuElement path[] = e.getPath();
695: MenuElement selectedPath[] = manager.getSelectedPath();
696:
697: for (int i = selectedPath.length - 1; i >= 0; i--) {
698: if (selectedPath[i] == menuItem) {
699: JPopupMenu popupMenu = ((JMenu) menuItem)
700: .getPopupMenu();
701: if (!popupMenu.isVisible()) {
702: return; // Do not invoke items from invisible popup
703: }
704: MenuElement items[] = popupMenu.getSubElements();
705:
706: MenuElement currentItem = selectedPath[selectedPath.length - 1];
707: int currentIndex = -1;
708: int matches = 0;
709: int firstMatch = -1;
710: int indexes[] = null;
711:
712: for (int j = 0; j < items.length; j++) {
713: int key = ((JMenuItem) items[j]).getMnemonic();
714: if (lower((char) key) == lower(keyChar)) {
715: if (matches == 0) {
716: firstMatch = j;
717: matches++;
718: } else {
719: if (indexes == null) {
720: indexes = new int[items.length];
721: indexes[0] = firstMatch;
722: }
723: indexes[matches++] = j;
724: }
725: }
726: if (currentItem == items[j]) {
727: currentIndex = matches - 1;
728: }
729: }
730:
731: if (matches == 0) {
732: ; // no op (consume)
733: } else if (matches == 1) {
734: // Invoke the menu action
735: JMenuItem item = (JMenuItem) items[firstMatch];
736: if (!(item instanceof JMenu)) {
737: // Let Submenus be handled by menuKeyTyped
738: manager.clearSelectedPath();
739: item.doClick();
740: }
741: } else {
742: // Select the menu item with the matching mnemonic. If
743: // the same mnemonic has been invoked then select the next
744: // menu item in the cycle.
745: MenuElement newItem = null;
746:
747: newItem = items[indexes[(currentIndex + 1)
748: % matches]];
749:
750: MenuElement newPath[] = new MenuElement[path.length + 2];
751: System.arraycopy(path, 0, newPath, 0,
752: path.length);
753: newPath[path.length] = popupMenu;
754: newPath[path.length + 1] = newItem;
755: manager.setSelectedPath(newPath);
756: }
757: e.consume();
758: return;
759: }
760: }
761: }
762:
763: public void menuKeyReleased(MenuKeyEvent e) {
764: }
765:
766: private char lower(char keyChar) {
767: return Character.toLowerCase(keyChar);
768: }
769: }
770:
771: /**
772: * Method which renders the text of the current menu item.
773: * <p/>
774: *
775: * @param g Graphics context
776: * @param menuItem Current menu item to render
777: * @param textRect Bounding rectangle to render the text.
778: * @param text String to render
779: * @since 1.4
780: */
781: @Override
782: protected void paintText(Graphics g, JMenuItem menuItem,
783: Rectangle textRect, String text) {
784: // Note: This method is almost identical to the same method in WindowsMenuItemUI
785: ButtonModel model = menuItem.getModel();
786:
787: if (!(menuItem instanceof JMenu)
788: || !((JMenu) menuItem).isTopLevelMenu()) {
789: if (menuItem.getComponentOrientation().isLeftToRight()) {
790: int defaultTextIconGap = UIDefaultsLookup
791: .getInt("MenuItem.textIconGap");
792: int defaultShadowWidth = UIDefaultsLookup
793: .getInt("MenuItem.shadowWidth");
794: textRect.x = defaultShadowWidth + defaultTextIconGap;
795: } else {
796: // isLeftToRight is false
797: }
798: }
799:
800: if (!model.isEnabled()) {
801: // *** paint the text disabled
802: textRect.y++;
803: WindowsGraphicsUtils.paintText(g, menuItem, textRect, text,
804: 0);
805: } else {
806: FontMetrics fm = g.getFontMetrics();
807: int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
808: // W2K Feature: Check to see if the Underscore should be rendered.
809: if (WindowsLookAndFeel.isMnemonicHidden()) {
810: mnemonicIndex = -1;
811: }
812:
813: Color oldColor = g.getColor();
814:
815: if (model.isArmed()
816: || (menuItem instanceof JMenu && model.isSelected())
817: || isMouseOver()) {
818: g.setColor(selectionForeground); // Uses protected field.
819: }
820: JideSwingUtilities.drawStringUnderlineCharAt(menuItem, g,
821: text, mnemonicIndex, textRect.x, textRect.y
822: + fm.getAscent() - 1);
823: g.setColor(oldColor);
824: }
825: }
826:
827: /**
828: * Set the temporary flag to indicate if the mouse has entered the menu.
829: */
830: protected void setMouseOver(boolean over) {
831: isMouseOver = over;
832: menuItem.getModel().setRollover(isMouseOver);
833: }
834:
835: /**
836: * Get the temporary flag to indicate if the mouse has entered the menu.
837: */
838: protected boolean isMouseOver() {
839: return isMouseOver;
840: }
841:
842: @Override
843: public Dimension getPreferredSize(JComponent c) {
844: Dimension size = super .getPreferredSize(c);
845: if (menuItem instanceof JMenu
846: && ((JMenu) menuItem).isTopLevelMenu()
847: && isDownArrowVisible(menuItem.getParent())) {
848: if (JideSwingUtilities.getOrientationOf(menuItem) == SwingConstants.HORIZONTAL)
849: size.width += 11;
850: else
851: size.height += 11;
852: }
853: return size;
854: }
855: }
|