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