FileDocCategorySizeDatePackage
BasicMenuItemUI.javaAPI DocJava SE 6 API50694Tue Jun 10 00:26:48 BST 2008javax.swing.plaf.basic

BasicMenuItemUI

public class BasicMenuItemUI extends MenuItemUI
BasicMenuItem implementation
version
1.143 06/21/07
author
Georges Saab
author
David Karlton
author
Arnaud Weber
author
Fredrik Lagerblad

Fields Summary
protected JMenuItem
menuItem
protected Color
selectionBackground
protected Color
selectionForeground
protected Color
disabledForeground
protected Color
acceleratorForeground
protected Color
acceleratorSelectionForeground
private String
acceleratorDelimiter
protected int
defaultTextIconGap
protected Font
acceleratorFont
protected MouseInputListener
mouseInputListener
protected MenuDragMouseListener
menuDragMouseListener
protected MenuKeyListener
menuKeyListener
protected PropertyChangeListener
propertyChangeListener
PropertyChangeListener returned from createPropertyChangeListener. You should not need to access this field, rather if you want to customize the PropertyChangeListener override createPropertyChangeListener.
Handler
handler
protected Icon
arrowIcon
protected Icon
checkIcon
protected boolean
oldBorderPainted
private static final boolean
TRACE
private static final boolean
VERBOSE
private static final boolean
DEBUG
static final String
MAX_ARROW_ICON_WIDTH
static final String
MAX_CHECK_ICON_WIDTH
static final String
MAX_ICON_WIDTH
static final String
MAX_TEXT_WIDTH
static final String
MAX_ACC_WIDTH
static final StringBuffer
MAX_ICON_OFFSET
static Rectangle
zeroRect
static Rectangle
iconRect
static Rectangle
textRect
static Rectangle
acceleratorRect
static Rectangle
checkIconRect
static Rectangle
arrowIconRect
static Rectangle
viewRect
static Rectangle
r
Constructors Summary
Methods Summary
private voidaddMaxWidth(javax.swing.JComponent parent, java.lang.String propertyName, int curWidth, int defaultTextIconGap, boolean forceGap)

        // Get maximal width from parent client property
        Integer maxWidth = null;
        if (parent != null) {
            maxWidth = (Integer) parent.getClientProperty(propertyName);
        }    
        if (maxWidth == null) {
            maxWidth = 0;
        }
        
        // Store new maximal width in parent client property 
        if (curWidth > maxWidth) {
            maxWidth = curWidth;
            if (parent != null) {
                parent.putClientProperty(propertyName, maxWidth);
            }
        }

        // Add calculated maximal width and gap
        if (maxWidth > 0) {
            r.width += defaultTextIconGap;
            r.width += maxWidth;
        } else {
            if (forceGap) {
                r.width += defaultTextIconGap;
            }
        }
    
javax.swing.InputMapcreateInputMap(int condition)

	if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
	    return new ComponentInputMapUIResource(menuItem);
	}
	return null;
    
protected javax.swing.event.MenuDragMouseListenercreateMenuDragMouseListener(javax.swing.JComponent c)

        return getHandler();
    
protected javax.swing.event.MenuKeyListenercreateMenuKeyListener(javax.swing.JComponent c)

	return null;
    
protected javax.swing.event.MouseInputListenercreateMouseInputListener(javax.swing.JComponent c)

        return getHandler();
    
protected java.beans.PropertyChangeListenercreatePropertyChangeListener(javax.swing.JComponent c)
Creates a PropertyChangeListener which will be added to the menu item. If this method returns null then it will not be added to the menu item.

return
an instance of a PropertyChangeListener or null
since
1.6

	return getHandler();
    
public static javax.swing.plaf.ComponentUIcreateUI(javax.swing.JComponent c)

        return new BasicMenuItemUI();
    
protected voiddoClick(javax.swing.MenuSelectionManager msm)
Call this method when a menu item is to be activated. This method handles some of the details of menu item activation such as clearing the selected path and messaging the JMenuItem's doClick() method.

param
msm A MenuSelectionManager. The visual feedback and internal bookkeeping tasks are delegated to this MenuSelectionManager. If null is passed as this argument, the MenuSelectionManager.defaultManager is used.
see
MenuSelectionManager
see
JMenuItem#doClick(int)
since
1.4

	// Auditory cue
	if (! isInternalFrameSystemMenu()) {
            BasicLookAndFeel.playSound(menuItem, getPropertyPrefix() +
                                       ".commandSound");
	}
	// Visual feedback
	if (msm == null) {
	    msm = MenuSelectionManager.defaultManager();
	}
	msm.clearSelectedPath();
	menuItem.doClick(0);
    
javax.swing.plaf.basic.BasicMenuItemUI$HandlergetHandler()

        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    
public java.awt.DimensiongetMaximumSize(javax.swing.JComponent c)

	Dimension d = null;
 	View v = (View) c.getClientProperty(BasicHTML.propertyKey);
 	if (v != null) {
	    d = getPreferredSize(c);
 	    d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
 	}
 	return d;
    
private javax.swing.JComponentgetMenuItemParent(javax.swing.JMenuItem mi)

        Container parent = mi.getParent();
        if ((parent instanceof JComponent) &&
             (!(mi instanceof JMenu) ||
               !((JMenu)mi).isTopLevelMenu())) {
            return (JComponent) parent;
        } else {
            return null;
        }
    
public java.awt.DimensiongetMinimumSize(javax.swing.JComponent c)

	Dimension d = null;
 	View v = (View) c.getClientProperty(BasicHTML.propertyKey);
 	if (v != null) {
	    d = getPreferredSize(c);
 	    d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
 	}
 	return d;	
    
public javax.swing.MenuElement[]getPath()

        MenuSelectionManager m = MenuSelectionManager.defaultManager();
        MenuElement oldPath[] = m.getSelectedPath();
        MenuElement newPath[];
        int i = oldPath.length;
        if (i == 0)
            return new MenuElement[0];
        Component parent = menuItem.getParent();
        if (oldPath[i-1].getComponent() == parent) {
            // The parent popup menu is the last so far
            newPath = new MenuElement[i+1];
            System.arraycopy(oldPath, 0, newPath, 0, i);
            newPath[i] = menuItem;
        } else {
            // A sibling menuitem is the current selection
            // 
            //  This probably needs to handle 'exit submenu into 
            // a menu item.  Search backwards along the current
            // selection until you find the parent popup menu,
            // then copy up to that and add yourself...
            int j;
            for (j = oldPath.length-1; j >= 0; j--) {
                if (oldPath[j].getComponent() == parent)
                    break;
            }
            newPath = new MenuElement[j+2];
            System.arraycopy(oldPath, 0, newPath, 0, j+1);
            newPath[j+1] = menuItem;
            /*
            System.out.println("Sibling condition -- ");
            System.out.println("Old array : ");
            printMenuElementArray(oldPath, false);
            System.out.println("New array : ");
            printMenuElementArray(newPath, false);
            */
        }
        return newPath;
    
protected java.awt.DimensiongetPreferredMenuItemSize(javax.swing.JComponent c, javax.swing.Icon checkIcon, javax.swing.Icon arrowIcon, int defaultTextIconGap)

        JMenuItem b = (JMenuItem) c;
        
        Icon icon = null;
        /* 
         * in case .checkIconFactory is defined for this UI and the icon is 
         * compatible with it then the icon is handled by the checkIcon.
         * That is if useCheckAndArrow() is true.
         */
        MenuItemCheckIconFactory iconFactory = 
            (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() 
                + ".checkIconFactory");
        if (! useCheckAndArrow() 
                || iconFactory == null
                || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) {
           icon = b.getIcon();  
        }
        String text = b.getText();
        KeyStroke accelerator =  b.getAccelerator();
        String acceleratorText = "";

        if (accelerator != null) {
            int modifiers = accelerator.getModifiers();
            if (modifiers > 0) {
                acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
                //acceleratorText += "-";
                acceleratorText += acceleratorDelimiter;
          }
            int keyCode = accelerator.getKeyCode();
            if (keyCode != 0) {
                acceleratorText += KeyEvent.getKeyText(keyCode);
            } else {
                acceleratorText += accelerator.getKeyChar();
            }
        }

        Font font = b.getFont();
        FontMetrics fm = b.getFontMetrics(font);
        FontMetrics fmAccel = b.getFontMetrics( acceleratorFont );

        resetRects();
        
        layoutMenuItem(
                  fm, text, fmAccel, acceleratorText, icon, checkIcon, arrowIcon,
                  b.getVerticalAlignment(), b.getHorizontalAlignment(),
                  b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
                  viewRect, iconRect, textRect, acceleratorRect, checkIconRect, arrowIconRect,
                  text == null ? 0 : defaultTextIconGap,
                  defaultTextIconGap
                  );

        // labelRect contains size of text and label   
        Rectangle labelRect = iconRect.union(textRect);

        // Find the result height
        r.height = max(labelRect.height, checkIconRect.height,
                       arrowIconRect.height, acceleratorRect.height);
        
        // Find the result width

        // Add the leading gap, 
        // the closing one will be added by the latest addMaxWidth() call  
        r.width = defaultTextIconGap;

        // To determine the width of the parent popup menu (through DefaultMenuLayout) 
        // and to make accelerator texts appear in a column, 
        // find the widest icon, text, check icon, arrow icon and accelerator text.
        // For the latest menu item we will know them exactly.
        // It will be the widest menu item and it will determine 
        // the width of the parent popup menu.
        JComponent p = getMenuItemParent(menuItem);
        addMaxWidth(p, BasicMenuItemUI.MAX_ICON_WIDTH, iconRect.width, 
                defaultTextIconGap, false);
        addMaxWidth(p, BasicMenuItemUI.MAX_TEXT_WIDTH, textRect.width, 
                defaultTextIconGap, false);
        addMaxWidth(p, BasicMenuItemUI.MAX_ACC_WIDTH, acceleratorRect.width, 
                defaultTextIconGap, false);
	if( useCheckAndArrow() ) {
            // Force gap for the check icon to avoid absence of the gap between 
            // the text and arrow icon because of the layoutMenuItem() features
            addMaxWidth(p, BasicMenuItemUI.MAX_CHECK_ICON_WIDTH, 
                        checkIconRect.width, defaultTextIconGap, true);
            addMaxWidth(p, BasicMenuItemUI.MAX_ARROW_ICON_WIDTH, 
                        arrowIconRect.width, defaultTextIconGap, false);
        }	

        Insets insets = b.getInsets();
        if(insets != null) {
            r.width += insets.left + insets.right;
            r.height += insets.top + insets.bottom;
        }

        // if the width is even, bump it up one. This is critical
        // for the focus dash line to draw properly
        if(r.width%2 == 0) {
            r.width++;
        }

        // if the height is even, bump it up one. This is critical
        // for the text to center properly
        if(r.height%2 == 0 
                && Boolean.TRUE != 
                    UIManager.get(getPropertyPrefix() + ".evenHeight")) {
            r.height++;
        }
/*
	if(!(b instanceof JMenu && ((JMenu) b).isTopLevelMenu()) ) {
	    
	    // Container parent = menuItem.getParent();
	    JComponent p = (JComponent) parent;
	    
	    System.out.println("MaxText: "+p.getClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH));
	    System.out.println("MaxACC"+p.getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH));
	    
	    System.out.println("returning pref.width: " + r.width);
	    System.out.println("Current getSize: " + b.getSize() + "\n");
        }*/
	return r.getSize();
    
public java.awt.DimensiongetPreferredSize(javax.swing.JComponent c)

        return getPreferredMenuItemSize(c,
                                        checkIcon, 
                                        arrowIcon, 
                                        defaultTextIconGap);
    
protected java.lang.StringgetPropertyPrefix()

        return "MenuItem";
    
protected voidinstallComponents(javax.swing.JMenuItem menuItem)

since
1.3

 	BasicHTML.updateRenderer(menuItem, menuItem.getText());
    
protected voidinstallDefaults()

        String prefix = getPropertyPrefix();

        acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");

        Object opaque = UIManager.get(getPropertyPrefix() + ".opaque");
        if (opaque != null) {
            LookAndFeel.installProperty(menuItem, "opaque", opaque);
        }
        else {
            LookAndFeel.installProperty(menuItem, "opaque", Boolean.TRUE);
        }
        if(menuItem.getMargin() == null || 
           (menuItem.getMargin() instanceof UIResource)) {
            menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
        }

        LookAndFeel.installProperty(menuItem, "iconTextGap", new Integer(4));
        defaultTextIconGap = menuItem.getIconTextGap();

        LookAndFeel.installBorder(menuItem, prefix + ".border");
        oldBorderPainted = menuItem.isBorderPainted();
        LookAndFeel.installProperty(menuItem, "borderPainted",
                                    UIManager.get(prefix + ".borderPainted"));
        LookAndFeel.installColorsAndFont(menuItem,
                                         prefix + ".background",
                                         prefix + ".foreground",
                                         prefix + ".font");
        
        // MenuItem specific defaults
        if (selectionBackground == null || 
            selectionBackground instanceof UIResource) {
            selectionBackground = 
                UIManager.getColor(prefix + ".selectionBackground");
        }
        if (selectionForeground == null || 
            selectionForeground instanceof UIResource) {
            selectionForeground = 
                UIManager.getColor(prefix + ".selectionForeground");
        }
        if (disabledForeground == null || 
            disabledForeground instanceof UIResource) {
            disabledForeground = 
                UIManager.getColor(prefix + ".disabledForeground");
        }
        if (acceleratorForeground == null || 
            acceleratorForeground instanceof UIResource) {
            acceleratorForeground = 
                UIManager.getColor(prefix + ".acceleratorForeground");
        }
        if (acceleratorSelectionForeground == null || 
            acceleratorSelectionForeground instanceof UIResource) {
            acceleratorSelectionForeground = 
                UIManager.getColor(prefix + ".acceleratorSelectionForeground");
        }
	// Get accelerator delimiter
	acceleratorDelimiter = 
	    UIManager.getString("MenuItem.acceleratorDelimiter");
	if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; }
        // Icons
        if (arrowIcon == null ||
            arrowIcon instanceof UIResource) {
            arrowIcon = UIManager.getIcon(prefix + ".arrowIcon");
        }
        if (checkIcon == null ||
            checkIcon instanceof UIResource) {
            checkIcon = UIManager.getIcon(prefix + ".checkIcon");
            MenuItemCheckIconFactory iconFactory = 
                (MenuItemCheckIconFactory) UIManager.get(prefix 
                    + ".checkIconFactory");
            if (iconFactory != null
                    && iconFactory.isCompatible(checkIcon, prefix)) {
                checkIcon = iconFactory.getIcon(menuItem);
            }
        }
    
protected voidinstallKeyboardActions()

        installLazyActionMap();
	updateAcceleratorBinding();
    
voidinstallLazyActionMap()

        LazyActionMap.installLazyActionMap(menuItem, BasicMenuItemUI.class,
                                           getPropertyPrefix() + ".actionMap");
    
protected voidinstallListeners()

	if ((mouseInputListener = createMouseInputListener(menuItem)) != null) {
	    menuItem.addMouseListener(mouseInputListener);
	    menuItem.addMouseMotionListener(mouseInputListener);
	}
        if ((menuDragMouseListener = createMenuDragMouseListener(menuItem)) != null) {
	    menuItem.addMenuDragMouseListener(menuDragMouseListener);
	}
	if ((menuKeyListener = createMenuKeyListener(menuItem)) != null) {
	    menuItem.addMenuKeyListener(menuKeyListener);
	}
	if ((propertyChangeListener = createPropertyChangeListener(menuItem)) != null) {
	    menuItem.addPropertyChangeListener(propertyChangeListener);
	}
    
public voidinstallUI(javax.swing.JComponent c)

        menuItem = (JMenuItem) c;

        installDefaults();
        installComponents(menuItem);
        installListeners();
        installKeyboardActions();
    
private booleanisInternalFrameSystemMenu()
This is to see if the menu item in question is part of the system menu on an internal frame. The Strings that are being checked can be found in MetalInternalFrameTitlePaneUI.java, WindowsInternalFrameTitlePaneUI.java, and MotifInternalFrameTitlePaneUI.java.

since
1.4

	String actionCommand = menuItem.getActionCommand();
 	if ((actionCommand == "Close") ||
	    (actionCommand == "Minimize") ||
	    (actionCommand == "Restore") ||
	    (actionCommand == "Maximize")) {
	  return true;
	} else {
	  return false;
	} 
    
private java.lang.StringlayoutMenuItem(java.awt.FontMetrics fm, java.lang.String text, java.awt.FontMetrics fmAccel, java.lang.String acceleratorText, javax.swing.Icon icon, javax.swing.Icon checkIcon, javax.swing.Icon arrowIcon, int verticalAlignment, int horizontalAlignment, int verticalTextPosition, int horizontalTextPosition, java.awt.Rectangle viewRect, java.awt.Rectangle iconRect, java.awt.Rectangle textRect, java.awt.Rectangle acceleratorRect, java.awt.Rectangle checkIconRect, java.awt.Rectangle arrowIconRect, int textIconGap, int menuItemGap)
Compute and return the location of the icons origin, the location of origin of the text baseline, and a possibly clipped version of the compound labels string. Locations are computed relative to the viewRect rectangle.


        SwingUtilities.layoutCompoundLabel(
                            menuItem, fm, text, icon, verticalAlignment, 
                            horizontalAlignment, verticalTextPosition, 
                            horizontalTextPosition, viewRect, iconRect, textRect, 
                            textIconGap);

        /* Initialize the acceelratorText bounds rectangle textRect.  If a null 
         * or and empty String was specified we substitute "" here 
         * and use 0,0,0,0 for acceleratorTextRect.
         */
        if( (acceleratorText == null) || acceleratorText.equals("") ) {
            acceleratorRect.width = acceleratorRect.height = 0;
            acceleratorText = "";
        }
        else {
            acceleratorRect.width = SwingUtilities2.stringWidth(
                                         menuItem, fmAccel, acceleratorText);
            acceleratorRect.height = fmAccel.getHeight();
        }

        /* Initialize the checkIcon bounds rectangle's width & height.
         */

	if( useCheckAndArrow()) {
	    if (checkIcon != null) {
		checkIconRect.width = checkIcon.getIconWidth();
		checkIconRect.height = checkIcon.getIconHeight();
	    } 
	    else {
		checkIconRect.width = checkIconRect.height = 0;
	    }
	    
	    /* Initialize the arrowIcon bounds rectangle width & height.
	     */
	    
	    if (arrowIcon != null) {
		arrowIconRect.width = arrowIcon.getIconWidth();
		arrowIconRect.height = arrowIcon.getIconHeight();
	    } else {
		arrowIconRect.width = arrowIconRect.height = 0;
	    }
        }

        JComponent p = getMenuItemParent(menuItem);

        Rectangle labelRect = iconRect.union(textRect);        
        
        int checkIconOffset = menuItemGap;
        Object checkIconOffsetObject = 
            UIManager.get(getPropertyPrefix() + ".checkIconOffset");
        if (checkIconOffsetObject instanceof Integer) {
            checkIconOffset = (Integer) checkIconOffsetObject;
        }
        if( BasicGraphicsUtils.isLeftToRight(menuItem) ) {
            /* get minimum text offset. It is defined for LTR case only. */
            int minimumTextOffset = 0;
            Object minimumTextOffsetObject = 
                UIManager.get(getPropertyPrefix() 
                    + ".minimumTextOffset");
            if (minimumTextOffsetObject instanceof Integer) {
                minimumTextOffset = (Integer) minimumTextOffsetObject;
            }
            textRect.x += menuItemGap;
            iconRect.x += menuItemGap;

            // Position the Accelerator text rect
            acceleratorRect.x = viewRect.x + viewRect.width - arrowIconRect.width 
                             - menuItemGap - acceleratorRect.width;
            
            // Position the Check and Arrow Icons 
            if (useCheckAndArrow()) {
                checkIconRect.x = viewRect.x + checkIconOffset;
                if(icon == null || checkIcon != null) {
                    iconRect.x += menuItemGap + checkIconRect.width;
                }
                textRect.x += menuItemGap + checkIconRect.width;                
                textRect.x = Math.max(textRect.x, minimumTextOffset);
                arrowIconRect.x = viewRect.x + viewRect.width - menuItemGap
                                  - arrowIconRect.width;
            }
            /* Align icons and text vertically */
            if(p != null) {
                Integer maxIconOffset = (Integer)
                         p.getClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET);
                Integer maxTextOffset = (Integer)
                         p.getClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET);
                int maxIconValue = maxIconOffset == null ? 0 : maxIconOffset;
                int maxTextValue = maxTextOffset == null ? 0 : maxTextOffset;

                int thisTextOffset = textRect.x - viewRect.x;
                if(thisTextOffset > maxTextValue) {
                    p.putClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET,
                                        new Integer(thisTextOffset));
                } else {
                    textRect.x = maxTextValue + viewRect.x;
                }

                if(icon != null) {
                    if(horizontalTextPosition == SwingConstants.TRAILING ||
                       horizontalTextPosition == SwingConstants.RIGHT) {
                        int thisIconOffset = iconRect.x - viewRect.x;
                        if(thisIconOffset > maxIconValue) {
                            p.putClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET,
                                    new Integer(thisIconOffset));
                        } else {
                            iconRect.x = maxIconValue+viewRect.x;
                        }
                    } else if(horizontalTextPosition
                                  == SwingConstants.LEADING ||
                              horizontalTextPosition == SwingConstants.LEFT) {
                        iconRect.x = textRect.x + textRect.width + menuItemGap;
                    } else {
                        iconRect.x = Math.max(textRect.x + textRect.width/2
                            - iconRect.width/2, maxIconValue + viewRect.x);

                    }
                }
            }
        } else {
            textRect.x -= menuItemGap;
            iconRect.x -= menuItemGap;

            // Position the Accelerator text rect
            acceleratorRect.x = viewRect.x + arrowIconRect.width + menuItemGap;

            // Position the Check and Arrow Icons 
            if (useCheckAndArrow()) {
                checkIconRect.x = viewRect.x + viewRect.width - checkIconOffset
                                  - checkIconRect.width;
                if(icon == null || checkIcon != null) {
                    iconRect.x -= menuItemGap + checkIconRect.width;      
                }
                textRect.x -= menuItemGap + checkIconRect.width;
                arrowIconRect.x = viewRect.x + menuItemGap;
            }
            /* Align icons and text vertically */
            if(p != null) {
                Integer maxIconOffset = (Integer)
                         p.getClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET);
                Integer maxTextOffset = (Integer)
                         p.getClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET);
                int maxIconValue =  maxIconOffset == null ? 0 : maxIconOffset;
                int maxTextValue =  maxTextOffset == null ? 0 : maxTextOffset;

                int thisTextOffset = viewRect.x + viewRect.width
                                     - textRect.x - textRect.width;
                if(thisTextOffset > maxTextValue) {
                    p.putClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET,
                                        new Integer(thisTextOffset));
                } else {
                    textRect.x = viewRect.x + viewRect.width
                                 - maxTextValue - textRect.width;
                }

                int thisIconOffset = 0;
                if(icon != null) {
                    if(horizontalTextPosition == SwingConstants.TRAILING ||
                       horizontalTextPosition == SwingConstants.LEFT) {
                        thisIconOffset = viewRect.x + viewRect.width
                                - iconRect.x - iconRect.width;
                        if(thisIconOffset > maxIconValue) {
                            p.putClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET,
                                    new Integer(thisIconOffset));
                        } else {
                            iconRect.x = viewRect.x + viewRect.width
                                    - maxIconValue - iconRect.width;
                        }
                    } else if(horizontalTextPosition
                                  == SwingConstants.LEADING ||
                              horizontalTextPosition == SwingConstants.RIGHT) {
                        iconRect.x = textRect.x - menuItemGap - iconRect.width;
                    } else {
                        iconRect.x = textRect.x + textRect.width/2
                                     - iconRect.width/2;
                        if(iconRect.x + iconRect.width >
                               viewRect.x + viewRect.width - maxIconValue  ) {
                            iconRect.x = iconRect.x = viewRect.x +
                                viewRect.width - maxIconValue - iconRect.width;
                        }
                    }
                }
            }
        }

        // Align the accelertor text and the check and arrow icons vertically
        // with the center of the label rect.  
        acceleratorRect.y = labelRect.y + (labelRect.height/2) - (acceleratorRect.height/2);
        if( useCheckAndArrow() ) {
            arrowIconRect.y = labelRect.y + (labelRect.height/2) - (arrowIconRect.height/2);
            checkIconRect.y = labelRect.y + (labelRect.height/2) - (checkIconRect.height/2);
        }

        /*
        System.out.println("Layout: text="+menuItem.getText()+"\n\tv="
                           +viewRect+"\n\tc="+checkIconRect+"\n\ti="
                           +iconRect+"\n\tt="+textRect+"\n\tacc="
                           +acceleratorRect+"\n\ta="+arrowIconRect+"\n");
        */
        
        return text;
    
static voidloadActionMap(javax.swing.plaf.basic.LazyActionMap map)


        
        // NOTE: BasicMenuUI also calls into this method.
	map.put(new Actions(Actions.CLICK));
        BasicLookAndFeel.installAudioActionMap(map);
    
private intmax(int values)

        int maxValue = Integer.MIN_VALUE;
        for (int i : values) {
            if (i > maxValue) {
                maxValue = i;
            }
        }
        return maxValue;
    
public voidpaint(java.awt.Graphics g, javax.swing.JComponent c)

        paintMenuItem(g, c, checkIcon, arrowIcon,
                      selectionBackground, selectionForeground,
                      defaultTextIconGap);
    
protected voidpaintBackground(java.awt.Graphics g, javax.swing.JMenuItem menuItem, java.awt.Color bgColor)
Draws the background of the menu item.

param
g the paint graphics
param
menuItem menu item to be painted
param
bgColor selection background color
since
1.4

	ButtonModel model = menuItem.getModel();
        Color oldColor = g.getColor();
        int menuWidth = menuItem.getWidth();
        int menuHeight = menuItem.getHeight();

        if(menuItem.isOpaque()) {
            if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) {
                g.setColor(bgColor);
                g.fillRect(0,0, menuWidth, menuHeight);
            } else {
                g.setColor(menuItem.getBackground());
                g.fillRect(0,0, menuWidth, menuHeight);
            }
            g.setColor(oldColor);
        }
        else if (model.isArmed() || (menuItem instanceof JMenu &&
                                     model.isSelected())) {
            g.setColor(bgColor);
            g.fillRect(0,0, menuWidth, menuHeight);
            g.setColor(oldColor);
        }
    
protected voidpaintMenuItem(java.awt.Graphics g, javax.swing.JComponent c, javax.swing.Icon checkIcon, javax.swing.Icon arrowIcon, java.awt.Color background, java.awt.Color foreground, int defaultTextIconGap)

        JMenuItem b = (JMenuItem) c;
        ButtonModel model = b.getModel();

        //   Dimension size = b.getSize();
        int menuWidth = b.getWidth();
        int menuHeight = b.getHeight();
        Insets i = c.getInsets();
	
        resetRects();

        viewRect.setBounds( 0, 0, menuWidth, menuHeight );

        viewRect.x += i.left;
        viewRect.y += i.top;
        viewRect.width -= (i.right + viewRect.x);
        viewRect.height -= (i.bottom + viewRect.y);


        Font holdf = g.getFont();
        Font f = c.getFont();
        g.setFont( f );
        FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
        FontMetrics fmAccel = SwingUtilities2.getFontMetrics(
                                   c, g, acceleratorFont);

        // get Accelerator text
        KeyStroke accelerator =  b.getAccelerator();
        String acceleratorText = "";
        if (accelerator != null) {
            int modifiers = accelerator.getModifiers();
            if (modifiers > 0) {
                acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
                //acceleratorText += "-";
                acceleratorText += acceleratorDelimiter;
	    }

            int keyCode = accelerator.getKeyCode();
            if (keyCode != 0) {
                acceleratorText += KeyEvent.getKeyText(keyCode);
            } else {
                acceleratorText += accelerator.getKeyChar();
            }
        }
        Icon icon = null;
        /* 
         * in case .checkIconFactory is defined for this UI and the icon is 
         * compatible with it then the icon is handled by the checkIcon.
         * That is if useCheckAndArrow() is true.
         */
        MenuItemCheckIconFactory iconFactory = 
            (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() 
                + ".checkIconFactory");
        if (! useCheckAndArrow() 
                || iconFactory == null
                || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) {
           icon = b.getIcon();  
        }
        // layout the text and icon
        String text = layoutMenuItem(
            fm, b.getText(), fmAccel, acceleratorText, icon,
            checkIcon, arrowIcon,
            b.getVerticalAlignment(), b.getHorizontalAlignment(),
            b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
            viewRect, iconRect, textRect, acceleratorRect, 
            checkIconRect, arrowIconRect,
            b.getText() == null ? 0 : defaultTextIconGap,
            defaultTextIconGap
        ); 
        // Paint background
	paintBackground(g, b, background);

        Color holdc = g.getColor();

        // Paint the Check
        if (checkIcon != null) {
            if(model.isArmed() || (c instanceof JMenu && model.isSelected())) {
                g.setColor(foreground);
            } else {
                g.setColor(holdc);
            }
            if( useCheckAndArrow() )
		checkIcon.paintIcon(c, g, checkIconRect.x, checkIconRect.y);
            g.setColor(holdc);
        }

        // Paint the Icon
        if(icon != null ) { 
            if(!model.isEnabled()) {
                icon = (Icon) b.getDisabledIcon();
            } else if(model.isPressed() && model.isArmed()) {
                icon = (Icon) b.getPressedIcon();
                if(icon == null) {
                    // Use default icon
                    icon = (Icon) b.getIcon();
                } 
            } else {
                icon = (Icon) b.getIcon();
            }
              
            if (icon!=null) {
                icon.paintIcon(c, g, iconRect.x, iconRect.y);
                g.setColor(holdc);
            }
        }

        // Draw the Text
        if(text != null) {
 	    View v = (View) c.getClientProperty(BasicHTML.propertyKey);
 	    if (v != null) {
 		v.paint(g, textRect);
 	    } else {
		paintText(g, b, textRect, text);
	    }
	}
	
        // Draw the Accelerator Text
        if(acceleratorText != null && !acceleratorText.equals("")) {

	  //Get the maxAccWidth from the parent to calculate the offset.
	  int accOffset = 0;
          JComponent p = getMenuItemParent(menuItem);
          if(p != null) {
	    Integer maxValueInt = (Integer) p.getClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH);
	    int maxValue = maxValueInt != null ?
                maxValueInt.intValue() : acceleratorRect.width;

	    //Calculate the offset, with which the accelerator texts will be drawn with.
	    accOffset = maxValue - acceleratorRect.width;
	  }
	  
	  g.setFont( acceleratorFont );
            if(!model.isEnabled()) {
                // *** paint the acceleratorText disabled
	      if ( disabledForeground != null )
		  {
                  g.setColor( disabledForeground );
                  SwingUtilities2.drawString(b, g,acceleratorText,
                                                acceleratorRect.x - accOffset, 
                                                acceleratorRect.y + fmAccel.getAscent());
                }
                else
                {
                  g.setColor(b.getBackground().brighter());
                  SwingUtilities2.drawString(b, g,acceleratorText,
                                                acceleratorRect.x - accOffset, 
						acceleratorRect.y + fmAccel.getAscent());
                  g.setColor(b.getBackground().darker());
                  SwingUtilities2.drawString(b, g,acceleratorText,
                                                acceleratorRect.x - accOffset - 1, 
						acceleratorRect.y + fmAccel.getAscent() - 1);
                }
            } else {
                // *** paint the acceleratorText normally
                if (model.isArmed()|| (c instanceof JMenu && model.isSelected())) {
                    g.setColor( acceleratorSelectionForeground );
                } else {
                    g.setColor( acceleratorForeground );
                }
                SwingUtilities2.drawString(b, g,acceleratorText,
                                              acceleratorRect.x - accOffset,
                                              acceleratorRect.y + fmAccel.getAscent());
            }
        }

        // Paint the Arrow
        if (arrowIcon != null) {
            if(model.isArmed() || (c instanceof JMenu &&model.isSelected()))
                g.setColor(foreground);
            if(useCheckAndArrow())
                arrowIcon.paintIcon(c, g, arrowIconRect.x, arrowIconRect.y);
        }
        g.setColor(holdc);
        g.setFont(holdf);
    
protected voidpaintText(java.awt.Graphics g, javax.swing.JMenuItem menuItem, java.awt.Rectangle textRect, java.lang.String text)
Renders the text of the current menu item.

param
g graphics context
param
menuItem menu item to render
param
textRect bounding rectangle for rendering the text
param
text string to render
since
1.4

	ButtonModel model = menuItem.getModel();
	FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g);
	int mnemIndex = menuItem.getDisplayedMnemonicIndex();

	if(!model.isEnabled()) {
	    // *** paint the text disabled
	    if ( UIManager.get("MenuItem.disabledForeground") instanceof Color ) {
		g.setColor( UIManager.getColor("MenuItem.disabledForeground") );
		SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
                          mnemIndex, textRect.x,  textRect.y + fm.getAscent());
	    } else {
		g.setColor(menuItem.getBackground().brighter());
		SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text,
                           mnemIndex, textRect.x, textRect.y + fm.getAscent());
		g.setColor(menuItem.getBackground().darker());
		SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
                           mnemIndex,  textRect.x - 1, textRect.y +
                           fm.getAscent() - 1);
	    }
	} else {
	    // *** paint the text normally
	    if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) {
		g.setColor(selectionForeground); // Uses protected field.
	    }
	    SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text,
                           mnemIndex, textRect.x, textRect.y + fm.getAscent());
	}
    
voidprintMenuElementArray(javax.swing.MenuElement[] path, boolean dumpStack)

        System.out.println("Path is(");
        int i, j;
        for(i=0,j=path.length; i<j ;i++){
            for (int k=0; k<=i; k++)
                System.out.print("  ");
            MenuElement me = (MenuElement) path[i];
            if(me instanceof JMenuItem) 
                System.out.println(((JMenuItem)me).getText() + ", ");
            else if (me == null)
                System.out.println("NULL , ");
            else
                System.out.println("" + me + ", ");
        }
        System.out.println(")");

        if (dumpStack == true)
            Thread.dumpStack();
    
private voidresetRects()


       
        iconRect.setBounds(zeroRect);
        textRect.setBounds(zeroRect);
        acceleratorRect.setBounds(zeroRect);
        checkIconRect.setBounds(zeroRect);
        arrowIconRect.setBounds(zeroRect);
        viewRect.setBounds(0,0,Short.MAX_VALUE, Short.MAX_VALUE);
        r.setBounds(zeroRect);
    
protected voiduninstallComponents(javax.swing.JMenuItem menuItem)

since
1.3

	BasicHTML.updateRenderer(menuItem, "");
    
protected voiduninstallDefaults()

        LookAndFeel.uninstallBorder(menuItem);
        LookAndFeel.installProperty(menuItem, "borderPainted", oldBorderPainted);
        if (menuItem.getMargin() instanceof UIResource)
            menuItem.setMargin(null);
        if (arrowIcon instanceof UIResource)
            arrowIcon = null;
        if (checkIcon instanceof UIResource)
            checkIcon = null;
    
protected voiduninstallKeyboardActions()

	SwingUtilities.replaceUIActionMap(menuItem, null);
        SwingUtilities.replaceUIInputMap(menuItem, JComponent.
                                         WHEN_IN_FOCUSED_WINDOW, null);
    
protected voiduninstallListeners()

	if (mouseInputListener != null) {
	    menuItem.removeMouseListener(mouseInputListener);
	    menuItem.removeMouseMotionListener(mouseInputListener);
	}
	if (menuDragMouseListener != null) {
	    menuItem.removeMenuDragMouseListener(menuDragMouseListener);
	}
	if (menuKeyListener != null) {
	    menuItem.removeMenuKeyListener(menuKeyListener);
	}
	if (propertyChangeListener != null) {
	    menuItem.removePropertyChangeListener(propertyChangeListener);
	}

        mouseInputListener = null;
        menuDragMouseListener = null;
        menuKeyListener = null;
        propertyChangeListener = null;
        handler = null;
    
public voiduninstallUI(javax.swing.JComponent c)

	menuItem = (JMenuItem)c;
        uninstallDefaults();
        uninstallComponents(menuItem);
        uninstallListeners();
        uninstallKeyboardActions();

	
	//Remove the textWidth and accWidth values from the parent's Client Properties.
        JComponent p = getMenuItemParent(menuItem);
        if(p != null) {
            p.putClientProperty(BasicMenuItemUI.MAX_CHECK_ICON_WIDTH, null );
            p.putClientProperty(BasicMenuItemUI.MAX_ARROW_ICON_WIDTH, null );
	    p.putClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH, null );
	    p.putClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH, null ); 
            p.putClientProperty(BasicMenuItemUI.MAX_ICON_WIDTH, null ); 
            p.putClientProperty(BasicMenuItemUI.MAX_ICON_OFFSET, null );
            p.putClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET, null );
	}

	menuItem = null;
    
public voidupdate(java.awt.Graphics g, javax.swing.JComponent c)
We draw the background in paintMenuItem() so override update (which fills the background of opaque components by default) to just call paint().

        paint(g, c);
    
voidupdateAcceleratorBinding()

	KeyStroke accelerator = menuItem.getAccelerator();
        InputMap windowInputMap = SwingUtilities.getUIInputMap(
                       menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);

	if (windowInputMap != null) {
	    windowInputMap.clear();
	}
	if (accelerator != null) {
	    if (windowInputMap == null) {
		windowInputMap = createInputMap(JComponent.
						WHEN_IN_FOCUSED_WINDOW);
		SwingUtilities.replaceUIInputMap(menuItem,
			   JComponent.WHEN_IN_FOCUSED_WINDOW, windowInputMap);
	    }
	    windowInputMap.put(accelerator, "doClick");
	}
    
private booleanuseCheckAndArrow()

	boolean b = true;
	if((menuItem instanceof JMenu) &&
	   (((JMenu)menuItem).isTopLevelMenu())) {
	    b = false;
	}
	return b;