Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]

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

Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]