0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.swing.plaf.basic;
0027
0028 import sun.swing.MenuItemCheckIconFactory;
0029 import sun.swing.SwingUtilities2;
0030 import static sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET;
0031 import java.awt.*;
0032 import java.awt.event.*;
0033 import java.beans.PropertyChangeEvent;
0034 import java.beans.PropertyChangeListener;
0035
0036 import javax.swing.*;
0037 import javax.swing.event.*;
0038 import javax.swing.border.*;
0039 import javax.swing.plaf.*;
0040 import javax.swing.text.View;
0041
0042 import sun.swing.UIAction;
0043
0044 /**
0045 * BasicMenuItem implementation
0046 *
0047 * @version 1.149 06/07/07
0048 * @author Georges Saab
0049 * @author David Karlton
0050 * @author Arnaud Weber
0051 * @author Fredrik Lagerblad
0052 */
0053 public class BasicMenuItemUI extends MenuItemUI {
0054 protected JMenuItem menuItem = null;
0055 protected Color selectionBackground;
0056 protected Color selectionForeground;
0057 protected Color disabledForeground;
0058 protected Color acceleratorForeground;
0059 protected Color acceleratorSelectionForeground;
0060 private String acceleratorDelimiter;
0061
0062 protected int defaultTextIconGap;
0063 protected Font acceleratorFont;
0064
0065 protected MouseInputListener mouseInputListener;
0066 protected MenuDragMouseListener menuDragMouseListener;
0067 protected MenuKeyListener menuKeyListener;
0068 /**
0069 * <code>PropertyChangeListener</code> returned from
0070 * <code>createPropertyChangeListener</code>. You should not
0071 * need to access this field, rather if you want to customize the
0072 * <code>PropertyChangeListener</code> override
0073 * <code>createPropertyChangeListener</code>.
0074 *
0075 * @since 1.6
0076 * @see #createPropertyChangeListener
0077 */
0078 protected PropertyChangeListener propertyChangeListener;
0079 // BasicMenuUI also uses this.
0080 Handler handler;
0081
0082 protected Icon arrowIcon = null;
0083 protected Icon checkIcon = null;
0084
0085 protected boolean oldBorderPainted;
0086
0087 /* diagnostic aids -- should be false for production builds. */
0088 private static final boolean TRACE = false; // trace creates and disposes
0089
0090 private static final boolean VERBOSE = false; // show reuse hits/misses
0091 private static final boolean DEBUG = false; // show bad params, misc.
0092
0093 /* Client Property keys for icon, text and accelerator widths */
0094 static final String MAX_ARROW_ICON_WIDTH = "maxArrowIconWidth";
0095 static final String MAX_CHECK_ICON_WIDTH = "maxCheckIconWidth";
0096 static final String MAX_ICON_WIDTH = "maxIconWidth";
0097 static final String MAX_TEXT_WIDTH = "maxTextWidth";
0098 static final String MAX_ACC_WIDTH = "maxAccWidth";
0099
0100 /* Client Property key for the icon offset */
0101 static final StringBuffer MAX_ICON_OFFSET = new StringBuffer(
0102 "maxIconOffset");
0103
0104 static void loadActionMap(LazyActionMap map) {
0105 // NOTE: BasicMenuUI also calls into this method.
0106 map.put(new Actions(Actions.CLICK));
0107 BasicLookAndFeel.installAudioActionMap(map);
0108 }
0109
0110 public static ComponentUI createUI(JComponent c) {
0111 return new BasicMenuItemUI();
0112 }
0113
0114 public void installUI(JComponent c) {
0115 menuItem = (JMenuItem) c;
0116
0117 installDefaults();
0118 installComponents(menuItem);
0119 installListeners();
0120 installKeyboardActions();
0121 }
0122
0123 protected void installDefaults() {
0124 String prefix = getPropertyPrefix();
0125
0126 acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
0127
0128 Object opaque = UIManager.get(getPropertyPrefix() + ".opaque");
0129 if (opaque != null) {
0130 LookAndFeel.installProperty(menuItem, "opaque", opaque);
0131 } else {
0132 LookAndFeel.installProperty(menuItem, "opaque",
0133 Boolean.TRUE);
0134 }
0135 if (menuItem.getMargin() == null
0136 || (menuItem.getMargin() instanceof UIResource)) {
0137 menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
0138 }
0139
0140 LookAndFeel.installProperty(menuItem, "iconTextGap",
0141 new Integer(4));
0142 defaultTextIconGap = menuItem.getIconTextGap();
0143
0144 LookAndFeel.installBorder(menuItem, prefix + ".border");
0145 oldBorderPainted = menuItem.isBorderPainted();
0146 LookAndFeel.installProperty(menuItem, "borderPainted",
0147 UIManager.get(prefix + ".borderPainted"));
0148 LookAndFeel.installColorsAndFont(menuItem, prefix
0149 + ".background", prefix + ".foreground", prefix
0150 + ".font");
0151
0152 // MenuItem specific defaults
0153 if (selectionBackground == null
0154 || selectionBackground instanceof UIResource) {
0155 selectionBackground = UIManager.getColor(prefix
0156 + ".selectionBackground");
0157 }
0158 if (selectionForeground == null
0159 || selectionForeground instanceof UIResource) {
0160 selectionForeground = UIManager.getColor(prefix
0161 + ".selectionForeground");
0162 }
0163 if (disabledForeground == null
0164 || disabledForeground instanceof UIResource) {
0165 disabledForeground = UIManager.getColor(prefix
0166 + ".disabledForeground");
0167 }
0168 if (acceleratorForeground == null
0169 || acceleratorForeground instanceof UIResource) {
0170 acceleratorForeground = UIManager.getColor(prefix
0171 + ".acceleratorForeground");
0172 }
0173 if (acceleratorSelectionForeground == null
0174 || acceleratorSelectionForeground instanceof UIResource) {
0175 acceleratorSelectionForeground = UIManager.getColor(prefix
0176 + ".acceleratorSelectionForeground");
0177 }
0178 // Get accelerator delimiter
0179 acceleratorDelimiter = UIManager
0180 .getString("MenuItem.acceleratorDelimiter");
0181 if (acceleratorDelimiter == null) {
0182 acceleratorDelimiter = "+";
0183 }
0184 // Icons
0185 if (arrowIcon == null || arrowIcon instanceof UIResource) {
0186 arrowIcon = UIManager.getIcon(prefix + ".arrowIcon");
0187 }
0188 if (checkIcon == null || checkIcon instanceof UIResource) {
0189 checkIcon = UIManager.getIcon(prefix + ".checkIcon");
0190 MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager
0191 .get(prefix + ".checkIconFactory");
0192 if (iconFactory != null
0193 && iconFactory.isCompatible(checkIcon, prefix)) {
0194 checkIcon = iconFactory.getIcon(menuItem);
0195 }
0196 }
0197 }
0198
0199 /**
0200 * @since 1.3
0201 */
0202 protected void installComponents(JMenuItem menuItem) {
0203 BasicHTML.updateRenderer(menuItem, menuItem.getText());
0204 }
0205
0206 protected String getPropertyPrefix() {
0207 return "MenuItem";
0208 }
0209
0210 protected void installListeners() {
0211 if ((mouseInputListener = createMouseInputListener(menuItem)) != null) {
0212 menuItem.addMouseListener(mouseInputListener);
0213 menuItem.addMouseMotionListener(mouseInputListener);
0214 }
0215 if ((menuDragMouseListener = createMenuDragMouseListener(menuItem)) != null) {
0216 menuItem.addMenuDragMouseListener(menuDragMouseListener);
0217 }
0218 if ((menuKeyListener = createMenuKeyListener(menuItem)) != null) {
0219 menuItem.addMenuKeyListener(menuKeyListener);
0220 }
0221 if ((propertyChangeListener = createPropertyChangeListener(menuItem)) != null) {
0222 menuItem.addPropertyChangeListener(propertyChangeListener);
0223 }
0224 }
0225
0226 protected void installKeyboardActions() {
0227 installLazyActionMap();
0228 updateAcceleratorBinding();
0229 }
0230
0231 void installLazyActionMap() {
0232 LazyActionMap.installLazyActionMap(menuItem,
0233 BasicMenuItemUI.class, getPropertyPrefix()
0234 + ".actionMap");
0235 }
0236
0237 public void uninstallUI(JComponent c) {
0238 menuItem = (JMenuItem) c;
0239 uninstallDefaults();
0240 uninstallComponents(menuItem);
0241 uninstallListeners();
0242 uninstallKeyboardActions();
0243
0244 //Remove the textWidth and accWidth values from the parent's Client Properties.
0245 JComponent p = getMenuItemParent(menuItem);
0246 if (p != null) {
0247 p.putClientProperty(BasicMenuItemUI.MAX_CHECK_ICON_WIDTH,
0248 null);
0249 p.putClientProperty(BasicMenuItemUI.MAX_ARROW_ICON_WIDTH,
0250 null);
0251 p.putClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH, null);
0252 p.putClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH, null);
0253 p.putClientProperty(BasicMenuItemUI.MAX_ICON_WIDTH, null);
0254 p.putClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET, null);
0255 p.putClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET, null);
0256 }
0257
0258 menuItem = null;
0259 }
0260
0261 protected void uninstallDefaults() {
0262 LookAndFeel.uninstallBorder(menuItem);
0263 LookAndFeel.installProperty(menuItem, "borderPainted",
0264 oldBorderPainted);
0265 if (menuItem.getMargin() instanceof UIResource)
0266 menuItem.setMargin(null);
0267 if (arrowIcon instanceof UIResource)
0268 arrowIcon = null;
0269 if (checkIcon instanceof UIResource)
0270 checkIcon = null;
0271 }
0272
0273 /**
0274 * @since 1.3
0275 */
0276 protected void uninstallComponents(JMenuItem menuItem) {
0277 BasicHTML.updateRenderer(menuItem, "");
0278 }
0279
0280 protected void uninstallListeners() {
0281 if (mouseInputListener != null) {
0282 menuItem.removeMouseListener(mouseInputListener);
0283 menuItem.removeMouseMotionListener(mouseInputListener);
0284 }
0285 if (menuDragMouseListener != null) {
0286 menuItem.removeMenuDragMouseListener(menuDragMouseListener);
0287 }
0288 if (menuKeyListener != null) {
0289 menuItem.removeMenuKeyListener(menuKeyListener);
0290 }
0291 if (propertyChangeListener != null) {
0292 menuItem
0293 .removePropertyChangeListener(propertyChangeListener);
0294 }
0295
0296 mouseInputListener = null;
0297 menuDragMouseListener = null;
0298 menuKeyListener = null;
0299 propertyChangeListener = null;
0300 handler = null;
0301 }
0302
0303 protected void uninstallKeyboardActions() {
0304 SwingUtilities.replaceUIActionMap(menuItem, null);
0305 SwingUtilities.replaceUIInputMap(menuItem,
0306 JComponent.WHEN_IN_FOCUSED_WINDOW, null);
0307 }
0308
0309 protected MouseInputListener createMouseInputListener(JComponent c) {
0310 return getHandler();
0311 }
0312
0313 protected MenuDragMouseListener createMenuDragMouseListener(
0314 JComponent c) {
0315 return getHandler();
0316 }
0317
0318 protected MenuKeyListener createMenuKeyListener(JComponent c) {
0319 return null;
0320 }
0321
0322 /**
0323 * Creates a <code>PropertyChangeListener</code> which will be added to
0324 * the menu item.
0325 * If this method returns null then it will not be added to the menu item.
0326 *
0327 * @return an instance of a <code>PropertyChangeListener</code> or null
0328 * @since 1.6
0329 */
0330 protected PropertyChangeListener createPropertyChangeListener(
0331 JComponent c) {
0332 return getHandler();
0333 }
0334
0335 Handler getHandler() {
0336 if (handler == null) {
0337 handler = new Handler();
0338 }
0339 return handler;
0340 }
0341
0342 InputMap createInputMap(int condition) {
0343 if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
0344 return new ComponentInputMapUIResource(menuItem);
0345 }
0346 return null;
0347 }
0348
0349 void updateAcceleratorBinding() {
0350 KeyStroke accelerator = menuItem.getAccelerator();
0351 InputMap windowInputMap = SwingUtilities.getUIInputMap(
0352 menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
0353
0354 if (windowInputMap != null) {
0355 windowInputMap.clear();
0356 }
0357 if (accelerator != null) {
0358 if (windowInputMap == null) {
0359 windowInputMap = createInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
0360 SwingUtilities.replaceUIInputMap(menuItem,
0361 JComponent.WHEN_IN_FOCUSED_WINDOW,
0362 windowInputMap);
0363 }
0364 windowInputMap.put(accelerator, "doClick");
0365 }
0366 }
0367
0368 public Dimension getMinimumSize(JComponent c) {
0369 Dimension d = null;
0370 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0371 if (v != null) {
0372 d = getPreferredSize(c);
0373 d.width -= v.getPreferredSpan(View.X_AXIS)
0374 - v.getMinimumSpan(View.X_AXIS);
0375 }
0376 return d;
0377 }
0378
0379 public Dimension getPreferredSize(JComponent c) {
0380 return getPreferredMenuItemSize(c, checkIcon, arrowIcon,
0381 defaultTextIconGap);
0382 }
0383
0384 public Dimension getMaximumSize(JComponent c) {
0385 Dimension d = null;
0386 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0387 if (v != null) {
0388 d = getPreferredSize(c);
0389 d.width += v.getMaximumSpan(View.X_AXIS)
0390 - v.getPreferredSpan(View.X_AXIS);
0391 }
0392 return d;
0393 }
0394
0395 // these rects are used for painting and preferredsize calculations.
0396 // they used to be regenerated constantly. Now they are reused.
0397 static Rectangle zeroRect = new Rectangle(0, 0, 0, 0);
0398 static Rectangle iconRect = new Rectangle();
0399 static Rectangle textRect = new Rectangle();
0400 static Rectangle acceleratorRect = new Rectangle();
0401 static Rectangle checkIconRect = new Rectangle();
0402 static Rectangle arrowIconRect = new Rectangle();
0403 static Rectangle viewRect = new Rectangle(Short.MAX_VALUE,
0404 Short.MAX_VALUE);
0405 static Rectangle r = new Rectangle();
0406
0407 private void resetRects() {
0408 iconRect.setBounds(zeroRect);
0409 textRect.setBounds(zeroRect);
0410 acceleratorRect.setBounds(zeroRect);
0411 checkIconRect.setBounds(zeroRect);
0412 arrowIconRect.setBounds(zeroRect);
0413 viewRect.setBounds(0, 0, Short.MAX_VALUE, Short.MAX_VALUE);
0414 r.setBounds(zeroRect);
0415 }
0416
0417 // Returns parent of this component if it is not a top-level menu
0418 // Otherwise returns null
0419 private JComponent getMenuItemParent(JMenuItem mi) {
0420 Container parent = mi.getParent();
0421 if ((parent instanceof JComponent)
0422 && (!(mi instanceof JMenu) || !((JMenu) mi)
0423 .isTopLevelMenu())) {
0424 return (JComponent) parent;
0425 } else {
0426 return null;
0427 }
0428 }
0429
0430 protected Dimension getPreferredMenuItemSize(JComponent c,
0431 Icon checkIcon, Icon arrowIcon, int defaultTextIconGap) {
0432 JMenuItem b = (JMenuItem) c;
0433
0434 Icon icon = null;
0435 /*
0436 * in case .checkIconFactory is defined for this UI and the icon is
0437 * compatible with it then the icon is handled by the checkIcon.
0438 * That is if useCheckAndArrow() is true.
0439 */
0440 MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager
0441 .get(getPropertyPrefix() + ".checkIconFactory");
0442 if (!useCheckAndArrow()
0443 || iconFactory == null
0444 || !iconFactory.isCompatible(checkIcon,
0445 getPropertyPrefix())) {
0446 icon = b.getIcon();
0447 }
0448 String text = b.getText();
0449 KeyStroke accelerator = b.getAccelerator();
0450 String acceleratorText = "";
0451
0452 if (accelerator != null) {
0453 int modifiers = accelerator.getModifiers();
0454 if (modifiers > 0) {
0455 acceleratorText = KeyEvent
0456 .getKeyModifiersText(modifiers);
0457 //acceleratorText += "-";
0458 acceleratorText += acceleratorDelimiter;
0459 }
0460 int keyCode = accelerator.getKeyCode();
0461 if (keyCode != 0) {
0462 acceleratorText += KeyEvent.getKeyText(keyCode);
0463 } else {
0464 acceleratorText += accelerator.getKeyChar();
0465 }
0466 }
0467
0468 Font font = b.getFont();
0469 FontMetrics fm = b.getFontMetrics(font);
0470 FontMetrics fmAccel = b.getFontMetrics(acceleratorFont);
0471
0472 resetRects();
0473
0474 layoutMenuItem(fm, text, fmAccel, acceleratorText, icon,
0475 checkIcon, arrowIcon, b.getVerticalAlignment(), b
0476 .getHorizontalAlignment(), b
0477 .getVerticalTextPosition(), b
0478 .getHorizontalTextPosition(), viewRect,
0479 iconRect, textRect, acceleratorRect, checkIconRect,
0480 arrowIconRect, text == null ? 0 : defaultTextIconGap,
0481 defaultTextIconGap);
0482
0483 // labelRect contains size of text and label
0484 Rectangle labelRect = iconRect.union(textRect);
0485
0486 // Find the result height
0487 r.height = max(labelRect.height, checkIconRect.height,
0488 arrowIconRect.height, acceleratorRect.height);
0489
0490 // Find the result width
0491
0492 // Add the leading gap,
0493 // the closing one will be added by the latest addMaxWidth() call
0494 r.width = defaultTextIconGap;
0495
0496 // To determine the width of the parent popup menu (through DefaultMenuLayout)
0497 // and to make accelerator texts appear in a column,
0498 // find the widest icon, text, check icon, arrow icon and accelerator text.
0499 // For the latest menu item we will know them exactly.
0500 // It will be the widest menu item and it will determine
0501 // the width of the parent popup menu.
0502 JComponent p = getMenuItemParent(menuItem);
0503 addMaxWidth(p, BasicMenuItemUI.MAX_ICON_WIDTH, iconRect.width,
0504 defaultTextIconGap, false);
0505 addMaxWidth(p, BasicMenuItemUI.MAX_TEXT_WIDTH, textRect.width,
0506 defaultTextIconGap, false);
0507 addMaxWidth(p, BasicMenuItemUI.MAX_ACC_WIDTH,
0508 acceleratorRect.width, defaultTextIconGap, false);
0509 if (useCheckAndArrow()) {
0510 // Force gap for the check icon to avoid absence of the gap between
0511 // the text and arrow icon because of the layoutMenuItem() features
0512 addMaxWidth(p, BasicMenuItemUI.MAX_CHECK_ICON_WIDTH,
0513 checkIconRect.width, defaultTextIconGap, true);
0514 addMaxWidth(p, BasicMenuItemUI.MAX_ARROW_ICON_WIDTH,
0515 arrowIconRect.width, defaultTextIconGap, false);
0516 }
0517
0518 Insets insets = b.getInsets();
0519 if (insets != null) {
0520 r.width += insets.left + insets.right;
0521 r.height += insets.top + insets.bottom;
0522 }
0523
0524 // if the width is even, bump it up one. This is critical
0525 // for the focus dash line to draw properly
0526 if (r.width % 2 == 0) {
0527 r.width++;
0528 }
0529
0530 // if the height is even, bump it up one. This is critical
0531 // for the text to center properly
0532 if (r.height % 2 == 0
0533 && Boolean.TRUE != UIManager.get(getPropertyPrefix()
0534 + ".evenHeight")) {
0535 r.height++;
0536 }
0537 /*
0538 if(!(b instanceof JMenu && ((JMenu) b).isTopLevelMenu()) ) {
0539
0540 // Container parent = menuItem.getParent();
0541 JComponent p = (JComponent) parent;
0542
0543 System.out.println("MaxText: "+p.getClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH));
0544 System.out.println("MaxACC"+p.getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH));
0545
0546 System.out.println("returning pref.width: " + r.width);
0547 System.out.println("Current getSize: " + b.getSize() + "\n");
0548 }*/
0549 return r.getSize();
0550 }
0551
0552 private int max(int... values) {
0553 int maxValue = Integer.MIN_VALUE;
0554 for (int i : values) {
0555 if (i > maxValue) {
0556 maxValue = i;
0557 }
0558 }
0559 return maxValue;
0560 }
0561
0562 // Calculates maximal width through specified parent component client property
0563 // and adds it to the width of rectangle r
0564 private void addMaxWidth(JComponent parent, String propertyName,
0565 int curWidth, int defaultTextIconGap, boolean forceGap) {
0566 // Get maximal width from parent client property
0567 Integer maxWidth = null;
0568 if (parent != null) {
0569 maxWidth = (Integer) parent.getClientProperty(propertyName);
0570 }
0571 if (maxWidth == null) {
0572 maxWidth = 0;
0573 }
0574
0575 // Store new maximal width in parent client property
0576 if (curWidth > maxWidth) {
0577 maxWidth = curWidth;
0578 if (parent != null) {
0579 parent.putClientProperty(propertyName, maxWidth);
0580 }
0581 }
0582
0583 // Add calculated maximal width and gap
0584 if (maxWidth > 0) {
0585 r.width += defaultTextIconGap;
0586 r.width += maxWidth;
0587 } else {
0588 if (forceGap) {
0589 r.width += defaultTextIconGap;
0590 }
0591 }
0592 }
0593
0594 /**
0595 * We draw the background in paintMenuItem()
0596 * so override update (which fills the background of opaque
0597 * components by default) to just call paint().
0598 *
0599 */
0600 public void update(Graphics g, JComponent c) {
0601 paint(g, c);
0602 }
0603
0604 public void paint(Graphics g, JComponent c) {
0605 paintMenuItem(g, c, checkIcon, arrowIcon, selectionBackground,
0606 selectionForeground, defaultTextIconGap);
0607 }
0608
0609 protected void paintMenuItem(Graphics g, JComponent c,
0610 Icon checkIcon, Icon arrowIcon, Color background,
0611 Color foreground, int defaultTextIconGap) {
0612 JMenuItem b = (JMenuItem) c;
0613 ButtonModel model = b.getModel();
0614
0615 // Dimension size = b.getSize();
0616 int menuWidth = b.getWidth();
0617 int menuHeight = b.getHeight();
0618 Insets i = c.getInsets();
0619
0620 resetRects();
0621
0622 viewRect.setBounds(0, 0, menuWidth, menuHeight);
0623
0624 viewRect.x += i.left;
0625 viewRect.y += i.top;
0626 viewRect.width -= (i.right + viewRect.x);
0627 viewRect.height -= (i.bottom + viewRect.y);
0628
0629 Font holdf = g.getFont();
0630 Font f = c.getFont();
0631 g.setFont(f);
0632 FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
0633 FontMetrics fmAccel = SwingUtilities2.getFontMetrics(c, g,
0634 acceleratorFont);
0635
0636 // get Accelerator text
0637 KeyStroke accelerator = b.getAccelerator();
0638 String acceleratorText = "";
0639 if (accelerator != null) {
0640 int modifiers = accelerator.getModifiers();
0641 if (modifiers > 0) {
0642 acceleratorText = KeyEvent
0643 .getKeyModifiersText(modifiers);
0644 //acceleratorText += "-";
0645 acceleratorText += acceleratorDelimiter;
0646 }
0647
0648 int keyCode = accelerator.getKeyCode();
0649 if (keyCode != 0) {
0650 acceleratorText += KeyEvent.getKeyText(keyCode);
0651 } else {
0652 acceleratorText += accelerator.getKeyChar();
0653 }
0654 }
0655 Icon icon = null;
0656 /*
0657 * in case .checkIconFactory is defined for this UI and the icon is
0658 * compatible with it then the icon is handled by the checkIcon.
0659 * That is if useCheckAndArrow() is true.
0660 */
0661 MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager
0662 .get(getPropertyPrefix() + ".checkIconFactory");
0663 if (!useCheckAndArrow()
0664 || iconFactory == null
0665 || !iconFactory.isCompatible(checkIcon,
0666 getPropertyPrefix())) {
0667 icon = b.getIcon();
0668 }
0669 // layout the text and icon
0670 String text = layoutMenuItem(fm, b.getText(), fmAccel,
0671 acceleratorText, icon, checkIcon, arrowIcon, b
0672 .getVerticalAlignment(), b
0673 .getHorizontalAlignment(), b
0674 .getVerticalTextPosition(), b
0675 .getHorizontalTextPosition(), viewRect,
0676 iconRect, textRect, acceleratorRect, checkIconRect,
0677 arrowIconRect, b.getText() == null ? 0
0678 : defaultTextIconGap, defaultTextIconGap);
0679 // Paint background
0680 paintBackground(g, b, background);
0681
0682 Color holdc = g.getColor();
0683
0684 // Paint the Check
0685 if (checkIcon != null) {
0686 if (model.isArmed()
0687 || (c instanceof JMenu && model.isSelected())) {
0688 g.setColor(foreground);
0689 } else {
0690 g.setColor(holdc);
0691 }
0692 if (useCheckAndArrow())
0693 checkIcon.paintIcon(c, g, checkIconRect.x,
0694 checkIconRect.y);
0695 g.setColor(holdc);
0696 }
0697
0698 // Paint the Icon
0699 if (icon != null) {
0700 if (!model.isEnabled()) {
0701 icon = (Icon) b.getDisabledIcon();
0702 } else if (model.isPressed() && model.isArmed()) {
0703 icon = (Icon) b.getPressedIcon();
0704 if (icon == null) {
0705 // Use default icon
0706 icon = (Icon) b.getIcon();
0707 }
0708 } else {
0709 icon = (Icon) b.getIcon();
0710 }
0711
0712 if (icon != null) {
0713 icon.paintIcon(c, g, iconRect.x, iconRect.y);
0714 g.setColor(holdc);
0715 }
0716 }
0717
0718 // Draw the Text
0719 if (text != null) {
0720 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0721 if (v != null) {
0722 v.paint(g, textRect);
0723 } else {
0724 paintText(g, b, textRect, text);
0725 }
0726 }
0727
0728 // Draw the Accelerator Text
0729 if (acceleratorText != null && !acceleratorText.equals("")) {
0730
0731 //Get the maxAccWidth from the parent to calculate the offset.
0732 int accOffset = 0;
0733 JComponent p = getMenuItemParent(menuItem);
0734 if (p != null) {
0735 Integer maxValueInt = (Integer) p
0736 .getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH);
0737 int maxValue = maxValueInt != null ? maxValueInt
0738 .intValue() : acceleratorRect.width;
0739
0740 //Calculate the offset, with which the accelerator texts will be drawn with.
0741 accOffset = maxValue - acceleratorRect.width;
0742 }
0743
0744 g.setFont(acceleratorFont);
0745 if (!model.isEnabled()) {
0746 // *** paint the acceleratorText disabled
0747 if (disabledForeground != null) {
0748 g.setColor(disabledForeground);
0749 SwingUtilities2.drawString(b, g, acceleratorText,
0750 acceleratorRect.x - accOffset,
0751 acceleratorRect.y + fmAccel.getAscent());
0752 } else {
0753 g.setColor(b.getBackground().brighter());
0754 SwingUtilities2.drawString(b, g, acceleratorText,
0755 acceleratorRect.x - accOffset,
0756 acceleratorRect.y + fmAccel.getAscent());
0757 g.setColor(b.getBackground().darker());
0758 SwingUtilities2
0759 .drawString(b, g, acceleratorText,
0760 acceleratorRect.x - accOffset - 1,
0761 acceleratorRect.y
0762 + fmAccel.getAscent() - 1);
0763 }
0764 } else {
0765 // *** paint the acceleratorText normally
0766 if (model.isArmed()
0767 || (c instanceof JMenu && model.isSelected())) {
0768 g.setColor(acceleratorSelectionForeground);
0769 } else {
0770 g.setColor(acceleratorForeground);
0771 }
0772 SwingUtilities2.drawString(b, g, acceleratorText,
0773 acceleratorRect.x - accOffset,
0774 acceleratorRect.y + fmAccel.getAscent());
0775 }
0776 }
0777
0778 // Paint the Arrow
0779 if (arrowIcon != null) {
0780 if (model.isArmed()
0781 || (c instanceof JMenu && model.isSelected()))
0782 g.setColor(foreground);
0783 if (useCheckAndArrow())
0784 arrowIcon.paintIcon(c, g, arrowIconRect.x,
0785 arrowIconRect.y);
0786 }
0787 g.setColor(holdc);
0788 g.setFont(holdf);
0789 }
0790
0791 /**
0792 * Draws the background of the menu item.
0793 *
0794 * @param g the paint graphics
0795 * @param menuItem menu item to be painted
0796 * @param bgColor selection background color
0797 * @since 1.4
0798 */
0799 protected void paintBackground(Graphics g, JMenuItem menuItem,
0800 Color bgColor) {
0801 ButtonModel model = menuItem.getModel();
0802 Color oldColor = g.getColor();
0803 int menuWidth = menuItem.getWidth();
0804 int menuHeight = menuItem.getHeight();
0805
0806 if (menuItem.isOpaque()) {
0807 if (model.isArmed()
0808 || (menuItem instanceof JMenu && model.isSelected())) {
0809 g.setColor(bgColor);
0810 g.fillRect(0, 0, menuWidth, menuHeight);
0811 } else {
0812 g.setColor(menuItem.getBackground());
0813 g.fillRect(0, 0, menuWidth, menuHeight);
0814 }
0815 g.setColor(oldColor);
0816 } else if (model.isArmed()
0817 || (menuItem instanceof JMenu && model.isSelected())) {
0818 g.setColor(bgColor);
0819 g.fillRect(0, 0, menuWidth, menuHeight);
0820 g.setColor(oldColor);
0821 }
0822 }
0823
0824 /**
0825 * Renders the text of the current menu item.
0826 * <p>
0827 * @param g graphics context
0828 * @param menuItem menu item to render
0829 * @param textRect bounding rectangle for rendering the text
0830 * @param text string to render
0831 * @since 1.4
0832 */
0833 protected void paintText(Graphics g, JMenuItem menuItem,
0834 Rectangle textRect, String text) {
0835 ButtonModel model = menuItem.getModel();
0836 FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g);
0837 int mnemIndex = menuItem.getDisplayedMnemonicIndex();
0838
0839 if (!model.isEnabled()) {
0840 // *** paint the text disabled
0841 if (UIManager.get("MenuItem.disabledForeground") instanceof Color) {
0842 g.setColor(UIManager
0843 .getColor("MenuItem.disabledForeground"));
0844 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,
0845 text, mnemIndex, textRect.x, textRect.y
0846 + fm.getAscent());
0847 } else {
0848 g.setColor(menuItem.getBackground().brighter());
0849 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,
0850 text, mnemIndex, textRect.x, textRect.y
0851 + fm.getAscent());
0852 g.setColor(menuItem.getBackground().darker());
0853 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,
0854 text, mnemIndex, textRect.x - 1, textRect.y
0855 + fm.getAscent() - 1);
0856 }
0857 } else {
0858 // *** paint the text normally
0859 if (model.isArmed()
0860 || (menuItem instanceof JMenu && model.isSelected())) {
0861 g.setColor(selectionForeground); // Uses protected field.
0862 }
0863 SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,
0864 text, mnemIndex, textRect.x, textRect.y
0865 + fm.getAscent());
0866 }
0867 }
0868
0869 /**
0870 * Compute and return the location of the icons origin, the
0871 * location of origin of the text baseline, and a possibly clipped
0872 * version of the compound labels string. Locations are computed
0873 * relative to the viewRect rectangle.
0874 */
0875
0876 private String layoutMenuItem(FontMetrics fm, String text,
0877 FontMetrics fmAccel, String acceleratorText, Icon icon,
0878 Icon checkIcon, Icon arrowIcon, int verticalAlignment,
0879 int horizontalAlignment, int verticalTextPosition,
0880 int horizontalTextPosition, Rectangle viewRect,
0881 Rectangle iconRect, Rectangle textRect,
0882 Rectangle acceleratorRect, Rectangle checkIconRect,
0883 Rectangle arrowIconRect, int textIconGap, int menuItemGap) {
0884
0885 SwingUtilities.layoutCompoundLabel(menuItem, fm, text, icon,
0886 verticalAlignment, horizontalAlignment,
0887 verticalTextPosition, horizontalTextPosition, viewRect,
0888 iconRect, textRect, textIconGap);
0889
0890 /* Initialize the acceelratorText bounds rectangle textRect. If a null
0891 * or and empty String was specified we substitute "" here
0892 * and use 0,0,0,0 for acceleratorTextRect.
0893 */
0894 if ((acceleratorText == null) || acceleratorText.equals("")) {
0895 acceleratorRect.width = acceleratorRect.height = 0;
0896 acceleratorText = "";
0897 } else {
0898 acceleratorRect.width = SwingUtilities2.stringWidth(
0899 menuItem, fmAccel, acceleratorText);
0900 acceleratorRect.height = fmAccel.getHeight();
0901 }
0902
0903 /* Initialize the checkIcon bounds rectangle's width & height.
0904 */
0905
0906 if (useCheckAndArrow()) {
0907 if (checkIcon != null) {
0908 checkIconRect.width = checkIcon.getIconWidth();
0909 checkIconRect.height = checkIcon.getIconHeight();
0910 } else {
0911 checkIconRect.width = checkIconRect.height = 0;
0912 }
0913
0914 /* Initialize the arrowIcon bounds rectangle width & height.
0915 */
0916
0917 if (arrowIcon != null) {
0918 arrowIconRect.width = arrowIcon.getIconWidth();
0919 arrowIconRect.height = arrowIcon.getIconHeight();
0920 } else {
0921 arrowIconRect.width = arrowIconRect.height = 0;
0922 }
0923 }
0924
0925 JComponent p = getMenuItemParent(menuItem);
0926
0927 Rectangle labelRect = iconRect.union(textRect);
0928
0929 int checkIconOffset = menuItemGap;
0930 Object checkIconOffsetObject = UIManager
0931 .get(getPropertyPrefix() + ".checkIconOffset");
0932 if (checkIconOffsetObject instanceof Integer) {
0933 checkIconOffset = (Integer) checkIconOffsetObject;
0934 }
0935 if (BasicGraphicsUtils.isLeftToRight(menuItem)) {
0936 /* get minimum text offset. It is defined for LTR case only. */
0937 int minimumTextOffset = 0;
0938 Object minimumTextOffsetObject = UIManager
0939 .get(getPropertyPrefix() + ".minimumTextOffset");
0940 if (minimumTextOffsetObject instanceof Integer) {
0941 minimumTextOffset = (Integer) minimumTextOffsetObject;
0942 }
0943 textRect.x += menuItemGap;
0944 iconRect.x += menuItemGap;
0945
0946 // Position the Accelerator text rect
0947 acceleratorRect.x = viewRect.x + viewRect.width
0948 - arrowIconRect.width - menuItemGap
0949 - acceleratorRect.width;
0950
0951 // Position the Check and Arrow Icons
0952 if (useCheckAndArrow()) {
0953 checkIconRect.x = viewRect.x + checkIconOffset;
0954 if (icon == null || checkIcon != null) {
0955 iconRect.x += menuItemGap + checkIconRect.width;
0956 }
0957 textRect.x += menuItemGap + checkIconRect.width;
0958 textRect.x = Math.max(textRect.x, minimumTextOffset);
0959 arrowIconRect.x = viewRect.x + viewRect.width
0960 - menuItemGap - arrowIconRect.width;
0961 }
0962 /* Align icons and text vertically */
0963 if (p != null) {
0964 Integer maxIconOffset = (Integer) p
0965 .getClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET);
0966 Integer maxTextOffset = (Integer) p
0967 .getClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET);
0968 int maxIconValue = maxIconOffset == null ? 0
0969 : maxIconOffset;
0970 int maxTextValue = maxTextOffset == null ? 0
0971 : maxTextOffset;
0972
0973 int this TextOffset = textRect.x - viewRect.x;
0974 if (this TextOffset > maxTextValue) {
0975 p.putClientProperty(
0976 BASICMENUITEMUI_MAX_TEXT_OFFSET,
0977 new Integer(this TextOffset));
0978 } else {
0979 textRect.x = maxTextValue + viewRect.x;
0980 }
0981
0982 if (icon != null) {
0983 if (horizontalTextPosition == SwingConstants.TRAILING
0984 || horizontalTextPosition == SwingConstants.RIGHT) {
0985 int this IconOffset = iconRect.x - viewRect.x;
0986 if (this IconOffset > maxIconValue) {
0987 p.putClientProperty(
0988 BasicMenuItemUI.MAX_ICON_OFFSET,
0989 new Integer(this IconOffset));
0990 } else {
0991 iconRect.x = maxIconValue + viewRect.x;
0992 }
0993 } else if (horizontalTextPosition == SwingConstants.LEADING
0994 || horizontalTextPosition == SwingConstants.LEFT) {
0995 iconRect.x = textRect.x + textRect.width
0996 + menuItemGap;
0997 } else {
0998 iconRect.x = Math.max(textRect.x
0999 + textRect.width / 2 - iconRect.width
1000 / 2, maxIconValue + viewRect.x);
1001
1002 }
1003 }
1004 }
1005 } else {
1006 textRect.x -= menuItemGap;
1007 iconRect.x -= menuItemGap;
1008
1009 // Position the Accelerator text rect
1010 acceleratorRect.x = viewRect.x + arrowIconRect.width
1011 + menuItemGap;
1012
1013 // Position the Check and Arrow Icons
1014 if (useCheckAndArrow()) {
1015 checkIconRect.x = viewRect.x + viewRect.width
1016 - checkIconOffset - checkIconRect.width;
1017 if (icon == null || checkIcon != null) {
1018 iconRect.x -= menuItemGap + checkIconRect.width;
1019 }
1020 textRect.x -= menuItemGap + checkIconRect.width;
1021 arrowIconRect.x = viewRect.x + menuItemGap;
1022 }
1023 /* Align icons and text vertically */
1024 if (p != null) {
1025 Integer maxIconOffset = (Integer) p
1026 .getClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET);
1027 Integer maxTextOffset = (Integer) p
1028 .getClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET);
1029 int maxIconValue = maxIconOffset == null ? 0
1030 : maxIconOffset;
1031 int maxTextValue = maxTextOffset == null ? 0
1032 : maxTextOffset;
1033
1034 int this TextOffset = viewRect.x + viewRect.width
1035 - textRect.x - textRect.width;
1036 if (this TextOffset > maxTextValue) {
1037 p.putClientProperty(
1038 BASICMENUITEMUI_MAX_TEXT_OFFSET,
1039 new Integer(this TextOffset));
1040 } else {
1041 textRect.x = viewRect.x + viewRect.width
1042 - maxTextValue - textRect.width;
1043 }
1044
1045 int this IconOffset = 0;
1046 if (icon != null) {
1047 if (horizontalTextPosition == SwingConstants.TRAILING
1048 || horizontalTextPosition == SwingConstants.LEFT) {
1049 this IconOffset = viewRect.x + viewRect.width
1050 - iconRect.x - iconRect.width;
1051 if (this IconOffset > maxIconValue) {
1052 p.putClientProperty(
1053 BasicMenuItemUI.MAX_ICON_OFFSET,
1054 new Integer(this IconOffset));
1055 } else {
1056 iconRect.x = viewRect.x + viewRect.width
1057 - maxIconValue - iconRect.width;
1058 }
1059 } else if (horizontalTextPosition == SwingConstants.LEADING
1060 || horizontalTextPosition == SwingConstants.RIGHT) {
1061 iconRect.x = textRect.x - menuItemGap
1062 - iconRect.width;
1063 } else {
1064 iconRect.x = textRect.x + textRect.width / 2
1065 - iconRect.width / 2;
1066 if (iconRect.x + iconRect.width > viewRect.x
1067 + viewRect.width - maxIconValue) {
1068 iconRect.x = iconRect.x = viewRect.x
1069 + viewRect.width - maxIconValue
1070 - iconRect.width;
1071 }
1072 }
1073 }
1074 }
1075 }
1076
1077 // Align the accelertor text and the check and arrow icons vertically
1078 // with the center of the label rect.
1079 acceleratorRect.y = labelRect.y + (labelRect.height / 2)
1080 - (acceleratorRect.height / 2);
1081 if (useCheckAndArrow()) {
1082 arrowIconRect.y = labelRect.y + (labelRect.height / 2)
1083 - (arrowIconRect.height / 2);
1084 checkIconRect.y = labelRect.y + (labelRect.height / 2)
1085 - (checkIconRect.height / 2);
1086 }
1087
1088 /*
1089 System.out.println("Layout: text="+menuItem.getText()+"\n\tv="
1090 +viewRect+"\n\tc="+checkIconRect+"\n\ti="
1091 +iconRect+"\n\tt="+textRect+"\n\tacc="
1092 +acceleratorRect+"\n\ta="+arrowIconRect+"\n");
1093 */
1094
1095 return text;
1096 }
1097
1098 /*
1099 * Returns false if the component is a JMenu and it is a top
1100 * level menu (on the menubar).
1101 */
1102 private boolean useCheckAndArrow() {
1103 boolean b = true;
1104 if ((menuItem instanceof JMenu)
1105 && (((JMenu) menuItem).isTopLevelMenu())) {
1106 b = false;
1107 }
1108 return b;
1109 }
1110
1111 public MenuElement[] getPath() {
1112 MenuSelectionManager m = MenuSelectionManager.defaultManager();
1113 MenuElement oldPath[] = m.getSelectedPath();
1114 MenuElement newPath[];
1115 int i = oldPath.length;
1116 if (i == 0)
1117 return new MenuElement[0];
1118 Component parent = menuItem.getParent();
1119 if (oldPath[i - 1].getComponent() == parent) {
1120 // The parent popup menu is the last so far
1121 newPath = new MenuElement[i + 1];
1122 System.arraycopy(oldPath, 0, newPath, 0, i);
1123 newPath[i] = menuItem;
1124 } else {
1125 // A sibling menuitem is the current selection
1126 //
1127 // This probably needs to handle 'exit submenu into
1128 // a menu item. Search backwards along the current
1129 // selection until you find the parent popup menu,
1130 // then copy up to that and add yourself...
1131 int j;
1132 for (j = oldPath.length - 1; j >= 0; j--) {
1133 if (oldPath[j].getComponent() == parent)
1134 break;
1135 }
1136 newPath = new MenuElement[j + 2];
1137 System.arraycopy(oldPath, 0, newPath, 0, j + 1);
1138 newPath[j + 1] = menuItem;
1139 /*
1140 System.out.println("Sibling condition -- ");
1141 System.out.println("Old array : ");
1142 printMenuElementArray(oldPath, false);
1143 System.out.println("New array : ");
1144 printMenuElementArray(newPath, false);
1145 */
1146 }
1147 return newPath;
1148 }
1149
1150 void printMenuElementArray(MenuElement path[], boolean dumpStack) {
1151 System.out.println("Path is(");
1152 int i, j;
1153 for (i = 0, j = path.length; i < j; i++) {
1154 for (int k = 0; k <= i; k++)
1155 System.out.print(" ");
1156 MenuElement me = (MenuElement) path[i];
1157 if (me instanceof JMenuItem)
1158 System.out.println(((JMenuItem) me).getText() + ", ");
1159 else if (me == null)
1160 System.out.println("NULL , ");
1161 else
1162 System.out.println("" + me + ", ");
1163 }
1164 System.out.println(")");
1165
1166 if (dumpStack == true)
1167 Thread.dumpStack();
1168 }
1169
1170 protected class MouseInputHandler implements MouseInputListener {
1171 // NOTE: This class exists only for backward compatability. All
1172 // its functionality has been moved into Handler. If you need to add
1173 // new functionality add it to the Handler, but make sure this
1174 // class calls into the Handler.
1175
1176 public void mouseClicked(MouseEvent e) {
1177 getHandler().mouseClicked(e);
1178 }
1179
1180 public void mousePressed(MouseEvent e) {
1181 getHandler().mousePressed(e);
1182 }
1183
1184 public void mouseReleased(MouseEvent e) {
1185 getHandler().mouseReleased(e);
1186 }
1187
1188 public void mouseEntered(MouseEvent e) {
1189 getHandler().mouseEntered(e);
1190 }
1191
1192 public void mouseExited(MouseEvent e) {
1193 getHandler().mouseExited(e);
1194 }
1195
1196 public void mouseDragged(MouseEvent e) {
1197 getHandler().mouseDragged(e);
1198 }
1199
1200 public void mouseMoved(MouseEvent e) {
1201 getHandler().mouseMoved(e);
1202 }
1203 }
1204
1205 private static class Actions extends UIAction {
1206 private static final String CLICK = "doClick";
1207
1208 Actions(String key) {
1209 super (key);
1210 }
1211
1212 public void actionPerformed(ActionEvent e) {
1213 JMenuItem mi = (JMenuItem) e.getSource();
1214 MenuSelectionManager.defaultManager().clearSelectedPath();
1215 mi.doClick();
1216 }
1217 }
1218
1219 /**
1220 * Call this method when a menu item is to be activated.
1221 * This method handles some of the details of menu item activation
1222 * such as clearing the selected path and messaging the
1223 * JMenuItem's doClick() method.
1224 *
1225 * @param msm A MenuSelectionManager. The visual feedback and
1226 * internal bookkeeping tasks are delegated to
1227 * this MenuSelectionManager. If <code>null</code> is
1228 * passed as this argument, the
1229 * <code>MenuSelectionManager.defaultManager</code> is
1230 * used.
1231 * @see MenuSelectionManager
1232 * @see JMenuItem#doClick(int)
1233 * @since 1.4
1234 */
1235 protected void doClick(MenuSelectionManager msm) {
1236 // Auditory cue
1237 if (!isInternalFrameSystemMenu()) {
1238 BasicLookAndFeel.playSound(menuItem, getPropertyPrefix()
1239 + ".commandSound");
1240 }
1241 // Visual feedback
1242 if (msm == null) {
1243 msm = MenuSelectionManager.defaultManager();
1244 }
1245 msm.clearSelectedPath();
1246 menuItem.doClick(0);
1247 }
1248
1249 /**
1250 * This is to see if the menu item in question is part of the
1251 * system menu on an internal frame.
1252 * The Strings that are being checked can be found in
1253 * MetalInternalFrameTitlePaneUI.java,
1254 * WindowsInternalFrameTitlePaneUI.java, and
1255 * MotifInternalFrameTitlePaneUI.java.
1256 *
1257 * @since 1.4
1258 */
1259 private boolean isInternalFrameSystemMenu() {
1260 String actionCommand = menuItem.getActionCommand();
1261 if ((actionCommand == "Close") || (actionCommand == "Minimize")
1262 || (actionCommand == "Restore")
1263 || (actionCommand == "Maximize")) {
1264 return true;
1265 } else {
1266 return false;
1267 }
1268 }
1269
1270 // BasicMenuUI subclasses this.
1271 class Handler implements MenuDragMouseListener, MouseInputListener,
1272 PropertyChangeListener {
1273 //
1274 // MouseInputListener
1275 //
1276 public void mouseClicked(MouseEvent e) {
1277 }
1278
1279 public void mousePressed(MouseEvent e) {
1280 }
1281
1282 public void mouseReleased(MouseEvent e) {
1283 if (!menuItem.isEnabled()) {
1284 return;
1285 }
1286 MenuSelectionManager manager = MenuSelectionManager
1287 .defaultManager();
1288 Point p = e.getPoint();
1289 if (p.x >= 0 && p.x < menuItem.getWidth() && p.y >= 0
1290 && p.y < menuItem.getHeight()) {
1291 doClick(manager);
1292 } else {
1293 manager.processMouseEvent(e);
1294 }
1295 }
1296
1297 public void mouseEntered(MouseEvent e) {
1298 MenuSelectionManager manager = MenuSelectionManager
1299 .defaultManager();
1300 int modifiers = e.getModifiers();
1301 // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
1302 if ((modifiers & (InputEvent.BUTTON1_MASK
1303 | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) != 0) {
1304 MenuSelectionManager.defaultManager()
1305 .processMouseEvent(e);
1306 } else {
1307 manager.setSelectedPath(getPath());
1308 }
1309 }
1310
1311 public void mouseExited(MouseEvent e) {
1312 MenuSelectionManager manager = MenuSelectionManager
1313 .defaultManager();
1314
1315 int modifiers = e.getModifiers();
1316 // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
1317 if ((modifiers & (InputEvent.BUTTON1_MASK
1318 | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) != 0) {
1319 MenuSelectionManager.defaultManager()
1320 .processMouseEvent(e);
1321 } else {
1322
1323 MenuElement path[] = manager.getSelectedPath();
1324 if (path.length > 1
1325 && path[path.length - 1] == menuItem) {
1326 MenuElement newPath[] = new MenuElement[path.length - 1];
1327 int i, c;
1328 for (i = 0, c = path.length - 1; i < c; i++)
1329 newPath[i] = path[i];
1330 manager.setSelectedPath(newPath);
1331 }
1332 }
1333 }
1334
1335 public void mouseDragged(MouseEvent e) {
1336 MenuSelectionManager.defaultManager().processMouseEvent(e);
1337 }
1338
1339 public void mouseMoved(MouseEvent e) {
1340 }
1341
1342 //
1343 // MenuDragListener
1344 //
1345 public void menuDragMouseEntered(MenuDragMouseEvent e) {
1346 MenuSelectionManager manager = e.getMenuSelectionManager();
1347 MenuElement path[] = e.getPath();
1348 manager.setSelectedPath(path);
1349 }
1350
1351 public void menuDragMouseDragged(MenuDragMouseEvent e) {
1352 MenuSelectionManager manager = e.getMenuSelectionManager();
1353 MenuElement path[] = e.getPath();
1354 manager.setSelectedPath(path);
1355 }
1356
1357 public void menuDragMouseExited(MenuDragMouseEvent e) {
1358 }
1359
1360 public void menuDragMouseReleased(MenuDragMouseEvent e) {
1361 if (!menuItem.isEnabled()) {
1362 return;
1363 }
1364 MenuSelectionManager manager = e.getMenuSelectionManager();
1365 MenuElement path[] = e.getPath();
1366 Point p = e.getPoint();
1367 if (p.x >= 0 && p.x < menuItem.getWidth() && p.y >= 0
1368 && p.y < menuItem.getHeight()) {
1369 doClick(manager);
1370 } else {
1371 manager.clearSelectedPath();
1372 }
1373 }
1374
1375 //
1376 // PropertyChangeListener
1377 //
1378 public void propertyChange(PropertyChangeEvent e) {
1379 String name = e.getPropertyName();
1380
1381 if (name == "labelFor" || name == "displayedMnemonic"
1382 || name == "accelerator") {
1383 updateAcceleratorBinding();
1384 } else if (name == "text" || "font" == name
1385 || "foreground" == name) {
1386 // remove the old html view client property if one
1387 // existed, and install a new one if the text installed
1388 // into the JLabel is html source.
1389 JMenuItem lbl = ((JMenuItem) e.getSource());
1390 String text = lbl.getText();
1391 BasicHTML.updateRenderer(lbl, text);
1392 } else if (name == "iconTextGap") {
1393 defaultTextIconGap = ((Number) e.getNewValue())
1394 .intValue();
1395 }
1396 }
1397 }
1398 }
|