src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java

Print this page




  54  * appropriate for short term storage or RMI between applications running
  55  * the same version of Swing.  As of 1.4, support for long term storage
  56  * of all JavaBeans™
  57  * has been added to the <code>java.beans</code> package.
  58  * Please see {@link java.beans.XMLEncoder}.
  59  *
  60  * @author Tom Santos
  61  * @author Mark Davidson
  62  */
  63 @SuppressWarnings("serial") // Same-version serialization only
  64 public class BasicComboPopup extends JPopupMenu implements ComboPopup {
  65     // An empty ListMode, this is used when the UI changes to allow
  66     // the JList to be gc'ed.
  67     private static class EmptyListModelClass implements ListModel<Object>, Serializable {
  68         public int getSize() { return 0; }
  69         public Object getElementAt(int index) { return null; }
  70         public void addListDataListener(ListDataListener l) {}
  71         public void removeListDataListener(ListDataListener l) {}
  72     };
  73 
  74     static final ListModel EmptyListModel = new EmptyListModelClass();
  75 
  76     private static Border LIST_BORDER = new LineBorder(Color.BLACK, 1);
  77 
  78     protected JComboBox                comboBox;
  79     /**
  80      * This protected field is implementation specific. Do not access directly
  81      * or override. Use the accessor methods instead.
  82      *
  83      * @see #getList
  84      * @see #createList
  85      */
  86     protected JList                    list;
  87     /**
  88      * This protected field is implementation specific. Do not access directly
  89      * or override. Use the create method instead
  90      *
  91      * @see #createScroller
  92      */
  93     protected JScrollPane              scroller;
  94 
  95     /**
  96      * As of Java 2 platform v1.4 this previously undocumented field is no
  97      * longer used.
  98      */
  99     protected boolean                  valueIsAdjusting = false;
 100 
 101     // Listeners that are required by the ComboPopup interface
 102 
 103     /**
 104      * Implementation of all the listener classes.
 105      */
 106     private Handler handler;


 212     /**
 213      * Implementation of ComboPopup.hide().
 214      */
 215     public void hide() {
 216         MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 217         MenuElement [] selection = manager.getSelectedPath();
 218         for ( int i = 0 ; i < selection.length ; i++ ) {
 219             if ( selection[i] == this ) {
 220                 manager.clearSelectedPath();
 221                 break;
 222             }
 223         }
 224         if (selection.length > 0) {
 225             comboBox.repaint();
 226         }
 227     }
 228 
 229     /**
 230      * Implementation of ComboPopup.getList().
 231      */
 232     public JList getList() {
 233         return list;
 234     }
 235 
 236     /**
 237      * Implementation of ComboPopup.getMouseListener().
 238      *
 239      * @return a <code>MouseListener</code> or null
 240      * @see ComboPopup#getMouseListener
 241      */
 242     public MouseListener getMouseListener() {
 243         if (mouseListener == null) {
 244             mouseListener = createMouseListener();
 245         }
 246         return mouseListener;
 247     }
 248 
 249     /**
 250      * Implementation of ComboPopup.getMouseMotionListener().
 251      *
 252      * @return a <code>MouseMotionListener</code> or null


 286         }
 287         uninstallComboBoxModelListeners(comboBox.getModel());
 288         uninstallKeyboardActions();
 289         uninstallListListeners();
 290         // We do this, otherwise the listener the ui installs on
 291         // the model (the combobox model in this case) will keep a
 292         // reference to the list, causing the list (and us) to never get gced.
 293         list.setModel(EmptyListModel);
 294     }
 295 
 296     //
 297     // end ComboPopup method implementations
 298     //======================================
 299 
 300     /**
 301      * Removes the listeners from the combo box model
 302      *
 303      * @param model The combo box model to install listeners
 304      * @see #installComboBoxModelListeners
 305      */
 306     protected void uninstallComboBoxModelListeners( ComboBoxModel model ) {
 307         if (model != null && listDataListener != null) {
 308             model.removeListDataListener(listDataListener);
 309         }
 310     }
 311 
 312     protected void uninstallKeyboardActions() {
 313         // XXX - shouldn't call this method
 314 //        comboBox.unregisterKeyboardAction( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ) );
 315     }
 316 
 317 
 318 
 319     //===================================================================
 320     // begin Initialization routines
 321     //
 322     public BasicComboPopup( JComboBox combo ) {
 323         super();
 324         setName("ComboPopup.popup");
 325         comboBox = combo;
 326 
 327         setLightWeightPopupEnabled( comboBox.isLightWeightPopupEnabled() );
 328 
 329         // UI construction of the popup.
 330         list = createList();
 331         list.setName("ComboBox.list");
 332         configureList();
 333         scroller = createScroller();
 334         scroller.setName("ComboBox.scrollPane");
 335         configureScroller();
 336         configurePopup();
 337 
 338         installComboBoxListeners();
 339         installKeyboardActions();
 340     }
 341 
 342     // Overriden PopupMenuListener notification methods to inform combo box


 464      * @return an instance of an <code>ItemListener</code> or null
 465      */
 466     protected ItemListener createItemListener() {
 467         return getHandler();
 468     }
 469 
 470     private Handler getHandler() {
 471         if (handler == null) {
 472             handler = new Handler();
 473         }
 474         return handler;
 475     }
 476 
 477     /**
 478      * Creates the JList used in the popup to display
 479      * the items in the combo box model. This method is called when the UI class
 480      * is created.
 481      *
 482      * @return a <code>JList</code> used to display the combo box items
 483      */
 484     protected JList createList() {
 485         return new JList( comboBox.getModel() ) {
 486             public void processMouseEvent(MouseEvent e)  {
 487                 if (BasicGraphicsUtils.isMenuShortcutKeyDown(e))  {
 488                     // Fix for 4234053. Filter out the Control Key from the list.
 489                     // ie., don't allow CTRL key deselection.
 490                     Toolkit toolkit = Toolkit.getDefaultToolkit();
 491                     e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(),
 492                                        e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(),
 493                                        e.getX(), e.getY(),
 494                                        e.getXOnScreen(), e.getYOnScreen(),
 495                                        e.getClickCount(),
 496                                        e.isPopupTrigger(),
 497                                        MouseEvent.NOBUTTON);
 498                 }
 499                 super.processMouseEvent(e);
 500             }
 501         };
 502     }
 503 
 504     /**
 505      * Configures the list which is used to hold the combo box items in the


 593      * This method adds the necessary listeners to the JComboBox.
 594      */
 595     protected void installComboBoxListeners() {
 596         if ((propertyChangeListener = createPropertyChangeListener()) != null) {
 597             comboBox.addPropertyChangeListener(propertyChangeListener);
 598         }
 599         if ((itemListener = createItemListener()) != null) {
 600             comboBox.addItemListener(itemListener);
 601         }
 602         installComboBoxModelListeners(comboBox.getModel());
 603     }
 604 
 605     /**
 606      * Installs the listeners on the combo box model. Any listeners installed
 607      * on the combo box model should be removed in
 608      * <code>uninstallComboBoxModelListeners</code>.
 609      *
 610      * @param model The combo box model to install listeners
 611      * @see #uninstallComboBoxModelListeners
 612      */
 613     protected void installComboBoxModelListeners( ComboBoxModel model ) {
 614         if (model != null && (listDataListener = createListDataListener()) != null) {
 615             model.addListDataListener(listDataListener);
 616         }
 617     }
 618 
 619     protected void installKeyboardActions() {
 620 
 621         /* XXX - shouldn't call this method. take it out for testing.
 622         ActionListener action = new ActionListener() {
 623             public void actionPerformed(ActionEvent e){
 624             }
 625         };
 626 
 627         comboBox.registerKeyboardAction( action,
 628                                          KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ),
 629                                          JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); */
 630 
 631     }
 632 
 633     //


 911                             startAutoScrolling( directionToScroll );
 912                         }
 913                         else if ( !isAutoScrolling ) {
 914                             startAutoScrolling( directionToScroll );
 915                         }
 916                     }
 917                     else {
 918                         if ( e.getPoint().y < 0 ) {
 919                             hasEntered = true;
 920                             startAutoScrolling( SCROLL_UP );
 921                         }
 922                     }
 923                 }
 924             }
 925         }
 926 
 927         //
 928         // PropertyChangeListener
 929         //
 930         public void propertyChange(PropertyChangeEvent e) {
 931             JComboBox comboBox = (JComboBox)e.getSource();

 932             String propertyName = e.getPropertyName();
 933 
 934             if ( propertyName == "model" ) {
 935                 ComboBoxModel oldModel = (ComboBoxModel)e.getOldValue();
 936                 ComboBoxModel newModel = (ComboBoxModel)e.getNewValue();


 937                 uninstallComboBoxModelListeners(oldModel);
 938                 installComboBoxModelListeners(newModel);
 939 
 940                 list.setModel(newModel);
 941 
 942                 if ( isVisible() ) {
 943                     hide();
 944                 }
 945             }
 946             else if ( propertyName == "renderer" ) {
 947                 list.setCellRenderer( comboBox.getRenderer() );
 948                 if ( isVisible() ) {
 949                     hide();
 950                 }
 951             }
 952             else if (propertyName == "componentOrientation") {
 953                 // Pass along the new component orientation
 954                 // to the list and the scroller
 955 
 956                 ComponentOrientation o =(ComponentOrientation)e.getNewValue();
 957 
 958                 JList list = getList();
 959                 if (list!=null && list.getComponentOrientation()!=o) {
 960                     list.setComponentOrientation(o);
 961                 }
 962 
 963                 if (scroller!=null && scroller.getComponentOrientation()!=o) {
 964                     scroller.setComponentOrientation(o);
 965                 }
 966 
 967                 if (o!=getComponentOrientation()) {
 968                     setComponentOrientation(o);
 969                 }
 970             }
 971             else if (propertyName == "lightWeightPopupEnabled") {
 972                 setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
 973             }
 974         }
 975 
 976         //
 977         // ItemListener
 978         //
 979         public void itemStateChanged( ItemEvent e ) {
 980             if (e.getStateChange() == ItemEvent.SELECTED) {
 981                 JComboBox comboBox = (JComboBox)e.getSource();

 982                 setListSelection(comboBox.getSelectedIndex());
 983             }
 984         }
 985     }
 986 
 987     //
 988     // end Event Listeners
 989     //=================================================================
 990 
 991 
 992     /**
 993      * Overridden to unconditionally return false.
 994      */
 995     public boolean isFocusTraversable() {
 996         return false;
 997     }
 998 
 999     //===================================================================
1000     // begin Autoscroll methods
1001     //


1155                                               e.getModifiers(),
1156                                               convertedPoint.x,
1157                                               convertedPoint.y,
1158                                               e.getXOnScreen(),
1159                                               e.getYOnScreen(),
1160                                               e.getClickCount(),
1161                                               e.isPopupTrigger(),
1162                                               MouseEvent.NOBUTTON );
1163         return newEvent;
1164     }
1165 
1166 
1167     /**
1168      * Retrieves the height of the popup based on the current
1169      * ListCellRenderer and the maximum row count.
1170      */
1171     protected int getPopupHeightForRowCount(int maxRowCount) {
1172         // Set the cached value of the minimum row count
1173         int minRowCount = Math.min( maxRowCount, comboBox.getItemCount() );
1174         int height = 0;
1175         ListCellRenderer renderer = list.getCellRenderer();
1176         Object value = null;
1177 
1178         for ( int i = 0; i < minRowCount; ++i ) {
1179             value = list.getModel().getElementAt( i );
1180             Component c = renderer.getListCellRendererComponent( list, value, i, false, false );
1181             height += c.getPreferredSize().height;
1182         }
1183 
1184         if (height == 0) {
1185             height = comboBox.getHeight();
1186         }
1187 
1188         Border border = scroller.getViewportBorder();
1189         if (border != null) {
1190             Insets insets = border.getBorderInsets(null);
1191             height += insets.top + insets.bottom;
1192         }
1193 
1194         border = scroller.getBorder();
1195         if (border != null) {




  54  * appropriate for short term storage or RMI between applications running
  55  * the same version of Swing.  As of 1.4, support for long term storage
  56  * of all JavaBeans&trade;
  57  * has been added to the <code>java.beans</code> package.
  58  * Please see {@link java.beans.XMLEncoder}.
  59  *
  60  * @author Tom Santos
  61  * @author Mark Davidson
  62  */
  63 @SuppressWarnings("serial") // Same-version serialization only
  64 public class BasicComboPopup extends JPopupMenu implements ComboPopup {
  65     // An empty ListMode, this is used when the UI changes to allow
  66     // the JList to be gc'ed.
  67     private static class EmptyListModelClass implements ListModel<Object>, Serializable {
  68         public int getSize() { return 0; }
  69         public Object getElementAt(int index) { return null; }
  70         public void addListDataListener(ListDataListener l) {}
  71         public void removeListDataListener(ListDataListener l) {}
  72     };
  73 
  74     static final ListModel<Object> EmptyListModel = new EmptyListModelClass();
  75 
  76     private static Border LIST_BORDER = new LineBorder(Color.BLACK, 1);
  77 
  78     protected JComboBox<Object>             comboBox;
  79     /**
  80      * This protected field is implementation specific. Do not access directly
  81      * or override. Use the accessor methods instead.
  82      *
  83      * @see #getList
  84      * @see #createList
  85      */
  86     protected JList<Object>                 list;
  87     /**
  88      * This protected field is implementation specific. Do not access directly
  89      * or override. Use the create method instead
  90      *
  91      * @see #createScroller
  92      */
  93     protected JScrollPane              scroller;
  94 
  95     /**
  96      * As of Java 2 platform v1.4 this previously undocumented field is no
  97      * longer used.
  98      */
  99     protected boolean                  valueIsAdjusting = false;
 100 
 101     // Listeners that are required by the ComboPopup interface
 102 
 103     /**
 104      * Implementation of all the listener classes.
 105      */
 106     private Handler handler;


 212     /**
 213      * Implementation of ComboPopup.hide().
 214      */
 215     public void hide() {
 216         MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 217         MenuElement [] selection = manager.getSelectedPath();
 218         for ( int i = 0 ; i < selection.length ; i++ ) {
 219             if ( selection[i] == this ) {
 220                 manager.clearSelectedPath();
 221                 break;
 222             }
 223         }
 224         if (selection.length > 0) {
 225             comboBox.repaint();
 226         }
 227     }
 228 
 229     /**
 230      * Implementation of ComboPopup.getList().
 231      */
 232     public JList<Object> getList() {
 233         return list;
 234     }
 235 
 236     /**
 237      * Implementation of ComboPopup.getMouseListener().
 238      *
 239      * @return a <code>MouseListener</code> or null
 240      * @see ComboPopup#getMouseListener
 241      */
 242     public MouseListener getMouseListener() {
 243         if (mouseListener == null) {
 244             mouseListener = createMouseListener();
 245         }
 246         return mouseListener;
 247     }
 248 
 249     /**
 250      * Implementation of ComboPopup.getMouseMotionListener().
 251      *
 252      * @return a <code>MouseMotionListener</code> or null


 286         }
 287         uninstallComboBoxModelListeners(comboBox.getModel());
 288         uninstallKeyboardActions();
 289         uninstallListListeners();
 290         // We do this, otherwise the listener the ui installs on
 291         // the model (the combobox model in this case) will keep a
 292         // reference to the list, causing the list (and us) to never get gced.
 293         list.setModel(EmptyListModel);
 294     }
 295 
 296     //
 297     // end ComboPopup method implementations
 298     //======================================
 299 
 300     /**
 301      * Removes the listeners from the combo box model
 302      *
 303      * @param model The combo box model to install listeners
 304      * @see #installComboBoxModelListeners
 305      */
 306     protected void uninstallComboBoxModelListeners( ComboBoxModel<?> model ) {
 307         if (model != null && listDataListener != null) {
 308             model.removeListDataListener(listDataListener);
 309         }
 310     }
 311 
 312     protected void uninstallKeyboardActions() {
 313         // XXX - shouldn't call this method
 314 //        comboBox.unregisterKeyboardAction( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ) );
 315     }
 316 
 317 
 318 
 319     //===================================================================
 320     // begin Initialization routines
 321     //
 322     public BasicComboPopup( JComboBox<Object> combo ) {
 323         super();
 324         setName("ComboPopup.popup");
 325         comboBox = combo;
 326 
 327         setLightWeightPopupEnabled( comboBox.isLightWeightPopupEnabled() );
 328 
 329         // UI construction of the popup.
 330         list = createList();
 331         list.setName("ComboBox.list");
 332         configureList();
 333         scroller = createScroller();
 334         scroller.setName("ComboBox.scrollPane");
 335         configureScroller();
 336         configurePopup();
 337 
 338         installComboBoxListeners();
 339         installKeyboardActions();
 340     }
 341 
 342     // Overriden PopupMenuListener notification methods to inform combo box


 464      * @return an instance of an <code>ItemListener</code> or null
 465      */
 466     protected ItemListener createItemListener() {
 467         return getHandler();
 468     }
 469 
 470     private Handler getHandler() {
 471         if (handler == null) {
 472             handler = new Handler();
 473         }
 474         return handler;
 475     }
 476 
 477     /**
 478      * Creates the JList used in the popup to display
 479      * the items in the combo box model. This method is called when the UI class
 480      * is created.
 481      *
 482      * @return a <code>JList</code> used to display the combo box items
 483      */
 484     protected JList<Object> createList() {
 485         return new JList<Object>( comboBox.getModel() ) {
 486             public void processMouseEvent(MouseEvent e)  {
 487                 if (BasicGraphicsUtils.isMenuShortcutKeyDown(e))  {
 488                     // Fix for 4234053. Filter out the Control Key from the list.
 489                     // ie., don't allow CTRL key deselection.
 490                     Toolkit toolkit = Toolkit.getDefaultToolkit();
 491                     e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(),
 492                                        e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(),
 493                                        e.getX(), e.getY(),
 494                                        e.getXOnScreen(), e.getYOnScreen(),
 495                                        e.getClickCount(),
 496                                        e.isPopupTrigger(),
 497                                        MouseEvent.NOBUTTON);
 498                 }
 499                 super.processMouseEvent(e);
 500             }
 501         };
 502     }
 503 
 504     /**
 505      * Configures the list which is used to hold the combo box items in the


 593      * This method adds the necessary listeners to the JComboBox.
 594      */
 595     protected void installComboBoxListeners() {
 596         if ((propertyChangeListener = createPropertyChangeListener()) != null) {
 597             comboBox.addPropertyChangeListener(propertyChangeListener);
 598         }
 599         if ((itemListener = createItemListener()) != null) {
 600             comboBox.addItemListener(itemListener);
 601         }
 602         installComboBoxModelListeners(comboBox.getModel());
 603     }
 604 
 605     /**
 606      * Installs the listeners on the combo box model. Any listeners installed
 607      * on the combo box model should be removed in
 608      * <code>uninstallComboBoxModelListeners</code>.
 609      *
 610      * @param model The combo box model to install listeners
 611      * @see #uninstallComboBoxModelListeners
 612      */
 613     protected void installComboBoxModelListeners( ComboBoxModel<?> model ) {
 614         if (model != null && (listDataListener = createListDataListener()) != null) {
 615             model.addListDataListener(listDataListener);
 616         }
 617     }
 618 
 619     protected void installKeyboardActions() {
 620 
 621         /* XXX - shouldn't call this method. take it out for testing.
 622         ActionListener action = new ActionListener() {
 623             public void actionPerformed(ActionEvent e){
 624             }
 625         };
 626 
 627         comboBox.registerKeyboardAction( action,
 628                                          KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ),
 629                                          JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); */
 630 
 631     }
 632 
 633     //


 911                             startAutoScrolling( directionToScroll );
 912                         }
 913                         else if ( !isAutoScrolling ) {
 914                             startAutoScrolling( directionToScroll );
 915                         }
 916                     }
 917                     else {
 918                         if ( e.getPoint().y < 0 ) {
 919                             hasEntered = true;
 920                             startAutoScrolling( SCROLL_UP );
 921                         }
 922                     }
 923                 }
 924             }
 925         }
 926 
 927         //
 928         // PropertyChangeListener
 929         //
 930         public void propertyChange(PropertyChangeEvent e) {
 931             @SuppressWarnings("unchecked")
 932             JComboBox<Object> comboBox = (JComboBox)e.getSource();
 933             String propertyName = e.getPropertyName();
 934 
 935             if ( propertyName == "model" ) {
 936                 @SuppressWarnings("unchecked")
 937                 ComboBoxModel<Object> oldModel = (ComboBoxModel)e.getOldValue();
 938                 @SuppressWarnings("unchecked")
 939                 ComboBoxModel<Object> newModel = (ComboBoxModel)e.getNewValue();
 940                 uninstallComboBoxModelListeners(oldModel);
 941                 installComboBoxModelListeners(newModel);
 942 
 943                 list.setModel(newModel);
 944 
 945                 if ( isVisible() ) {
 946                     hide();
 947                 }
 948             }
 949             else if ( propertyName == "renderer" ) {
 950                 list.setCellRenderer( comboBox.getRenderer() );
 951                 if ( isVisible() ) {
 952                     hide();
 953                 }
 954             }
 955             else if (propertyName == "componentOrientation") {
 956                 // Pass along the new component orientation
 957                 // to the list and the scroller
 958 
 959                 ComponentOrientation o =(ComponentOrientation)e.getNewValue();
 960 
 961                 JList<?> list = getList();
 962                 if (list!=null && list.getComponentOrientation()!=o) {
 963                     list.setComponentOrientation(o);
 964                 }
 965 
 966                 if (scroller!=null && scroller.getComponentOrientation()!=o) {
 967                     scroller.setComponentOrientation(o);
 968                 }
 969 
 970                 if (o!=getComponentOrientation()) {
 971                     setComponentOrientation(o);
 972                 }
 973             }
 974             else if (propertyName == "lightWeightPopupEnabled") {
 975                 setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
 976             }
 977         }
 978 
 979         //
 980         // ItemListener
 981         //
 982         public void itemStateChanged( ItemEvent e ) {
 983             if (e.getStateChange() == ItemEvent.SELECTED) {
 984                 @SuppressWarnings("unchecked")
 985                 JComboBox<Object> comboBox = (JComboBox)e.getSource();
 986                 setListSelection(comboBox.getSelectedIndex());
 987             }
 988         }
 989     }
 990 
 991     //
 992     // end Event Listeners
 993     //=================================================================
 994 
 995 
 996     /**
 997      * Overridden to unconditionally return false.
 998      */
 999     public boolean isFocusTraversable() {
1000         return false;
1001     }
1002 
1003     //===================================================================
1004     // begin Autoscroll methods
1005     //


1159                                               e.getModifiers(),
1160                                               convertedPoint.x,
1161                                               convertedPoint.y,
1162                                               e.getXOnScreen(),
1163                                               e.getYOnScreen(),
1164                                               e.getClickCount(),
1165                                               e.isPopupTrigger(),
1166                                               MouseEvent.NOBUTTON );
1167         return newEvent;
1168     }
1169 
1170 
1171     /**
1172      * Retrieves the height of the popup based on the current
1173      * ListCellRenderer and the maximum row count.
1174      */
1175     protected int getPopupHeightForRowCount(int maxRowCount) {
1176         // Set the cached value of the minimum row count
1177         int minRowCount = Math.min( maxRowCount, comboBox.getItemCount() );
1178         int height = 0;
1179         ListCellRenderer<Object> renderer = list.getCellRenderer();
1180         Object value = null;
1181 
1182         for ( int i = 0; i < minRowCount; ++i ) {
1183             value = list.getModel().getElementAt( i );
1184             Component c = renderer.getListCellRendererComponent( list, value, i, false, false );
1185             height += c.getPreferredSize().height;
1186         }
1187 
1188         if (height == 0) {
1189             height = comboBox.getHeight();
1190         }
1191 
1192         Border border = scroller.getViewportBorder();
1193         if (border != null) {
1194             Insets insets = border.getBorderInsets(null);
1195             height += insets.top + insets.bottom;
1196         }
1197 
1198         border = scroller.getBorder();
1199         if (border != null) {