972 lines · 36.7 KB · Java
RawDownload
/* * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.basic; import java.awt.*;import java.awt.event.*;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener; import javax.swing.*;import javax.swing.event.*;import javax.swing.plaf.*;import javax.swing.text.View; import sun.swing.*; /** * BasicMenuItem implementation * * @author Georges Saab * @author David Karlton * @author Arnaud Weber * @author Fredrik Lagerblad */public class BasicMenuItemUI extends MenuItemUI{    protected JMenuItem menuItem = null;    protected Color selectionBackground;    protected Color selectionForeground;    protected Color disabledForeground;    protected Color acceleratorForeground;    protected Color acceleratorSelectionForeground;     /**     * Accelerator delimiter string, such as {@code '+'} in {@code 'Ctrl+C'}.     * @since 1.7     */    protected String acceleratorDelimiter;     protected int defaultTextIconGap;    protected Font acceleratorFont;     protected MouseInputListener mouseInputListener;    protected MenuDragMouseListener menuDragMouseListener;    protected MenuKeyListener menuKeyListener;    /**     * <code>PropertyChangeListener</code> returned from     * <code>createPropertyChangeListener</code>. You should not     * need to access this field, rather if you want to customize the     * <code>PropertyChangeListener</code> override     * <code>createPropertyChangeListener</code>.     *     * @since 1.6     * @see #createPropertyChangeListener     */    protected PropertyChangeListener propertyChangeListener;    // BasicMenuUI also uses this.    Handler handler;     protected Icon arrowIcon = null;    protected Icon checkIcon = null;     protected boolean oldBorderPainted;     /* diagnostic aids -- should be false for production builds. */    private static final boolean TRACE =   false; // trace creates and disposes     private static final boolean VERBOSE = false; // show reuse hits/misses    private static final boolean DEBUG =   false;  // show bad params, misc.     static void loadActionMap(LazyActionMap map) {        // NOTE: BasicMenuUI also calls into this method.        map.put(new Actions(Actions.CLICK));        BasicLookAndFeel.installAudioActionMap(map);    }     public static ComponentUI createUI(JComponent c) {        return new BasicMenuItemUI();    }     public void installUI(JComponent c) {        menuItem = (JMenuItem) c;         installDefaults();        installComponents(menuItem);        installListeners();        installKeyboardActions();    }      protected void installDefaults() {        String prefix = getPropertyPrefix();         acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");        // use default if missing so that BasicMenuItemUI can be used in other        // LAFs like Nimbus        if (acceleratorFont == null) {            acceleratorFont = UIManager.getFont("MenuItem.font");        }         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", Integer.valueOf(4));        defaultTextIconGap = menuItem.getIconTextGap();         LookAndFeel.installBorder(menuItem, prefix + ".border");        oldBorderPainted = menuItem.isBorderPainted();        LookAndFeel.installProperty(menuItem, "borderPainted",                                    UIManager.getBoolean(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");            //In case of column layout, .checkIconFactory is defined for this UI,            //the icon is compatible with it and useCheckAndArrow() is true,            //then the icon is handled by the checkIcon.            boolean isColumnLayout = MenuItemLayoutHelper.isColumnLayout(                    BasicGraphicsUtils.isLeftToRight(menuItem), menuItem);            if (isColumnLayout) {                MenuItemCheckIconFactory iconFactory =                    (MenuItemCheckIconFactory) UIManager.get(prefix                        + ".checkIconFactory");                if (iconFactory != null                        && MenuItemLayoutHelper.useCheckAndArrow(menuItem)                        && iconFactory.isCompatible(checkIcon, prefix)) {                    checkIcon = iconFactory.getIcon(menuItem);                }            }        }    }     /**     * @since 1.3     */    protected void installComponents(JMenuItem menuItem){        BasicHTML.updateRenderer(menuItem, menuItem.getText());    }     protected String getPropertyPrefix() {        return "MenuItem";    }     protected void installListeners() {        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);        }    }     protected void installKeyboardActions() {        installLazyActionMap();        updateAcceleratorBinding();    }     void installLazyActionMap() {        LazyActionMap.installLazyActionMap(menuItem, BasicMenuItemUI.class,                                           getPropertyPrefix() + ".actionMap");    }     public void uninstallUI(JComponent c) {        menuItem = (JMenuItem)c;        uninstallDefaults();        uninstallComponents(menuItem);        uninstallListeners();        uninstallKeyboardActions();        MenuItemLayoutHelper.clearUsedParentClientProperties(menuItem);        menuItem = null;    }      protected void uninstallDefaults() {        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;    }     /**     * @since 1.3     */    protected void uninstallComponents(JMenuItem menuItem){        BasicHTML.updateRenderer(menuItem, "");    }     protected void uninstallListeners() {        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;    }     protected void uninstallKeyboardActions() {        SwingUtilities.replaceUIActionMap(menuItem, null);        SwingUtilities.replaceUIInputMap(menuItem, JComponent.                                         WHEN_IN_FOCUSED_WINDOW, null);    }     protected MouseInputListener createMouseInputListener(JComponent c) {        return getHandler();    }     protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) {        return getHandler();    }     protected MenuKeyListener createMenuKeyListener(JComponent c) {        return null;    }     /**     * Creates a <code>PropertyChangeListener</code> 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 <code>PropertyChangeListener</code> or null     * @since 1.6     */    protected PropertyChangeListener                                  createPropertyChangeListener(JComponent c) {        return getHandler();    }     Handler getHandler() {        if (handler == null) {            handler = new Handler();        }        return handler;    }     InputMap createInputMap(int condition) {        if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {            return new ComponentInputMapUIResource(menuItem);        }        return null;    }     void updateAcceleratorBinding() {        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");        }    }     public Dimension getMinimumSize(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 Dimension getPreferredSize(JComponent c) {        return getPreferredMenuItemSize(c,                                        checkIcon,                                        arrowIcon,                                        defaultTextIconGap);    }     public Dimension getMaximumSize(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;    }     protected Dimension getPreferredMenuItemSize(JComponent c,                                                 Icon checkIcon,                                                 Icon arrowIcon,                                                 int defaultTextIconGap) {         // The method also determines the preferred width of the        // parent popup menu (through DefaultMenuLayout class).        // The menu width equals to the maximal width        // among child menu items.         // Menu item width will be a sum of the widest check icon, label,        // arrow icon and accelerator text among neighbor menu items.        // For the latest menu item we will know the maximal widths exactly.        // It will be the widest menu item and it will determine        // the width of the parent popup menu.         // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!        // There is a conceptual problem: if user sets preferred size manually        // for a menu item, this method won't be called for it        // (see JComponent.getPreferredSize()),        // maximal widths won't be calculated, other menu items won't be able        // to take them into account and will be layouted in such a way,        // as there is no the item with manual preferred size.        // But after the first paint() method call, all maximal widths        // will be correctly calculated and layout of some menu items        // can be changed. For example, it can cause a shift of        // the icon and text when user points a menu item by mouse.         JMenuItem mi = (JMenuItem) c;        MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,                arrowIcon, MenuItemLayoutHelper.createMaxRect(), defaultTextIconGap,                acceleratorDelimiter, BasicGraphicsUtils.isLeftToRight(mi),                mi.getFont(), acceleratorFont,                MenuItemLayoutHelper.useCheckAndArrow(menuItem),                getPropertyPrefix());         Dimension result = new Dimension();         // Calculate the result width        result.width = lh.getLeadingGap();        MenuItemLayoutHelper.addMaxWidth(lh.getCheckSize(),                lh.getAfterCheckIconGap(), result);        // Take into account mimimal text offset.        if ((!lh.isTopLevelMenu())                && (lh.getMinTextOffset() > 0)                && (result.width < lh.getMinTextOffset())) {            result.width = lh.getMinTextOffset();        }        MenuItemLayoutHelper.addMaxWidth(lh.getLabelSize(), lh.getGap(), result);        MenuItemLayoutHelper.addMaxWidth(lh.getAccSize(), lh.getGap(), result);        MenuItemLayoutHelper.addMaxWidth(lh.getArrowSize(), lh.getGap(), result);         // Calculate the result height        result.height = MenuItemLayoutHelper.max(lh.getCheckSize().getHeight(),                lh.getLabelSize().getHeight(), lh.getAccSize().getHeight(),                lh.getArrowSize().getHeight());         // Take into account menu item insets        Insets insets = lh.getMenuItem().getInsets();        if(insets != null) {            result.width += insets.left + insets.right;            result.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(result.width%2 == 0) {            result.width++;        }         // if the height is even, bump it up one. This is critical        // for the text to center properly        if(result.height%2 == 0                && Boolean.TRUE !=                    UIManager.get(getPropertyPrefix() + ".evenHeight")) {            result.height++;        }         return result;    }     /**     * We draw the background in paintMenuItem()     * so override update (which fills the background of opaque     * components by default) to just call paint().     *     */    public void update(Graphics g, JComponent c) {        paint(g, c);    }     public void paint(Graphics g, JComponent c) {        paintMenuItem(g, c, checkIcon, arrowIcon,                      selectionBackground, selectionForeground,                      defaultTextIconGap);    }     protected void paintMenuItem(Graphics g, JComponent c,                                     Icon checkIcon, Icon arrowIcon,                                     Color background, Color foreground,                                     int defaultTextIconGap) {        // Save original graphics font and color        Font holdf = g.getFont();        Color holdc = g.getColor();         JMenuItem mi = (JMenuItem) c;        g.setFont(mi.getFont());         Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());        applyInsets(viewRect, mi.getInsets());         MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,                arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter,                BasicGraphicsUtils.isLeftToRight(mi), mi.getFont(),                acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),                getPropertyPrefix());        MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem(); 

Lines 1–500 of 972.