KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > plaf > basic > BasicMenuItemUI


1 /*
2  * @(#)BasicMenuItemUI.java 1.129 07/01/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7  
8 package javax.swing.plaf.basic;
9
10 import sun.swing.MenuItemCheckIconFactory;
11 import com.sun.java.swing.SwingUtilities2;
12 import java.awt.*;
13 import java.awt.event.*;
14 import java.beans.PropertyChangeEvent JavaDoc;
15 import java.beans.PropertyChangeListener JavaDoc;
16
17 import javax.swing.*;
18 import javax.swing.event.*;
19 import javax.swing.border.*;
20 import javax.swing.plaf.*;
21 import javax.swing.text.View JavaDoc;
22
23 import sun.swing.UIAction;
24
25 /**
26  * BasicMenuItem implementation
27  *
28  * @version 1.129 01/18/07
29  * @author Georges Saab
30  * @author David Karlton
31  * @author Arnaud Weber
32  * @author Fredrik Lagerblad
33  */

34 public class BasicMenuItemUI extends MenuItemUI
35 {
36     protected JMenuItem menuItem = null;
37     protected Color selectionBackground;
38     protected Color selectionForeground;
39     protected Color disabledForeground;
40     protected Color acceleratorForeground;
41     protected Color acceleratorSelectionForeground;
42     private String JavaDoc acceleratorDelimiter;
43
44     protected int defaultTextIconGap;
45     protected Font acceleratorFont;
46
47     protected MouseInputListener mouseInputListener;
48     protected MenuDragMouseListener menuDragMouseListener;
49     protected MenuKeyListener menuKeyListener;
50     // BasicMenuUI also uses this.
51
Handler handler;
52     
53     protected Icon arrowIcon = null;
54     protected Icon checkIcon = null;
55
56     protected boolean oldBorderPainted;
57
58     /* diagnostic aids -- should be false for production builds. */
59     private static final boolean TRACE = false; // trace creates and disposes
60

61     private static final boolean VERBOSE = false; // show reuse hits/misses
62
private static final boolean DEBUG = false; // show bad params, misc.
63

64     /* Client Property keys for text and accelerator text widths */
65     static final String JavaDoc MAX_TEXT_WIDTH = "maxTextWidth";
66     static final String JavaDoc MAX_ACC_WIDTH = "maxAccWidth";
67
68     static void loadActionMap(LazyActionMap JavaDoc map) {
69         // NOTE: BasicMenuUI also calls into this method.
70
map.put(new Actions(Actions.CLICK));
71         BasicLookAndFeel.installAudioActionMap(map);
72     }
73
74     public static ComponentUI createUI(JComponent c) {
75         return new BasicMenuItemUI JavaDoc();
76     }
77
78     public void installUI(JComponent c) {
79         menuItem = (JMenuItem) c;
80
81         installDefaults();
82         installComponents(menuItem);
83         installListeners();
84         installKeyboardActions();
85     }
86     
87
88     protected void installDefaults() {
89         String JavaDoc prefix = getPropertyPrefix();
90
91         acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
92
93         Object JavaDoc opaque = UIManager.get(getPropertyPrefix() + ".opaque");
94         if (opaque != null) {
95             LookAndFeel.installProperty(menuItem, "opaque", opaque);
96         }
97         else {
98             LookAndFeel.installProperty(menuItem, "opaque", Boolean.TRUE);
99         }
100         if(menuItem.getMargin() == null ||
101            (menuItem.getMargin() instanceof UIResource)) {
102             menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
103         }
104
105         defaultTextIconGap = 4; // Should be from table
106

107         LookAndFeel.installBorder(menuItem, prefix + ".border");
108         oldBorderPainted = menuItem.isBorderPainted(); // not used anymore
109
LookAndFeel.installProperty(menuItem, "borderPainted",
110                                     UIManager.get(prefix + ".borderPainted"));
111         LookAndFeel.installColorsAndFont(menuItem,
112                                          prefix + ".background",
113                                          prefix + ".foreground",
114                                          prefix + ".font");
115         
116         // MenuItem specific defaults
117
if (selectionBackground == null ||
118             selectionBackground instanceof UIResource) {
119             selectionBackground =
120                 UIManager.getColor(prefix + ".selectionBackground");
121         }
122         if (selectionForeground == null ||
123             selectionForeground instanceof UIResource) {
124             selectionForeground =
125                 UIManager.getColor(prefix + ".selectionForeground");
126         }
127         if (disabledForeground == null ||
128             disabledForeground instanceof UIResource) {
129             disabledForeground =
130                 UIManager.getColor(prefix + ".disabledForeground");
131         }
132         if (acceleratorForeground == null ||
133             acceleratorForeground instanceof UIResource) {
134             acceleratorForeground =
135                 UIManager.getColor(prefix + ".acceleratorForeground");
136         }
137         if (acceleratorSelectionForeground == null ||
138             acceleratorSelectionForeground instanceof UIResource) {
139             acceleratorSelectionForeground =
140                 UIManager.getColor(prefix + ".acceleratorSelectionForeground");
141         }
142     // Get accelerator delimiter
143
acceleratorDelimiter =
144         UIManager.getString("MenuItem.acceleratorDelimiter");
145     if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; }
146         // Icons
147
if (arrowIcon == null ||
148             arrowIcon instanceof UIResource) {
149             arrowIcon = UIManager.getIcon(prefix + ".arrowIcon");
150         }
151         if (checkIcon == null ||
152             checkIcon instanceof UIResource) {
153             checkIcon = UIManager.getIcon(prefix + ".checkIcon");
154             MenuItemCheckIconFactory iconFactory =
155                 (MenuItemCheckIconFactory) UIManager.get(prefix
156                     + ".checkIconFactory");
157             if (iconFactory != null
158                     && iconFactory.isCompatible(checkIcon, prefix)) {
159                 checkIcon = iconFactory.getIcon(menuItem);
160             }
161         }
162     }
163
164     /**
165      * @since 1.3
166      */

167     protected void installComponents(JMenuItem menuItem){
168     BasicHTML.updateRenderer(menuItem, menuItem.getText());
169     }
170
171     protected String JavaDoc getPropertyPrefix() {
172         return "MenuItem";
173     }
174
175     protected void installListeners() {
176     if ((mouseInputListener = createMouseInputListener(menuItem)) != null) {
177         menuItem.addMouseListener(mouseInputListener);
178         menuItem.addMouseMotionListener(mouseInputListener);
179     }
180         if ((menuDragMouseListener = createMenuDragMouseListener(menuItem)) != null) {
181         menuItem.addMenuDragMouseListener(menuDragMouseListener);
182     }
183     if ((menuKeyListener = createMenuKeyListener(menuItem)) != null) {
184         menuItem.addMenuKeyListener(menuKeyListener);
185     }
186         menuItem.addPropertyChangeListener(getHandler());
187     }
188
189     protected void installKeyboardActions() {
190         installLazyActionMap();
191     updateAcceleratorBinding();
192     }
193
194     void installLazyActionMap() {
195         LazyActionMap.installLazyActionMap(menuItem, BasicMenuItemUI JavaDoc.class,
196                                            getPropertyPrefix() + ".actionMap");
197     }
198
199     public void uninstallUI(JComponent c) {
200     menuItem = (JMenuItem)c;
201         uninstallDefaults();
202         uninstallComponents(menuItem);
203         uninstallListeners();
204         uninstallKeyboardActions();
205
206     
207     //Remove the textWidth and accWidth values from the parent's Client Properties.
208
Container parent = menuItem.getParent();
209     if ( (parent != null && parent instanceof JComponent) &&
210          !(menuItem instanceof JMenu && ((JMenu) menuItem).isTopLevelMenu())) {
211         JComponent p = (JComponent) parent;
212         p.putClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH, null );
213         p.putClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH, null );
214     }
215
216     menuItem = null;
217     }
218
219
220     protected void uninstallDefaults() {
221         LookAndFeel.uninstallBorder(menuItem);
222         if (menuItem.getMargin() instanceof UIResource)
223             menuItem.setMargin(null);
224         if (arrowIcon instanceof UIResource)
225             arrowIcon = null;
226         if (checkIcon instanceof UIResource)
227             checkIcon = null;
228     }
229
230     /**
231      * @since 1.3
232      */

233     protected void uninstallComponents(JMenuItem menuItem){
234     BasicHTML.updateRenderer(menuItem, "");
235     }
236
237     protected void uninstallListeners() {
238     if (mouseInputListener != null) {
239         menuItem.removeMouseListener(mouseInputListener);
240         menuItem.removeMouseMotionListener(mouseInputListener);
241     }
242     if (menuDragMouseListener != null) {
243         menuItem.removeMenuDragMouseListener(menuDragMouseListener);
244     }
245     if (menuKeyListener != null) {
246         menuItem.removeMenuKeyListener(menuKeyListener);
247     }
248         menuItem.removePropertyChangeListener(getHandler());
249
250         mouseInputListener = null;
251         menuDragMouseListener = null;
252         menuKeyListener = null;
253         handler = null;
254     }
255
256     protected void uninstallKeyboardActions() {
257     SwingUtilities.replaceUIActionMap(menuItem, null);
258         SwingUtilities.replaceUIInputMap(menuItem, JComponent.
259                                          WHEN_IN_FOCUSED_WINDOW, null);
260     }
261
262     protected MouseInputListener createMouseInputListener(JComponent c) {
263         return getHandler();
264     }
265
266     protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) {
267         return getHandler();
268     }
269
270     protected MenuKeyListener createMenuKeyListener(JComponent c) {
271     return null;
272     }
273
274     Handler getHandler() {
275         if (handler == null) {
276             handler = new Handler();
277         }
278         return handler;
279     }
280
281     InputMap createInputMap(int condition) {
282     if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
283         return new ComponentInputMapUIResource(menuItem);
284     }
285     return null;
286     }
287
288     void updateAcceleratorBinding() {
289     KeyStroke accelerator = menuItem.getAccelerator();
290         InputMap windowInputMap = SwingUtilities.getUIInputMap(
291                        menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
292
293     if (windowInputMap != null) {
294         windowInputMap.clear();
295     }
296     if (accelerator != null) {
297         if (windowInputMap == null) {
298         windowInputMap = createInputMap(JComponent.
299                         WHEN_IN_FOCUSED_WINDOW);
300         SwingUtilities.replaceUIInputMap(menuItem,
301                JComponent.WHEN_IN_FOCUSED_WINDOW, windowInputMap);
302         }
303         windowInputMap.put(accelerator, "doClick");
304     }
305     }
306
307     public Dimension getMinimumSize(JComponent c) {
308     Dimension d = null;
309     View JavaDoc v = (View JavaDoc) c.getClientProperty(BasicHTML.propertyKey);
310     if (v != null) {
311         d = getPreferredSize(c);
312         d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
313     }
314     return d;
315     }
316
317     public Dimension getPreferredSize(JComponent c) {
318         return getPreferredMenuItemSize(c,
319                                         checkIcon,
320                                         arrowIcon,
321                                         defaultTextIconGap);
322     }
323
324     public Dimension getMaximumSize(JComponent c) {
325     Dimension d = null;
326     View JavaDoc v = (View JavaDoc) c.getClientProperty(BasicHTML.propertyKey);
327     if (v != null) {
328         d = getPreferredSize(c);
329         d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
330     }
331     return d;
332     }
333
334     // these rects are used for painting and preferredsize calculations.
335
// they used to be regenerated constantly. Now they are reused.
336
static Rectangle zeroRect = new Rectangle(0,0,0,0);
337     static Rectangle iconRect = new Rectangle();
338     static Rectangle textRect = new Rectangle();
339     static Rectangle acceleratorRect = new Rectangle();
340     static Rectangle checkIconRect = new Rectangle();
341     static Rectangle arrowIconRect = new Rectangle();
342     static Rectangle viewRect = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE);
343     static Rectangle r = new Rectangle();
344
345     private void resetRects() {
346         iconRect.setBounds(zeroRect);
347         textRect.setBounds(zeroRect);
348         acceleratorRect.setBounds(zeroRect);
349         checkIconRect.setBounds(zeroRect);
350         arrowIconRect.setBounds(zeroRect);
351         viewRect.setBounds(0,0,Short.MAX_VALUE, Short.MAX_VALUE);
352         r.setBounds(zeroRect);
353     }
354
355     protected Dimension getPreferredMenuItemSize(JComponent c,
356                                                      Icon checkIcon,
357                                                      Icon arrowIcon,
358                                                      int defaultTextIconGap) {
359         JMenuItem b = (JMenuItem) c;
360         
361         Icon icon = null;
362         /*
363          * in case .checkIconFactory is defined for this UI and the icon is
364          * compatible with it then the icon is handled by the checkIcon.
365          */

366         MenuItemCheckIconFactory iconFactory =
367             (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix()
368                 + ".checkIconFactory");
369         if (iconFactory == null
370                 || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) {
371            icon = b.getIcon();
372         }
373         String JavaDoc text = b.getText();
374         KeyStroke accelerator = b.getAccelerator();
375         String JavaDoc acceleratorText = "";
376
377         if (accelerator != null) {
378             int modifiers = accelerator.getModifiers();
379             if (modifiers > 0) {
380                 acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
381                 //acceleratorText += "-";
382
acceleratorText += acceleratorDelimiter;
383           }
384             int keyCode = accelerator.getKeyCode();
385             if (keyCode != 0) {
386                 acceleratorText += KeyEvent.getKeyText(keyCode);
387             } else {
388                 acceleratorText += accelerator.getKeyChar();
389             }
390         }
391
392         Font font = b.getFont();
393         FontMetrics fm = b.getFontMetrics(font);
394         FontMetrics fmAccel = b.getFontMetrics( acceleratorFont );
395
396         resetRects();
397         
398         layoutMenuItem(
399                   fm, text, fmAccel, acceleratorText, icon, checkIcon, arrowIcon,
400                   b.getVerticalAlignment(), b.getHorizontalAlignment(),
401                   b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
402                   viewRect, iconRect, textRect, acceleratorRect, checkIconRect, arrowIconRect,
403                   text == null ? 0 : defaultTextIconGap,
404                   defaultTextIconGap
405                   );
406         // find the union of the icon and text rects
407
r.setBounds(textRect);
408         r = SwingUtilities.computeUnion(iconRect.x,
409                                         iconRect.y,
410                                         iconRect.width,
411                                         iconRect.height,
412                                         r);
413         // Find the result height
414
r.height = Math.max(
415             Math.max(r.height, checkIconRect.height),
416             Math.max(arrowIconRect.height, acceleratorRect.height));
417         // r = iconRect.union(textRect);
418

419     
420     // To make the accelerator texts appear in a column, find the widest MenuItem text
421
// and the widest accelerator text.
422

423     //Get the parent, which stores the information.
424
Container parent = menuItem.getParent();
425     
426     //Check the parent, and see that it is not a top-level menu.
427
if (parent != null && parent instanceof JComponent &&
428         !(menuItem instanceof JMenu && ((JMenu) menuItem).isTopLevelMenu())) {
429         JComponent p = (JComponent) parent;
430         
431         //Get widest text so far from parent, if no one exists null is returned.
432
Integer JavaDoc maxTextWidth = (Integer JavaDoc) p.getClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH);
433         Integer JavaDoc maxAccWidth = (Integer JavaDoc) p.getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH);
434         
435         int maxTextValue = maxTextWidth!=null ? maxTextWidth.intValue() : 0;
436         int maxAccValue = maxAccWidth!=null ? maxAccWidth.intValue() : 0;
437         
438         //Compare the text widths, and adjust the r.width to the widest.
439
if (r.width < maxTextValue) {
440         r.width = maxTextValue;
441         } else {
442         p.putClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH, new Integer JavaDoc(r.width) );
443         }
444         
445       //Compare the accelarator widths.
446
if (acceleratorRect.width > maxAccValue) {
447         maxAccValue = acceleratorRect.width;
448         p.putClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH, new Integer JavaDoc(acceleratorRect.width) );
449         }
450         
451         //Add on the widest accelerator
452
r.width += maxAccValue;
453         r.width += defaultTextIconGap;
454         
455     }
456     
457     if( useCheckAndArrow() ) {
458         // Add in the checkIcon
459
r.width += checkIconRect.width;
460         r.width += defaultTextIconGap;
461
462         // Add in the arrowIcon
463
r.width += defaultTextIconGap;
464         r.width += arrowIconRect.width;
465         }
466
467     r.width += 2*defaultTextIconGap;
468
469         Insets insets = b.getInsets();
470         if(insets != null) {
471             r.width += insets.left + insets.right;
472             r.height += insets.top + insets.bottom;
473         }
474
475         // if the width is even, bump it up one. This is critical
476
// for the focus dash line to draw properly
477
if(r.width%2 == 0) {
478             r.width++;
479         }
480
481         // if the height is even, bump it up one. This is critical
482
// for the text to center properly
483
if(r.height%2 == 0
484                 && Boolean.TRUE !=
485                     UIManager.get(getPropertyPrefix() + ".evenHeight")) {
486             r.height++;
487         }
488 /*
489     if(!(b instanceof JMenu && ((JMenu) b).isTopLevelMenu()) ) {
490         
491         // Container parent = menuItem.getParent();
492         JComponent p = (JComponent) parent;
493         
494         System.out.println("MaxText: "+p.getClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH));
495         System.out.println("MaxACC"+p.getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH));
496         
497         System.out.println("returning pref.width: " + r.width);
498         System.out.println("Current getSize: " + b.getSize() + "\n");
499         }*/

500     return r.getSize();
501     }
502
503     /**
504      * We draw the background in paintMenuItem()
505      * so override update (which fills the background of opaque
506      * components by default) to just call paint().
507      *
508      */

509     public void update(Graphics g, JComponent c) {
510         paint(g, c);
511     }
512
513     public void paint(Graphics g, JComponent c) {
514         paintMenuItem(g, c, checkIcon, arrowIcon,
515                       selectionBackground, selectionForeground,
516                       defaultTextIconGap);
517     }
518
519
520     protected void paintMenuItem(Graphics g, JComponent c,
521                                      Icon checkIcon, Icon arrowIcon,
522                                      Color background, Color foreground,
523                                      int defaultTextIconGap) {
524         JMenuItem b = (JMenuItem) c;
525         ButtonModel model = b.getModel();
526
527         // Dimension size = b.getSize();
528
int menuWidth = b.getWidth();
529         int menuHeight = b.getHeight();
530         Insets i = c.getInsets();
531     
532         resetRects();
533
534         viewRect.setBounds( 0, 0, menuWidth, menuHeight );
535
536         viewRect.x += i.left;
537         viewRect.y += i.top;
538         viewRect.width -= (i.right + viewRect.x);
539         viewRect.height -= (i.bottom + viewRect.y);
540
541
542         Font holdf = g.getFont();
543         Font f = c.getFont();
544         g.setFont( f );
545         FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
546         FontMetrics fmAccel = SwingUtilities2.getFontMetrics(
547                                    c, g, acceleratorFont);
548
549         // get Accelerator text
550
KeyStroke accelerator = b.getAccelerator();
551         String JavaDoc acceleratorText = "";
552         if (accelerator != null) {
553             int modifiers = accelerator.getModifiers();
554             if (modifiers > 0) {
555                 acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
556                 //acceleratorText += "-";
557
acceleratorText += acceleratorDelimiter;
558         }
559
560             int keyCode = accelerator.getKeyCode();
561             if (keyCode != 0) {
562                 acceleratorText += KeyEvent.getKeyText(keyCode);
563             } else {
564                 acceleratorText += accelerator.getKeyChar();
565             }
566         }
567         Icon icon = null;
568         /*
569          * in case .checkIconFactory is defined for this UI and the icon is
570          * compatible with it then the icon is handled by the checkIcon.
571          */

572         MenuItemCheckIconFactory iconFactory =
573             (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix()
574                 + ".checkIconFactory");
575         if (iconFactory == null
576                 || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) {
577            icon = b.getIcon();
578         }
579         // layout the text and icon
580
String JavaDoc text = layoutMenuItem(
581             fm, b.getText(), fmAccel, acceleratorText, icon,
582             checkIcon, arrowIcon,
583             b.getVerticalAlignment(), b.getHorizontalAlignment(),
584             b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
585             viewRect, iconRect, textRect, acceleratorRect,
586             checkIconRect, arrowIconRect,
587             b.getText() == null ? 0 : defaultTextIconGap,
588             defaultTextIconGap
589         );
590         // Paint background
591
paintBackground(g, b, background);
592
593         Color holdc = g.getColor();
594
595         // Paint the Check
596
if (checkIcon != null) {
597             if(model.isArmed() || (c instanceof JMenu && model.isSelected())) {
598                 g.setColor(foreground);
599             } else {
600                 g.setColor(holdc);
601             }
602             if( useCheckAndArrow() )
603         checkIcon.paintIcon(c, g, checkIconRect.x, checkIconRect.y);
604             g.setColor(holdc);
605         }
606
607         // Paint the Icon
608
if(icon != null ) {
609             if(!model.isEnabled()) {
610                 icon = (Icon) b.getDisabledIcon();
611             } else if(model.isPressed() && model.isArmed()) {
612                 icon = (Icon) b.getPressedIcon();
613                 if(icon == null) {
614                     // Use default icon
615
icon = (Icon) b.getIcon();
616                 }
617             } else {
618                 icon = (Icon) b.getIcon();
619             }
620               
621             if (icon!=null)
622                 icon.paintIcon(c, g, iconRect.x, iconRect.y);
623         }
624
625         // Draw the Text
626
if(text != null) {
627         View JavaDoc v = (View JavaDoc) c.getClientProperty(BasicHTML.propertyKey);
628         if (v != null) {
629         v.paint(g, textRect);
630         } else {
631         paintText(g, b, textRect, text);
632         }
633     }
634     
635         // Draw the Accelerator Text
636
if(acceleratorText != null && !acceleratorText.equals("")) {
637
638       //Get the maxAccWidth from the parent to calculate the offset.
639
int accOffset = 0;
640       Container parent = menuItem.getParent();
641       if (parent != null && parent instanceof JComponent) {
642         JComponent p = (JComponent) parent;
643         Integer JavaDoc maxValueInt = (Integer JavaDoc) p.getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH);
644         int maxValue = maxValueInt != null ?
645                 maxValueInt.intValue() : acceleratorRect.width;
646
647         //Calculate the offset, with which the accelerator texts will be drawn with.
648
accOffset = maxValue - acceleratorRect.width;
649       }
650       
651       g.setFont( acceleratorFont );
652             if(!model.isEnabled()) {
653                 // *** paint the acceleratorText disabled
654
if ( disabledForeground != null )
655           {
656                   g.setColor( disabledForeground );
657                   SwingUtilities2.drawString(b, g,acceleratorText,
658                                                 acceleratorRect.x - accOffset,
659                                                 acceleratorRect.y + fmAccel.getAscent());
660                 }
661                 else
662                 {
663                   g.setColor(b.getBackground().brighter());
664                   SwingUtilities2.drawString(b, g,acceleratorText,
665                                                 acceleratorRect.x - accOffset,
666                         acceleratorRect.y + fmAccel.getAscent());
667                   g.setColor(b.getBackground().darker());
668                   SwingUtilities2.drawString(b, g,acceleratorText,
669                                                 acceleratorRect.x - accOffset - 1,
670                         acceleratorRect.y + fmAccel.getAscent() - 1);
671                 }
672             } else {
673                 // *** paint the acceleratorText normally
674
if (model.isArmed()|| (c instanceof JMenu && model.isSelected())) {
675                     g.setColor( acceleratorSelectionForeground );
676                 } else {
677                     g.setColor( acceleratorForeground );
678                 }
679                 SwingUtilities2.drawString(b, g,acceleratorText,
680                                               acceleratorRect.x - accOffset,
681                                               acceleratorRect.y + fmAccel.getAscent());
682             }
683         }
684
685         // Paint the Arrow
686
if (arrowIcon != null) {
687             if(model.isArmed() || (c instanceof JMenu &&model.isSelected()))
688                 g.setColor(foreground);
689             if(useCheckAndArrow())
690                 arrowIcon.paintIcon(c, g, arrowIconRect.x, arrowIconRect.y);
691         }
692         g.setColor(holdc);
693         g.setFont(holdf);
694     }
695
696     /**
697      * Draws the background of the menu item.
698      *
699      * @param g the paint graphics
700      * @param menuItem menu item to be painted
701      * @param bgColor selection background color
702      * @since 1.4
703      */

704     protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
705     ButtonModel model = menuItem.getModel();
706         Color oldColor = g.getColor();
707         int menuWidth = menuItem.getWidth();
708         int menuHeight = menuItem.getHeight();
709
710         if(menuItem.isOpaque()) {
711             if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) {
712                 g.setColor(bgColor);
713                 g.fillRect(0,0, menuWidth, menuHeight);
714             } else {
715                 g.setColor(menuItem.getBackground());
716                 g.fillRect(0,0, menuWidth, menuHeight);
717             }
718             g.setColor(oldColor);
719         }
720         else if (model.isArmed() || (menuItem instanceof JMenu &&
721                                      model.isSelected())) {
722             g.setColor(bgColor);
723             g.fillRect(0,0, menuWidth, menuHeight);
724             g.setColor(oldColor);
725         }
726     }
727
728     /**
729      * Renders the text of the current menu item.
730      * <p>
731      * @param g graphics context
732      * @param menuItem menu item to render
733      * @param textRect bounding rectangle for rendering the text
734      * @param text string to render
735      * @since 1.4
736      */

737     protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String JavaDoc text) {
738     ButtonModel model = menuItem.getModel();
739     FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g);
740     int mnemIndex = menuItem.getDisplayedMnemonicIndex();
741
742     if(!model.isEnabled()) {
743         // *** paint the text disabled
744
if ( UIManager.get("MenuItem.disabledForeground") instanceof Color ) {
745         g.setColor( UIManager.getColor("MenuItem.disabledForeground") );
746         SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
747                           mnemIndex, textRect.x, textRect.y + fm.getAscent());
748         } else {
749         g.setColor(menuItem.getBackground().brighter());
750         SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text,
751                            mnemIndex, textRect.x, textRect.y + fm.getAscent());
752         g.setColor(menuItem.getBackground().darker());
753         SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
754                            mnemIndex, textRect.x - 1, textRect.y +
755                            fm.getAscent() - 1);
756         }
757     } else {
758         // *** paint the text normally
759
if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) {
760         g.setColor(selectionForeground); // Uses protected field.
761
}
762         SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
763                            mnemIndex, textRect.x, textRect.y + fm.getAscent());
764     }
765     }
766
767
768     /**
769      * Compute and return the location of the icons origin, the
770      * location of origin of the text baseline, and a possibly clipped
771      * version of the compound labels string. Locations are computed
772      * relative to the viewRect rectangle.
773      */

774
775     private String JavaDoc layoutMenuItem(
776         FontMetrics fm,
777         String JavaDoc text,
778         FontMetrics fmAccel,
779         String JavaDoc acceleratorText,
780         Icon icon,
781         Icon checkIcon,
782         Icon arrowIcon,
783         int verticalAlignment,
784         int horizontalAlignment,
785         int verticalTextPosition,
786         int horizontalTextPosition,
787         Rectangle viewRect,
788         Rectangle iconRect,
789         Rectangle textRect,
790         Rectangle acceleratorRect,
791         Rectangle checkIconRect,
792         Rectangle arrowIconRect,
793         int textIconGap,
794         int menuItemGap
795         )
796     {
797
798         SwingUtilities.layoutCompoundLabel(
799                             menuItem, fm, text, icon, verticalAlignment,
800                             horizontalAlignment, verticalTextPosition,
801                             horizontalTextPosition, viewRect, iconRect, textRect,
802                             textIconGap);
803
804         /* Initialize the acceelratorText bounds rectangle textRect. If a null
805          * or and empty String was specified we substitute "" here
806          * and use 0,0,0,0 for acceleratorTextRect.
807          */

808         if( (acceleratorText == null) || acceleratorText.equals("") ) {
809             acceleratorRect.width = acceleratorRect.height = 0;
810             acceleratorText = "";
811         }
812         else {
813             acceleratorRect.width = SwingUtilities2.stringWidth(
814                                          menuItem, fmAccel, acceleratorText);
815             acceleratorRect.height = fmAccel.getHeight();
816         }
817
818         /* Initialize the checkIcon bounds rectangle's width & height.
819          */

820
821     if( useCheckAndArrow()) {
822         if (checkIcon != null) {
823         checkIconRect.width = checkIcon.getIconWidth();
824         checkIconRect.height = checkIcon.getIconHeight();
825         }
826         else {
827         checkIconRect.width = checkIconRect.height = 0;
828         }
829         
830         /* Initialize the arrowIcon bounds rectangle width & height.
831          */

832         
833         if (arrowIcon != null) {
834         arrowIconRect.width = arrowIcon.getIconWidth();
835         arrowIconRect.height = arrowIcon.getIconHeight();
836         } else {
837         arrowIconRect.width = arrowIconRect.height = 0;
838         }
839         }
840
841         Rectangle labelRect = iconRect.union(textRect);
842
843         int checkIconOffset = menuItemGap;
844         Object JavaDoc checkIconOffsetObject =
845             UIManager.get(getPropertyPrefix() + ".checkIconOffset");
846         if (checkIconOffsetObject instanceof Integer JavaDoc) {
847             checkIconOffset = (Integer JavaDoc) checkIconOffsetObject;
848         }
849         if( BasicGraphicsUtils.isLeftToRight(menuItem) ) {
850             /* get minimum text offset. It is defined for LTR case only. */
851             int minimumTextOffset = 0;
852             Object JavaDoc minimumTextOffsetObject =
853                 UIManager.get(getPropertyPrefix()
854                     + ".minimumTextOffset");
855             if (minimumTextOffsetObject instanceof Integer JavaDoc) {
856                 minimumTextOffset = (Integer JavaDoc) minimumTextOffsetObject;
857             }
858             textRect.x += menuItemGap;
859             iconRect.x += menuItemGap;
860
861             // Position the Accelerator text rect
862
acceleratorRect.x = viewRect.x + viewRect.width - arrowIconRect.width
863                              - menuItemGap - acceleratorRect.width;
864             
865             // Position the Check and Arrow Icons
866
if (useCheckAndArrow()) {
867                 checkIconRect.x = viewRect.x + checkIconOffset;
868                 textRect.x += checkIconOffset + checkIconRect.width;
869                 textRect.x = Math.max(textRect.x, minimumTextOffset);
870                 iconRect.x += checkIconOffset + checkIconRect.width;
871                 arrowIconRect.x = viewRect.x + viewRect.width - menuItemGap
872                                   - arrowIconRect.width;
873             }
874         } else {
875             textRect.x -= menuItemGap;
876             iconRect.x -= menuItemGap;
877
878             // Position the Accelerator text rect
879
acceleratorRect.x = viewRect.x + arrowIconRect.width + menuItemGap;
880
881             // Position the Check and Arrow Icons
882
if (useCheckAndArrow()) {
883                 checkIconRect.x = viewRect.x + viewRect.width - menuItemGap
884                                   - checkIconRect.width;
885                 textRect.x -= menuItemGap + checkIconRect.width;
886                 iconRect.x -= menuItemGap + checkIconRect.width;
887                 arrowIconRect.x = viewRect.x + menuItemGap;
888             }
889         }
890
891         // Align the accelertor text and the check and arrow icons vertically
892
// with the center of the label rect.
893
acceleratorRect.y = labelRect.y + (labelRect.height/2) - (acceleratorRect.height/2);
894         if( useCheckAndArrow() ) {
895             arrowIconRect.y = labelRect.y + (labelRect.height/2) - (arrowIconRect.height/2);
896             checkIconRect.y = labelRect.y + (labelRect.height/2) - (checkIconRect.height/2);
897         }
898
899         /*
900         System.out.println("Layout: text="+menuItem.getText()+"\n\tv="
901                            +viewRect+"\n\tc="+checkIconRect+"\n\ti="
902                            +iconRect+"\n\tt="+textRect+"\n\tacc="
903                            +acceleratorRect+"\n\ta="+arrowIconRect+"\n");
904         */

905         
906         return text;
907     }
908
909     /*
910      * Returns false if the component is a JMenu and it is a top
911      * level menu (on the menubar).
912      */

913     private boolean useCheckAndArrow(){
914     boolean b = true;
915     if((menuItem instanceof JMenu) &&
916        (((JMenu)menuItem).isTopLevelMenu())) {
917         b = false;
918     }
919     return b;
920     }
921
922     public MenuElement[] getPath() {
923         MenuSelectionManager m = MenuSelectionManager.defaultManager();
924         MenuElement oldPath[] = m.getSelectedPath();
925         MenuElement newPath[];
926         int i = oldPath.length;
927         if (i == 0)
928             return new MenuElement[0];
929         Component parent = menuItem.getParent();
930         if (oldPath[i-1].getComponent() == parent) {
931             // The parent popup menu is the last so far
932
newPath = new MenuElement[i+1];
933             System.arraycopy(oldPath, 0, newPath, 0, i);
934             newPath[i] = menuItem;
935         } else {
936             // A sibling menuitem is the current selection
937
//
938
// This probably needs to handle 'exit submenu into
939
// a menu item. Search backwards along the current
940
// selection until you find the parent popup menu,
941
// then copy up to that and add yourself...
942
int j;
943             for (j = oldPath.length-1; j >= 0; j--) {
944                 if (oldPath[j].getComponent() == parent)
945                     break;
946             }
947             newPath = new MenuElement[j+2];
948             System.arraycopy(oldPath, 0, newPath, 0, j+1);
949             newPath[j+1] = menuItem;
950             /*
951             System.out.println("Sibling condition -- ");
952             System.out.println("Old array : ");
953             printMenuElementArray(oldPath, false);
954             System.out.println("New array : ");
955             printMenuElementArray(newPath, false);
956             */

957         }
958         return newPath;
959     }
960
961     void printMenuElementArray(MenuElement path[], boolean dumpStack) {
962         System.out.println("Path is(");
963         int i, j;
964         for(i=0,j=path.length; i<j ;i++){
965             for (int k=0; k<=i; k++)
966                 System.out.print(" ");
967             MenuElement me = (MenuElement) path[i];
968             if(me instanceof JMenuItem)
969                 System.out.println(((JMenuItem)me).getText() + ", ");
970             else if (me == null)
971                 System.out.println("NULL , ");
972             else
973                 System.out.println("" + me + ", ");
974         }
975         System.out.println(")");
976
977         if (dumpStack == true)
978             Thread.dumpStack();
979     }
980     protected class MouseInputHandler implements MouseInputListener {
981         // NOTE: This class exists only for backward compatability. All
982
// its functionality has been moved into Handler. If you need to add
983
// new functionality add it to the Handler, but make sure this
984
// class calls into the Handler.
985

986         public void mouseClicked(MouseEvent e) {
987             getHandler().mouseClicked(e);
988         }
989         public void mousePressed(MouseEvent e) {
990             getHandler().mousePressed(e);
991         }
992         public void mouseReleased(MouseEvent e) {
993             getHandler().mouseReleased(e);
994         }
995         public void mouseEntered(MouseEvent e) {
996             getHandler().mouseEntered(e);
997         }
998         public void mouseExited(MouseEvent e) {
999             getHandler().mouseExited(e);
1000        }
1001        public void mouseDragged(MouseEvent e) {
1002            getHandler().mouseDragged(e);
1003        }
1004        public void mouseMoved(MouseEvent e) {
1005            getHandler().mouseMoved(e);
1006        }
1007    }
1008
1009
1010    private static class Actions extends UIAction {
1011        private static final String JavaDoc CLICK = "doClick";
1012
1013        Actions(String JavaDoc key) {
1014            super(key);
1015        }
1016
1017    public void actionPerformed(ActionEvent e) {
1018        JMenuItem mi = (JMenuItem)e.getSource();
1019        MenuSelectionManager.defaultManager().clearSelectedPath();
1020        mi.doClick();
1021    }
1022    }
1023
1024    /**
1025     * Call this method when a menu item is to be activated.
1026     * This method handles some of the details of menu item activation
1027     * such as clearing the selected path and messaging the
1028     * JMenuItem's doClick() method.
1029     *
1030     * @param msm A MenuSelectionManager. The visual feedback and
1031     * internal bookkeeping tasks are delegated to
1032     * this MenuSelectionManager. If <code>null</code> is
1033     * passed as this argument, the
1034     * <code>MenuSelectionManager.defaultManager</code> is
1035     * used.
1036     * @see MenuSelectionManager
1037     * @see JMenuItem#doClick(int)
1038     * @since 1.4
1039     */

1040    protected void doClick(MenuSelectionManager msm) {
1041    // Auditory cue
1042
if (! isInternalFrameSystemMenu()) {
1043            BasicLookAndFeel.playSound(menuItem, getPropertyPrefix() +
1044                                       ".commandSound");
1045    }
1046    // Visual feedback
1047
if (msm == null) {
1048        msm = MenuSelectionManager.defaultManager();
1049    }
1050    msm.clearSelectedPath();
1051    menuItem.doClick(0);
1052    }
1053
1054    /**
1055     * This is to see if the menu item in question is part of the
1056     * system menu on an internal frame.
1057     * The Strings that are being checked can be found in
1058     * MetalInternalFrameTitlePaneUI.java,
1059     * WindowsInternalFrameTitlePaneUI.java, and
1060     * MotifInternalFrameTitlePaneUI.java.
1061     *
1062     * @since 1.4
1063     */

1064    private boolean isInternalFrameSystemMenu() {
1065    String JavaDoc actionCommand = menuItem.getActionCommand();
1066    if ((actionCommand == "Close") ||
1067        (actionCommand == "Minimize") ||
1068        (actionCommand == "Restore") ||
1069        (actionCommand == "Maximize")) {
1070      return true;
1071    } else {
1072      return false;
1073    }
1074    }
1075
1076
1077    // BasicMenuUI subclasses this.
1078
class Handler implements MenuDragMouseListener,
1079                          MouseInputListener, PropertyChangeListener JavaDoc {
1080        //
1081
// MouseInputListener
1082
//
1083
public void mouseClicked(MouseEvent e) {}
1084        public void mousePressed(MouseEvent e) {
1085        }
1086        public void mouseReleased(MouseEvent e) {
1087            MenuSelectionManager manager =
1088                MenuSelectionManager.defaultManager();
1089            Point p = e.getPoint();
1090            if(p.x >= 0 && p.x < menuItem.getWidth() &&
1091               p.y >= 0 && p.y < menuItem.getHeight()) {
1092        doClick(manager);
1093            } else {
1094                manager.processMouseEvent(e);
1095            }
1096        }
1097        public void mouseEntered(MouseEvent e) {
1098            MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1099        int modifiers = e.getModifiers();
1100        // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
1101
if ((modifiers & (InputEvent.BUTTON1_MASK |
1102                  InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) !=0 ) {
1103        MenuSelectionManager.defaultManager().processMouseEvent(e);
1104        } else {
1105        manager.setSelectedPath(getPath());
1106         }
1107        }
1108        public void mouseExited(MouseEvent e) {
1109            MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1110
1111        int modifiers = e.getModifiers();
1112        // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
1113
if ((modifiers & (InputEvent.BUTTON1_MASK |
1114                  InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) !=0 ) {
1115        MenuSelectionManager.defaultManager().processMouseEvent(e);
1116        } else {
1117
1118        MenuElement path[] = manager.getSelectedPath();
1119        if (path.length > 1 && path[path.length-1] == menuItem) {
1120            MenuElement newPath[] = new MenuElement[path.length-1];
1121            int i,c;
1122            for(i=0,c=path.length-1;i<c;i++)
1123            newPath[i] = path[i];
1124            manager.setSelectedPath(newPath);
1125        }
1126        }
1127        }
1128
1129        public void mouseDragged(MouseEvent e) {
1130            MenuSelectionManager.defaultManager().processMouseEvent(e);
1131        }
1132        public void mouseMoved(MouseEvent e) {
1133        }
1134
1135        //
1136
// MenuDragListener
1137
//
1138
public void menuDragMouseEntered(MenuDragMouseEvent e) {
1139            MenuSelectionManager manager = e.getMenuSelectionManager();
1140            MenuElement path[] = e.getPath();
1141            manager.setSelectedPath(path);
1142        }
1143        public void menuDragMouseDragged(MenuDragMouseEvent e) {
1144            MenuSelectionManager manager = e.getMenuSelectionManager();
1145            MenuElement path[] = e.getPath();
1146            manager.setSelectedPath(path);
1147        }
1148        public void menuDragMouseExited(MenuDragMouseEvent e) {}
1149        public void menuDragMouseReleased(MenuDragMouseEvent e) {
1150            MenuSelectionManager manager = e.getMenuSelectionManager();
1151            MenuElement path[] = e.getPath();
1152            Point p = e.getPoint();
1153            if(p.x >= 0 && p.x < menuItem.getWidth() &&
1154               p.y >= 0 && p.y < menuItem.getHeight()) {
1155        doClick(manager);
1156            } else {
1157                manager.clearSelectedPath();
1158            }
1159        }
1160
1161
1162        //
1163
// PropertyChangeListener
1164
//
1165
public void propertyChange(PropertyChangeEvent JavaDoc e) {
1166        String JavaDoc name = e.getPropertyName();
1167
1168        if (name == "labelFor" || name == "displayedMnemonic" ||
1169        name == "accelerator") {
1170        updateAcceleratorBinding();
1171        } else if (name == "text" || "font" == name ||
1172                       "foreground" == name) {
1173        // remove the old html view client property if one
1174
// existed, and install a new one if the text installed
1175
// into the JLabel is html source.
1176
JMenuItem lbl = ((JMenuItem) e.getSource());
1177        String JavaDoc text = lbl.getText();
1178        BasicHTML.updateRenderer(lbl, text);
1179        }
1180    }
1181    }
1182}
1183
Popular Tags