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