changeset 1247:0f911a5c52bb

RT-22025: [ComboBox] initial size doesn't respond the size of the widest content
author jgiles
date Wed, 06 Jun 2012 13:09:31 +1200
parents 612f0c898954
children 29dd9c8675ec
files javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java
diffstat 1 files changed, 132 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed Jun 06 10:59:48 2012 +1200
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed Jun 06 13:09:31 2012 +1200
@@ -57,6 +57,14 @@
     // This may one day become a property on the ComboBox itself.
     private static final String COMBO_BOX_ROWS_TO_MEASURE_WIDTH_KEY = "comboBoxRowsToMeasureWidth";
     
+    
+    
+    /***************************************************************************
+     *                                                                         *
+     * Private fields                                                          *
+     *                                                                         *
+     **************************************************************************/    
+    
     private final ComboBox<T> comboBox;
     
     private ListCell<T> buttonCell;
@@ -67,6 +75,36 @@
     
     private ObservableList<T> listViewItems;
     
+    private boolean listSelectionLock = false;
+    private boolean listViewSelectionDirty = false;
+    
+    
+    
+    /***************************************************************************
+     *                                                                         *
+     * Listeners                                                               *
+     *                                                                         *
+     **************************************************************************/
+    
+    private boolean itemCountDirty;
+    private final ListChangeListener listViewItemsListener = new ListChangeListener() {
+        @Override public void onChanged(ListChangeListener.Change c) {
+            itemCountDirty = true;
+            requestLayout();
+        }
+    };
+    
+    private final WeakListChangeListener weakListViewItemsListener =
+            new WeakListChangeListener(listViewItemsListener);
+    
+    
+    
+    /***************************************************************************
+     *                                                                         *
+     * Constructors                                                            *
+     *                                                                         *
+     **************************************************************************/   
+    
     public ComboBoxListViewSkin(final ComboBox<T> comboBox) {
         super(comboBox, new ComboBoxListViewBehavior<T>(comboBox));
         this.comboBox = comboBox;
@@ -133,60 +171,15 @@
         registerChangeListener(comboBox.buttonCellProperty(), "BUTTON_CELL");
     }
     
-    private void updateValue(T newValue) {
-        if (newValue == null) {
-            listView.getSelectionModel().clearSelection();
-        } else {
-            int index = comboBox.getSelectionModel().getSelectedIndex();
-            if (index >= 0 && index < comboBox.getItems().size()) {
-                T itemsObj = comboBox.getItems().get(index);
-                if (itemsObj != null && itemsObj.equals(newValue)) {
-                    listView.getSelectionModel().select(index);
-                } else {
-                    listView.getSelectionModel().select(newValue);
-                }
-            } else {
-                // just select the first instance of newValue in the list
-                int listViewIndex = listView.getItems().indexOf(newValue);
-                if (listViewIndex == -1) {
-                    // RT-21336 Show the ComboBox value even though it doesn't
-                    // exist in the ComboBox items list (part one of fix)
-                    updateDisplayNode();
-                } else {
-                    listView.getSelectionModel().select(listViewIndex);
-                }
-            }
-        }
-    }
     
-    public void updateListViewItems() {
-        if (listViewItems != null) {
-            listViewItems.removeListener(weakListViewItemsListener);
-        }
-
-        this.listViewItems = comboBox.getItems();
-        listView.setItems(null);
-        listView.setItems(listViewItems);
-
-        if (listViewItems != null) {
-            listViewItems.addListener(weakListViewItemsListener);
-        }
-        
-        itemCountDirty = true;
-        requestLayout();
-    }
     
-    private boolean itemCountDirty;
-    private final ListChangeListener listViewItemsListener = new ListChangeListener() {
-        @Override public void onChanged(ListChangeListener.Change c) {
-            itemCountDirty = true;
-            requestLayout();
-        }
-    };
+    /***************************************************************************
+     *                                                                         *
+     * Public API                                                              *
+     *                                                                         *
+     **************************************************************************/  
     
-    private final WeakListChangeListener weakListViewItemsListener =
-            new WeakListChangeListener(listViewItemsListener);
-    
+    /** {@inheritDoc} */
     @Override protected void handleControlPropertyChanged(String p) {
         // Fix for RT-21207
         if (p == "SHOWING") {
@@ -218,6 +211,7 @@
         }
     }
     
+    /** {@inheritDoc} */
     @Override public Node getDisplayNode() {
         Node displayNode;
         if (comboBox.isEditable()) {
@@ -234,6 +228,88 @@
         return displayNode;
     }
     
+    /**
+     * 
+     */
+    public void updateListViewItems() {
+        if (listViewItems != null) {
+            listViewItems.removeListener(weakListViewItemsListener);
+        }
+
+        this.listViewItems = comboBox.getItems();
+        listView.setItems(null);
+        listView.setItems(listViewItems);
+
+        if (listViewItems != null) {
+            listViewItems.addListener(weakListViewItemsListener);
+        }
+        
+        itemCountDirty = true;
+        requestLayout();
+    }
+    
+    @Override public Node getPopupContent() {
+        return listView;
+    }
+    
+    @Override protected double computePrefWidth(double height) {
+        return listView.prefWidth(height);
+    }
+    
+    @Override protected double computeMinWidth(double height) {
+        return 50;
+    }
+    
+    @Override protected void layoutChildren() {
+        if (listViewSelectionDirty) {
+            try {
+                listSelectionLock = true;
+                T item = comboBox.getSelectionModel().getSelectedItem();
+                listView.getSelectionModel().clearSelection();
+                listView.getSelectionModel().select(item);
+            } finally {
+                listSelectionLock = false;
+                listViewSelectionDirty = false;
+            }
+        }
+        
+        super.layoutChildren();
+    }
+    
+    
+    
+    /***************************************************************************
+     *                                                                         *
+     * Private methods                                                         *
+     *                                                                         *
+     **************************************************************************/    
+    
+    private void updateValue(T newValue) {
+        if (newValue == null) {
+            listView.getSelectionModel().clearSelection();
+        } else {
+            int index = comboBox.getSelectionModel().getSelectedIndex();
+            if (index >= 0 && index < comboBox.getItems().size()) {
+                T itemsObj = comboBox.getItems().get(index);
+                if (itemsObj != null && itemsObj.equals(newValue)) {
+                    listView.getSelectionModel().select(index);
+                } else {
+                    listView.getSelectionModel().select(newValue);
+                }
+            } else {
+                // just select the first instance of newValue in the list
+                int listViewIndex = listView.getItems().indexOf(newValue);
+                if (listViewIndex == -1) {
+                    // RT-21336 Show the ComboBox value even though it doesn't
+                    // exist in the ComboBox items list (part one of fix)
+                    updateDisplayNode();
+                } else {
+                    listView.getSelectionModel().select(listViewIndex);
+                }
+            }
+        }
+    }
+    
     private TextField getEditableInputNode() {
         if (textField != null) return textField;
         
@@ -335,10 +411,6 @@
         buttonCell.setMouseTransparent(true);
     }
 
-    @Override public Node getPopupContent() {
-        return listView;
-    }
-    
     private void updateCellFactory() {
         Callback<ListView<T>, ListCell<T>> cf = comboBox.getCellFactory();
         cellFactory = cf != null ? cf : getDefaultCellFactory();
@@ -358,10 +430,9 @@
         };
     }
     
-    private boolean listSelectionLock = false;
-    
     private ListView<T> createListView() {
         final ListView<T> listView = new ListView<T>() {
+            private boolean isFirstSizeCalculation = true;
             
             @Override protected double computeMinHeight(double width) {
                 return 30;
@@ -398,12 +469,14 @@
             }
             
             private void doCSSCheck() {
-                if (getSkin() == null) {
+                Parent parent = getPopup().getScene().getRoot();
+                if ((isFirstSizeCalculation || getSkin() == null) && parent.getScene() != null) {
                     // if the skin is null, it means that the css related to the
                     // listview skin hasn't been loaded yet, so we force it here.
                     // This ensures the combobox button is the correct width
                     // when it is first displayed, before the listview is shown.
-                    getPopup().getScene().getRoot().impl_processCSS(true);
+                    parent.impl_processCSS(true);
+                    isFirstSizeCalculation = false;
                 }
             }
         };
@@ -474,30 +547,6 @@
         return ph;
     }
 
-    @Override protected double computePrefWidth(double height) {
-        return listView.prefWidth(height);
-    }
-    
-    @Override protected double computeMinWidth(double height) {
-        return 50;
-    }
-    
-    private boolean listViewSelectionDirty = false;
-    @Override protected void layoutChildren() {
-        if (listViewSelectionDirty) {
-            try {
-                listSelectionLock = true;
-                T item = comboBox.getSelectionModel().getSelectedItem();
-                listView.getSelectionModel().clearSelection();
-                listView.getSelectionModel().select(item);
-            } finally {
-                listSelectionLock = false;
-                listViewSelectionDirty = false;
-            }
-        }
-        
-        super.layoutChildren();
-    }
 
     
     /**************************************************************************