KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > plaf > synth > SynthMenuItemUI


1 /*
2  * @(#)SynthMenuItemUI.java 1.22 06/12/14
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.plaf.synth;
8
9 import javax.swing.plaf.basic.BasicHTML JavaDoc;
10 import java.awt.*;
11 import java.awt.event.*;
12 import java.beans.PropertyChangeEvent JavaDoc;
13 import java.beans.PropertyChangeListener JavaDoc;
14
15 import javax.swing.*;
16 import javax.swing.event.*;
17 import javax.swing.border.*;
18 import javax.swing.plaf.*;
19 import javax.swing.plaf.basic.*;
20 import javax.swing.text.View JavaDoc;
21 import sun.swing.plaf.synth.*;
22 import com.sun.java.swing.SwingUtilities2;
23
24
25 /**
26  * Synth's MenuItemUI.
27  *
28  * @version 1.22, 12/14/06
29  * @author Georges Saab
30  * @author David Karlton
31  * @author Arnaud Weber
32  * @author Fredrik Lagerblad
33  */

34 class SynthMenuItemUI extends BasicMenuItemUI implements
35                                    PropertyChangeListener JavaDoc, SynthUI {
36     private SynthStyle JavaDoc style;
37     private SynthStyle JavaDoc accStyle;
38
39     private String JavaDoc acceleratorDelimiter;
40
41     public static ComponentUI createUI(JComponent c) {
42         return new SynthMenuItemUI JavaDoc();
43     }
44
45     //
46
// The next handful of static methods are used by both SynthMenuUI
47
// and SynthMenuItemUI. This is necessitated by SynthMenuUI not
48
// extending SynthMenuItemUI.
49
//
50
static Dimension getPreferredMenuItemSize(SynthContext JavaDoc context,
51            SynthContext JavaDoc accContext, boolean useCheckAndArrow, JComponent c,
52            Icon checkIcon, Icon arrowIcon, int defaultTextIconGap,
53            String JavaDoc acceleratorDelimiter) {
54         JMenuItem b = (JMenuItem) c;
55         Icon icon = (Icon) b.getIcon();
56         String JavaDoc text = b.getText();
57         KeyStroke accelerator = b.getAccelerator();
58         String JavaDoc acceleratorText = "";
59
60         if (accelerator != null) {
61             int modifiers = accelerator.getModifiers();
62             if (modifiers > 0) {
63                 acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
64                 acceleratorText += acceleratorDelimiter;
65           }
66             int keyCode = accelerator.getKeyCode();
67             if (keyCode != 0) {
68                 acceleratorText += KeyEvent.getKeyText(keyCode);
69             } else {
70                 acceleratorText += accelerator.getKeyChar();
71             }
72         }
73
74         Font font = context.getStyle().getFont(context);
75         FontMetrics fm = b.getFontMetrics(font);
76         FontMetrics fmAccel = b.getFontMetrics(accContext.getStyle().
77                                                getFont(accContext));
78
79         resetRects();
80         
81         layoutMenuItem(
82                   context, fm, accContext, text, fmAccel, acceleratorText,
83                   icon, checkIcon, arrowIcon, b.getVerticalAlignment(),
84                   b.getHorizontalAlignment(), b.getVerticalTextPosition(),
85                   b.getHorizontalTextPosition(), viewRect, iconRect, textRect,
86                   acceleratorRect, checkIconRect, arrowIconRect,
87                   text == null ? 0 : defaultTextIconGap, defaultTextIconGap,
88                   useCheckAndArrow);
89         // find the union of the icon and text rects
90
r.setBounds(textRect);
91         r = SwingUtilities.computeUnion(iconRect.x,
92                                         iconRect.y,
93                                         iconRect.width,
94                                         iconRect.height,
95                                         r);
96
97     // To make the accelerator texts appear in a column,
98
// find the widest MenuItem text and the widest accelerator text.
99

100     // Get the parent, which stores the information.
101
Container parent = b.getParent();
102
103         if (parent instanceof JPopupMenu) {
104             SynthPopupMenuUI JavaDoc popupUI = (SynthPopupMenuUI JavaDoc)SynthLookAndFeel.
105                              getUIOfType(((JPopupMenu)parent).getUI(),
106                                          SynthPopupMenuUI JavaDoc.class);
107
108             if (popupUI != null) {
109                 r.width = popupUI.adjustTextWidth(r.width);
110
111                 popupUI.adjustAcceleratorWidth(acceleratorRect.width);
112         
113                 r.width += popupUI.getMaxAcceleratorWidth();
114             }
115     }
116         else if (parent != null && !(b instanceof JMenu &&
117                                      ((JMenu)b).isTopLevelMenu())) {
118         r.width += acceleratorRect.width;
119         }
120     
121     if( useCheckAndArrow ) {
122         // Add in the checkIcon
123
r.width += checkIconRect.width;
124         r.width += defaultTextIconGap;
125
126         // Add in the arrowIcon
127
r.width += defaultTextIconGap;
128         r.width += arrowIconRect.width;
129         }
130
131     r.width += 2*defaultTextIconGap;
132
133         Insets insets = b.getInsets();
134         if(insets != null) {
135             r.width += insets.left + insets.right;
136             r.height += insets.top + insets.bottom;
137         }
138
139         // if the width is even, bump it up one. This is critical
140
// for the focus dash line to draw properly
141
if(r.width%2 == 0) {
142             r.width++;
143         }
144
145         // if the height is even, bump it up one. This is critical
146
// for the text to center properly
147
if(r.height%2 == 0) {
148             r.height++;
149         }
150     return r.getSize();
151     }
152
153     static void paint(SynthContext JavaDoc context, SynthContext JavaDoc accContext,
154                       Graphics g, Icon checkIcon, Icon arrowIcon,
155                       boolean useCheckAndArrow, String JavaDoc acceleratorDelimiter,
156                       int defaultTextIconGap) {
157         JComponent c = context.getComponent();
158         JMenuItem b = (JMenuItem)c;
159         ButtonModel model = b.getModel();
160         Insets i = b.getInsets();
161
162         resetRects();
163
164         viewRect.setBounds(0, 0, b.getWidth(), b.getHeight());
165
166         viewRect.x += i.left;
167         viewRect.y += i.top;
168         viewRect.width -= (i.right + viewRect.x);
169         viewRect.height -= (i.bottom + viewRect.y);
170
171         SynthStyle JavaDoc style = context.getStyle();
172         Font f = style.getFont(context);
173         g.setFont(f);
174         FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
175         FontMetrics accFM = SwingUtilities2.getFontMetrics(c, g,
176                                  accContext.getStyle().
177                                              getFont(accContext));
178
179         // get Accelerator text
180
KeyStroke accelerator = b.getAccelerator();
181         String JavaDoc acceleratorText = "";
182         if (accelerator != null) {
183             int modifiers = accelerator.getModifiers();
184             if (modifiers > 0) {
185                 acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
186                 acceleratorText += acceleratorDelimiter;
187         }
188
189             int keyCode = accelerator.getKeyCode();
190             if (keyCode != 0) {
191                 acceleratorText += KeyEvent.getKeyText(keyCode);
192             } else {
193                 acceleratorText += accelerator.getKeyChar();
194             }
195         }
196         
197         // layoutl the text and icon
198
String JavaDoc text = layoutMenuItem(context, fm, accContext,
199             b.getText(), accFM, acceleratorText, b.getIcon(),
200             checkIcon, arrowIcon,
201             b.getVerticalAlignment(), b.getHorizontalAlignment(),
202             b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
203             viewRect, iconRect, textRect, acceleratorRect,
204             checkIconRect, arrowIconRect,
205             b.getText() == null ? 0 : defaultTextIconGap,
206             defaultTextIconGap, useCheckAndArrow
207         );
208
209         // Paint the Check
210
if (checkIcon != null && useCheckAndArrow ) {
211             SynthIcon.paintIcon(checkIcon, context, g, checkIconRect.x,
212                     checkIconRect.y, checkIconRect.width, checkIconRect.height);
213         }
214
215         // Paint the Icon
216
if(b.getIcon() != null) {
217             Icon icon;
218             if(!model.isEnabled()) {
219                 icon = (Icon) b.getDisabledIcon();
220             } else if(model.isPressed() && model.isArmed()) {
221                 icon = (Icon) b.getPressedIcon();
222                 if(icon == null) {
223                     // Use default icon
224
icon = (Icon) b.getIcon();
225                 }
226             } else {
227                 icon = (Icon) b.getIcon();
228             }
229               
230             if (icon!=null) {
231                 SynthIcon.paintIcon(icon, context, g, iconRect.x,
232                     iconRect.y, iconRect.width, iconRect.height);
233             }
234         }
235
236         // Draw the Text
237
if(text != null) {
238         View JavaDoc v = (View JavaDoc) c.getClientProperty(BasicHTML.propertyKey);
239         if (v != null) {
240         v.paint(g, textRect);
241         } else {
242                 g.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
243                 g.setFont(style.getFont(context));
244                 style.getGraphicsUtils(context).paintText(context, g, text,
245                         textRect.x, textRect.y, b.getDisplayedMnemonicIndex());
246         }
247     }
248     
249         // Draw the Accelerator Text
250
if(acceleratorText != null && !acceleratorText.equals("")) {
251             // Get the maxAccWidth from the parent to calculate the offset.
252
int accOffset = 0;
253             Container parent = b.getParent();
254             if (parent != null && parent instanceof JPopupMenu) {
255                 SynthPopupMenuUI JavaDoc popupUI = (SynthPopupMenuUI JavaDoc)
256                                        ((JPopupMenu)parent).getUI();
257                 if (popupUI != null) {
258                     // Calculate the offset, with which the accelerator texts
259
// will be drawn with.
260
int max = popupUI.getMaxAcceleratorWidth();
261                     if (max > 0) {
262                         accOffset = max - acceleratorRect.width;
263                     }
264                 }
265             }
266
267             SynthStyle JavaDoc accStyle = accContext.getStyle();
268
269             g.setColor(accStyle.getColor(accContext,
270                                          ColorType.TEXT_FOREGROUND));
271             g.setFont(accStyle.getFont(accContext));
272             accStyle.getGraphicsUtils(accContext).paintText(
273                      accContext, g, acceleratorText, acceleratorRect.x -
274                      accOffset, acceleratorRect.y, -1);
275         }
276
277         // Paint the Arrow
278
if (arrowIcon != null && useCheckAndArrow) {
279             SynthIcon.paintIcon(arrowIcon, context, g, arrowIconRect.x,
280                     arrowIconRect.y, arrowIconRect.width, arrowIconRect.height);
281         }
282     }
283
284     /**
285      * Compute and return the location of the icons origin, the
286      * location of origin of the text baseline, and a possibly clipped
287      * version of the compound labels string. Locations are computed
288      * relative to the viewRect rectangle.
289      */

290
291     private static String JavaDoc layoutMenuItem(
292         SynthContext JavaDoc context,
293         FontMetrics fm,
294         SynthContext JavaDoc accContext,
295         String JavaDoc text,
296         FontMetrics fmAccel,
297         String JavaDoc acceleratorText,
298         Icon icon,
299         Icon checkIcon,
300         Icon arrowIcon,
301         int verticalAlignment,
302         int horizontalAlignment,
303         int verticalTextPosition,
304         int horizontalTextPosition,
305         Rectangle viewRect,
306         Rectangle iconRect,
307         Rectangle textRect,
308         Rectangle acceleratorRect,
309         Rectangle checkIconRect,
310         Rectangle arrowIconRect,
311         int textIconGap,
312         int menuItemGap, boolean useCheckAndArrow
313         )
314     {
315
316         context.getStyle().getGraphicsUtils(context).layoutText(
317                 context, fm, text, icon,horizontalAlignment, verticalAlignment,
318                 horizontalTextPosition, verticalTextPosition, viewRect,
319                 iconRect, textRect, textIconGap);
320
321         /* Initialize the acceelratorText bounds rectangle textRect. If a null
322          * or and empty String was specified we substitute "" here
323          * and use 0,0,0,0 for acceleratorTextRect.
324          */

325         if( (acceleratorText == null) || acceleratorText.equals("") ) {
326             acceleratorRect.width = acceleratorRect.height = 0;
327             acceleratorText = "";
328         }
329         else {
330             SynthStyle JavaDoc style = accContext.getStyle();
331             acceleratorRect.width = style.getGraphicsUtils(accContext).
332                     computeStringWidth(accContext, fmAccel.getFont(), fmAccel,
333                                        acceleratorText);
334             acceleratorRect.height = fmAccel.getHeight();
335         }
336
337         /* Initialize the checkIcon bounds rectangle's width & height.
338          */

339
340     if( useCheckAndArrow) {
341         if (checkIcon != null) {
342         checkIconRect.width = SynthIcon.getIconWidth(checkIcon,
343                                                              context);
344         checkIconRect.height = SynthIcon.getIconHeight(checkIcon,
345                                                                context);
346         }
347         else {
348         checkIconRect.width = checkIconRect.height = 0;
349         }
350         
351         /* Initialize the arrowIcon bounds rectangle width & height.
352          */

353         
354         if (arrowIcon != null) {
355         arrowIconRect.width = SynthIcon.getIconWidth(arrowIcon,
356                                                              context);
357         arrowIconRect.height = SynthIcon.getIconHeight(arrowIcon,
358                                                                context);
359         } else {
360         arrowIconRect.width = arrowIconRect.height = 0;
361         }
362         }
363
364         Rectangle labelRect = iconRect.union(textRect);
365         if( SynthLookAndFeel.isLeftToRight(context.getComponent()) ) {
366             textRect.x += menuItemGap;
367             iconRect.x += menuItemGap;
368
369             // Position the Accelerator text rect
370
acceleratorRect.x = viewRect.x + viewRect.width -
371                 arrowIconRect.width - menuItemGap - acceleratorRect.width;
372             
373             // Position the Check and Arrow Icons
374
if (useCheckAndArrow) {
375                 checkIconRect.x = viewRect.x + menuItemGap;
376                 textRect.x += menuItemGap + checkIconRect.width;
377                 iconRect.x += menuItemGap + checkIconRect.width;
378                 arrowIconRect.x = viewRect.x + viewRect.width - menuItemGap
379                                   - arrowIconRect.width;
380             }
381         } else {
382             textRect.x -= menuItemGap;
383             iconRect.x -= menuItemGap;
384
385             // Position the Accelerator text rect
386
acceleratorRect.x = viewRect.x + arrowIconRect.width + menuItemGap;
387
388             // Position the Check and Arrow Icons
389
if (useCheckAndArrow) {
390                 checkIconRect.x = viewRect.x + viewRect.width - menuItemGap
391                                   - checkIconRect.width;
392                 textRect.x -= menuItemGap + checkIconRect.width;
393                 iconRect.x -= menuItemGap + checkIconRect.width;
394                 arrowIconRect.x = viewRect.x + menuItemGap;
395             }
396         }
397
398         // Align the accelertor text and the check and arrow icons vertically
399
// with the center of the label rect.
400
acceleratorRect.y = labelRect.y + (labelRect.height/2) - (acceleratorRect.height/2);
401         if( useCheckAndArrow ) {
402             arrowIconRect.y = labelRect.y + (labelRect.height/2) - (arrowIconRect.height/2);
403             checkIconRect.y = labelRect.y + (labelRect.height/2) - (checkIconRect.height/2);
404         }
405
406         return text;
407     }
408
409     // these rects are used for painting and preferredsize calculations.
410
// they used to be regenerated constantly. Now they are reused.
411
static Rectangle iconRect = new Rectangle();
412     static Rectangle textRect = new Rectangle();
413     static Rectangle acceleratorRect = new Rectangle();
414     static Rectangle checkIconRect = new Rectangle();
415     static Rectangle arrowIconRect = new Rectangle();
416     static Rectangle viewRect = new Rectangle(Short.MAX_VALUE,Short.MAX_VALUE);
417     static Rectangle r = new Rectangle();
418
419     private static void resetRects() {
420         iconRect.setBounds(0, 0, 0, 0);
421         textRect.setBounds(0, 0, 0, 0);
422         acceleratorRect.setBounds(0, 0, 0, 0);
423         checkIconRect.setBounds(0, 0, 0, 0);
424         arrowIconRect.setBounds(0, 0, 0, 0);
425         viewRect.setBounds(0,0,Short.MAX_VALUE, Short.MAX_VALUE);
426         r.setBounds(0, 0, 0, 0);
427     }
428
429
430     protected void installDefaults() {
431         updateStyle(menuItem);
432     }
433
434     protected void installListeners() {
435         super.installListeners();
436         menuItem.addPropertyChangeListener(this);
437     }
438
439     private void updateStyle(JMenuItem mi) {
440         SynthContext JavaDoc context = getContext(mi, ENABLED);
441         SynthStyle JavaDoc oldStyle = style;
442
443         style = SynthLookAndFeel.updateStyle(context, this);
444         if (oldStyle != style) {
445             String JavaDoc prefix = getPropertyPrefix();
446             defaultTextIconGap = style.getInt(
447                            context, prefix + ".textIconGap", 4);
448             if (menuItem.getMargin() == null ||
449                          (menuItem.getMargin() instanceof UIResource)) {
450                 Insets insets = (Insets)style.get(context, prefix + ".margin");
451
452                 if (insets == null) {
453                     // Some places assume margins are non-null.
454
insets = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
455                 }
456                 menuItem.setMargin(insets);
457             }
458             acceleratorDelimiter = style.getString(context, prefix +
459                                             ".acceleratorDelimiter", "+");
460
461             arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
462
463             checkIcon = style.getIcon(context, prefix + ".checkIcon");
464             if (oldStyle != null) {
465                 uninstallKeyboardActions();
466                 installKeyboardActions();
467             }
468         }
469         context.dispose();
470
471         SynthContext JavaDoc accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
472                                              ENABLED);
473
474         accStyle = SynthLookAndFeel.updateStyle(accContext, this);
475         accContext.dispose();
476     }
477
478     protected void uninstallDefaults() {
479         SynthContext JavaDoc context = getContext(menuItem, ENABLED);
480         style.uninstallDefaults(context);
481         context.dispose();
482         style = null;
483
484         SynthContext JavaDoc accContext = getContext(menuItem,
485                                      Region.MENU_ITEM_ACCELERATOR, ENABLED);
486         accStyle.uninstallDefaults(accContext);
487         accContext.dispose();
488         accStyle = null;
489
490         super.uninstallDefaults();
491     }
492
493     protected void uninstallListeners() {
494         super.uninstallListeners();
495         menuItem.removePropertyChangeListener(this);
496     }
497
498     public SynthContext JavaDoc getContext(JComponent c) {
499         return getContext(c, getComponentState(c));
500     }
501
502     SynthContext JavaDoc getContext(JComponent c, int state) {
503         return SynthContext.getContext(SynthContext JavaDoc.class, c,
504                     SynthLookAndFeel.getRegion(c), style, state);
505     }
506
507     public SynthContext JavaDoc getContext(JComponent c, Region JavaDoc region) {
508         return getContext(c, region, getComponentState(c, region));
509     }
510
511     private SynthContext JavaDoc getContext(JComponent c, Region JavaDoc region, int state) {
512         return SynthContext.getContext(SynthContext JavaDoc.class, c,
513                                        region, accStyle, state);
514     }
515
516     private Region JavaDoc getRegion(JComponent c) {
517         return SynthLookAndFeel.getRegion(c);
518     }
519
520     private int getComponentState(JComponent c) {
521         int state;
522
523         if (!c.isEnabled()) {
524             state = DISABLED;
525         } else {
526             if (menuItem.isArmed()) {
527                 state = MOUSE_OVER;
528             }
529             else {
530                 state = SynthLookAndFeel.getComponentState(c);
531             }
532         }
533         if (menuItem.isSelected()) {
534             state |= SELECTED;
535         }
536         return state;
537     }
538
539     private int getComponentState(JComponent c, Region JavaDoc region) {
540         return getComponentState(c);
541     }
542
543     protected Dimension getPreferredMenuItemSize(JComponent c,
544                                                      Icon checkIcon,
545                                                      Icon arrowIcon,
546                                                      int defaultTextIconGap) {
547         SynthContext JavaDoc context = getContext(c);
548         SynthContext JavaDoc accContext = getContext(c, Region.MENU_ITEM_ACCELERATOR);
549         Dimension value = getPreferredMenuItemSize(context, accContext,
550                   true, c, checkIcon, arrowIcon, defaultTextIconGap,
551                   acceleratorDelimiter);
552         context.dispose();
553         accContext.dispose();
554         return value;
555     }
556
557
558     public void update(Graphics g, JComponent c) {
559         SynthContext JavaDoc context = getContext(c);
560
561         SynthLookAndFeel.update(context, g);
562         paintBackground(context, g, c);
563         paint(context, g);
564         context.dispose();
565     }
566
567     public void paint(Graphics g, JComponent c) {
568         SynthContext JavaDoc context = getContext(c);
569
570         paint(context, g);
571         context.dispose();
572     }
573
574     protected void paint(SynthContext JavaDoc context, Graphics g) {
575         SynthContext JavaDoc accContext = getContext(menuItem,
576                                              Region.MENU_ITEM_ACCELERATOR);
577
578         String JavaDoc prefix = getPropertyPrefix();
579         paint(context, accContext, g,
580                 style.getIcon(getContext(context.getComponent()),
581                     prefix + ".checkIcon"),
582                 style.getIcon(getContext(context.getComponent()),
583                     prefix + ".arrowIcon"),
584                 true, acceleratorDelimiter, defaultTextIconGap);
585         accContext.dispose();
586     }
587
588     void paintBackground(SynthContext JavaDoc context, Graphics g, JComponent c) {
589         context.getPainter().paintMenuItemBackground(context, g, 0, 0,
590                                                 c.getWidth(), c.getHeight());
591     }
592
593     public void paintBorder(SynthContext JavaDoc context, Graphics g, int x,
594                             int y, int w, int h) {
595         context.getPainter().paintMenuItemBorder(context, g, x, y, w, h);
596     }
597
598     public void propertyChange(PropertyChangeEvent JavaDoc e) {
599         if (SynthLookAndFeel.shouldUpdateStyle(e)) {
600             updateStyle((JMenuItem)e.getSource());
601         }
602     }
603 }
604
Popular Tags