changeset 6675:6aee7411349a

RT-35679:[ListView, TreeView, et al]: The first item should be selected if nothing else is already selected
author jgiles
date Thu, 10 Apr 2014 09:47:11 +1200
parents 1ecd11e10561
children cb7df1eb29ed
files modules/controls/src/main/java/javafx/scene/control/ListView.java modules/controls/src/main/java/javafx/scene/control/TableView.java modules/controls/src/main/java/javafx/scene/control/TreeTableView.java modules/controls/src/main/java/javafx/scene/control/TreeView.java modules/controls/src/test/java/javafx/scene/control/ListViewTest.java modules/controls/src/test/java/javafx/scene/control/TableViewTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java
diffstat 8 files changed, 209 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/javafx/scene/control/ListView.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/ListView.java	Thu Apr 10 09:47:11 2014 +1200
@@ -30,6 +30,8 @@
 import java.util.HashMap;
 import java.util.List;
 
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.ObjectProperty;
@@ -319,6 +321,8 @@
 
         // ...edit commit handler
         setOnEditCommit(DEFAULT_EDIT_COMMIT_HANDLER);
+
+        focusedProperty().addListener(focusedListener);
     }
     
     
@@ -335,6 +339,20 @@
         if (index < 0 || index >= list.size()) return;
         list.set(index, t.getNewValue());
     };
+
+    private InvalidationListener focusedListener = observable -> {
+        // RT-25679 - we select the first item in the control if there is no
+        // current selection or focus on any other cell
+        List<T> items = getItems();
+        MultipleSelectionModel<T> sm = getSelectionModel();
+        FocusModel<T> fm = getFocusModel();
+
+        if (items != null && items.size() > 0 &&
+            sm != null && sm.isEmpty() &&
+            fm != null && fm.getFocusedIndex() == -1) {
+                sm.select(0);
+        }
+    };
     
     
     
--- a/modules/controls/src/main/java/javafx/scene/control/TableView.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TableView.java	Thu Apr 10 09:47:11 2014 +1200
@@ -550,6 +550,8 @@
             }
         });
 
+        focusedProperty().addListener(focusedListener);
+
         isInited = true;
     }
 
@@ -686,6 +688,21 @@
     
     private final WeakInvalidationListener weakCellSelectionModelInvalidationListener = 
             new WeakInvalidationListener(cellSelectionModelInvalidationListener);
+
+    private InvalidationListener focusedListener = observable -> {
+        // RT-25679 - we select the first item in the control if there is no
+        // current selection or focus on any other cell
+        List<S> items = getItems();
+        MultipleSelectionModel<S> sm = getSelectionModel();
+        FocusModel<S> fm = getFocusModel();
+
+        if (items != null && items.size() > 0 &&
+                sm != null && sm.isEmpty() &&
+                fm != null && fm.getFocusedIndex() == -1) {
+            sm.select(0);
+        }
+    };
+
     
     /***************************************************************************
      *                                                                         *
--- a/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Thu Apr 10 09:47:11 2014 +1200
@@ -395,6 +395,8 @@
             }
         });
 
+        focusedProperty().addListener(focusedListener);
+
         isInited = true;
     }
     
@@ -746,6 +748,19 @@
     
     private final WeakInvalidationListener weakCellSelectionModelInvalidationListener = 
             new WeakInvalidationListener(cellSelectionModelInvalidationListener);
+
+    private InvalidationListener focusedListener = observable -> {
+        // RT-25679 - we select the first item in the control if there is no
+        // current selection or focus on any other cell
+        MultipleSelectionModel<TreeItem<S>> sm = getSelectionModel();
+        FocusModel<TreeItem<S>> fm = getFocusModel();
+
+        if (getExpandedItemCount() > 0 &&
+                sm != null && sm.isEmpty() &&
+                fm != null && fm.getFocusedIndex() == -1) {
+            sm.select(0);
+        }
+    };
     
     /***************************************************************************
      *                                                                         *
--- a/modules/controls/src/main/java/javafx/scene/control/TreeView.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeView.java	Thu Apr 10 09:47:11 2014 +1200
@@ -29,6 +29,7 @@
 import com.sun.javafx.scene.control.skin.TreeViewSkin;
 import javafx.application.Platform;
 import javafx.beans.DefaultProperty;
+import javafx.beans.InvalidationListener;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.ObjectProperty;
@@ -328,6 +329,8 @@
         MultipleSelectionModel<TreeItem<T>> sm = new TreeViewBitSetSelectionModel<T>(this);
         setSelectionModel(sm);
         setFocusModel(new TreeViewFocusModel<T>(this));
+
+        focusedProperty().addListener(focusedListener);
     }
     
     
@@ -377,6 +380,19 @@
     };
     
     private WeakEventHandler<TreeModificationEvent<T>> weakRootEventListener;
+
+    private InvalidationListener focusedListener = observable -> {
+        // RT-25679 - we select the first item in the control if there is no
+        // current selection or focus on any other cell
+        MultipleSelectionModel<TreeItem<T>> sm = getSelectionModel();
+        FocusModel<TreeItem<T>> fm = getFocusModel();
+
+        if (getExpandedItemCount() > 0 &&
+                sm != null && sm.isEmpty() &&
+                fm != null && fm.getFocusedIndex() == -1) {
+            sm.select(0);
+        }
+    };
     
     
     /***************************************************************************
--- a/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java	Thu Apr 10 09:47:11 2014 +1200
@@ -847,4 +847,36 @@
 
         assertEquals(0, rt_35889_cancel_count);
     }
+
+    @Test public void test_rt25679() {
+        Button focusBtn = new Button("Focus here");
+
+        final ListView<String> listView = new ListView<String>();
+        SelectionModel sm = listView.getSelectionModel();
+        listView.setItems(FXCollections.observableArrayList("A", "B", "C"));
+
+        VBox vbox = new VBox(focusBtn, listView);
+
+        StageLoader sl = new StageLoader(vbox);
+        sl.getStage().requestFocus();
+        focusBtn.requestFocus();
+        Toolkit.getToolkit().firePulse();
+
+        // test initial state
+        assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
+        assertTrue(focusBtn.isFocused());
+        assertEquals(-1, sm.getSelectedIndex());
+        assertNull(sm.getSelectedItem());
+
+        // move focus to the listview
+        listView.requestFocus();
+
+        // ensure that there is a selection (where previously there was not one)
+        assertEquals(sl.getStage().getScene().getFocusOwner(), listView);
+        assertTrue(listView.isFocused());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("A", sm.getSelectedItem());
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Thu Apr 10 09:47:11 2014 +1200
@@ -54,6 +54,7 @@
 import javafx.scene.control.cell.*;
 import javafx.scene.image.ImageView;
 import javafx.scene.input.KeyCode;
+import javafx.scene.layout.VBox;
 import javafx.scene.paint.Color;
 import javafx.scene.shape.Rectangle;
 import javafx.util.Callback;
@@ -2835,4 +2836,39 @@
 
         sl.dispose();
     }
+
+    @Test public void test_rt25679() {
+        Button focusBtn = new Button("Focus here");
+
+        TableView<String> tableView = new TableView<>(FXCollections.observableArrayList("A", "B", "C"));
+
+        TableColumn<String, String> tableColumn = new TableColumn<>();
+        tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue()));
+        tableView.getColumns().add(tableColumn);
+        SelectionModel sm = tableView.getSelectionModel();
+
+        VBox vbox = new VBox(focusBtn, tableView);
+
+        StageLoader sl = new StageLoader(vbox);
+        sl.getStage().requestFocus();
+        focusBtn.requestFocus();
+        Toolkit.getToolkit().firePulse();
+
+        // test initial state
+        assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
+        assertTrue(focusBtn.isFocused());
+        assertEquals(-1, sm.getSelectedIndex());
+        assertNull(sm.getSelectedItem());
+
+        // move focus to the tableView
+        tableView.requestFocus();
+
+        // ensure that there is a selection (where previously there was not one)
+        assertEquals(sl.getStage().getScene().getFocusOwner(), tableView);
+        assertTrue(tableView.isFocused());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("A", sm.getSelectedItem());
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Thu Apr 10 09:47:11 2014 +1200
@@ -48,6 +48,7 @@
 import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.beans.property.ReadOnlyStringWrapper;
 import javafx.beans.property.SimpleObjectProperty;
+import javafx.beans.property.SimpleStringProperty;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
@@ -62,6 +63,7 @@
 import javafx.scene.image.ImageView;
 import javafx.scene.input.KeyCode;
 import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
 import javafx.scene.paint.Color;
 import javafx.scene.shape.Circle;
 import javafx.scene.shape.Rectangle;
@@ -3279,4 +3281,43 @@
 
         sl.dispose();
     }
+
+    @Test public void test_rt25679() {
+        Button focusBtn = new Button("Focus here");
+
+        TreeItem<String> root = new TreeItem<>("Root");
+        root.getChildren().setAll(new TreeItem("a"), new TreeItem("b"));
+        root.setExpanded(true);
+
+        final TreeTableView<String> treeView = new TreeTableView<>(root);
+        TreeTableColumn<String, String> tableColumn = new TreeTableColumn<>();
+        tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue().getValue()));
+        treeView.getColumns().add(tableColumn);
+
+        SelectionModel sm = treeView.getSelectionModel();
+
+        VBox vbox = new VBox(focusBtn, treeView);
+
+        StageLoader sl = new StageLoader(vbox);
+        sl.getStage().requestFocus();
+        focusBtn.requestFocus();
+        Toolkit.getToolkit().firePulse();
+
+        // test initial state
+        assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
+        assertTrue(focusBtn.isFocused());
+        assertEquals(-1, sm.getSelectedIndex());
+        assertNull(sm.getSelectedItem());
+
+        // move focus to the TreeTableView
+        treeView.requestFocus();
+
+        // ensure that there is a selection (where previously there was not one)
+        assertEquals(sl.getStage().getScene().getFocusOwner(), treeView);
+        assertTrue(treeView.isFocused());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(root, sm.getSelectedItem());
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java	Wed Apr 09 15:06:15 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java	Thu Apr 10 09:47:11 2014 +1200
@@ -1711,6 +1711,40 @@
         view.getSelectionModel().select(b);
         assertEquals(Arrays.asList(b), view.getSelectionModel().getSelectedItems());
         assertFalse(b.isExpanded());
+    }
 
+    @Test public void test_rt25679() {
+        Button focusBtn = new Button("Focus here");
+
+        TreeItem<String> root = new TreeItem<>("Root");
+        root.getChildren().setAll(new TreeItem("a"), new TreeItem("b"));
+        root.setExpanded(true);
+
+        final TreeView<String> treeView = new TreeView<>(root);
+        SelectionModel sm = treeView.getSelectionModel();
+
+        VBox vbox = new VBox(focusBtn, treeView);
+
+        StageLoader sl = new StageLoader(vbox);
+        sl.getStage().requestFocus();
+        focusBtn.requestFocus();
+        Toolkit.getToolkit().firePulse();
+
+        // test initial state
+        assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
+        assertTrue(focusBtn.isFocused());
+        assertEquals(-1, sm.getSelectedIndex());
+        assertNull(sm.getSelectedItem());
+
+        // move focus to the treeview
+        treeView.requestFocus();
+
+        // ensure that there is a selection (where previously there was not one)
+        assertEquals(sl.getStage().getScene().getFocusOwner(), treeView);
+        assertTrue(treeView.isFocused());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(root, sm.getSelectedItem());
+
+        sl.dispose();
     }
 }