changeset 6239:0745342829aa

RT-34407:[TableView, TreeView, TreeTableView] shift+PgUp/Down deselection is incorrect.
author jgiles
date Mon, 03 Feb 2014 14:24:56 +1300
parents 9625e5b8f3b9
children a649f412d78b
files modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ListViewSkin.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkinBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeViewSkin.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/VirtualFlow.java modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java
diffstat 11 files changed, 186 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Mon Feb 03 14:24:56 2014 +1300
@@ -231,8 +231,8 @@
     private boolean isShiftDown = false;
     private boolean isShortcutDown = false;
     
-    private Callback<Integer, Integer> onScrollPageUp;
-    private Callback<Integer, Integer> onScrollPageDown;
+    private Callback<Boolean, Integer> onScrollPageUp;
+    private Callback<Boolean, Integer> onScrollPageDown;
     private Runnable onFocusPreviousRow;
     private Runnable onFocusNextRow;
     private Runnable onSelectPreviousRow;
@@ -240,8 +240,8 @@
     private Runnable onMoveToFirstCell;
     private Runnable onMoveToLastCell;
 
-    public void setOnScrollPageUp(Callback<Integer, Integer> c) { onScrollPageUp = c; }
-    public void setOnScrollPageDown(Callback<Integer, Integer> c) { onScrollPageDown = c; }
+    public void setOnScrollPageUp(Callback<Boolean, Integer> c) { onScrollPageUp = c; }
+    public void setOnScrollPageDown(Callback<Boolean, Integer> c) { onScrollPageDown = c; }
     public void setOnFocusPreviousRow(Runnable r) { onFocusPreviousRow = r; }
     public void setOnFocusNextRow(Runnable r) { onFocusNextRow = r; }
     public void setOnSelectPreviousRow(Runnable r) { onSelectPreviousRow = r; }
@@ -387,7 +387,7 @@
     private void scrollPageUp() {
         int newSelectedIndex = -1;
         if (onScrollPageUp != null) {
-            newSelectedIndex = onScrollPageUp.call(getAnchor());
+            newSelectedIndex = onScrollPageUp.call(false);
         }
         if (newSelectedIndex == -1) return;
         
@@ -399,7 +399,7 @@
     private void scrollPageDown() {
         int newSelectedIndex = -1;
         if (onScrollPageDown != null) {
-            newSelectedIndex = onScrollPageDown.call(getAnchor());
+            newSelectedIndex = onScrollPageDown.call(false);
         }
         if (newSelectedIndex == -1) return;
         
@@ -457,7 +457,7 @@
     }
     
     private void focusPageUp() {
-        int newFocusIndex = onScrollPageUp.call(getAnchor());
+        int newFocusIndex = onScrollPageUp.call(true);
         
         FocusModel<T> fm = getControl().getFocusModel();
         if (fm == null) return;
@@ -465,7 +465,7 @@
     }
     
     private void focusPageDown() {
-        int newFocusIndex = onScrollPageDown.call(getAnchor());
+        int newFocusIndex = onScrollPageDown.call(true);
         
         FocusModel<T> fm = getControl().getFocusModel();
         if (fm == null) return;
@@ -603,7 +603,10 @@
             setAnchor(leadIndex);
         }
         
-        int leadSelectedIndex = onScrollPageUp.call(getAnchor());
+        int leadSelectedIndex = onScrollPageUp.call(false);
+
+        // fix for RT-34407
+        int adjust = leadIndex < leadSelectedIndex ? 1 : -1;
 
         MultipleSelectionModel<T> sm = getControl().getSelectionModel();
         if (sm == null) return;
@@ -613,7 +616,7 @@
             sm.select(leadSelectedIndex);
         } else {
             sm.clearSelection();
-            sm.selectRange(leadIndex, leadSelectedIndex - 1);
+            sm.selectRange(leadIndex, leadSelectedIndex + adjust);
         }
         selectionChanging = false;
     }
@@ -628,17 +631,20 @@
             setAnchor(leadIndex);
         }
         
-        int leadSelectedIndex = onScrollPageDown.call(getAnchor());
+        int leadSelectedIndex = onScrollPageDown.call(false);
+
+        // fix for RT-34407
+        int adjust = leadIndex < leadSelectedIndex ? 1 : -1;
         
         MultipleSelectionModel<T> sm = getControl().getSelectionModel();
         if (sm == null) return;
-        
+
         selectionChanging = true;
         if (sm.getSelectionMode() == SelectionMode.SINGLE) {
             sm.select(leadSelectedIndex);
         } else {
             sm.clearSelection();
-            sm.selectRange(leadIndex, leadSelectedIndex + 1);
+            sm.selectRange(leadIndex, leadSelectedIndex + adjust);
         }
         selectionChanging = false;
     }
@@ -813,7 +819,7 @@
         if (fm == null) return;
 
         int leadIndex = fm.getFocusedIndex();
-        int leadSelectedIndex = onScrollPageUp.call(getAnchor());
+        int leadSelectedIndex = onScrollPageUp.call(false);
         sm.selectRange(leadIndex, leadSelectedIndex - 1);
     }
     
@@ -825,7 +831,7 @@
         if (fm == null) return;
         
         int leadIndex = fm.getFocusedIndex();
-        int leadSelectedIndex = onScrollPageDown.call(getAnchor());
+        int leadSelectedIndex = onScrollPageDown.call(false);
         sm.selectRange(leadIndex, leadSelectedIndex + 1);
     }
     
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Mon Feb 03 14:24:56 2014 +1300
@@ -1007,7 +1007,10 @@
         }
         
         int leadSelectedIndex = onScrollPageUp.call(false);
-        
+
+        // fix for RT-34407
+        int adjust = leadIndex < leadSelectedIndex ? 1 : -1;
+
         selectionChanging = true;
         if (sm.getSelectionMode() == null || sm.getSelectionMode() == SelectionMode.SINGLE) {
             if (sm.isCellSelectionEnabled()) {
@@ -1018,9 +1021,9 @@
         } else {
             sm.clearSelection();
             if (sm.isCellSelectionEnabled()) {
-                sm.selectRange(leadIndex, col, leadSelectedIndex - 1, col);
+                sm.selectRange(leadIndex, col, leadSelectedIndex + adjust, col);
             } else {
-                sm.selectRange(leadIndex, leadSelectedIndex - 1);
+                sm.selectRange(leadIndex, leadSelectedIndex + adjust);
             }
         }
         selectionChanging = false;
@@ -1041,6 +1044,9 @@
         }
         
         int leadSelectedIndex = onScrollPageDown.call(false);
+
+        // fix for RT-34407
+        int adjust = leadIndex < leadSelectedIndex ? 1 : -1;
         
         selectionChanging = true;
         if (sm.getSelectionMode() == null || sm.getSelectionMode() == SelectionMode.SINGLE) {
@@ -1053,11 +1059,11 @@
             sm.clearSelection();
 
             if (sm.isCellSelectionEnabled()) {
-                for (int _row = leadIndex; _row <= leadSelectedIndex + 1; _row++) {
+                for (int _row = leadIndex; _row <= leadSelectedIndex + adjust; _row++) {
                     sm.select(_row, col);
                 }
             } else {
-                sm.selectRange(leadIndex, leadSelectedIndex + 1);
+                sm.selectRange(leadIndex, leadSelectedIndex + adjust);
             }
         }
         selectionChanging = false;
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Mon Feb 03 14:24:56 2014 +1300
@@ -187,11 +187,11 @@
     // set when focus is moved by keyboard to allow for proper selection positions
 //    private int selectPos = -1;
     
-    private Callback<Integer, Integer> onScrollPageUp;
-    public void setOnScrollPageUp(Callback<Integer, Integer> c) { onScrollPageUp = c; }
+    private Callback<Boolean, Integer> onScrollPageUp;
+    public void setOnScrollPageUp(Callback<Boolean, Integer> c) { onScrollPageUp = c; }
 
-    private Callback<Integer, Integer> onScrollPageDown;
-    public void setOnScrollPageDown(Callback<Integer, Integer> c) { onScrollPageDown = c; }
+    private Callback<Boolean, Integer> onScrollPageDown;
+    public void setOnScrollPageDown(Callback<Boolean, Integer> c) { onScrollPageDown = c; }
 
     private Runnable onSelectPreviousRow;
     public void setOnSelectPreviousRow(Runnable r) { onSelectPreviousRow = r; }
@@ -304,7 +304,7 @@
     private void scrollUp() {
         int newSelectedIndex = -1;
         if (onScrollPageUp != null) {
-            newSelectedIndex = onScrollPageUp.call(getAnchor());
+            newSelectedIndex = onScrollPageUp.call(false);
         }
         if (newSelectedIndex == -1) return;
         
@@ -316,7 +316,7 @@
     private void scrollDown() {
         int newSelectedIndex = -1;
         if (onScrollPageDown != null) {
-            newSelectedIndex = onScrollPageDown.call(getAnchor());
+            newSelectedIndex = onScrollPageDown.call(false);
         }
         if (newSelectedIndex == -1) return;
         
@@ -374,7 +374,7 @@
     }
     
     private void focusPageUp() {
-        int newFocusIndex = onScrollPageUp.call(getAnchor());
+        int newFocusIndex = onScrollPageUp.call(true);
         
         FocusModel<TreeItem<T>> fm = getControl().getFocusModel();
         if (fm == null) return;
@@ -382,7 +382,7 @@
     }
     
     private void focusPageDown() {
-        int newFocusIndex = onScrollPageDown.call(getAnchor());
+        int newFocusIndex = onScrollPageDown.call(true);
         
         FocusModel<TreeItem<T>> fm = getControl().getFocusModel();
         if (fm == null) return;
@@ -562,7 +562,10 @@
             setAnchor(leadIndex);
         }
         
-        int leadSelectedIndex = onScrollPageUp.call(getAnchor());
+        int leadSelectedIndex = onScrollPageUp.call(false);
+
+        // fix for RT-34407
+        int adjust = leadIndex < leadSelectedIndex ? 1 : -1;
         
         MultipleSelectionModel<TreeItem<T>> sm = getControl().getSelectionModel();
         if (sm == null) return;
@@ -572,7 +575,7 @@
             sm.select(leadSelectedIndex);
         } else {
             sm.clearSelection();
-            sm.selectRange(leadIndex, leadSelectedIndex - 1);
+            sm.selectRange(leadIndex, leadSelectedIndex + adjust);
         }
         selectionChanging = false;
     }
@@ -587,7 +590,10 @@
             setAnchor(leadIndex);
         }
         
-        int leadSelectedIndex = onScrollPageDown.call(getAnchor());
+        int leadSelectedIndex = onScrollPageDown.call(false);
+
+        // fix for RT-34407
+        int adjust = leadIndex < leadSelectedIndex ? 1 : -1;
         
         MultipleSelectionModel<TreeItem<T>> sm = getControl().getSelectionModel();
         if (sm == null) return;
@@ -597,7 +603,7 @@
             sm.select(leadSelectedIndex);
         } else {
             sm.clearSelection();
-            sm.selectRange(leadIndex, leadSelectedIndex + 1);
+            sm.selectRange(leadIndex, leadSelectedIndex + adjust);
         }
         selectionChanging = false;
     }
@@ -804,7 +810,7 @@
         if (fm == null) return;
 
         int leadIndex = fm.getFocusedIndex();
-        int leadSelectedIndex = onScrollPageUp.call(getAnchor());
+        int leadSelectedIndex = onScrollPageUp.call(false);
         sm.selectRange(leadIndex, leadSelectedIndex - 1);
     }
     
@@ -816,7 +822,7 @@
         if (fm == null) return;
         
         int leadIndex = fm.getFocusedIndex();
-        int leadSelectedIndex = onScrollPageDown.call(getAnchor());
+        int leadSelectedIndex = onScrollPageDown.call(false);
         sm.selectRange(leadIndex, leadSelectedIndex + 1);
     }
     
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ListViewSkin.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ListViewSkin.java	Mon Feb 03 14:24:56 2014 +1300
@@ -130,11 +130,11 @@
         getBehavior().setOnMoveToLastCell(new Runnable() {
             @Override public void run() { onMoveToLastCell(); }
         });
-        getBehavior().setOnScrollPageDown(new Callback<Integer, Integer>() {
-            @Override public Integer call(Integer anchor) { return onScrollPageDown(anchor); }
+        getBehavior().setOnScrollPageDown(new Callback<Boolean, Integer>() {
+            @Override public Integer call(Boolean isFocusDriven) { return onScrollPageDown(isFocusDriven); }
         });
-        getBehavior().setOnScrollPageUp(new Callback<Integer, Integer>() {
-            @Override public Integer call(Integer anchor) { return onScrollPageUp(anchor); }
+        getBehavior().setOnScrollPageUp(new Callback<Boolean, Integer>() {
+            @Override public Integer call(Boolean isFocusDriven) { return onScrollPageUp(isFocusDriven); }
         });
         getBehavior().setOnSelectPreviousRow(new Runnable() {
             @Override public void run() { onSelectPreviousCell(); }
@@ -416,7 +416,7 @@
      * Function used to scroll the container down by one 'page', although
      * if this is a horizontal container, then the scrolling will be to the right.
      */
-    private int onScrollPageDown(int anchor) {
+    private int onScrollPageDown(boolean isFocusDriven) {
         ListCell<T> lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
         if (lastVisibleCell == null) return -1;
 
@@ -425,13 +425,28 @@
         if (sm == null || fm == null) return -1;
 
         int lastVisibleCellIndex = lastVisibleCell.getIndex();
-        if (sm.isSelected(lastVisibleCellIndex) || fm.isFocused(lastVisibleCellIndex) || lastVisibleCellIndex == anchor) {
-            // if the last visible cell is selected, we want to shift that cell up
-            // to be the top-most cell, or at least as far to the top as we can go.
-            flow.showAsFirst(lastVisibleCell);
 
-            ListCell<T> newLastVisibleCell = flow.getLastVisibleCellWithinViewPort();
-            lastVisibleCell = newLastVisibleCell == null ? lastVisibleCell : newLastVisibleCell;
+//        boolean isSelected = sm.isSelected(lastVisibleCellIndex) || fm.isFocused(lastVisibleCellIndex) || lastVisibleCellIndex == anchor;
+        // isSelected represents focus OR selection
+        boolean isSelected = false;
+        if (isFocusDriven) {
+            isSelected = lastVisibleCell.isFocused() || fm.isFocused(lastVisibleCellIndex);
+        } else {
+            isSelected = lastVisibleCell.isSelected() || sm.isSelected(lastVisibleCellIndex);
+        }
+
+        if (isSelected) {
+            boolean isLeadIndex = (isFocusDriven && fm.getFocusedIndex() == lastVisibleCellIndex)
+                               || (! isFocusDriven && sm.getSelectedIndex() == lastVisibleCellIndex);
+
+            if (isLeadIndex) {
+                // if the last visible cell is selected, we want to shift that cell up
+                // to be the top-most cell, or at least as far to the top as we can go.
+                flow.showAsFirst(lastVisibleCell);
+
+                ListCell<T> newLastVisibleCell = flow.getLastVisibleCellWithinViewPort();
+                lastVisibleCell = newLastVisibleCell == null ? lastVisibleCell : newLastVisibleCell;
+            }
         } else {
             // if the selection is not on the 'bottom' most cell, we firstly move
             // the selection down to that, without scrolling the contents, so
@@ -447,7 +462,7 @@
      * Function used to scroll the container up by one 'page', although
      * if this is a horizontal container, then the scrolling will be to the left.
      */
-    private int onScrollPageUp(int anchor) {
+    private int onScrollPageUp(boolean isFocusDriven) {
         ListCell<T> firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
         if (firstVisibleCell == null) return -1;
 
@@ -456,13 +471,27 @@
         if (sm == null || fm == null) return -1;
 
         int firstVisibleCellIndex = firstVisibleCell.getIndex();
-        if (sm.isSelected(firstVisibleCellIndex) || fm.isFocused(firstVisibleCellIndex) || firstVisibleCellIndex == anchor) {
-            // if the first visible cell is selected, we want to shift that cell down
-            // to be the bottom-most cell, or at least as far to the bottom as we can go.
-            flow.showAsLast(firstVisibleCell);
 
-            ListCell<T> newFirstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
-            firstVisibleCell = newFirstVisibleCell == null ? firstVisibleCell : newFirstVisibleCell;
+        // isSelected represents focus OR selection
+        boolean isSelected = false;
+        if (isFocusDriven) {
+            isSelected = firstVisibleCell.isFocused() || fm.isFocused(firstVisibleCellIndex);
+        } else {
+            isSelected = firstVisibleCell.isSelected() || sm.isSelected(firstVisibleCellIndex);
+        }
+
+        if (isSelected) {
+            boolean isLeadIndex = (isFocusDriven && fm.getFocusedIndex() == firstVisibleCellIndex)
+                               || (! isFocusDriven && sm.getSelectedIndex() == firstVisibleCellIndex);
+
+            if (isLeadIndex) {
+                // if the first visible cell is selected, we want to shift that cell down
+                // to be the bottom-most cell, or at least as far to the bottom as we can go.
+                flow.showAsLast(firstVisibleCell);
+
+                ListCell<T> newFirstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
+                firstVisibleCell = newFirstVisibleCell == null ? firstVisibleCell : newFirstVisibleCell;
+            }
         } else {
             // if the selection is not on the 'top' most cell, we firstly move
             // the selection up to that, without scrolling the contents, so
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkinBase.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkinBase.java	Mon Feb 03 14:24:56 2014 +1300
@@ -37,8 +37,7 @@
 import javafx.collections.ObservableList;
 import javafx.geometry.Insets;
 import javafx.scene.Node;
-import javafx.scene.control.Label;
-import javafx.scene.control.SelectionModel;
+import javafx.scene.control.*;
 
 import javafx.scene.layout.Region;
 import javafx.scene.layout.StackPane;
@@ -54,14 +53,6 @@
 import javafx.event.EventHandler;
 import javafx.geometry.HPos;
 import javafx.geometry.VPos;
-import javafx.scene.control.Control;
-import javafx.scene.control.IndexedCell;
-import javafx.scene.control.ResizeFeaturesBase;
-import javafx.scene.control.ScrollToEvent;
-import javafx.scene.control.TableColumnBase;
-import javafx.scene.control.TableFocusModel;
-import javafx.scene.control.TablePositionBase;
-import javafx.scene.control.TableSelectionModel;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -447,6 +438,9 @@
      * if this is a horizontal container, then the scrolling will be to the right.
      */
     public int onScrollPageDown(boolean isFocusDriven) {
+        TableSelectionModel<S> sm = getSelectionModel();
+        if (sm == null) return -1;
+
         final int itemCount = getItemCount();
 
         I lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
@@ -460,7 +454,7 @@
         lastVisibleCellIndex = lastVisibleCellIndex >= itemCount ? itemCount - 1 : lastVisibleCellIndex;
         
         // isSelected represents focus OR selection
-        boolean isSelected = false;
+        boolean isSelected;
         if (isFocusDriven) {
             isSelected = lastVisibleCell.isFocused() || isCellFocused(lastVisibleCellIndex);
         } else {
@@ -468,12 +462,16 @@
         }
         
         if (isSelected) {
-            // if the last visible cell is selected, we want to shift that cell up
-            // to be the top-most cell, or at least as far to the top as we can go.
-            flow.showAsFirst(lastVisibleCell);
+            boolean isLeadIndex = isLeadIndex(isFocusDriven, lastVisibleCellIndex);
 
-            I newLastVisibleCell = flow.getLastVisibleCellWithinViewPort();
-            lastVisibleCell = newLastVisibleCell == null ? lastVisibleCell : newLastVisibleCell;
+            if (isLeadIndex) {
+                // if the last visible cell is selected, we want to shift that cell up
+                // to be the top-most cell, or at least as far to the top as we can go.
+                flow.showAsFirst(lastVisibleCell);
+
+                I newLastVisibleCell = flow.getLastVisibleCellWithinViewPort();
+                lastVisibleCell = newLastVisibleCell == null ? lastVisibleCell : newLastVisibleCell;
+            }
         } 
 
         int newSelectionIndex = lastVisibleCell.getIndex();
@@ -489,7 +487,7 @@
     public int onScrollPageUp(boolean isFocusDriven) {
         I firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
         if (firstVisibleCell == null) return -1;
-        
+
         int firstVisibleCellIndex = firstVisibleCell.getIndex();
 
         // isSelected represents focus OR selection
@@ -501,18 +499,30 @@
         }
 
         if (isSelected) {
-            // if the first visible cell is selected, we want to shift that cell down
-            // to be the bottom-most cell, or at least as far to the bottom as we can go.
-            flow.showAsLast(firstVisibleCell);
+            boolean isLeadIndex = isLeadIndex(isFocusDriven, firstVisibleCellIndex);
 
-            I newFirstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
-            firstVisibleCell = newFirstVisibleCell == null ? firstVisibleCell : newFirstVisibleCell;
+            if (isLeadIndex) {
+                // if the first visible cell is selected, we want to shift that cell down
+                // to be the bottom-most cell, or at least as far to the bottom as we can go.
+                flow.showAsLast(firstVisibleCell);
+
+                I newFirstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
+                firstVisibleCell = newFirstVisibleCell == null ? firstVisibleCell : newFirstVisibleCell;
+            }
         }
 
         int newSelectionIndex = firstVisibleCell.getIndex();
         flow.show(newSelectionIndex);
         return newSelectionIndex;
     }
+
+    private boolean isLeadIndex(boolean isFocusDriven, int index) {
+        final TableSelectionModel<S> sm = getSelectionModel();
+        final FocusModel fm = getFocusModel();
+
+        return (isFocusDriven && fm.getFocusedIndex() == index)
+                || (! isFocusDriven && sm.getSelectedIndex() == index);
+    }
     
      boolean isColumnPartiallyOrFullyVisible(TC col) {
         if (col == null || !col.isVisible()) return false;
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Mon Feb 03 14:24:56 2014 +1300
@@ -108,11 +108,11 @@
         getBehavior().setOnMoveToLastCell(new Runnable() {
             @Override public void run() { onMoveToLastCell(); }
         });
-        getBehavior().setOnScrollPageDown(new Callback<Integer, Integer>() {
-            @Override public Integer call(Integer anchor) { return onScrollPageDown(anchor); }
+        getBehavior().setOnScrollPageDown(new Callback<Boolean, Integer>() {
+            @Override public Integer call(Boolean isFocusDriven) { return onScrollPageDown(isFocusDriven); }
         });
-        getBehavior().setOnScrollPageUp(new Callback<Integer, Integer>() {
-            @Override public Integer call(Integer anchor) { return onScrollPageUp(anchor); }
+        getBehavior().setOnScrollPageUp(new Callback<Boolean, Integer>() {
+            @Override public Integer call(Boolean isFocusDriven) { return onScrollPageUp(isFocusDriven); }
         });
         getBehavior().setOnSelectPreviousRow(new Runnable() {
             @Override public void run() { onSelectPreviousCell(); }
@@ -402,7 +402,7 @@
     /**
      * Function used to scroll the container down by one 'page'.
      */
-    public int onScrollPageDown(int anchor) {
+    public int onScrollPageDown(boolean isFocusDriven) {
         TreeCell<T> lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
         if (lastVisibleCell == null) return -1;
 
@@ -411,13 +411,27 @@
         if (sm == null || fm == null) return -1;
 
         int lastVisibleCellIndex = lastVisibleCell.getIndex();
-        if (sm.isSelected(lastVisibleCellIndex) || fm.isFocused(lastVisibleCellIndex) || lastVisibleCellIndex == anchor) {
-            // if the last visible cell is selected, we want to shift that cell up
-            // to be the top-most cell, or at least as far to the top as we can go.
-            flow.showAsFirst(lastVisibleCell);
-            
-            TreeCell<T> newLastVisibleCell = flow.getLastVisibleCellWithinViewPort();
-            lastVisibleCell = newLastVisibleCell == null ? lastVisibleCell : newLastVisibleCell;
+
+        // isSelected represents focus OR selection
+        boolean isSelected = false;
+        if (isFocusDriven) {
+            isSelected = lastVisibleCell.isFocused() || fm.isFocused(lastVisibleCellIndex);
+        } else {
+            isSelected = lastVisibleCell.isSelected() || sm.isSelected(lastVisibleCellIndex);
+        }
+
+        if (isSelected) {
+            boolean isLeadIndex = (isFocusDriven && fm.getFocusedIndex() == lastVisibleCellIndex)
+                    || (! isFocusDriven && sm.getSelectedIndex() == lastVisibleCellIndex);
+
+            if (isLeadIndex) {
+                // if the last visible cell is selected, we want to shift that cell up
+                // to be the top-most cell, or at least as far to the top as we can go.
+                flow.showAsFirst(lastVisibleCell);
+
+                TreeCell<T> newLastVisibleCell = flow.getLastVisibleCellWithinViewPort();
+                lastVisibleCell = newLastVisibleCell == null ? lastVisibleCell : newLastVisibleCell;
+            }
         } else {
             // if the selection is not on the 'bottom' most cell, we firstly move
             // the selection down to that, without scrolling the contents, so
@@ -432,7 +446,7 @@
     /**
      * Function used to scroll the container up by one 'page'.
      */
-    public int onScrollPageUp(int anchor) {
+    public int onScrollPageUp(boolean isFocusDriven) {
         TreeCell<T> firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
         if (firstVisibleCell == null) return -1;
 
@@ -441,13 +455,27 @@
         if (sm == null || fm == null) return -1;
 
         int firstVisibleCellIndex = firstVisibleCell.getIndex();
-        if (sm.isSelected(firstVisibleCellIndex) || fm.isFocused(firstVisibleCellIndex) || firstVisibleCellIndex == anchor) {
-            // if the first visible cell is selected, we want to shift that cell down
-            // to be the bottom-most cell, or at least as far to the bottom as we can go.
-            flow.showAsLast(firstVisibleCell);
 
-            TreeCell<T> newFirstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
-            firstVisibleCell = newFirstVisibleCell == null ? firstVisibleCell : newFirstVisibleCell;
+        // isSelected represents focus OR selection
+        boolean isSelected = false;
+        if (isFocusDriven) {
+            isSelected = firstVisibleCell.isFocused() || fm.isFocused(firstVisibleCellIndex);
+        } else {
+            isSelected = firstVisibleCell.isSelected() || sm.isSelected(firstVisibleCellIndex);
+        }
+
+        if (isSelected) {
+            boolean isLeadIndex = (isFocusDriven && fm.getFocusedIndex() == firstVisibleCellIndex)
+                    || (! isFocusDriven && sm.getSelectedIndex() == firstVisibleCellIndex);
+
+            if (isLeadIndex) {
+                // if the first visible cell is selected, we want to shift that cell down
+                // to be the bottom-most cell, or at least as far to the bottom as we can go.
+                flow.showAsLast(firstVisibleCell);
+
+                TreeCell<T> newFirstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
+                firstVisibleCell = newFirstVisibleCell == null ? firstVisibleCell : newFirstVisibleCell;
+            }
         } else {
             // if the selection is not on the 'top' most cell, we firstly move
             // the selection up to that, without scrolling the contents, so
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/VirtualFlow.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/VirtualFlow.java	Mon Feb 03 14:24:56 2014 +1300
@@ -1969,7 +1969,10 @@
 
             final double cellStart = getCellPosition(cell);
             final double cellEnd = cellStart + getCellLength(cell);
-            if (cellEnd <= max) {
+
+            // we use the magic +2 to allow for a little bit of fuzziness,
+            // this is to help in situations such as RT-34407
+            if (cellEnd <= (max + 2)) {
                 return cell;
             }
         }
--- a/modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java	Mon Feb 03 14:24:56 2014 +1300
@@ -1796,7 +1796,6 @@
         assertTrue(isSelected(1, 2));
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_down_down_up() {
         final int items = 100;
         listView.getItems().clear();
@@ -1836,7 +1835,6 @@
         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_up_up_down() {
         final int items = 100;
         listView.getItems().clear();
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Mon Feb 03 14:24:56 2014 +1300
@@ -809,7 +809,7 @@
         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
-        assertTrue(isSelected(0,1,2));
+        assertTrue(debug(), isSelected(0,1,2));
         assertTrue(isAnchor(2));
     }
     
@@ -3219,7 +3219,6 @@
         assertTrue(sm.isSelected(2));
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_down_down_up() {
         final int items = 100;
         tableView.getItems().clear();
@@ -3261,7 +3260,6 @@
         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_up_up_down() {
         final int items = 100;
         tableView.getItems().clear();
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Mon Feb 03 14:24:56 2014 +1300
@@ -3740,7 +3740,6 @@
         assertTrue(sm.isSelected(2));
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_down_down_up() {
         final int items = 100;
         root.getChildren().clear();
@@ -3783,7 +3782,6 @@
         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_up_up_down() {
         final int items = 100;
         root.getChildren().clear();
@@ -3791,7 +3789,7 @@
         for (int i = 0; i < items; i++) {
             root.getChildren().add(new TreeItem<>("Row " + i));
         }
-        tableView.setPrefHeight(130); // roughly room for four rows
+        tableView.setPrefHeight(160); // roughly room for four rows
 
         new StageLoader(tableView);
         final TableFocusModel fm = tableView.getFocusModel();
@@ -3820,8 +3818,8 @@
         assertEquals(4, selectedIndicesCount);
 
         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
-        assertEquals(99 - diff * 2, sm.getSelectedIndex());
-        assertEquals(selectedIndicesCount * 2 - 1, sm.getSelectedIndices().size());
+        assertEquals(99 - diff * 2 - 1, sm.getSelectedIndex());
+        assertEquals(selectedIndicesCount * 2, sm.getSelectedIndices().size());
 
         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
         assertEquals(leadSelectedIndex, sm.getSelectedIndex());
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Mon Feb 03 14:46:17 2014 -0500
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Mon Feb 03 14:24:56 2014 +1300
@@ -2023,7 +2023,6 @@
         assertTrue(isSelected(1, 2));
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_down_down_up() {
         final int items = 100;
         root.getChildren().clear();
@@ -2064,7 +2063,6 @@
         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
     }
 
-    @Ignore("Bug not resolved yet")
     @Test public void test_rt34407_up_up_down() {
         final int items = 100;
         root.getChildren().clear();