changeset 111:c4437d337bad

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.1/scrum/controls/jfx/rt
author Jonathan Giles
date Fri, 02 Dec 2011 17:51:52 +1000
parents 2becf153e10c 963d7c07346e
children e69ac8c4bab6
files
diffstat 11 files changed, 157 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Fri Dec 02 17:51:52 2011 +1000
@@ -161,7 +161,8 @@
             listViewItems.addListener(weakListViewItemsListener);
         }
 
-        updateCellCount();
+        itemCountDirty = true;
+        requestLayout();
     }
 
     @Override public int getItemCount() {
@@ -171,16 +172,16 @@
     void updateCellCount() {
         if (flow == null) return;
         
-        // we're about to recreate all cells - but before that we detach them
-        // from the ListView, such that their listeners can be uninstalled.
-        // If we don't do this, we start to get multiple events firing when
-        // properties on the ListView trigger listeners in the cells.
-        for (int i = 0; i < flow.cells.size(); i++) {
-            ((ListCell)flow.cells.get(i)).updateListView(null);
-        }
+        int oldCount = flow.getCellCount();
+        int newCount = getItemCount();
         
         flow.setCellCount(getItemCount());
-        flow.recreateCells();
+        
+        if (newCount != oldCount) {
+            flow.recreateCells();
+        } else {
+            flow.reconfigureCells();
+        }
     }
 
     @Override public ListCell<T> createCell() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableRowSkin.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableRowSkin.java	Fri Dec 02 17:51:52 2011 +1000
@@ -90,8 +90,8 @@
 
         initBindings();
 
+        registerChangeListener(tableRow.itemProperty(), "ITEM");
         registerChangeListener(tableRow.editingProperty(), "EDITING");
-        registerChangeListener(tableRow.indexProperty(), "ROW");
         registerChangeListener(tableRow.tableViewProperty(), "TABLE_VIEW");
     }
 
@@ -105,9 +105,10 @@
 
         super.handleControlPropertyChanged(p);
 
-        if (p == "ROW") {
+        if (p == "ITEM") {
             updateCells = true;
             requestLayout();
+            layout();
         } else if (p == "TABLE_VIEW") {
             for (int i = 0; i < getChildren().size(); i++) {
                 Node n = getChildren().get(i);
@@ -162,8 +163,6 @@
         
         if (showColumns && ! table.getVisibleLeafColumns().isEmpty()) {
             // layout the individual column cells
-            TableColumn<T,?> col;
-            TableCell cell;
             double x = getInsets().getLeft();
             double width;
             double height;
@@ -172,10 +171,8 @@
             double verticalPadding = getInsets().getTop() + getInsets().getBottom();
             double horizontalPadding = getInsets().getLeft() + getInsets().getRight();
             
-            for (int i = 0; i < leafColumns.size(); i++) {
-                col = leafColumns.get(i);
-                cell = cellsMap.get(col);
-                if (cell == null) continue;
+            for (int i = 0; i < getChildren().size(); i++) {
+                TableCell cell = (TableCell) getChildren().get(i);
 
                 width = snapSize(cell.prefWidth(-1) - horizontalPadding);
                 height = Math.max(getHeight(), cell.prefHeight(-1));
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Fri Dec 02 17:51:52 2011 +1000
@@ -523,7 +523,8 @@
             newList.addListener(weakRowCountListener);
         }
 
-        updateRowCount();
+        rowCountDirty = true;
+        requestLayout();
     }
 
     /**
@@ -602,7 +603,8 @@
     }
 
     private void refreshView() {
-        updateRowCount();
+        rowCountDirty = true;
+        requestLayout();
     }
 
     private void reconfigureCells() {
@@ -611,24 +613,23 @@
 
     private void updateRowCount() {
         updatePlaceholderRegionVisibility();
+
+        int oldCount = flow.getCellCount();
+        int newCount = getItemCount();
         
-        // we're about to recreate all cells - but before that we detach them
-        // from the TableView, such that their listeners can be uninstalled.
-        // If we don't do this, we start to get multiple events firing when
-        // properties on the TableView trigger listeners in the cells.
-        for (int i = 0; i < flow.cells.size(); i++) {
-            ((TableRow)flow.cells.get(i)).updateTableView(null);
-        }
-
         // if this is not called even when the count is the same, we get a 
         // memory leak in VirtualFlow.sheet.children. This can probably be 
         // optimised in the future when time permits.
-        flow.setCellCount(getItemCount());
+        flow.setCellCount(newCount);
         
-        // FIXME updateRowCount is called _a lot_. Perhaps we can make recreateCells
-        // smarter. Imagine if items has one million items added - do we really
-        // need to recreateCells a million times?
-        flow.recreateCells();
+        if (newCount != oldCount) {
+            // FIXME updateRowCount is called _a lot_. Perhaps we can make recreateCells
+            // smarter. Imagine if items has one million items added - do we really
+            // need to recreateCells a million times?
+            flow.recreateCells();
+        } else {
+            flow.reconfigureCells();
+        }
     }
 
     private void onFocusPreviousCell() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Fri Dec 02 17:51:52 2011 +1000
@@ -173,12 +173,17 @@
     private int cellCount;
     public int getCellCount() { return cellCount; }
     public void setCellCount(int i) {
+        int oldCount = getCellCount();
         this.cellCount = i;
+        
+        boolean countChanged = oldCount != cellCount;
 
         // ensure that the virtual scrollbar adjusts in size based on the current
         // cell count.
-        VirtualScrollBar lengthBar = isVertical() ? vbar : hbar;
-        lengthBar.setMax(i);
+        if (countChanged) {
+            VirtualScrollBar lengthBar = isVertical() ? vbar : hbar;
+            lengthBar.setMax(i);
+        }
 
         // I decided *not* to reset maxPrefBreadth here for the following
         // situation. Suppose I have 30 cells and then I add 10 more. Just
@@ -196,7 +201,7 @@
         // was at its maximum position.
         // FIXME this should be only executed on the pulse, so this will likely
         // lead to performance degradation until it is handled properly.
-        layoutChildren();
+        if (countChanged) layoutChildren();
 
         // Fix for RT-13965: Without this line of code, the number of items in
         // the sheet would constantly grow, leaking memory for the life of the
@@ -204,8 +209,10 @@
         // cells changes - regardless of whether it became bigger or smaller.
         sheet.getChildren().clear();
 
-        Parent parent = getParent();
-        if (parent != null) parent.requestLayout();
+        if (countChanged) {
+            Parent parent = getParent();
+            if (parent != null) parent.requestLayout();
+        }
         // TODO suppose I had 100 cells and I added 100 more. Further
         // suppose I was scrolled to the bottom when that happened. I
         // actually want to update the position of the mapper such that
@@ -265,6 +272,7 @@
         this.createCell = cc;
 
         if (createCell != null) {
+            accumCell = null;
             setNeedsLayout(true);
             recreateCells();
             if (getParent() != null) getParent().requestLayout();
@@ -703,6 +711,25 @@
     }
 
     @Override protected void layoutChildren() {
+       if (needsRecreateCells) {
+            maxPrefBreadth = -1;
+            lastWidth = -1;
+            lastHeight = -1;
+            releaseCell(accumCell);
+            accumCell = null;
+            accumCellParent.getChildren().clear();
+            addAllToPile();
+            pile.clear();
+            needsRecreateCells = false;
+        } 
+        
+        if (needsReconfigureCells) {
+            maxPrefBreadth = -1;
+            lastWidth = -1;
+            lastHeight = -1;
+            needsReconfigureCells = false;
+        }
+
         // if the width and/or height is 0, then there is no point doing
         // any of this work. In particular, this can happen during startup
         if (getWidth() <= 0 || getHeight() <= 0) {
@@ -1433,12 +1460,10 @@
 
     private void setCellIndex(IndexedCell cell, int index) {
         if (cell == null) return;
-        int old = cell.getIndex();
 
-        if (old != index) {
-            cell.updateIndex(index);
+        cell.updateIndex(index);
+        if (cell.isNeedsLayout()) {
             cell.impl_processCSS(false);
-//            cell.layout();
         }
     }
 
@@ -1454,23 +1479,31 @@
      * necessary.
      */
     private IndexedCell getAvailableCell(int prefIndex) {
+        IndexedCell cell = null;
+        
         // Fix for RT-12822. We try to retrieve the cell from the pile rather
         // than just grab a random cell from the pile (or create another cell).
         for (int i = 0; i < pile.size(); i++) {
-            IndexedCell cell = pile.get(i);
-            if (cell != null && cell.getIndex() == prefIndex) {
+            IndexedCell _cell = pile.get(i);
+            if (_cell != null && _cell.getIndex() == prefIndex) {
                 pile.remove(i);
-                return cell;
+                cell = _cell;
             }
         }
 
-        if (pile.size() > 0) {
-            return pile.removeFirst();
-        } else {
-            IndexedCell cell = createCell.run();
+        if (cell == null) {
+            if (pile.size() > 0) {
+                cell = pile.removeFirst();
+            } else {
+                cell = createCell.run();
+            }
+        }
+        
+        if (! sheet.getChildren().contains(cell)) {
             sheet.getChildren().add(cell);
-            return cell;
         }
+        
+        return cell;
     }
 
     private void addAllToPile() {
@@ -1748,32 +1781,16 @@
         return delta; // TODO fake
     }
 
-//    // current *HACK* for the TreeView
-//    public void updateCount(int newCount, boolean stable) {
-//        // for the viewport to remain stable, we need to ...
-//        setCellCount(newCount);
-//        if (getPosition() == 1.0f) {
-//            mapper.adjustPosition(.9999f);
-//        }
-//        reconfigureCells();
-//    }
-
+    private boolean needsReconfigureCells = false;
+    private boolean needsRecreateCells = false;
+    
     public void reconfigureCells() {
-        maxPrefBreadth = -1;
-        lastWidth = -1;
-        lastHeight = -1;
+        needsReconfigureCells = true;
         requestLayout();
     }
 
     public void recreateCells() {
-        maxPrefBreadth = -1;
-        lastWidth = -1;
-        lastHeight = -1;
-        releaseCell(accumCell);
-        accumCell = null;
-        accumCellParent.getChildren().clear();
-        addAllToPile();
-        pile.clear();
+        needsRecreateCells = true;
         requestLayout();
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Fri Dec 02 17:51:52 2011 +1000
@@ -2387,20 +2387,21 @@
     -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
 }
 
-.table-view:focused .table-cell:filled:focused:selected {
+.table-view:focused .table-row-cell:filled .table-cell:focused:selected {
     -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
     -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
     -fx-background: -fx-accent;
     -fx-text-fill: -fx-selection-bar-text;
 }
 
-.table-view:focused .table-cell:filled:selected, .table-view:cell-selection .table-cell:filled:hover:selected {
+.table-view:focused .table-row-cell:filled .table-cell:selected, .table-view:cell-selection .table-row-cell:filled .table-cell:hover:selected {
     -fx-background: -fx-accent;
     -fx-background-color: -fx-selection-bar;
     -fx-text-fill: -fx-selection-bar-text;
-}
-
-.table-view:focused .table-cell:filled:focused:selected:hover {
+    -fx-background-insets: 0 0 1 0;
+}
+
+.table-view:focused .table-row-cell:filled .table-cell:focused:selected:hover {
     -fx-background: -fx-accent;
     -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
     -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
@@ -2408,7 +2409,7 @@
 }
 
 /* When the TableView is _not_ focused, we show alternate selection colors */
-.table-cell:filled:selected:focused, .table-cell:filled:selected {
+ .table-row-cell:filled .table-cell:selected:focused,  .table-row-cell:filled .table-cell:selected {
     -fx-background-color: lightgray;
     -fx-text-fill: -fx-selection-bar-text;
 }
@@ -2422,12 +2423,13 @@
     -fx-background-insets: 0, 1.4;
 }*/
 
-.table-view:cell-selection .table-cell:filled:hover {
+.table-view:cell-selection  .table-row-cell:filled .table-cell:hover {
     -fx-background-color: -fx-cell-hover-color;
     -fx-text-fill: -fx-text-inner-color;
-}
-
-.table-view:cell-selection .table-cell:filled:focused:hover {
+    -fx-background-insets: 0 0 1 0;
+}
+
+.table-view:cell-selection .table-row-cell:filled .table-cell:focused:hover {
     -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
     -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
     -fx-text-fill: -fx-text-inner-color;
--- a/javafx-ui-controls/src/javafx/scene/control/Cell.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/Cell.java	Fri Dec 02 17:51:52 2011 +1000
@@ -398,7 +398,7 @@
      */
     public final ReadOnlyBooleanProperty selectedProperty() { return selected.getReadOnlyProperty(); }
 
-    private void setSelected(boolean value) { selected.set(value); }
+    void setSelected(boolean value) { selected.set(value); }
     
     /**
      * Returns whether this cell is currently selected or not.
--- a/javafx-ui-controls/src/javafx/scene/control/IndexedCell.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/IndexedCell.java	Fri Dec 02 17:51:52 2011 +1000
@@ -110,6 +110,11 @@
      */
     public void updateIndex(int i) { 
         index.set(i);
+        indexChanged();
+    }
+    
+    void indexChanged() { 
+        // no-op
     }
     
     /* *************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Fri Dec 02 17:51:52 2011 +1000
@@ -105,11 +105,15 @@
      */
     private InvalidationListener indexListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
-            updateItem();
-            updateSelection();
-            updateFocus();
-        }
-    };
+            indexChanged();
+         }
+     };
+    
+    @Override void indexChanged() {
+        updateItem();
+        updateSelection();
+        updateFocus();
+    }
 
     /**
      * Listens to the editing index on the ListView. It is possible for the developer
--- a/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Fri Dec 02 17:51:52 2011 +1000
@@ -92,13 +92,20 @@
      *                                                                         *
      **************************************************************************/
     
+    private boolean itemDirty = false;
+    
     private InvalidationListener indexListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
-            updateItem();
+            indexChanged();
             updateSelection();
             updateFocus();
         }
     };
+    
+    @Override void indexChanged() {
+        itemDirty = true;
+        requestLayout();
+    }
 
     /*
      * This is the list observer we use to keep an eye on the SelectedCells
@@ -122,7 +129,8 @@
     // same as above, but for for changes to the properties on TableRow
     private final InvalidationListener tableRowUpdateObserver = new InvalidationListener() {
         @Override public void invalidated(Observable value) {
-            updateItem();
+            itemDirty = true;
+            requestLayout();
         }
     };
 
@@ -369,7 +377,16 @@
      * Overriding methods                                                      *
      *                                                                         *
      **************************************************************************/
-    
+
+    /** {@inheritDoc} */
+    @Override public void updateSelected(boolean selected) {
+        // copied from Cell, with the first conditional clause below commented 
+        // out, as it is valid for an empty TableCell to be selected, as long 
+        // as the parent TableRow is not empty (see RT-15529).
+        /*if (selected && isEmpty()) return;*/
+        if (getTableRow() == null || getTableRow().isEmpty()) return;
+        setSelected(selected);
+    }
 
 
     /* *************************************************************************
@@ -520,6 +537,15 @@
         observableValue.addListener(weaktableRowUpdateObserver);
     }
 
+    @Override protected void layoutChildren() {
+        if (itemDirty) {
+            updateItem();
+            itemDirty = false;
+        }
+        super.layoutChildren();
+    }
+
+    
 
 
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/TableRow.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/TableRow.java	Fri Dec 02 17:51:52 2011 +1000
@@ -82,12 +82,16 @@
 
     private InvalidationListener indexInvalidationListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
-            updateItem();
+            indexChanged();
             updateSelection();
             updateFocus();
         }
     };
     
+    @Override void indexChanged() {
+        updateItem();
+    }
+    
 
     /***************************************************************************
      *                                                                         *
@@ -230,7 +234,7 @@
         List<T> items = tv.getItems();
 
         // Compute whether the index for this cell is for a real item
-        boolean valid = getIndex() >=0 && getIndex() < items.size();
+        boolean valid = getIndex() >= 0 && getIndex() < items.size();
 
         // Cause the cell to update itself
         if (valid) {
--- a/javafx-ui-controls/test/javafx/scene/control/CellTest.java	Thu Dec 01 17:21:38 2011 -0500
+++ b/javafx-ui-controls/test/javafx/scene/control/CellTest.java	Fri Dec 02 17:51:52 2011 +1000
@@ -43,6 +43,15 @@
 
     @Before public void setup() throws Exception {
         cell = (Cell<String>) type.newInstance();
+        
+        // Empty TableCells can be selected, as long as the row they exist in
+        // is not empty, so here we set a TableRow to ensure testing works 
+        // properly
+        if (cell instanceof TableCell) {
+            TableRow tableRow = new TableRow();
+            tableRow.updateItem("TableRow", false);
+            ((TableCell)cell).updateTableRow(tableRow);
+        }
     }
 
     /*********************************************************************