rev 53939 : 8213116: javax/swing/JComboBox/WindowsComboBoxSize/WindowsComboBoxSizeTest.java fails in Windows
Reviewed-by: prr

   1 /*
   2  * Copyright (c) 1997, 2014, 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 com.sun.java.swing.plaf.windows;
  27 
  28 import java.beans.PropertyChangeListener;
  29 import java.beans.PropertyChangeEvent;
  30 import javax.swing.plaf.basic.*;
  31 import javax.swing.plaf.*;
  32 import javax.swing.border.*;
  33 import javax.swing.*;
  34 import java.awt.event.*;
  35 import java.awt.*;
  36 
  37 import static com.sun.java.swing.plaf.windows.TMSchema.Part;
  38 import static com.sun.java.swing.plaf.windows.TMSchema.State;
  39 import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
  40 
  41 import sun.swing.DefaultLookup;
  42 import sun.swing.StringUIClientPropertyKey;
  43 
  44 import com.sun.java.swing.plaf.windows.WindowsBorders.DashedBorder;
  45 
  46 /**
  47  * Windows combo box.
  48  * <p>
  49  * <strong>Warning:</strong>
  50  * Serialized objects of this class will not be compatible with
  51  * future Swing releases.  The current serialization support is appropriate
  52  * for short term storage or RMI between applications running the same
  53  * version of Swing.  A future release of Swing will provide support for
  54  * long term persistence.
  55  *
  56  * @author Tom Santos
  57  * @author Igor Kushnirskiy
  58  */
  59 
  60 public class WindowsComboBoxUI extends BasicComboBoxUI {
  61 
  62     private static final MouseListener rolloverListener =
  63         new MouseAdapter() {
  64             private void handleRollover(MouseEvent e, boolean isRollover) {
  65                 JComboBox<?> comboBox = getComboBox(e);
  66                 WindowsComboBoxUI comboBoxUI = getWindowsComboBoxUI(e);
  67                 if (comboBox == null || comboBoxUI == null) {
  68                     return;
  69                 }
  70                 if (! comboBox.isEditable()) {
  71                     //mouse over editable ComboBox does not switch rollover
  72                     //for the arrow button
  73                     ButtonModel m = null;
  74                     if (comboBoxUI.arrowButton != null) {
  75                         m = comboBoxUI.arrowButton.getModel();
  76                     }
  77                     if (m != null ) {
  78                         m.setRollover(isRollover);
  79                     }
  80                 }
  81                 comboBoxUI.isRollover = isRollover;
  82                 comboBox.repaint();
  83             }
  84 
  85             public void mouseEntered(MouseEvent e) {
  86                 handleRollover(e, true);
  87             }
  88 
  89             public void mouseExited(MouseEvent e) {
  90                 handleRollover(e, false);
  91             }
  92 
  93             private JComboBox<?> getComboBox(MouseEvent event) {
  94                 Object source = event.getSource();
  95                 JComboBox<?> rv = null;
  96                 if (source instanceof JComboBox) {
  97                     rv = (JComboBox) source;
  98                 } else if (source instanceof XPComboBoxButton) {
  99                     rv = ((XPComboBoxButton) source)
 100                         .getWindowsComboBoxUI().comboBox;
 101                 } else if (source instanceof JTextField &&
 102                         ((JTextField) source).getParent() instanceof JComboBox) {
 103                     rv = (JComboBox) ((JTextField) source).getParent();
 104                 }
 105                 return rv;
 106             }
 107 
 108             private WindowsComboBoxUI getWindowsComboBoxUI(MouseEvent event) {
 109                 JComboBox<?> comboBox = getComboBox(event);
 110                 WindowsComboBoxUI rv = null;
 111                 if (comboBox != null
 112                     && comboBox.getUI() instanceof WindowsComboBoxUI) {
 113                     rv = (WindowsComboBoxUI) comboBox.getUI();
 114                 }
 115                 return rv;
 116             }
 117 
 118         };
 119     private boolean isRollover = false;
 120 
 121     private static final PropertyChangeListener componentOrientationListener =
 122         new PropertyChangeListener() {
 123             public void propertyChange(PropertyChangeEvent e) {
 124                 String propertyName = e.getPropertyName();
 125                 Object source = null;
 126                 if ("componentOrientation" == propertyName
 127                     && (source = e.getSource()) instanceof JComboBox
 128                     && ((JComboBox) source).getUI() instanceof
 129                       WindowsComboBoxUI) {
 130                     JComboBox<?> comboBox = (JComboBox) source;
 131                     WindowsComboBoxUI comboBoxUI = (WindowsComboBoxUI) comboBox.getUI();
 132                     if (comboBoxUI.arrowButton instanceof XPComboBoxButton) {
 133                         ((XPComboBoxButton) comboBoxUI.arrowButton).setPart(
 134                                     (comboBox.getComponentOrientation() ==
 135                                        ComponentOrientation.RIGHT_TO_LEFT)
 136                                     ? Part.CP_DROPDOWNBUTTONLEFT
 137                                     : Part.CP_DROPDOWNBUTTONRIGHT);
 138                             }
 139                         }
 140                     }
 141                 };
 142 
 143     public static ComponentUI createUI(JComponent c) {
 144         return new WindowsComboBoxUI();
 145     }
 146 
 147     public void installUI( JComponent c ) {
 148         super.installUI( c );
 149         isRollover = false;
 150         comboBox.setRequestFocusEnabled( true );
 151         if (XPStyle.getXP() != null && arrowButton != null) {
 152             //we can not do it in installListeners because arrowButton
 153             //is initialized after installListeners is invoked
 154             comboBox.addMouseListener(rolloverListener);
 155             arrowButton.addMouseListener(rolloverListener);
 156             // set empty border as default to see vista animated border
 157             comboBox.setBorder(new EmptyBorder(1,1,1,1));
 158         }
 159     }
 160 
 161     public void uninstallUI(JComponent c ) {
 162         comboBox.removeMouseListener(rolloverListener);
 163         if(arrowButton != null) {
 164             arrowButton.removeMouseListener(rolloverListener);
 165         }
 166         super.uninstallUI( c );
 167     }
 168 
 169     /**
 170      * {@inheritDoc}
 171      * @since 1.6
 172      */
 173     @Override
 174     protected void installListeners() {
 175         super.installListeners();
 176         XPStyle xp = XPStyle.getXP();
 177         //button glyph for LTR and RTL combobox might differ
 178         if (xp != null
 179               && xp.isSkinDefined(comboBox, Part.CP_DROPDOWNBUTTONRIGHT)) {
 180             comboBox.addPropertyChangeListener("componentOrientation",
 181                                                componentOrientationListener);
 182         }
 183     }
 184 
 185     /**
 186      * {@inheritDoc}
 187      * @since 1.6
 188      */
 189     @Override
 190     protected void uninstallListeners() {
 191         super.uninstallListeners();
 192         comboBox.removePropertyChangeListener("componentOrientation",
 193                                               componentOrientationListener);
 194     }
 195 
 196     /**
 197      * {@inheritDoc}
 198      * @since 1.6
 199      */
 200     protected void configureEditor() {
 201         super.configureEditor();
 202         if (XPStyle.getXP() != null) {
 203             editor.addMouseListener(rolloverListener);
 204         }
 205     }
 206 
 207     /**
 208      * {@inheritDoc}
 209      * @since 1.6
 210      */
 211     protected void unconfigureEditor() {
 212         super.unconfigureEditor();
 213         editor.removeMouseListener(rolloverListener);
 214     }
 215 
 216     /**
 217      * {@inheritDoc}
 218      * @since 1.6
 219      */
 220     public void paint(Graphics g, JComponent c) {
 221         if (XPStyle.getXP() != null) {
 222             paintXPComboBoxBackground(g, c);
 223         }
 224         super.paint(g, c);
 225     }
 226 
 227     State getXPComboBoxState(JComponent c) {
 228         State state = State.NORMAL;
 229         if (!c.isEnabled()) {
 230             state = State.DISABLED;
 231         } else if (isPopupVisible(comboBox)) {
 232             state = State.PRESSED;
 233         } else if (comboBox.isEditable()
 234                 && comboBox.getEditor().getEditorComponent().isFocusOwner()) {
 235             state = State.PRESSED;
 236         } else if (isRollover) {
 237             state = State.HOT;
 238         }
 239         return state;
 240     }
 241 
 242     private void paintXPComboBoxBackground(Graphics g, JComponent c) {
 243         XPStyle xp = XPStyle.getXP();
 244         if (xp == null) {
 245             return;
 246         }
 247         State state = getXPComboBoxState(c);
 248         Skin skin = null;
 249         if (! comboBox.isEditable()
 250               && xp.isSkinDefined(c, Part.CP_READONLY)) {
 251             skin = xp.getSkin(c, Part.CP_READONLY);
 252         }
 253         if (skin == null) {
 254             skin = xp.getSkin(c, Part.CP_BORDER);
 255         }
 256         skin.paintSkin(g, 0, 0, c.getWidth(), c.getHeight(), state);
 257     }
 258 
 259     /**
 260      * If necessary paints the currently selected item.
 261      *
 262      * @param g Graphics to paint to
 263      * @param bounds Region to paint current value to
 264      * @param hasFocus whether or not the JComboBox has focus
 265      * @throws NullPointerException if any of the arguments are null.
 266      * @since 1.5
 267      */
 268     public void paintCurrentValue(Graphics g, Rectangle bounds,
 269                                   boolean hasFocus) {
 270         XPStyle xp = XPStyle.getXP();
 271         if ( xp != null) {
 272             bounds.x += 2;
 273             bounds.y += 2;
 274             bounds.width -= 4;
 275             bounds.height -= 4;
 276         } else {
 277             bounds.x += 1;
 278             bounds.y += 1;
 279             bounds.width -= 2;
 280             bounds.height -= 2;
 281         }
 282         if (! comboBox.isEditable()
 283             && xp != null
 284             && xp.isSkinDefined(comboBox, Part.CP_READONLY)) {
 285             // On vista for READNLY ComboBox
 286             // color for currentValue is the same as for any other item
 287 
 288             // mostly copied from javax.swing.plaf.basic.BasicComboBoxUI.paintCurrentValue
 289             ListCellRenderer<Object> renderer = comboBox.getRenderer();
 290             Component c;
 291             if ( hasFocus && !isPopupVisible(comboBox) ) {
 292                 c = renderer.getListCellRendererComponent(
 293                         listBox,
 294                         comboBox.getSelectedItem(),
 295                         -1,
 296                         true,
 297                         false );
 298             } else {
 299                 c = renderer.getListCellRendererComponent(
 300                         listBox,
 301                         comboBox.getSelectedItem(),
 302                         -1,
 303                         false,
 304                         false );
 305             }
 306             c.setFont(comboBox.getFont());
 307             if ( comboBox.isEnabled() ) {
 308                 c.setForeground(comboBox.getForeground());
 309                 c.setBackground(comboBox.getBackground());
 310             } else {
 311                 c.setForeground(DefaultLookup.getColor(
 312                          comboBox, this, "ComboBox.disabledForeground", null));
 313                 c.setBackground(DefaultLookup.getColor(
 314                          comboBox, this, "ComboBox.disabledBackground", null));
 315             }
 316             boolean shouldValidate = false;
 317             if (c instanceof JPanel)  {
 318                 shouldValidate = true;
 319             }
 320             currentValuePane.paintComponent(g, c, comboBox, bounds.x, bounds.y,
 321                                             bounds.width, bounds.height, shouldValidate);
 322 
 323         } else {
 324             super.paintCurrentValue(g, bounds, hasFocus);
 325         }
 326     }
 327 
 328     /**
 329      * {@inheritDoc}
 330      * @since 1.6
 331      */
 332     public void paintCurrentValueBackground(Graphics g, Rectangle bounds,
 333                                             boolean hasFocus) {
 334         if (XPStyle.getXP() == null) {
 335             super.paintCurrentValueBackground(g, bounds, hasFocus);
 336         }
 337     }
 338 
 339     public Dimension getMinimumSize( JComponent c ) {
 340         Dimension d = super.getMinimumSize(c);
 341         if (XPStyle.getXP() != null) {
 342             d.width += 7;
 343             boolean isEditable = false;
 344             if (c instanceof JComboBox) {
 345                 isEditable = ((JComboBox) c).isEditable();
 346             }



 347             d.height += isEditable ? 4 : 6;

 348         } else {
 349             d.width += 4;
 350             d.height += 2;
 351         }
 352         return d;
 353     }
 354 
 355     /**
 356      * Creates a layout manager for managing the components which make up the
 357      * combo box.
 358      *
 359      * @return an instance of a layout manager
 360      */
 361     protected LayoutManager createLayoutManager() {
 362         return new BasicComboBoxUI.ComboBoxLayoutManager() {
 363             public void layoutContainer(Container parent) {
 364                 super.layoutContainer(parent);
 365 
 366                 if (XPStyle.getXP() != null && arrowButton != null) {
 367                     Dimension d = parent.getSize();
 368                     Insets insets = getInsets();
 369 
 370                     int borderInsetsCorrection = 0;
 371                     if (((JComboBox)parent).getBorder() instanceof EmptyBorder) {
 372                         borderInsetsCorrection = 1;
 373                     }
 374                     arrowButton.setBounds(
 375                         WindowsGraphicsUtils.isLeftToRight((JComboBox)parent)
 376                             ? (d.width - (insets.right - borderInsetsCorrection)
 377                                 - arrowButton.getPreferredSize().width)
 378                             : insets.left - borderInsetsCorrection,
 379                             insets.top - borderInsetsCorrection,
 380                             arrowButton.getPreferredSize().width,
 381                             d.height - (insets.top - borderInsetsCorrection) -
 382                                     (insets.bottom - borderInsetsCorrection));
 383                 }
 384             }
 385         };
 386     }
 387 
 388     protected void installKeyboardActions() {
 389         super.installKeyboardActions();
 390     }
 391 
 392     protected ComboPopup createPopup() {
 393         return new WinComboPopUp(comboBox);
 394     }
 395 
 396     /**
 397      * Creates the default editor that will be used in editable combo boxes.
 398      * A default editor will be used only if an editor has not been
 399      * explicitly set with <code>setEditor</code>.
 400      *
 401      * @return a <code>ComboBoxEditor</code> used for the combo box
 402      * @see javax.swing.JComboBox#setEditor
 403      */
 404     protected ComboBoxEditor createEditor() {
 405         return new WindowsComboBoxEditor();
 406     }
 407 
 408     /**
 409      * {@inheritDoc}
 410      * @since 1.6
 411      */
 412     @Override
 413     protected ListCellRenderer<Object> createRenderer() {
 414         XPStyle xp = XPStyle.getXP();
 415         if (xp != null && xp.isSkinDefined(comboBox, Part.CP_READONLY)) {
 416             return new WindowsComboBoxRenderer();
 417         } else {
 418             return super.createRenderer();
 419         }
 420     }
 421 
 422     /**
 423      * Creates an button which will be used as the control to show or hide
 424      * the popup portion of the combo box.
 425      *
 426      * @return a button which represents the popup control
 427      */
 428     protected JButton createArrowButton() {
 429         XPStyle xp = XPStyle.getXP();
 430         if (xp != null) {
 431             return new XPComboBoxButton(xp);
 432         } else {
 433             return super.createArrowButton();
 434         }
 435     }
 436 
 437     @SuppressWarnings("serial") // Superclass is not serializable across versions
 438     private class XPComboBoxButton extends XPStyle.GlyphButton {
 439         private State prevState = null;
 440 
 441         public XPComboBoxButton(XPStyle xp) {
 442             super(comboBox,
 443                   (! xp.isSkinDefined(comboBox, Part.CP_DROPDOWNBUTTONRIGHT))
 444                    ? Part.CP_DROPDOWNBUTTON
 445                    : (comboBox.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
 446                      ? Part.CP_DROPDOWNBUTTONLEFT
 447                      : Part.CP_DROPDOWNBUTTONRIGHT
 448                   );
 449             setRequestFocusEnabled(false);
 450         }
 451 
 452         @Override
 453         protected State getState() {
 454             State rv;
 455 
 456             getModel().setPressed(comboBox.isPopupVisible());
 457 
 458             rv = super.getState();
 459             XPStyle xp = XPStyle.getXP();
 460             if (rv != State.DISABLED
 461                     && comboBox != null && ! comboBox.isEditable()
 462                     && xp != null && xp.isSkinDefined(comboBox,
 463                             Part.CP_DROPDOWNBUTTONRIGHT)) {
 464                 /*
 465                  * for non editable ComboBoxes Vista seems to have the
 466                  * same glyph for all non DISABLED states
 467                  */
 468                 rv = State.NORMAL;
 469             }
 470             if (rv == State.NORMAL && (prevState == State.HOT || prevState == State.PRESSED)) {
 471                 /*
 472                  * State NORMAL of combobox button cannot overpaint states HOT or PRESSED
 473                  * Therefore HOT state must be painted from alpha 1 to 0 and not as usual that
 474                  * NORMAL state is painted from alpha 0 to alpha 1.
 475                  */
 476                 skin.switchStates(true);
 477             }
 478             if (rv != prevState) {
 479                 prevState = rv;
 480             }
 481 
 482             return rv;
 483         }
 484 
 485         public Dimension getPreferredSize() {
 486             return new Dimension(17, 21);
 487         }
 488 
 489         void setPart(Part part) {
 490             setPart(comboBox, part);
 491         }
 492 
 493         WindowsComboBoxUI getWindowsComboBoxUI() {
 494             return WindowsComboBoxUI.this;
 495         }
 496     }
 497 
 498 
 499     /**
 500      * Subclassed to add Windows specific Key Bindings.
 501      * This class is now obsolete and doesn't do anything.
 502      * Only included for backwards API compatibility.
 503      * Do not call or override.
 504      *
 505      * @deprecated As of Java 2 platform v1.4.
 506      */
 507     @Deprecated
 508     @SuppressWarnings("serial") // Superclass is not serializable across versions
 509     protected class WindowsComboPopup extends BasicComboPopup {
 510 
 511         public WindowsComboPopup( JComboBox<Object> cBox ) {
 512             super( cBox );
 513         }
 514 
 515         protected KeyListener createKeyListener() {
 516             return new InvocationKeyHandler();
 517         }
 518 
 519         protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler {
 520             protected InvocationKeyHandler() {
 521                 WindowsComboPopup.this.super();
 522             }
 523         }
 524     }
 525 
 526     @SuppressWarnings("serial") // Same-version serialization only
 527     protected class WinComboPopUp extends BasicComboPopup {
 528         private Skin listBoxBorder = null;
 529         private XPStyle xp;
 530 
 531         public WinComboPopUp(JComboBox<Object> combo) {
 532             super(combo);
 533             xp = XPStyle.getXP();
 534             if (xp != null && xp.isSkinDefined(combo, Part.LBCP_BORDER_NOSCROLL)) {
 535                 this.listBoxBorder = new Skin(combo, Part.LBCP_BORDER_NOSCROLL);
 536                 this.setBorder(new EmptyBorder(1,1,1,1));
 537             }
 538         }
 539 
 540         protected KeyListener createKeyListener() {
 541             return new InvocationKeyHandler();
 542         }
 543 
 544         protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler {
 545             protected InvocationKeyHandler() {
 546                 WinComboPopUp.this.super();
 547             }
 548         }
 549 
 550         protected void paintComponent(Graphics g) {
 551             super.paintComponent(g);
 552             if (this.listBoxBorder != null) {
 553                 this.listBoxBorder.paintSkinRaw(g, this.getX(), this.getY(),
 554                         this.getWidth(), this.getHeight(), State.HOT);
 555             }
 556         }
 557     }
 558 
 559 
 560     /**
 561      * Subclassed to highlight selected item in an editable combo box.
 562      */
 563     public static class WindowsComboBoxEditor
 564         extends BasicComboBoxEditor.UIResource {
 565 
 566         /**
 567          * {@inheritDoc}
 568          * @since 1.6
 569          */
 570         protected JTextField createEditorComponent() {
 571             JTextField editor = super.createEditorComponent();
 572             Border border = (Border)UIManager.get("ComboBox.editorBorder");
 573 
 574             if (border != null) {
 575                 editor.setBorder(border);
 576             }
 577             editor.setOpaque(false);
 578             return editor;
 579         }
 580 
 581         public void setItem(Object item) {
 582             super.setItem(item);
 583             Object focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
 584             if ((focus == editor) || (focus == editor.getParent())) {
 585                 editor.selectAll();
 586             }
 587         }
 588     }
 589 
 590     /**
 591      * Subclassed to set opacity {@code false} on the renderer
 592      * and to show border for focused cells.
 593      */
 594     @SuppressWarnings("serial") // Superclass is not serializable across versions
 595     private static class WindowsComboBoxRenderer
 596           extends BasicComboBoxRenderer.UIResource {
 597         private static final Object BORDER_KEY
 598             = new StringUIClientPropertyKey("BORDER_KEY");
 599         private static final Border NULL_BORDER = new EmptyBorder(0, 0, 0, 0);
 600 
 601         // Create own version of DashedBorder with more space on left side
 602         private class WindowsComboBoxDashedBorder extends DashedBorder {
 603 
 604             public WindowsComboBoxDashedBorder(Color color, int thickness) {
 605                 super(color, thickness);
 606             }
 607 
 608             public WindowsComboBoxDashedBorder(Color color) {
 609                 super(color);
 610             }
 611 
 612             @Override
 613             public Insets getBorderInsets(Component c, Insets i) {
 614                 return new Insets(0,2,0,0);
 615             }
 616         }
 617 
 618         public WindowsComboBoxRenderer() {
 619             super();
 620 
 621             // correct space on the left side of text items in the combo popup list
 622             Insets i = getBorder().getBorderInsets(this);
 623             setBorder(new EmptyBorder(0, 2, 0, i.right));
 624         }
 625         /**
 626          * {@inheritDoc}
 627          */
 628         @Override
 629         public Component getListCellRendererComponent(
 630                                                  JList<?> list,
 631                                                  Object value,
 632                                                  int index,
 633                                                  boolean isSelected,
 634                                                  boolean cellHasFocus) {
 635             Component rv =
 636                 super.getListCellRendererComponent(list, value, index,
 637                                                    isSelected, cellHasFocus);
 638             if (rv instanceof JComponent) {
 639                 JComponent component = (JComponent) rv;
 640                 if (index == -1 && isSelected) {
 641                     Border border = component.getBorder();
 642                     Border dashedBorder =
 643                         new WindowsComboBoxDashedBorder(list.getForeground());
 644                     component.setBorder(dashedBorder);
 645                     //store current border in client property if needed
 646                     if (component.getClientProperty(BORDER_KEY) == null) {
 647                         component.putClientProperty(BORDER_KEY,
 648                                        (border == null) ? NULL_BORDER : border);
 649                     }
 650                 } else {
 651                     if (component.getBorder() instanceof
 652                           WindowsBorders.DashedBorder) {
 653                         Object storedBorder = component.getClientProperty(BORDER_KEY);
 654                         if (storedBorder instanceof Border) {
 655                             component.setBorder(
 656                                 (storedBorder == NULL_BORDER) ? null
 657                                     : (Border) storedBorder);
 658                         }
 659                         component.putClientProperty(BORDER_KEY, null);
 660                     }
 661                 }
 662                 if (index == -1) {
 663                     component.setOpaque(false);
 664                     component.setForeground(list.getForeground());
 665                 } else {
 666                     component.setOpaque(true);
 667                 }
 668             }
 669             return rv;
 670         }
 671 
 672     }
 673 }
--- EOF ---