History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/plaf/basic/BasicMenuItemUI.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/plaf/basic/BasicMenuItemUI.java+972−0
@@ -0,0 +1,972 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing.plaf.basic;
27
28import java.awt.*;
29import java.awt.event.*;
30import java.beans.PropertyChangeEvent;
31import java.beans.PropertyChangeListener;
32
33import javax.swing.*;
34import javax.swing.event.*;
35import javax.swing.plaf.*;
36import javax.swing.text.View;
37
38import sun.swing.*;
39
40/**
41 * BasicMenuItem implementation
42 *
43 * @author Georges Saab
44 * @author David Karlton
45 * @author Arnaud Weber
46 * @author Fredrik Lagerblad
47 */
48public class BasicMenuItemUI extends MenuItemUI
49{
50 protected JMenuItem menuItem = null;
51 protected Color selectionBackground;
52 protected Color selectionForeground;
53 protected Color disabledForeground;
54 protected Color acceleratorForeground;
55 protected Color acceleratorSelectionForeground;
56
57 /**
58 * Accelerator delimiter string, such as {@code '+'} in {@code 'Ctrl+C'}.
59 * @since 1.7
60 */
61 protected String acceleratorDelimiter;
62
63 protected int defaultTextIconGap;
64 protected Font acceleratorFont;
65
66 protected MouseInputListener mouseInputListener;
67 protected MenuDragMouseListener menuDragMouseListener;
68 protected MenuKeyListener menuKeyListener;
69 /**
70 * <code>PropertyChangeListener</code> returned from
71 * <code>createPropertyChangeListener</code>. You should not
72 * need to access this field, rather if you want to customize the
73 * <code>PropertyChangeListener</code> override
74 * <code>createPropertyChangeListener</code>.
75 *
76 * @since 1.6
77 * @see #createPropertyChangeListener
78 */
79 protected PropertyChangeListener propertyChangeListener;
80 // BasicMenuUI also uses this.
81 Handler handler;
82
83 protected Icon arrowIcon = null;
84 protected Icon checkIcon = null;
85
86 protected boolean oldBorderPainted;
87
88 /* diagnostic aids -- should be false for production builds. */
89 private static final boolean TRACE = false; // trace creates and disposes
90
91 private static final boolean VERBOSE = false; // show reuse hits/misses
92 private static final boolean DEBUG = false; // show bad params, misc.
93
94 static void loadActionMap(LazyActionMap map) {
95 // NOTE: BasicMenuUI also calls into this method.
96 map.put(new Actions(Actions.CLICK));
97 BasicLookAndFeel.installAudioActionMap(map);
98 }
99
100 public static ComponentUI createUI(JComponent c) {
101 return new BasicMenuItemUI();
102 }
103
104 public void installUI(JComponent c) {
105 menuItem = (JMenuItem) c;
106
107 installDefaults();
108 installComponents(menuItem);
109 installListeners();
110 installKeyboardActions();
111 }
112
113
114 protected void installDefaults() {
115 String prefix = getPropertyPrefix();
116
117 acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
118 // use default if missing so that BasicMenuItemUI can be used in other
119 // LAFs like Nimbus
120 if (acceleratorFont == null) {
121 acceleratorFont = UIManager.getFont("MenuItem.font");
122 }
123
124 Object opaque = UIManager.get(getPropertyPrefix() + ".opaque");
125 if (opaque != null) {
126 LookAndFeel.installProperty(menuItem, "opaque", opaque);
127 }
128 else {
129 LookAndFeel.installProperty(menuItem, "opaque", Boolean.TRUE);
130 }
131 if(menuItem.getMargin() == null ||
132 (menuItem.getMargin() instanceof UIResource)) {
133 menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
134 }
135
136 LookAndFeel.installProperty(menuItem, "iconTextGap", Integer.valueOf(4));
137 defaultTextIconGap = menuItem.getIconTextGap();
138
139 LookAndFeel.installBorder(menuItem, prefix + ".border");
140 oldBorderPainted = menuItem.isBorderPainted();
141 LookAndFeel.installProperty(menuItem, "borderPainted",
142 UIManager.getBoolean(prefix + ".borderPainted"));
143 LookAndFeel.installColorsAndFont(menuItem,
144 prefix + ".background",
145 prefix + ".foreground",
146 prefix + ".font");
147
148 // MenuItem specific defaults
149 if (selectionBackground == null ||
150 selectionBackground instanceof UIResource) {
151 selectionBackground =
152 UIManager.getColor(prefix + ".selectionBackground");
153 }
154 if (selectionForeground == null ||
155 selectionForeground instanceof UIResource) {
156 selectionForeground =
157 UIManager.getColor(prefix + ".selectionForeground");
158 }
159 if (disabledForeground == null ||
160 disabledForeground instanceof UIResource) {
161 disabledForeground =
162 UIManager.getColor(prefix + ".disabledForeground");
163 }
164 if (acceleratorForeground == null ||
165 acceleratorForeground instanceof UIResource) {
166 acceleratorForeground =
167 UIManager.getColor(prefix + ".acceleratorForeground");
168 }
169 if (acceleratorSelectionForeground == null ||
170 acceleratorSelectionForeground instanceof UIResource) {
171 acceleratorSelectionForeground =
172 UIManager.getColor(prefix + ".acceleratorSelectionForeground");
173 }
174 // Get accelerator delimiter
175 acceleratorDelimiter =
176 UIManager.getString("MenuItem.acceleratorDelimiter");
177 if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; }
178 // Icons
179 if (arrowIcon == null ||
180 arrowIcon instanceof UIResource) {
181 arrowIcon = UIManager.getIcon(prefix + ".arrowIcon");
182 }
183 if (checkIcon == null ||
184 checkIcon instanceof UIResource) {
185 checkIcon = UIManager.getIcon(prefix + ".checkIcon");
186 //In case of column layout, .checkIconFactory is defined for this UI,
187 //the icon is compatible with it and useCheckAndArrow() is true,
188 //then the icon is handled by the checkIcon.
189 boolean isColumnLayout = MenuItemLayoutHelper.isColumnLayout(
190 BasicGraphicsUtils.isLeftToRight(menuItem), menuItem);
191 if (isColumnLayout) {
192 MenuItemCheckIconFactory iconFactory =
193 (MenuItemCheckIconFactory) UIManager.get(prefix
194 + ".checkIconFactory");
195 if (iconFactory != null
196 && MenuItemLayoutHelper.useCheckAndArrow(menuItem)
197 && iconFactory.isCompatible(checkIcon, prefix)) {
198 checkIcon = iconFactory.getIcon(menuItem);
199 }
200 }
201 }
202 }
203
204 /**
205 * @since 1.3
206 */
207 protected void installComponents(JMenuItem menuItem){
208 BasicHTML.updateRenderer(menuItem, menuItem.getText());
209 }
210
211 protected String getPropertyPrefix() {
212 return "MenuItem";
213 }
214
215 protected void installListeners() {
216 if ((mouseInputListener = createMouseInputListener(menuItem)) != null) {
217 menuItem.addMouseListener(mouseInputListener);
218 menuItem.addMouseMotionListener(mouseInputListener);
219 }
220 if ((menuDragMouseListener = createMenuDragMouseListener(menuItem)) != null) {
221 menuItem.addMenuDragMouseListener(menuDragMouseListener);
222 }
223 if ((menuKeyListener = createMenuKeyListener(menuItem)) != null) {
224 menuItem.addMenuKeyListener(menuKeyListener);
225 }
226 if ((propertyChangeListener = createPropertyChangeListener(menuItem)) != null) {
227 menuItem.addPropertyChangeListener(propertyChangeListener);
228 }
229 }
230
231 protected void installKeyboardActions() {
232 installLazyActionMap();
233 updateAcceleratorBinding();
234 }
235
236 void installLazyActionMap() {
237 LazyActionMap.installLazyActionMap(menuItem, BasicMenuItemUI.class,
238 getPropertyPrefix() + ".actionMap");
239 }
240
241 public void uninstallUI(JComponent c) {
242 menuItem = (JMenuItem)c;
243 uninstallDefaults();
244 uninstallComponents(menuItem);
245 uninstallListeners();
246 uninstallKeyboardActions();
247 MenuItemLayoutHelper.clearUsedParentClientProperties(menuItem);
248 menuItem = null;
249 }
250
251
252 protected void uninstallDefaults() {
253 LookAndFeel.uninstallBorder(menuItem);
254 LookAndFeel.installProperty(menuItem, "borderPainted", oldBorderPainted);
255 if (menuItem.getMargin() instanceof UIResource)
256 menuItem.setMargin(null);
257 if (arrowIcon instanceof UIResource)
258 arrowIcon = null;
259 if (checkIcon instanceof UIResource)
260 checkIcon = null;
261 }
262
263 /**
264 * @since 1.3
265 */
266 protected void uninstallComponents(JMenuItem menuItem){
267 BasicHTML.updateRenderer(menuItem, "");
268 }
269
270 protected void uninstallListeners() {
271 if (mouseInputListener != null) {
272 menuItem.removeMouseListener(mouseInputListener);
273 menuItem.removeMouseMotionListener(mouseInputListener);
274 }
275 if (menuDragMouseListener != null) {
276 menuItem.removeMenuDragMouseListener(menuDragMouseListener);
277 }
278 if (menuKeyListener != null) {
279 menuItem.removeMenuKeyListener(menuKeyListener);
280 }
281 if (propertyChangeListener != null) {
282 menuItem.removePropertyChangeListener(propertyChangeListener);
283 }
284
285 mouseInputListener = null;
286 menuDragMouseListener = null;
287 menuKeyListener = null;
288 propertyChangeListener = null;
289 handler = null;
290 }
291
292 protected void uninstallKeyboardActions() {
293 SwingUtilities.replaceUIActionMap(menuItem, null);
294 SwingUtilities.replaceUIInputMap(menuItem, JComponent.
295 WHEN_IN_FOCUSED_WINDOW, null);
296 }
297
298 protected MouseInputListener createMouseInputListener(JComponent c) {
299 return getHandler();
300 }
301
302 protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) {
303 return getHandler();
304 }
305
306 protected MenuKeyListener createMenuKeyListener(JComponent c) {
307 return null;
308 }
309
310 /**
311 * Creates a <code>PropertyChangeListener</code> which will be added to
312 * the menu item.
313 * If this method returns null then it will not be added to the menu item.
314 *
315 * @return an instance of a <code>PropertyChangeListener</code> or null
316 * @since 1.6
317 */
318 protected PropertyChangeListener
319 createPropertyChangeListener(JComponent c) {
320 return getHandler();
321 }
322
323 Handler getHandler() {
324 if (handler == null) {
325 handler = new Handler();
326 }
327 return handler;
328 }
329
330 InputMap createInputMap(int condition) {
331 if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
332 return new ComponentInputMapUIResource(menuItem);
333 }
334 return null;
335 }
336
337 void updateAcceleratorBinding() {
338 KeyStroke accelerator = menuItem.getAccelerator();
339 InputMap windowInputMap = SwingUtilities.getUIInputMap(
340 menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
341
342 if (windowInputMap != null) {
343 windowInputMap.clear();
344 }
345 if (accelerator != null) {
346 if (windowInputMap == null) {
347 windowInputMap = createInputMap(JComponent.
348 WHEN_IN_FOCUSED_WINDOW);
349 SwingUtilities.replaceUIInputMap(menuItem,
350 JComponent.WHEN_IN_FOCUSED_WINDOW, windowInputMap);
351 }
352 windowInputMap.put(accelerator, "doClick");
353 }
354 }
355
356 public Dimension getMinimumSize(JComponent c) {
357 Dimension d = null;
358 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
359 if (v != null) {
360 d = getPreferredSize(c);
361 d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
362 }
363 return d;
364 }
365
366 public Dimension getPreferredSize(JComponent c) {
367 return getPreferredMenuItemSize(c,
368 checkIcon,
369 arrowIcon,
370 defaultTextIconGap);
371 }
372
373 public Dimension getMaximumSize(JComponent c) {
374 Dimension d = null;
375 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
376 if (v != null) {
377 d = getPreferredSize(c);
378 d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
379 }
380 return d;
381 }
382
383 protected Dimension getPreferredMenuItemSize(JComponent c,
384 Icon checkIcon,
385 Icon arrowIcon,
386 int defaultTextIconGap) {
387
388 // The method also determines the preferred width of the
389 // parent popup menu (through DefaultMenuLayout class).
390 // The menu width equals to the maximal width
391 // among child menu items.
392
393 // Menu item width will be a sum of the widest check icon, label,
394 // arrow icon and accelerator text among neighbor menu items.
395 // For the latest menu item we will know the maximal widths exactly.
396 // It will be the widest menu item and it will determine
397 // the width of the parent popup menu.
398
399 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
400 // There is a conceptual problem: if user sets preferred size manually
401 // for a menu item, this method won't be called for it
402 // (see JComponent.getPreferredSize()),
403 // maximal widths won't be calculated, other menu items won't be able
404 // to take them into account and will be layouted in such a way,
405 // as there is no the item with manual preferred size.
406 // But after the first paint() method call, all maximal widths
407 // will be correctly calculated and layout of some menu items
408 // can be changed. For example, it can cause a shift of
409 // the icon and text when user points a menu item by mouse.
410
411 JMenuItem mi = (JMenuItem) c;
412 MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
413 arrowIcon, MenuItemLayoutHelper.createMaxRect(), defaultTextIconGap,
414 acceleratorDelimiter, BasicGraphicsUtils.isLeftToRight(mi),
415 mi.getFont(), acceleratorFont,
416 MenuItemLayoutHelper.useCheckAndArrow(menuItem),
417 getPropertyPrefix());
418
419 Dimension result = new Dimension();
420
421 // Calculate the result width
422 result.width = lh.getLeadingGap();
423 MenuItemLayoutHelper.addMaxWidth(lh.getCheckSize(),
424 lh.getAfterCheckIconGap(), result);
425 // Take into account mimimal text offset.
426 if ((!lh.isTopLevelMenu())
427 && (lh.getMinTextOffset() > 0)
428 && (result.width < lh.getMinTextOffset())) {
429 result.width = lh.getMinTextOffset();
430 }
431 MenuItemLayoutHelper.addMaxWidth(lh.getLabelSize(), lh.getGap(), result);
432 MenuItemLayoutHelper.addMaxWidth(lh.getAccSize(), lh.getGap(), result);
433 MenuItemLayoutHelper.addMaxWidth(lh.getArrowSize(), lh.getGap(), result);
434
435 // Calculate the result height
436 result.height = MenuItemLayoutHelper.max(lh.getCheckSize().getHeight(),
437 lh.getLabelSize().getHeight(), lh.getAccSize().getHeight(),
438 lh.getArrowSize().getHeight());
439
440 // Take into account menu item insets
441 Insets insets = lh.getMenuItem().getInsets();
442 if(insets != null) {
443 result.width += insets.left + insets.right;
444 result.height += insets.top + insets.bottom;
445 }
446
447 // if the width is even, bump it up one. This is critical
448 // for the focus dash line to draw properly
449 if(result.width%2 == 0) {
450 result.width++;
451 }
452
453 // if the height is even, bump it up one. This is critical
454 // for the text to center properly
455 if(result.height%2 == 0
456 && Boolean.TRUE !=
457 UIManager.get(getPropertyPrefix() + ".evenHeight")) {
458 result.height++;
459 }
460
461 return result;
462 }
463
464 /**
465 * We draw the background in paintMenuItem()
466 * so override update (which fills the background of opaque
467 * components by default) to just call paint().
468 *
469 */
470 public void update(Graphics g, JComponent c) {
471 paint(g, c);
472 }
473
474 public void paint(Graphics g, JComponent c) {
475 paintMenuItem(g, c, checkIcon, arrowIcon,
476 selectionBackground, selectionForeground,
477 defaultTextIconGap);
478 }
479
480 protected void paintMenuItem(Graphics g, JComponent c,
481 Icon checkIcon, Icon arrowIcon,
482 Color background, Color foreground,
483 int defaultTextIconGap) {
484 // Save original graphics font and color
485 Font holdf = g.getFont();
486 Color holdc = g.getColor();
487
488 JMenuItem mi = (JMenuItem) c;
489 g.setFont(mi.getFont());
490
491 Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
492 applyInsets(viewRect, mi.getInsets());
493
494 MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
495 arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter,
496 BasicGraphicsUtils.isLeftToRight(mi), mi.getFont(),
497 acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),
498 getPropertyPrefix());
499 MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
500
501 paintBackground(g, mi, background);
502 paintCheckIcon(g, lh, lr, holdc, foreground);
503 paintIcon(g, lh, lr, holdc);
504 paintText(g, lh, lr);
505 paintAccText(g, lh, lr);
506 paintArrowIcon(g, lh, lr, foreground);
507
508 // Restore original graphics font and color
509 g.setColor(holdc);
510 g.setFont(holdf);
511 }
512
513 private void paintIcon(Graphics g, MenuItemLayoutHelper lh,
514 MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
515 if (lh.getIcon() != null) {
516 Icon icon;
517 ButtonModel model = lh.getMenuItem().getModel();
518 if (!model.isEnabled()) {
519 icon = lh.getMenuItem().getDisabledIcon();
520 } else if (model.isPressed() && model.isArmed()) {
521 icon = lh.getMenuItem().getPressedIcon();
522 if (icon == null) {
523 // Use default icon
524 icon = lh.getMenuItem().getIcon();
525 }
526 } else {
527 icon = lh.getMenuItem().getIcon();
528 }
529
530 if (icon != null) {
531 icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x,
532 lr.getIconRect().y);
533 g.setColor(holdc);
534 }
535 }
536 }
537
538 private void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
539 MenuItemLayoutHelper.LayoutResult lr,
540 Color holdc, Color foreground) {
541 if (lh.getCheckIcon() != null) {
542 ButtonModel model = lh.getMenuItem().getModel();
543 if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
544 && model.isSelected())) {
545 g.setColor(foreground);
546 } else {
547 g.setColor(holdc);
548 }
549 if (lh.useCheckAndArrow()) {
550 lh.getCheckIcon().paintIcon(lh.getMenuItem(), g,
551 lr.getCheckRect().x, lr.getCheckRect().y);
552 }
553 g.setColor(holdc);
554 }
555 }
556
557 private void paintAccText(Graphics g, MenuItemLayoutHelper lh,
558 MenuItemLayoutHelper.LayoutResult lr) {
559 if (!lh.getAccText().equals("")) {
560 ButtonModel model = lh.getMenuItem().getModel();
561 g.setFont(lh.getAccFontMetrics().getFont());
562 if (!model.isEnabled()) {
563 // *** paint the accText disabled
564 if (disabledForeground != null) {
565 g.setColor(disabledForeground);
566 SwingUtilities2.drawString(lh.getMenuItem(), g,
567 lh.getAccText(), lr.getAccRect().x,
568 lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
569 } else {
570 g.setColor(lh.getMenuItem().getBackground().brighter());
571 SwingUtilities2.drawString(lh.getMenuItem(), g,
572 lh.getAccText(), lr.getAccRect().x,
573 lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
574 g.setColor(lh.getMenuItem().getBackground().darker());
575 SwingUtilities2.drawString(lh.getMenuItem(), g,
576 lh.getAccText(), lr.getAccRect().x - 1,
577 lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1);
578 }
579 } else {
580 // *** paint the accText normally
581 if (model.isArmed()
582 || (lh.getMenuItem() instanceof JMenu
583 && model.isSelected())) {
584 g.setColor(acceleratorSelectionForeground);
585 } else {
586 g.setColor(acceleratorForeground);
587 }
588 SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(),
589 lr.getAccRect().x, lr.getAccRect().y +
590 lh.getAccFontMetrics().getAscent());
591 }
592 }
593 }
594
595 private void paintText(Graphics g, MenuItemLayoutHelper lh,
596 MenuItemLayoutHelper.LayoutResult lr) {
597 if (!lh.getText().equals("")) {
598 if (lh.getHtmlView() != null) {
599 // Text is HTML
600 lh.getHtmlView().paint(g, lr.getTextRect());
601 } else {
602 // Text isn't HTML
603 paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText());
604 }
605 }
606 }
607
608 private void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
609 MenuItemLayoutHelper.LayoutResult lr,
610 Color foreground) {
611 if (lh.getArrowIcon() != null) {
612 ButtonModel model = lh.getMenuItem().getModel();
613 if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
614 && model.isSelected())) {
615 g.setColor(foreground);
616 }
617 if (lh.useCheckAndArrow()) {
618 lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
619 lr.getArrowRect().x, lr.getArrowRect().y);
620 }
621 }
622 }
623
624 private void applyInsets(Rectangle rect, Insets insets) {
625 if(insets != null) {
626 rect.x += insets.left;
627 rect.y += insets.top;
628 rect.width -= (insets.right + rect.x);
629 rect.height -= (insets.bottom + rect.y);
630 }
631 }
632
633 /**
634 * Draws the background of the menu item.
635 *
636 * @param g the paint graphics
637 * @param menuItem menu item to be painted
638 * @param bgColor selection background color
639 * @since 1.4
640 */
641 protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
642 ButtonModel model = menuItem.getModel();
643 Color oldColor = g.getColor();
644 int menuWidth = menuItem.getWidth();
645 int menuHeight = menuItem.getHeight();
646
647 if(menuItem.isOpaque()) {
648 if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) {
649 g.setColor(bgColor);
650 g.fillRect(0,0, menuWidth, menuHeight);
651 } else {
652 g.setColor(menuItem.getBackground());
653 g.fillRect(0,0, menuWidth, menuHeight);
654 }
655 g.setColor(oldColor);
656 }
657 else if (model.isArmed() || (menuItem instanceof JMenu &&
658 model.isSelected())) {
659 g.setColor(bgColor);
660 g.fillRect(0,0, menuWidth, menuHeight);
661 g.setColor(oldColor);
662 }
663 }
664
665 /**
666 * Renders the text of the current menu item.
667 * <p>
668 * @param g graphics context
669 * @param menuItem menu item to render
670 * @param textRect bounding rectangle for rendering the text
671 * @param text string to render
672 * @since 1.4
673 */
674 protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) {
675 ButtonModel model = menuItem.getModel();
676 FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g);
677 int mnemIndex = menuItem.getDisplayedMnemonicIndex();
678
679 if(!model.isEnabled()) {
680 // *** paint the text disabled
681 if ( UIManager.get("MenuItem.disabledForeground") instanceof Color ) {
682 g.setColor( UIManager.getColor("MenuItem.disabledForeground") );
683 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
684 mnemIndex, textRect.x, textRect.y + fm.getAscent());
685 } else {
686 g.setColor(menuItem.getBackground().brighter());
687 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text,
688 mnemIndex, textRect.x, textRect.y + fm.getAscent());
689 g.setColor(menuItem.getBackground().darker());
690 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
691 mnemIndex, textRect.x - 1, textRect.y +
692 fm.getAscent() - 1);
693 }
694 } else {
695 // *** paint the text normally
696 if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) {
697 g.setColor(selectionForeground); // Uses protected field.
698 }
699 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
700 mnemIndex, textRect.x, textRect.y + fm.getAscent());
701 }
702 }
703
704 public MenuElement[] getPath() {
705 MenuSelectionManager m = MenuSelectionManager.defaultManager();
706 MenuElement oldPath[] = m.getSelectedPath();
707 MenuElement newPath[];
708 int i = oldPath.length;
709 if (i == 0)
710 return new MenuElement[0];
711 Component parent = menuItem.getParent();
712 if (oldPath[i-1].getComponent() == parent) {
713 // The parent popup menu is the last so far
714 newPath = new MenuElement[i+1];
715 System.arraycopy(oldPath, 0, newPath, 0, i);
716 newPath[i] = menuItem;
717 } else {
718 // A sibling menuitem is the current selection
719 //
720 // This probably needs to handle 'exit submenu into
721 // a menu item. Search backwards along the current
722 // selection until you find the parent popup menu,
723 // then copy up to that and add yourself...
724 int j;
725 for (j = oldPath.length-1; j >= 0; j--) {
726 if (oldPath[j].getComponent() == parent)
727 break;
728 }
729 newPath = new MenuElement[j+2];
730 System.arraycopy(oldPath, 0, newPath, 0, j+1);
731 newPath[j+1] = menuItem;
732 /*
733 System.out.println("Sibling condition -- ");
734 System.out.println("Old array : ");
735 printMenuElementArray(oldPath, false);
736 System.out.println("New array : ");
737 printMenuElementArray(newPath, false);
738 */
739 }
740 return newPath;
741 }
742
743 void printMenuElementArray(MenuElement path[], boolean dumpStack) {
744 System.out.println("Path is(");
745 int i, j;
746 for(i=0,j=path.length; i<j ;i++){
747 for (int k=0; k<=i; k++)
748 System.out.print(" ");
749 MenuElement me = path[i];
750 if(me instanceof JMenuItem)
751 System.out.println(((JMenuItem)me).getText() + ", ");
752 else if (me == null)
753 System.out.println("NULL , ");
754 else
755 System.out.println("" + me + ", ");
756 }
757 System.out.println(")");
758
759 if (dumpStack == true)
760 Thread.dumpStack();
761 }
762 protected class MouseInputHandler implements MouseInputListener {
763 // NOTE: This class exists only for backward compatability. All
764 // its functionality has been moved into Handler. If you need to add
765 // new functionality add it to the Handler, but make sure this
766 // class calls into the Handler.
767
768 public void mouseClicked(MouseEvent e) {
769 getHandler().mouseClicked(e);
770 }
771 public void mousePressed(MouseEvent e) {
772 getHandler().mousePressed(e);
773 }
774 public void mouseReleased(MouseEvent e) {
775 getHandler().mouseReleased(e);
776 }
777 public void mouseEntered(MouseEvent e) {
778 getHandler().mouseEntered(e);
779 }
780 public void mouseExited(MouseEvent e) {
781 getHandler().mouseExited(e);
782 }
783 public void mouseDragged(MouseEvent e) {
784 getHandler().mouseDragged(e);
785 }
786 public void mouseMoved(MouseEvent e) {
787 getHandler().mouseMoved(e);
788 }
789 }
790
791
792 private static class Actions extends UIAction {
793 private static final String CLICK = "doClick";
794
795 Actions(String key) {
796 super(key);
797 }
798
799 public void actionPerformed(ActionEvent e) {
800 JMenuItem mi = (JMenuItem)e.getSource();
801 MenuSelectionManager.defaultManager().clearSelectedPath();
802 mi.doClick();
803 }
804 }
805
806 /**
807 * Call this method when a menu item is to be activated.
808 * This method handles some of the details of menu item activation
809 * such as clearing the selected path and messaging the
810 * JMenuItem's doClick() method.
811 *
812 * @param msm A MenuSelectionManager. The visual feedback and
813 * internal bookkeeping tasks are delegated to
814 * this MenuSelectionManager. If <code>null</code> is
815 * passed as this argument, the
816 * <code>MenuSelectionManager.defaultManager</code> is
817 * used.
818 * @see MenuSelectionManager
819 * @see JMenuItem#doClick(int)
820 * @since 1.4
821 */
822 protected void doClick(MenuSelectionManager msm) {
823 // Auditory cue
824 if (! isInternalFrameSystemMenu()) {
825 BasicLookAndFeel.playSound(menuItem, getPropertyPrefix() +
826 ".commandSound");
827 }
828 // Visual feedback
829 if (msm == null) {
830 msm = MenuSelectionManager.defaultManager();
831 }
832 msm.clearSelectedPath();
833 menuItem.doClick(0);
834 }
835
836 /**
837 * This is to see if the menu item in question is part of the
838 * system menu on an internal frame.
839 * The Strings that are being checked can be found in
840 * MetalInternalFrameTitlePaneUI.java,
841 * WindowsInternalFrameTitlePaneUI.java, and
842 * MotifInternalFrameTitlePaneUI.java.
843 *
844 * @since 1.4
845 */
846 private boolean isInternalFrameSystemMenu() {
847 String actionCommand = menuItem.getActionCommand();
848 if ((actionCommand == "Close") ||
849 (actionCommand == "Minimize") ||
850 (actionCommand == "Restore") ||
851 (actionCommand == "Maximize")) {
852 return true;
853 } else {
854 return false;
855 }
856 }
857
858
859 // BasicMenuUI subclasses this.
860 class Handler implements MenuDragMouseListener,
861 MouseInputListener, PropertyChangeListener {
862 //
863 // MouseInputListener
864 //
865 public void mouseClicked(MouseEvent e) {}
866 public void mousePressed(MouseEvent e) {
867 }
868 public void mouseReleased(MouseEvent e) {
869 if (!menuItem.isEnabled()) {
870 return;
871 }
872 MenuSelectionManager manager =
873 MenuSelectionManager.defaultManager();
874 Point p = e.getPoint();
875 if(p.x >= 0 && p.x < menuItem.getWidth() &&
876 p.y >= 0 && p.y < menuItem.getHeight()) {
877 doClick(manager);
878 } else {
879 manager.processMouseEvent(e);
880 }
881 }
882 public void mouseEntered(MouseEvent e) {
883 MenuSelectionManager manager = MenuSelectionManager.defaultManager();
884 int modifiers = e.getModifiers();
885 // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
886 if ((modifiers & (InputEvent.BUTTON1_MASK |
887 InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) !=0 ) {
888 MenuSelectionManager.defaultManager().processMouseEvent(e);
889 } else {
890 manager.setSelectedPath(getPath());
891 }
892 }
893 public void mouseExited(MouseEvent e) {
894 MenuSelectionManager manager = MenuSelectionManager.defaultManager();
895
896 int modifiers = e.getModifiers();
897 // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
898 if ((modifiers & (InputEvent.BUTTON1_MASK |
899 InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) !=0 ) {
900 MenuSelectionManager.defaultManager().processMouseEvent(e);
901 } else {
902
903 MenuElement path[] = manager.getSelectedPath();
904 if (path.length > 1 && path[path.length-1] == menuItem) {
905 MenuElement newPath[] = new MenuElement[path.length-1];
906 int i,c;
907 for(i=0,c=path.length-1;i<c;i++)
908 newPath[i] = path[i];
909 manager.setSelectedPath(newPath);
910 }
911 }
912 }
913
914 public void mouseDragged(MouseEvent e) {
915 MenuSelectionManager.defaultManager().processMouseEvent(e);
916 }
917 public void mouseMoved(MouseEvent e) {
918 }
919
920 //
921 // MenuDragListener
922 //
923 public void menuDragMouseEntered(MenuDragMouseEvent e) {
924 MenuSelectionManager manager = e.getMenuSelectionManager();
925 MenuElement path[] = e.getPath();
926 manager.setSelectedPath(path);
927 }
928 public void menuDragMouseDragged(MenuDragMouseEvent e) {
929 MenuSelectionManager manager = e.getMenuSelectionManager();
930 MenuElement path[] = e.getPath();
931 manager.setSelectedPath(path);
932 }
933 public void menuDragMouseExited(MenuDragMouseEvent e) {}
934 public void menuDragMouseReleased(MenuDragMouseEvent e) {
935 if (!menuItem.isEnabled()) {
936 return;
937 }
938 MenuSelectionManager manager = e.getMenuSelectionManager();
939 MenuElement path[] = e.getPath();
940 Point p = e.getPoint();
941 if (p.x >= 0 && p.x < menuItem.getWidth() &&
942 p.y >= 0 && p.y < menuItem.getHeight()) {
943 doClick(manager);
944 } else {
945 manager.clearSelectedPath();
946 }
947 }
948
949
950 //
951 // PropertyChangeListener
952 //
953 public void propertyChange(PropertyChangeEvent e) {
954 String name = e.getPropertyName();
955
956 if (name == "labelFor" || name == "displayedMnemonic" ||
957 name == "accelerator") {
958 updateAcceleratorBinding();
959 } else if (name == "text" || "font" == name ||
960 "foreground" == name) {
961 // remove the old html view client property if one
962 // existed, and install a new one if the text installed
963 // into the JLabel is html source.
964 JMenuItem lbl = ((JMenuItem) e.getSource());
965 String text = lbl.getText();
966 BasicHTML.updateRenderer(lbl, text);
967 } else if (name == "iconTextGap") {
968 defaultTextIconGap = ((Number)e.getNewValue()).intValue();
969 }
970 }
971 }
972}