< prev index next >

modules/javafx.controls/src/main/java/javafx/scene/control/ListView.java

Print this page
rev 10463 : 8089514: [TableView, TreeView, ListView, TreeTableView] Clicking outside of the edited cell, node, or entry should commit the value


 346         // ...selection model
 347         setSelectionModel(new ListView.ListViewBitSetSelectionModel<T>(this));
 348 
 349         // ...focus model
 350         setFocusModel(new ListView.ListViewFocusModel<T>(this));
 351 
 352         // ...edit commit handler
 353         setOnEditCommit(DEFAULT_EDIT_COMMIT_HANDLER);
 354 
 355         // Fix for RT-36651, which was introduced by RT-35679 (above) and resolved
 356         // by having special-case code to remove the listener when requested.
 357         // This is done by ComboBoxListViewSkin, so that selection is not done
 358         // when a ComboBox is shown.
 359         getProperties().addListener((MapChangeListener<Object, Object>) change -> {
 360             if (change.wasAdded() && "selectFirstRowByDefault".equals(change.getKey())) {
 361                 Boolean _selectFirstRowByDefault = (Boolean) change.getValueAdded();
 362                 if (_selectFirstRowByDefault == null) return;
 363                 selectFirstRowByDefault = _selectFirstRowByDefault;
 364             }
 365         });









 366     }
 367 
 368 
 369 
 370     /***************************************************************************
 371      *                                                                         *
 372      * Callbacks and Events                                                    *
 373      *                                                                         *
 374      **************************************************************************/
 375 
 376     private EventHandler<ListView.EditEvent<T>> DEFAULT_EDIT_COMMIT_HANDLER = t -> {
 377         int index = t.getIndex();
 378         List<T> list = getItems();
 379         if (index < 0 || index >= list.size()) return;
 380         list.set(index, t.getNewValue());
 381     };
 382 







 383 
 384 
 385     /***************************************************************************
 386      *                                                                         *
 387      * Properties                                                              *
 388      *                                                                         *
 389      **************************************************************************/
 390 
 391     // --- Items
 392     private ObjectProperty<ObservableList<T>> items;
 393 
 394     /**
 395      * Sets the underlying data model for the ListView. Note that it has a generic
 396      * type that must match the type of the ListView itself.
 397      * @param value the list of items for this ListView
 398      */
 399     public final void setItems(ObservableList<T> value) {
 400         itemsProperty().set(value);
 401     }
 402 


1211 
1212 
1213     // package for testing
1214     static class ListViewBitSetSelectionModel<T> extends MultipleSelectionModelBase<T> {
1215 
1216         /***********************************************************************
1217          *                                                                     *
1218          * Constructors                                                        *
1219          *                                                                     *
1220          **********************************************************************/
1221 
1222         public ListViewBitSetSelectionModel(final ListView<T> listView) {
1223             if (listView == null) {
1224                 throw new IllegalArgumentException("ListView can not be null");
1225             }
1226 
1227             this.listView = listView;
1228 
1229             ((SelectedItemsReadOnlyObservableList)getSelectedItems()).setItemsList(listView.getItems());
1230 
1231 
1232             /*
1233              * The following two listeners are used in conjunction with
1234              * SelectionModel.select(T obj) to allow for a developer to select
1235              * an item that is not actually in the data model. When this occurs,
1236              * we actively try to find an index that matches this object, going
1237              * so far as to actually watch for all changes to the items list,
1238              * rechecking each time.
1239              */
1240             itemsObserver = new InvalidationListener() {
1241                 private WeakReference<ObservableList<T>> weakItemsRef = new WeakReference<>(listView.getItems());
1242 
1243                 @Override public void invalidated(Observable observable) {
1244                     ObservableList<T> oldItems = weakItemsRef.get();
1245                     weakItemsRef = new WeakReference<>(listView.getItems());
1246                     ((SelectedItemsReadOnlyObservableList)getSelectedItems()).setItemsList(listView.getItems());
1247                     updateItemsObserver(oldItems, listView.getItems());
1248                 }
1249             };
1250 
1251             this.listView.itemsProperty().addListener(new WeakInvalidationListener(itemsObserver));


1343 //                System.out.println("\tWas replaced");
1344 //            }
1345 //            if (c.wasPermutated()) {
1346 //                System.out.println("\tWas permutated");
1347 //            }
1348             c.reset();
1349 
1350             List<Pair<Integer, Integer>> shifts = new ArrayList<>();
1351             while (c.next()) {
1352                 if (c.wasReplaced()) {
1353                     if (c.getList().isEmpty()) {
1354                         // the entire items list was emptied - clear selection
1355                         clearSelection();
1356                     } else {
1357                         int index = getSelectedIndex();
1358 
1359                         if (previousModelSize == c.getRemovedSize()) {
1360                             // all items were removed from the model
1361                             clearSelection();
1362                         } else if (index < getItemCount() && index >= 0) {
1363                             // Fix for RT-18969: the list had setAll called on it
1364                             // Use of makeAtomic is a fix for RT-20945
1365                             startAtomic();
1366                             clearSelection(index);
1367                             stopAtomic();
1368                             select(index);
1369                         } else {
1370                             // Fix for RT-22079
1371                             clearSelection();
1372                         }
1373                     }
1374                 } else if (c.wasAdded() || c.wasRemoved()) {
1375                     int shift = c.wasAdded() ? c.getAddedSize() : -c.getRemovedSize();
1376                     shifts.add(new Pair<>(c.getFrom(), shift));
1377                 } else if (c.wasPermutated()) {
1378 
1379                     // General approach:
1380                     //   -- detected a sort has happened
1381                     //   -- Create a permutation lookup map (1)
1382                     //   -- dump all the selected indices into a list (2)
1383                     //   -- clear the selected items / indexes (3)




 346         // ...selection model
 347         setSelectionModel(new ListView.ListViewBitSetSelectionModel<T>(this));
 348 
 349         // ...focus model
 350         setFocusModel(new ListView.ListViewFocusModel<T>(this));
 351 
 352         // ...edit commit handler
 353         setOnEditCommit(DEFAULT_EDIT_COMMIT_HANDLER);
 354 
 355         // Fix for RT-36651, which was introduced by RT-35679 (above) and resolved
 356         // by having special-case code to remove the listener when requested.
 357         // This is done by ComboBoxListViewSkin, so that selection is not done
 358         // when a ComboBox is shown.
 359         getProperties().addListener((MapChangeListener<Object, Object>) change -> {
 360             if (change.wasAdded() && "selectFirstRowByDefault".equals(change.getKey())) {
 361                 Boolean _selectFirstRowByDefault = (Boolean) change.getValueAdded();
 362                 if (_selectFirstRowByDefault == null) return;
 363                 selectFirstRowByDefault = _selectFirstRowByDefault;
 364             }
 365         });
 366 
 367         sceneProperty().addListener((o, oldScene, newScene) -> {
 368             if (oldScene != null) {
 369                 oldScene.focusOwnerProperty().removeListener(weakFocusOwnerListener);
 370             }
 371             if (newScene != null) {
 372                 newScene.focusOwnerProperty().addListener(weakFocusOwnerListener);
 373             }
 374         });
 375     }
 376 
 377 
 378 
 379     /***************************************************************************
 380      *                                                                         *
 381      * Callbacks and Events                                                    *
 382      *                                                                         *
 383      **************************************************************************/
 384 
 385     private EventHandler<ListView.EditEvent<T>> DEFAULT_EDIT_COMMIT_HANDLER = t -> {
 386         int index = t.getIndex();
 387         List<T> list = getItems();
 388         if (index < 0 || index >= list.size()) return;
 389         list.set(index, t.getNewValue());
 390     };
 391 
 392     private InvalidationListener focusOwnerListener = o -> {
 393         if (!ControlUtils.isFocusOnNodeOrAnyChild(this)) {
 394             edit(-1);
 395         }
 396     };
 397     private WeakInvalidationListener weakFocusOwnerListener = new WeakInvalidationListener(focusOwnerListener);
 398 
 399 
 400 
 401     /***************************************************************************
 402      *                                                                         *
 403      * Properties                                                              *
 404      *                                                                         *
 405      **************************************************************************/
 406 
 407     // --- Items
 408     private ObjectProperty<ObservableList<T>> items;
 409 
 410     /**
 411      * Sets the underlying data model for the ListView. Note that it has a generic
 412      * type that must match the type of the ListView itself.
 413      * @param value the list of items for this ListView
 414      */
 415     public final void setItems(ObservableList<T> value) {
 416         itemsProperty().set(value);
 417     }
 418 


1227 
1228 
1229     // package for testing
1230     static class ListViewBitSetSelectionModel<T> extends MultipleSelectionModelBase<T> {
1231 
1232         /***********************************************************************
1233          *                                                                     *
1234          * Constructors                                                        *
1235          *                                                                     *
1236          **********************************************************************/
1237 
1238         public ListViewBitSetSelectionModel(final ListView<T> listView) {
1239             if (listView == null) {
1240                 throw new IllegalArgumentException("ListView can not be null");
1241             }
1242 
1243             this.listView = listView;
1244 
1245             ((SelectedItemsReadOnlyObservableList)getSelectedItems()).setItemsList(listView.getItems());
1246 

1247             /*
1248              * The following two listeners are used in conjunction with
1249              * SelectionModel.select(T obj) to allow for a developer to select
1250              * an item that is not actually in the data model. When this occurs,
1251              * we actively try to find an index that matches this object, going
1252              * so far as to actually watch for all changes to the items list,
1253              * rechecking each time.
1254              */
1255             itemsObserver = new InvalidationListener() {
1256                 private WeakReference<ObservableList<T>> weakItemsRef = new WeakReference<>(listView.getItems());
1257 
1258                 @Override public void invalidated(Observable observable) {
1259                     ObservableList<T> oldItems = weakItemsRef.get();
1260                     weakItemsRef = new WeakReference<>(listView.getItems());
1261                     ((SelectedItemsReadOnlyObservableList)getSelectedItems()).setItemsList(listView.getItems());
1262                     updateItemsObserver(oldItems, listView.getItems());
1263                 }
1264             };
1265 
1266             this.listView.itemsProperty().addListener(new WeakInvalidationListener(itemsObserver));


1358 //                System.out.println("\tWas replaced");
1359 //            }
1360 //            if (c.wasPermutated()) {
1361 //                System.out.println("\tWas permutated");
1362 //            }
1363             c.reset();
1364 
1365             List<Pair<Integer, Integer>> shifts = new ArrayList<>();
1366             while (c.next()) {
1367                 if (c.wasReplaced()) {
1368                     if (c.getList().isEmpty()) {
1369                         // the entire items list was emptied - clear selection
1370                         clearSelection();
1371                     } else {
1372                         int index = getSelectedIndex();
1373 
1374                         if (previousModelSize == c.getRemovedSize()) {
1375                             // all items were removed from the model
1376                             clearSelection();
1377                         } else if (index < getItemCount() && index >= 0) {

1378                             // Use of makeAtomic is a fix for RT-20945
1379                             startAtomic();
1380                             clearSelection(index);
1381                             stopAtomic();
1382                             select(index);
1383                         } else {
1384                             // Fix for RT-22079
1385                             clearSelection();
1386                         }
1387                     }
1388                 } else if (c.wasAdded() || c.wasRemoved()) {
1389                     int shift = c.wasAdded() ? c.getAddedSize() : -c.getRemovedSize();
1390                     shifts.add(new Pair<>(c.getFrom(), shift));
1391                 } else if (c.wasPermutated()) {
1392 
1393                     // General approach:
1394                     //   -- detected a sort has happened
1395                     //   -- Create a permutation lookup map (1)
1396                     //   -- dump all the selected indices into a list (2)
1397                     //   -- clear the selected items / indexes (3)


< prev index next >