1 /* 2 * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.javafx.scene.control; 27 28 import com.sun.javafx.scene.control.VirtualScrollBar; 29 import com.sun.javafx.scene.control.behavior.ListCellBehavior; 30 import com.sun.javafx.tk.Toolkit; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.Collections; 34 import java.util.List; 35 import java.util.ListIterator; 36 import java.util.NoSuchElementException; 37 import javafx.application.Platform; 38 import javafx.beans.binding.Bindings; 39 import javafx.beans.property.ObjectProperty; 40 import javafx.beans.property.ReadOnlyBooleanWrapper; 41 import javafx.beans.property.SimpleObjectProperty; 42 import javafx.collections.FXCollections; 43 import javafx.collections.ListChangeListener; 44 import javafx.collections.ObservableList; 45 import javafx.collections.transformation.SortedList; 46 import javafx.scene.control.Button; 47 import javafx.scene.control.FocusModel; 48 import javafx.scene.control.IndexedCell; 49 import javafx.scene.control.ListCell; 50 import javafx.scene.control.ListCellShim; 51 import javafx.scene.control.ListView; 52 import javafx.scene.control.ListViewShim; 53 import javafx.scene.control.MultipleSelectionModel; 54 import javafx.scene.control.SelectionMode; 55 import javafx.scene.control.SelectionModel; 56 import javafx.scene.control.TextField; 57 import javafx.scene.control.cell.CheckBoxListCell; 58 import javafx.scene.control.cell.ComboBoxListCell; 59 import javafx.scene.control.cell.TextFieldListCell; 60 import javafx.scene.image.ImageView; 61 import javafx.scene.input.KeyCode; 62 import javafx.scene.layout.VBox; 63 import javafx.scene.paint.Color; 64 import javafx.scene.shape.Rectangle; 65 import javafx.util.Callback; 66 import static org.junit.Assert.assertArrayEquals; 67 import static org.junit.Assert.assertEquals; 68 import static org.junit.Assert.assertFalse; 69 import static org.junit.Assert.assertNotNull; 70 import static org.junit.Assert.assertNull; 71 import static org.junit.Assert.assertSame; 72 import static org.junit.Assert.assertTrue; 73 import static org.junit.Assert.fail; 74 import org.junit.Before; 75 import org.junit.Test; 76 import static test.com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertStyleClassContains; 77 import test.com.sun.javafx.scene.control.infrastructure.KeyEventFirer; 78 import test.com.sun.javafx.scene.control.infrastructure.KeyModifier; 79 import test.com.sun.javafx.scene.control.infrastructure.StageLoader; 80 import test.com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils; 81 import test.com.sun.javafx.scene.control.test.Person; 82 import test.com.sun.javafx.scene.control.test.RT_22463_Person; 83 84 public class ListViewTest { 85 private ListView<String> listView; 86 private MultipleSelectionModel<String> sm; 87 private FocusModel<String> fm; 88 89 @Before public void setup() { 90 listView = new ListView<>(); 91 sm = listView.getSelectionModel(); 92 fm = listView.getFocusModel(); 93 } 94 95 96 /********************************************************************* 97 * Tests for the constructors * 98 ********************************************************************/ 99 100 @Test public void noArgConstructorSetsTheStyleClass() { 101 assertStyleClassContains(listView, "list-view"); 102 } 103 104 @Test public void noArgConstructorSetsNonNullSelectionModel() { 105 assertNotNull(sm); 106 } 107 108 @Test public void noArgConstructorSetsNonNullItems() { 109 assertNotNull(listView.getItems()); 110 } 111 112 @Test public void noArgConstructor_selectedItemIsNull() { 113 assertNull(sm.getSelectedItem()); 114 } 115 116 @Test public void noArgConstructor_selectedIndexIsNegativeOne() { 117 assertEquals(-1, sm.getSelectedIndex()); 118 } 119 120 @Test public void singleArgConstructorSetsTheStyleClass() { 121 final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi")); 122 assertStyleClassContains(b2, "list-view"); 123 } 124 125 @Test public void singleArgConstructorSetsNonNullSelectionModel() { 126 final ListView<String> b2 = new ListView<>(FXCollections.<String>observableArrayList("Hi")); 127 assertNotNull(b2.getSelectionModel()); 128 } 129 130 @Test public void singleArgConstructorAllowsNullItems() { 131 final ListView<String> b2 = new ListView<String>(null); 132 assertNull(b2.getItems()); 133 } 134 135 @Test public void singleArgConstructorTakesItems() { 136 ObservableList<String> items = FXCollections.observableArrayList("Hi"); 137 final ListView<String> b2 = new ListView<>(items); 138 assertSame(items, b2.getItems()); 139 } 140 141 @Test public void singleArgConstructor_selectedItemIsNull() { 142 final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi")); 143 assertNull(b2.getSelectionModel().getSelectedItem()); 144 } 145 146 @Test public void singleArgConstructor_selectedIndexIsNegativeOne() { 147 final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi")); 148 assertEquals(-1, b2.getSelectionModel().getSelectedIndex()); 149 } 150 151 /********************************************************************* 152 * Tests for selection model * 153 ********************************************************************/ 154 155 @Test public void selectionModelCanBeNull() { 156 listView.setSelectionModel(null); 157 assertNull(listView.getSelectionModel()); 158 } 159 160 @Test public void selectionModelCanBeBound() { 161 MultipleSelectionModel<String> sm = ListViewShim.<String>getListViewBitSetSelectionModel(listView); 162 ObjectProperty<MultipleSelectionModel<String>> other = new SimpleObjectProperty<MultipleSelectionModel<String>>(sm); 163 listView.selectionModelProperty().bind(other); 164 assertSame(sm, sm); 165 } 166 167 @Test public void selectionModelCanBeChanged() { 168 MultipleSelectionModel<String> sm = ListViewShim.<String>getListViewBitSetSelectionModel(listView); 169 listView.setSelectionModel(sm); 170 assertSame(sm, sm); 171 } 172 173 @Test public void canSetSelectedItemToAnItemEvenWhenThereAreNoItems() { 174 final String randomString = new String("I AM A CRAZY RANDOM STRING"); 175 sm.select(randomString); 176 assertEquals(-1, sm.getSelectedIndex()); 177 assertSame(randomString, sm.getSelectedItem()); 178 } 179 180 @Test public void canSetSelectedItemToAnItemNotInTheDataModel() { 181 listView.getItems().addAll("Apple", "Orange", "Banana"); 182 final String randomString = new String("I AM A CRAZY RANDOM STRING"); 183 sm.select(randomString); 184 assertEquals(-1, sm.getSelectedIndex()); 185 assertSame(randomString, sm.getSelectedItem()); 186 } 187 188 @Test public void settingTheSelectedItemToAnItemInItemsResultsInTheCorrectSelectedIndex() { 189 listView.getItems().addAll("Apple", "Orange", "Banana"); 190 sm.select("Orange"); 191 assertEquals(1, sm.getSelectedIndex()); 192 assertSame("Orange", sm.getSelectedItem()); 193 } 194 195 @Test public void settingTheSelectedItemToANonexistantItemAndThenSettingItemsWhichContainsItResultsInCorrectSelectedIndex() { 196 sm.select("Orange"); 197 listView.getItems().addAll("Apple", "Orange", "Banana"); 198 assertEquals(1, sm.getSelectedIndex()); 199 assertSame("Orange", sm.getSelectedItem()); 200 } 201 202 @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex0() { 203 listView.getItems().addAll("Apple", "Orange", "Banana"); 204 sm.select(0); 205 listView.getItems().clear(); 206 assertEquals(-1, sm.getSelectedIndex()); 207 assertEquals(null, sm.getSelectedItem()); 208 } 209 210 @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex2() { 211 listView.getItems().addAll("Apple", "Orange", "Banana"); 212 sm.select(2); 213 listView.getItems().clear(); 214 assertEquals(-1, sm.getSelectedIndex()); 215 assertEquals(null, sm.getSelectedItem()); 216 } 217 218 @Test public void ensureSelectedItemRemainsAccurateWhenItemsAreCleared() { 219 listView.getItems().addAll("Apple", "Orange", "Banana"); 220 sm.select(2); 221 listView.getItems().clear(); 222 assertNull(sm.getSelectedItem()); 223 assertEquals(-1, sm.getSelectedIndex()); 224 225 listView.getItems().addAll("Kiwifruit", "Mandarin", "Pineapple"); 226 sm.select(2); 227 assertEquals("Pineapple", sm.getSelectedItem()); 228 } 229 230 @Test public void ensureSelectionShiftsDownWhenOneNewItemIsAdded() { 231 listView.getItems().addAll("Apple", "Orange", "Banana"); 232 sm.select(1); 233 assertEquals(1, sm.getSelectedIndex()); 234 assertEquals("Orange", sm.getSelectedItem()); 235 236 listView.getItems().add(0, "Kiwifruit"); 237 assertEquals(2, sm.getSelectedIndex()); 238 assertEquals("Orange", sm.getSelectedItem()); 239 } 240 241 @Test public void ensureSelectionShiftsDownWhenMultipleNewItemAreAdded() { 242 listView.getItems().addAll("Apple", "Orange", "Banana"); 243 sm.select(1); 244 assertEquals(1, sm.getSelectedIndex()); 245 assertEquals("Orange", sm.getSelectedItem()); 246 247 listView.getItems().addAll(0, Arrays.asList("Kiwifruit", "Pineapple", "Mandarin")); 248 assertEquals("Orange", sm.getSelectedItem()); 249 assertEquals(4, sm.getSelectedIndex()); 250 } 251 252 @Test public void ensureSelectionShiftsUpWhenOneItemIsRemoved() { 253 listView.getItems().addAll("Apple", "Orange", "Banana"); 254 sm.select(1); 255 assertEquals(1, sm.getSelectedIndex()); 256 assertEquals("Orange", sm.getSelectedItem()); 257 258 listView.getItems().remove("Apple"); 259 assertEquals(0, sm.getSelectedIndex()); 260 assertEquals("Orange", sm.getSelectedItem()); 261 } 262 263 @Test public void ensureSelectionShiftsUpWheMultipleItemsAreRemoved() { 264 listView.getItems().addAll("Apple", "Orange", "Banana"); 265 sm.select(2); 266 assertEquals(2, sm.getSelectedIndex()); 267 assertEquals("Banana", sm.getSelectedItem()); 268 269 listView.getItems().removeAll(Arrays.asList("Apple", "Orange")); 270 assertEquals(0, sm.getSelectedIndex()); 271 assertEquals("Banana", sm.getSelectedItem()); 272 } 273 274 @Test public void ensureSelectionIsCorrectWhenItemsChange() { 275 listView.setItems(FXCollections.observableArrayList("Item 1")); 276 sm.select(0); 277 assertEquals("Item 1", sm.getSelectedItem()); 278 279 listView.setItems(FXCollections.observableArrayList("Item 2")); 280 assertEquals(-1, sm.getSelectedIndex()); 281 assertNull(sm.getSelectedItem()); 282 assertEquals(0, fm.getFocusedIndex()); 283 assertEquals("Item 2", fm.getFocusedItem()); 284 } 285 286 @Test public void test_rt15793() { 287 // ListView selectedIndex is 0 although the items list is empty 288 final ListView lv = new ListView(); 289 final ObservableList list = FXCollections.observableArrayList(); 290 lv.setItems(list); 291 list.add("toto"); 292 lv.getSelectionModel().select(0); 293 assertEquals(0, lv.getSelectionModel().getSelectedIndex()); 294 list.remove(0); 295 assertEquals(-1, lv.getSelectionModel().getSelectedIndex()); 296 } 297 298 @Test public void test_rt17522_focusShouldMoveWhenItemAddedAtFocusIndex() { 299 final ListView lv = new ListView(); 300 FocusModel fm = lv.getFocusModel(); 301 lv.getItems().add("row1"); 302 fm.focus(0); 303 assertTrue(fm.isFocused(0)); 304 305 lv.getItems().add(0, "row0"); 306 assertTrue(fm.isFocused(1)); 307 } 308 309 @Test public void test_rt17522_focusShouldMoveWhenItemAddedBeforeFocusIndex() { 310 final ListView lv = new ListView(); 311 FocusModel fm = lv.getFocusModel(); 312 lv.getItems().addAll("row1", "row2"); 313 fm.focus(1); 314 assertTrue(fm.isFocused(1)); 315 assertEquals("row2", fm.getFocusedItem()); 316 317 lv.getItems().add(1, "row0"); 318 assertTrue(fm.isFocused(2)); 319 assertEquals("row2", fm.getFocusedItem()); 320 assertFalse(fm.isFocused(1)); 321 } 322 323 @Test public void test_rt17522_focusShouldNotMoveWhenItemAddedAfterFocusIndex() { 324 final ListView lv = new ListView(); 325 FocusModel fm = lv.getFocusModel(); 326 lv.getItems().addAll("row1"); 327 fm.focus(0); 328 assertTrue(fm.isFocused(0)); 329 assertEquals("row1", fm.getFocusedItem()); 330 331 lv.getItems().add(1, "row2"); 332 assertTrue(fm.isFocused(0)); 333 assertEquals("row1", fm.getFocusedItem()); 334 assertFalse(fm.isFocused(1)); 335 } 336 337 @Test public void test_rt17522_focusShouldBeResetWhenFocusedItemIsRemoved() { 338 final ListView lv = new ListView(); 339 FocusModel fm = lv.getFocusModel(); 340 lv.getItems().add("row1"); 341 fm.focus(0); 342 assertTrue(fm.isFocused(0)); 343 344 lv.getItems().remove("row1"); 345 assertTrue(fm.getFocusedIndex() == -1); 346 assertNull(fm.getFocusedItem()); 347 } 348 349 @Test public void test_rt17522_focusShouldMoveWhenItemRemovedBeforeFocusIndex() { 350 final ListView lv = new ListView(); 351 FocusModel fm = lv.getFocusModel(); 352 lv.getItems().addAll("row1", "row2"); 353 fm.focus(1); 354 assertTrue(fm.isFocused(1)); 355 assertEquals("row2", fm.getFocusedItem()); 356 357 lv.getItems().remove("row1"); 358 assertTrue(fm.isFocused(0)); 359 assertEquals("row2", fm.getFocusedItem()); 360 } 361 362 @Test public void test_rt17522_focusShouldNotMoveWhenItemRemovedAfterFocusIndex() { 363 final ListView lv = new ListView(); 364 FocusModel fm = lv.getFocusModel(); 365 lv.getItems().addAll("row1", "row2"); 366 fm.focus(0); 367 assertTrue(fm.isFocused(0)); 368 assertEquals("row1", fm.getFocusedItem()); 369 370 lv.getItems().remove("row2"); 371 assertTrue(fm.isFocused(0)); 372 assertEquals("row1", fm.getFocusedItem()); 373 } 374 375 @Test public void test_rt18385() { 376 listView.getItems().addAll("row1", "row2", "row3"); 377 sm.select(1); 378 listView.getItems().add("Another Row"); 379 assertEquals(1, sm.getSelectedIndices().size()); 380 assertEquals(1, sm.getSelectedItems().size()); 381 } 382 383 @Test public void test_rt18339_onlyEditWhenListViewIsEditable_editableIsFalse() { 384 listView.setEditable(false); 385 listView.edit(1); 386 assertEquals(-1, listView.getEditingIndex()); 387 } 388 389 @Test public void test_rt18339_onlyEditWhenListViewIsEditable_editableIsTrue() { 390 listView.setEditable(true); 391 listView.edit(1); 392 assertEquals(1, listView.getEditingIndex()); 393 } 394 395 @Test public void test_rt14451() { 396 listView.getItems().addAll("Apple", "Orange", "Banana"); 397 sm.setSelectionMode(SelectionMode.MULTIPLE); 398 sm.selectRange(0, 2); // select from 0 (inclusive) to 2 (exclusive) 399 assertEquals(2, sm.getSelectedIndices().size()); 400 } 401 402 private int rt_18969_hitCount = 0; 403 @Test public void test_rt18969() { 404 rt_18969_hitCount = 0; 405 ObservableList<String> emptyModel = FXCollections.observableArrayList(); 406 listView.setItems(emptyModel); 407 assertTrue(listView.getItems().isEmpty()); 408 409 sm.selectedItemProperty().addListener((observable, oldValue, newValue) -> { 410 rt_18969_hitCount++; 411 }); 412 413 ObservableList<String> mod = FXCollections.observableArrayList(); 414 mod.add(System.currentTimeMillis()+""); 415 listView.getItems().setAll(mod); 416 417 sm.select(0); 418 assertTrue(sm.isSelected(0)); 419 assertEquals(1, rt_18969_hitCount); 420 421 // sleep for 100ms so that the currentTimeMillis is guaranteed to be 422 // a different value than the first one 423 try { 424 Thread.sleep(100); 425 } catch (InterruptedException ex) { 426 ex.printStackTrace(); 427 } 428 429 // the list is totally changing (it is being cleared), so we should 430 // be nulling out the selection model state 431 mod = FXCollections.observableArrayList(); 432 mod.add(System.currentTimeMillis()+""); 433 listView.getItems().setAll(mod); 434 435 // it should be two, as there is no null event in between (although there 436 // used to be, so the test used to be for three hits) 437 assertEquals(2, rt_18969_hitCount); 438 } 439 440 @Test public void test_rt21586() { 441 listView.getItems().setAll("Apple", "Orange", "Banana"); 442 listView.getSelectionModel().select(1); 443 assertEquals(1, listView.getSelectionModel().getSelectedIndex()); 444 assertEquals("Orange", listView.getSelectionModel().getSelectedItem()); 445 446 listView.getItems().setAll("Kiwifruit", "Pineapple", "Grape"); 447 assertEquals(-1, listView.getSelectionModel().getSelectedIndex()); 448 assertNull(listView.getSelectionModel().getSelectedItem()); 449 } 450 451 @Test public void test_rt27820_1() { 452 listView.getItems().setAll("Apple", "Orange"); 453 listView.getSelectionModel().select(0); 454 assertEquals(1, listView.getSelectionModel().getSelectedItems().size()); 455 assertEquals("Apple", listView.getSelectionModel().getSelectedItem()); 456 457 listView.getItems().clear(); 458 assertEquals(0, listView.getSelectionModel().getSelectedItems().size()); 459 assertNull(listView.getSelectionModel().getSelectedItem()); 460 } 461 462 @Test public void test_rt27820_2() { 463 listView.getItems().setAll("Apple", "Orange"); 464 listView.getSelectionModel().select(1); 465 assertEquals(1, listView.getSelectionModel().getSelectedItems().size()); 466 assertEquals("Orange", listView.getSelectionModel().getSelectedItem()); 467 468 listView.getItems().clear(); 469 assertEquals(0, listView.getSelectionModel().getSelectedItems().size()); 470 assertNull(listView.getSelectionModel().getSelectedItem()); 471 } 472 473 @Test public void test_rt28534() { 474 ListView<Person> list = new ListView<Person>(); 475 list.setItems(FXCollections.observableArrayList( 476 new Person("Jacob", "Smith", "jacob.smith@example.com"), 477 new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 478 new Person("Ethan", "Williams", "ethan.williams@example.com"), 479 new Person("Emma", "Jones", "emma.jones@example.com"), 480 new Person("Michael", "Brown", "michael.brown@example.com"))); 481 482 VirtualFlowTestUtils.assertRowsNotEmpty(list, 0, 5); // rows 0 - 5 should be filled 483 VirtualFlowTestUtils.assertRowsEmpty(list, 5, -1); // rows 5+ should be empty 484 485 // now we replace the data and expect the cells that have no data 486 // to be empty 487 list.setItems(FXCollections.observableArrayList( 488 new Person("*_*Emma", "Jones", "emma.jones@example.com"), 489 new Person("_Michael", "Brown", "michael.brown@example.com"))); 490 491 VirtualFlowTestUtils.assertRowsNotEmpty(list, 0, 2); // rows 0 - 2 should be filled 492 VirtualFlowTestUtils.assertRowsEmpty(list, 2, -1); // rows 2+ should be empty 493 } 494 495 @Test public void test_rt22463() { 496 final ListView<RT_22463_Person> list = new ListView<RT_22463_Person>(); 497 498 // before the change things display fine 499 RT_22463_Person p1 = new RT_22463_Person(); 500 p1.setId(1l); 501 p1.setName("name1"); 502 RT_22463_Person p2 = new RT_22463_Person(); 503 p2.setId(2l); 504 p2.setName("name2"); 505 list.setItems(FXCollections.observableArrayList(p1, p2)); 506 VirtualFlowTestUtils.assertCellTextEquals(list, 0, "name1"); 507 VirtualFlowTestUtils.assertCellTextEquals(list, 1, "name2"); 508 509 // now we change the persons but they are still equal as the ID's don't 510 // change - but the items list is cleared so the cells should update 511 RT_22463_Person new_p1 = new RT_22463_Person(); 512 new_p1.setId(1l); 513 new_p1.setName("updated name1"); 514 RT_22463_Person new_p2 = new RT_22463_Person(); 515 new_p2.setId(2l); 516 new_p2.setName("updated name2"); 517 list.getItems().clear(); 518 list.setItems(FXCollections.observableArrayList(new_p1, new_p2)); 519 VirtualFlowTestUtils.assertCellTextEquals(list, 0, "updated name1"); 520 VirtualFlowTestUtils.assertCellTextEquals(list, 1, "updated name2"); 521 } 522 523 @Test public void test_rt28637() { 524 ObservableList<String> items = FXCollections.observableArrayList("String1", "String2", "String3", "String4"); 525 526 final ListView<String> listView = new ListView<String>(); 527 listView.setItems(items); 528 529 listView.getSelectionModel().select(0); 530 assertEquals("String1", listView.getSelectionModel().getSelectedItem()); 531 assertEquals("String1", listView.getSelectionModel().getSelectedItems().get(0)); 532 assertEquals(0, listView.getSelectionModel().getSelectedIndex()); 533 534 items.remove(listView.getSelectionModel().getSelectedItem()); 535 assertEquals("String2", listView.getSelectionModel().getSelectedItem()); 536 assertEquals("String2", listView.getSelectionModel().getSelectedItems().get(0)); 537 assertEquals(0, listView.getSelectionModel().getSelectedIndex()); 538 } 539 540 @Test public void test_rt28819_1() { 541 ObservableList<String> emptyModel = FXCollections.observableArrayList(); 542 543 final ListView<String> listView = new ListView<String>(); 544 listView.setItems(emptyModel); 545 VirtualFlowTestUtils.assertRowsEmpty(listView, 0, 5); 546 547 ObservableList<String> mod = FXCollections.observableArrayList(); 548 String value = System.currentTimeMillis()+""; 549 mod.add(value); 550 listView.setItems(mod); 551 VirtualFlowTestUtils.assertCellCount(listView, 1); 552 VirtualFlowTestUtils.assertCellTextEquals(listView, 0, value); 553 } 554 555 @Test public void test_rt28819_2() { 556 ObservableList<String> emptyModel = FXCollections.observableArrayList(); 557 558 final ListView<String> listView = new ListView<String>(); 559 listView.setItems(emptyModel); 560 VirtualFlowTestUtils.assertRowsEmpty(listView, 0, 5); 561 562 ObservableList<String> mod1 = FXCollections.observableArrayList(); 563 String value1 = System.currentTimeMillis()+""; 564 mod1.add(value1); 565 listView.getItems().setAll(mod1); 566 VirtualFlowTestUtils.assertCellCount(listView, 1); 567 VirtualFlowTestUtils.assertCellTextEquals(listView, 0, value1); 568 } 569 570 @Test public void test_rt29390() { 571 ObservableList<String> items = FXCollections.observableArrayList( 572 "String1", "String2", "String3", "String4", 573 "String1", "String2", "String3", "String4", 574 "String1", "String2", "String3", "String4", 575 "String1", "String2", "String3", "String4" 576 ); 577 578 final ListView<String> listView = new ListView<String>(items); 579 listView.setMaxHeight(50); 580 listView.setPrefHeight(50); 581 582 // we want the vertical scrollbar 583 VirtualScrollBar scrollBar = VirtualFlowTestUtils.getVirtualFlowVerticalScrollbar(listView); 584 585 assertNotNull(scrollBar); 586 assertTrue(scrollBar.isVisible()); 587 assertTrue(scrollBar.getVisibleAmount() > 0.0); 588 assertTrue(scrollBar.getVisibleAmount() < 1.0); 589 590 // this next test is likely to be brittle, but we'll see...If it is the 591 // cause of failure then it can be commented out 592 assertEquals(0.125, scrollBar.getVisibleAmount(), 0.0); 593 } 594 595 @Test public void test_rt30400() { 596 // create a listview that'll render cells using the check box cell factory 597 ObservableList<String> items = FXCollections.observableArrayList("String1"); 598 final ListView<String> listView = new ListView<String>(items); 599 listView.setMinHeight(100); 600 listView.setPrefHeight(100); 601 listView.setCellFactory(CheckBoxListCell.forListView(param -> new ReadOnlyBooleanWrapper(true))); 602 603 // because only the first row has data, all other rows should be 604 // empty (and not contain check boxes - we just check the first four here) 605 VirtualFlowTestUtils.assertRowsNotEmpty(listView, 0, 1); 606 VirtualFlowTestUtils.assertCellNotEmpty(VirtualFlowTestUtils.getCell(listView, 0)); 607 VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(listView, 1)); 608 VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(listView, 2)); 609 VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(listView, 3)); 610 } 611 612 @Test public void test_rt29420() { 613 final ListView<String> listView = new ListView<String>(); 614 615 VBox vbox = new VBox(listView); 616 StageLoader sl = new StageLoader(vbox); 617 618 // the initial width of a ListView should be the golden rectangle where 619 // the height is hardcoded to be 400 620 final double initialWidth = listView.prefWidth(-1); 621 assertEquals(400 * 0.618033987, initialWidth, 0.00); 622 623 // add in some items, and re-measure - seeing as the items are narrow, 624 // the width shouldn't change 625 listView.getItems().addAll("one", "two", "three", "four", "five", "six"); 626 Toolkit.getToolkit().firePulse(); 627 final double withContentWidth = listView.prefWidth(-1); 628 assertEquals(initialWidth, withContentWidth, 0.00); 629 630 // remove the items - and the width should remain the same 631 listView.getItems().clear(); 632 Toolkit.getToolkit().firePulse(); 633 final double afterEmptiedWidth = listView.prefWidth(-1); 634 assertEquals(initialWidth, afterEmptiedWidth, 0.00); 635 636 sl.dispose(); 637 } 638 639 @Test public void test_rt31165() { 640 final ObservableList names = FXCollections.observableArrayList("Adam", "Alex", "Alfred", "Albert"); 641 final ObservableList data = FXCollections.observableArrayList(); 642 for (int i = 0; i < 18; i++) { 643 data.add(""+i); 644 } 645 646 final ListView listView = new ListView(data); 647 listView.setPrefSize(200, 250); 648 listView.setEditable(true); 649 listView.setCellFactory(ComboBoxListCell.forListView(names)); 650 651 IndexedCell cell = VirtualFlowTestUtils.getCell(listView, 1); 652 assertEquals("1", cell.getText()); 653 assertFalse(cell.isEditing()); 654 655 listView.edit(1); 656 657 assertEquals(1, listView.getEditingIndex()); 658 assertTrue(cell.isEditing()); 659 660 VirtualFlowTestUtils.getVirtualFlow(listView).requestLayout(); 661 Toolkit.getToolkit().firePulse(); 662 663 assertEquals(1, listView.getEditingIndex()); 664 assertTrue(cell.isEditing()); 665 } 666 667 @Test public void test_rt31471() { 668 final ObservableList names = FXCollections.observableArrayList("Adam", "Alex", "Alfred", "Albert"); 669 final ListView listView = new ListView(names); 670 671 IndexedCell cell = VirtualFlowTestUtils.getCell(listView, 0); 672 assertEquals("Adam", cell.getItem()); 673 674 listView.setFixedCellSize(50); 675 676 VirtualFlowTestUtils.getVirtualFlow(listView).requestLayout(); 677 Toolkit.getToolkit().firePulse(); 678 679 assertEquals("Adam", cell.getItem()); 680 assertEquals(50, cell.getHeight(), 0.00); 681 } 682 683 private int rt_31200_count = 0; 684 @Test public void test_rt_31200() { 685 final ListView listView = new ListView(); 686 listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 687 @Override 688 public ListCell<String> call(ListView<String> param) { 689 return new ListCellShim<String>() { 690 ImageView view = new ImageView(); 691 { setGraphic(view); }; 692 693 @Override 694 public void updateItem(String item, boolean empty) { 695 if (getItem() == null ? item == null : getItem().equals(item)) { 696 rt_31200_count++; 697 } 698 super.updateItem(item, empty); 699 if (item == null || empty) { 700 view.setImage(null); 701 setText(null); 702 } else { 703 setText(item); 704 } 705 } 706 }; 707 } 708 }); 709 listView.getItems().setAll("one", "two", "three", "four", "five"); 710 711 StageLoader sl = new StageLoader(listView); 712 713 assertEquals(24, rt_31200_count); 714 715 // resize the stage 716 sl.getStage().setHeight(250); 717 Toolkit.getToolkit().firePulse(); 718 sl.getStage().setHeight(50); 719 Toolkit.getToolkit().firePulse(); 720 assertEquals(24, rt_31200_count); 721 722 sl.dispose(); 723 } 724 725 @Test public void test_rt_30484() { 726 final ListView listView = new ListView(); 727 listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 728 @Override public ListCell<String> call(ListView<String> param) { 729 return new ListCellShim<String>() { 730 Rectangle graphic = new Rectangle(10, 10, Color.RED); 731 { setGraphic(graphic); }; 732 733 @Override public void updateItem(String item, boolean empty) { 734 super.updateItem(item, empty); 735 if (item == null || empty) { 736 graphic.setVisible(false); 737 setText(null); 738 } else { 739 graphic.setVisible(true); 740 setText(item); 741 } 742 } 743 }; 744 } 745 }); 746 747 // First two rows have content, so the graphic should show. 748 // All other rows have no content, so graphic should not show. 749 listView.getItems().setAll("one", "two"); 750 751 VirtualFlowTestUtils.assertGraphicIsVisible(listView, 0); 752 VirtualFlowTestUtils.assertGraphicIsVisible(listView, 1); 753 VirtualFlowTestUtils.assertGraphicIsNotVisible(listView, 2); 754 VirtualFlowTestUtils.assertGraphicIsNotVisible(listView, 3); 755 VirtualFlowTestUtils.assertGraphicIsNotVisible(listView, 4); 756 VirtualFlowTestUtils.assertGraphicIsNotVisible(listView, 5); 757 } 758 759 private int rt_29650_start_count = 0; 760 private int rt_29650_commit_count = 0; 761 private int rt_29650_cancel_count = 0; 762 @Test public void test_rt_29650() { 763 listView.setOnEditStart(t -> { 764 rt_29650_start_count++; 765 }); 766 listView.setOnEditCommit(t -> { 767 rt_29650_commit_count++; 768 }); 769 listView.setOnEditCancel(t -> { 770 rt_29650_cancel_count++; 771 }); 772 773 listView.getItems().setAll("one", "two", "three", "four", "five"); 774 listView.setEditable(true); 775 listView.setCellFactory(TextFieldListCell.forListView()); 776 777 StageLoader sl = new StageLoader(listView); 778 779 listView.edit(0); 780 781 Toolkit.getToolkit().firePulse(); 782 783 ListCell rootCell = (ListCell) VirtualFlowTestUtils.getCell(listView, 0); 784 TextField textField = (TextField) rootCell.getGraphic(); 785 textField.setText("Testing!"); 786 KeyEventFirer keyboard = new KeyEventFirer(textField); 787 keyboard.doKeyPress(KeyCode.ENTER); 788 789 // TODO should the following assert be enabled? 790 // assertEquals("Testing!", listView.getItems().get(0)); 791 assertEquals(1, rt_29650_start_count); 792 assertEquals(1, rt_29650_commit_count); 793 assertEquals(0, rt_29650_cancel_count); 794 795 sl.dispose(); 796 } 797 798 @Test public void test_rt35039() { 799 final List<String> data = new ArrayList<>(); 800 data.add("aabbaa"); 801 data.add("bbc"); 802 803 final ListView<String> listView = new ListView<>(); 804 listView.setItems(FXCollections.observableArrayList(data)); 805 806 StageLoader sl = new StageLoader(listView); 807 808 // selection starts off on row -1 809 assertNull(listView.getSelectionModel().getSelectedItem()); 810 811 // select "bbc" and ensure everything is set to that 812 listView.getSelectionModel().select(1); 813 assertEquals("bbc", listView.getSelectionModel().getSelectedItem()); 814 815 // change the items list - but retain the same content. We expect 816 // that "bbc" remains selected as it is still in the list 817 listView.setItems(FXCollections.observableArrayList(data)); 818 assertEquals("bbc", listView.getSelectionModel().getSelectedItem()); 819 820 sl.dispose(); 821 } 822 823 @Test public void test_rt35857() { 824 ObservableList<String> fxList = FXCollections.observableArrayList("A", "B", "C"); 825 final ListView<String> listView = new ListView<String>(fxList); 826 827 listView.getSelectionModel().select(0); 828 829 ObservableList<String> selectedItems = listView.getSelectionModel().getSelectedItems(); 830 assertEquals(1, selectedItems.size()); 831 assertEquals("A", selectedItems.get(0)); 832 833 listView.getItems().removeAll(selectedItems); 834 assertEquals(2, fxList.size()); 835 assertEquals("B", fxList.get(0)); 836 assertEquals("C", fxList.get(1)); 837 } 838 839 private int rt_35889_cancel_count = 0; 840 @Test public void test_rt35889() { 841 final ListView<String> textFieldListView = new ListView<String>(); 842 textFieldListView.setItems(FXCollections.observableArrayList("A", "B", "C")); 843 textFieldListView.setEditable(true); 844 textFieldListView.setCellFactory(TextFieldListCell.forListView()); 845 textFieldListView.setOnEditCancel(t -> { 846 rt_35889_cancel_count++; 847 System.out.println("On Edit Cancel: " + t); 848 }); 849 850 ListCell cell0 = (ListCell) VirtualFlowTestUtils.getCell(textFieldListView, 0); 851 assertNull(cell0.getGraphic()); 852 assertEquals("A", cell0.getText()); 853 854 textFieldListView.edit(0); 855 TextField textField = (TextField) cell0.getGraphic(); 856 assertNotNull(textField); 857 858 assertEquals(0, rt_35889_cancel_count); 859 860 textField.setText("Z"); 861 KeyEventFirer keyboard = new KeyEventFirer(textField); 862 keyboard.doKeyPress(KeyCode.ENTER); 863 864 assertEquals(0, rt_35889_cancel_count); 865 } 866 867 @Test public void test_rt25679() { 868 Button focusBtn = new Button("Focus here"); 869 870 final ListView<String> listView = new ListView<String>(); 871 SelectionModel sm = listView.getSelectionModel(); 872 listView.setItems(FXCollections.observableArrayList("A", "B", "C")); 873 874 VBox vbox = new VBox(focusBtn, listView); 875 876 StageLoader sl = new StageLoader(vbox); 877 sl.getStage().requestFocus(); 878 focusBtn.requestFocus(); 879 Toolkit.getToolkit().firePulse(); 880 881 // test initial state 882 assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn); 883 assertTrue(focusBtn.isFocused()); 884 assertEquals(-1, sm.getSelectedIndex()); 885 assertNull(sm.getSelectedItem()); 886 887 // move focus to the listview 888 listView.requestFocus(); 889 890 // ensure that there is a selection (where previously there was not one) 891 assertEquals(sl.getStage().getScene().getFocusOwner(), listView); 892 assertTrue(listView.isFocused()); 893 assertEquals(-1, sm.getSelectedIndex()); 894 assertNull(sm.getSelectedItem()); 895 896 sl.dispose(); 897 } 898 899 private int rt_37061_index_counter = 0; 900 private int rt_37061_item_counter = 0; 901 @Test public void test_rt_37061() { 902 ListView<Integer> tv = new ListView<>(); 903 tv.getItems().add(1); 904 tv.getSelectionModel().select(0); 905 906 // note we add the listeners after the selection is made, so the counters 907 // at this point are still both at zero. 908 tv.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> { 909 rt_37061_index_counter++; 910 }); 911 912 tv.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { 913 rt_37061_item_counter++; 914 }); 915 916 // add a new item. This does not impact the selected index or selected item 917 // so the counters should remain at zero. 918 tv.getItems().add(2); 919 assertEquals(0, rt_37061_index_counter); 920 assertEquals(0, rt_37061_item_counter); 921 } 922 923 private int rt_37538_count = 0; 924 @Test public void test_rt_37538_noCNextCall() { 925 test_rt_37538(false, false); 926 } 927 928 @Test public void test_rt_37538_callCNextOnce() { 929 test_rt_37538(true, false); 930 } 931 932 @Test public void test_rt_37538_callCNextInLoop() { 933 test_rt_37538(false, true); 934 } 935 936 private void test_rt_37538(boolean callCNextOnce, boolean callCNextInLoop) { 937 ListView<Integer> list = new ListView<>(); 938 for ( int i = 1; i <= 50; i++ ) { 939 list.getItems().add(i); 940 } 941 942 list.getSelectionModel().getSelectedItems().addListener((ListChangeListener.Change<? extends Integer> c) -> { 943 if (callCNextOnce) { 944 c.next(); 945 } else if (callCNextInLoop) { 946 while (c.next()) { 947 // no-op 948 } 949 } 950 951 if (rt_37538_count >= 1) { 952 Thread.dumpStack(); 953 fail("This method should only be called once"); 954 } 955 956 rt_37538_count++; 957 }); 958 959 StageLoader sl = new StageLoader(list); 960 assertEquals(0, rt_37538_count); 961 list.getSelectionModel().select(0); 962 assertEquals(1, rt_37538_count); 963 sl.dispose(); 964 } 965 966 @Test 967 public void test_rt_35395_fixedCellSize() { 968 test_rt_35395(true); 969 } 970 971 @Test 972 public void test_rt_35395_notFixedCellSize() { 973 test_rt_35395(false); 974 } 975 976 private int rt_35395_counter; 977 978 private void test_rt_35395(boolean useFixedCellSize) { 979 rt_35395_counter = 0; 980 981 ObservableList<String> items = FXCollections.observableArrayList(); 982 for (int i = 0; i < 20; ++i) { 983 items.addAll("red", "green", "blue", "purple"); 984 } 985 986 ListView<String> listView = new ListView<>(items); 987 if (useFixedCellSize) { 988 listView.setFixedCellSize(24); 989 } 990 listView.setCellFactory(lv -> new ListCellShim<String>() { 991 @Override 992 public void updateItem(String color, boolean empty) { 993 rt_35395_counter += 1; 994 super.updateItem(color, empty); 995 setText(null); 996 if (empty) { 997 setGraphic(null); 998 } else { 999 Rectangle rect = new Rectangle(16, 16); 1000 rect.setStyle("-fx-fill: " + color); 1001 setGraphic(rect); 1002 } 1003 } 1004 }); 1005 1006 StageLoader sl = new StageLoader(listView); 1007 1008 Platform.runLater(() -> { 1009 rt_35395_counter = 0; 1010 items.set(10, "yellow"); 1011 Platform.runLater(() -> { 1012 Toolkit.getToolkit().firePulse(); 1013 assertEquals(1, rt_35395_counter); 1014 rt_35395_counter = 0; 1015 items.set(30, "yellow"); 1016 Platform.runLater(() -> { 1017 Toolkit.getToolkit().firePulse(); 1018 assertEquals(0, rt_35395_counter); 1019 rt_35395_counter = 0; 1020 items.remove(12); 1021 Platform.runLater(() -> { 1022 Toolkit.getToolkit().firePulse(); 1023 assertEquals(useFixedCellSize ? 39 : 45, rt_35395_counter); 1024 rt_35395_counter = 0; 1025 items.add(12, "yellow"); 1026 Platform.runLater(() -> { 1027 Toolkit.getToolkit().firePulse(); 1028 assertEquals(useFixedCellSize ? 39 : 45, rt_35395_counter); 1029 rt_35395_counter = 0; 1030 listView.scrollTo(5); 1031 Platform.runLater(() -> { 1032 Toolkit.getToolkit().firePulse(); 1033 assertEquals(5, rt_35395_counter); 1034 rt_35395_counter = 0; 1035 listView.scrollTo(55); 1036 Platform.runLater(() -> { 1037 Toolkit.getToolkit().firePulse(); 1038 assertEquals(useFixedCellSize ? 17 : 53, rt_35395_counter); 1039 sl.dispose(); 1040 }); 1041 }); 1042 }); 1043 }); 1044 }); 1045 }); 1046 }); 1047 } 1048 1049 @Test public void test_rt_37632() { 1050 final ObservableList<String> listOne = FXCollections.observableArrayList("A", "B", "C"); 1051 final ObservableList<String> listTwo = FXCollections.observableArrayList("C"); 1052 1053 final ListView<String> listView = new ListView<>(); 1054 MultipleSelectionModel<String> sm = listView.getSelectionModel(); 1055 listView.setItems(listOne); 1056 listView.getSelectionModel().selectFirst(); 1057 1058 assertEquals(0, sm.getSelectedIndex()); 1059 assertEquals("A", sm.getSelectedItem()); 1060 assertEquals(1, sm.getSelectedIndices().size()); 1061 assertEquals(0, (int) sm.getSelectedIndices().get(0)); 1062 assertEquals(1, sm.getSelectedItems().size()); 1063 assertEquals("A", sm.getSelectedItems().get(0)); 1064 1065 listView.setItems(listTwo); 1066 1067 assertEquals(-1, sm.getSelectedIndex()); 1068 assertNull(sm.getSelectedItem()); 1069 assertEquals(0, sm.getSelectedIndices().size()); 1070 assertEquals(0, sm.getSelectedItems().size()); 1071 } 1072 1073 private int rt_37853_cancelCount; 1074 private int rt_37853_commitCount; 1075 @Test public void test_rt_37853() { 1076 listView.setCellFactory(TextFieldListCell.forListView()); 1077 listView.setEditable(true); 1078 1079 for (int i = 0; i < 10; i++) { 1080 listView.getItems().add("" + i); 1081 } 1082 1083 StageLoader sl = new StageLoader(listView); 1084 1085 listView.setOnEditCancel(editEvent -> rt_37853_cancelCount++); 1086 listView.setOnEditCommit(editEvent -> rt_37853_commitCount++); 1087 1088 assertEquals(0, rt_37853_cancelCount); 1089 assertEquals(0, rt_37853_commitCount); 1090 1091 listView.edit(1); 1092 assertNotNull(listView.getEditingIndex()); 1093 1094 listView.getItems().clear(); 1095 assertEquals(1, rt_37853_cancelCount); 1096 assertEquals(0, rt_37853_commitCount); 1097 1098 sl.dispose(); 1099 } 1100 1101 @Test public void test_rt_38787_remove_b() { 1102 // selection moves to "a" 1103 test_rt_38787("a", 0, "b"); 1104 } 1105 1106 @Test public void test_rt_38787_remove_b_c() { 1107 // selection moves to "a" 1108 test_rt_38787("a", 0, "b", "c"); 1109 } 1110 1111 @Test public void test_rt_38787_remove_c_d() { 1112 // selection moves to "b" 1113 test_rt_38787("b", 1, "c", "d"); 1114 } 1115 1116 @Test public void test_rt_38787_remove_a() { 1117 // selection moves to "b", now in index 0 1118 test_rt_38787("b", 0, "a"); 1119 } 1120 1121 @Test public void test_rt_38787_remove_z() { 1122 // selection shouldn't move as 'z' doesn't exist 1123 test_rt_38787("b", 1, "z"); 1124 } 1125 1126 private void test_rt_38787(String expectedItem, int expectedIndex, String... itemsToRemove) { 1127 ListView<String> stringListView = new ListView<>(); 1128 stringListView.getItems().addAll("a","b","c","d"); 1129 1130 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1131 sm.select("b"); 1132 1133 // test pre-conditions 1134 assertEquals(1, sm.getSelectedIndex()); 1135 assertEquals(1, (int)sm.getSelectedIndices().get(0)); 1136 assertEquals("b", sm.getSelectedItem()); 1137 assertEquals("b", sm.getSelectedItems().get(0)); 1138 assertFalse(sm.isSelected(0)); 1139 assertTrue(sm.isSelected(1)); 1140 assertFalse(sm.isSelected(2)); 1141 1142 // removing items 1143 stringListView.getItems().removeAll(itemsToRemove); 1144 1145 // testing against expectations 1146 assertEquals(expectedIndex, sm.getSelectedIndex()); 1147 assertEquals(expectedIndex, (int)sm.getSelectedIndices().get(0)); 1148 assertEquals(expectedItem, sm.getSelectedItem()); 1149 assertEquals(expectedItem, sm.getSelectedItems().get(0)); 1150 } 1151 1152 private int rt_38341_indices_count = 0; 1153 private int rt_38341_items_count = 0; 1154 @Test public void test_rt_38341() { 1155 ListView<String> stringListView = new ListView<>(); 1156 stringListView.getItems().addAll("a","b","c","d"); 1157 1158 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1159 sm.getSelectedIndices().addListener((ListChangeListener<Integer>) c -> rt_38341_indices_count++); 1160 sm.getSelectedItems().addListener((ListChangeListener<String>) c -> rt_38341_items_count++); 1161 1162 assertEquals(0, rt_38341_indices_count); 1163 assertEquals(0, rt_38341_items_count); 1164 1165 // expand the first child of root, and select it (note: root isn't visible) 1166 sm.select(1); 1167 assertEquals(1, sm.getSelectedIndex()); 1168 assertEquals(1, sm.getSelectedIndices().size()); 1169 assertEquals(1, (int)sm.getSelectedIndices().get(0)); 1170 assertEquals(1, sm.getSelectedItems().size()); 1171 assertEquals("b", sm.getSelectedItem()); 1172 assertEquals("b", sm.getSelectedItems().get(0)); 1173 1174 assertEquals(1, rt_38341_indices_count); 1175 assertEquals(1, rt_38341_items_count); 1176 1177 // now delete it 1178 stringListView.getItems().remove(1); 1179 1180 // selection should move to the childs parent in index 0 1181 assertEquals(0, sm.getSelectedIndex()); 1182 assertEquals(1, sm.getSelectedIndices().size()); 1183 assertEquals(0, (int)sm.getSelectedIndices().get(0)); 1184 assertEquals(1, sm.getSelectedItems().size()); 1185 assertEquals("a", sm.getSelectedItem()); 1186 assertEquals("a", sm.getSelectedItems().get(0)); 1187 1188 // we also expect there to be an event in the selection model for 1189 // selected indices and selected items 1190 assertEquals(sm.getSelectedIndices() +"", 2, rt_38341_indices_count); 1191 assertEquals(2, rt_38341_items_count); 1192 } 1193 1194 @Test public void test_rt_39132() { 1195 ObservableList items = FXCollections.observableArrayList("one", "two", "three"); 1196 ListView listView = new ListView<>(); 1197 listView.setItems(items); 1198 1199 MultipleSelectionModel sm = listView.getSelectionModel(); 1200 sm.select(0); 1201 1202 assertEquals(0, sm.getSelectedIndex()); 1203 assertEquals("one", sm.getSelectedItem()); 1204 1205 items.add(0, "new item"); 1206 assertEquals(1, sm.getSelectedIndex()); 1207 assertEquals("one", sm.getSelectedItem()); 1208 } 1209 1210 private int rt_38943_index_count = 0; 1211 private int rt_38943_item_count = 0; 1212 @Test public void test_rt_38943() { 1213 ListView<String> listView = new ListView<>(FXCollections.observableArrayList("one", "two", "three")); 1214 1215 MultipleSelectionModel sm = listView.getSelectionModel(); 1216 1217 sm.selectedIndexProperty().addListener((observable, oldValue, newValue) -> rt_38943_index_count++); 1218 sm.selectedItemProperty().addListener((observable, oldValue, newValue) -> rt_38943_item_count++); 1219 1220 assertEquals(-1, sm.getSelectedIndex()); 1221 assertNull(sm.getSelectedItem()); 1222 assertEquals(0, rt_38943_index_count); 1223 assertEquals(0, rt_38943_item_count); 1224 1225 sm.select(0); 1226 assertEquals(0, sm.getSelectedIndex()); 1227 assertEquals("one", sm.getSelectedItem()); 1228 assertEquals(1, rt_38943_index_count); 1229 assertEquals(1, rt_38943_item_count); 1230 1231 sm.clearSelection(0); 1232 assertEquals(-1, sm.getSelectedIndex()); 1233 assertNull(sm.getSelectedItem()); 1234 assertEquals(2, rt_38943_index_count); 1235 assertEquals(2, rt_38943_item_count); 1236 } 1237 1238 @Test public void test_rt_38884() { 1239 ListView<String> listView = new ListView<>(); 1240 ObservableList<String> items = listView.getItems(); 1241 1242 listView.getSelectionModel().getSelectedItems().addListener((ListChangeListener.Change<? extends String> c) -> { 1243 while (c.next()) { 1244 if (c.wasRemoved()) { 1245 assertTrue(c.getRemovedSize() > 0); 1246 1247 List<? extends String> removed = c.getRemoved(); 1248 String removedItem = null; 1249 try { 1250 removedItem = removed.get(0); 1251 } catch (Exception e) { 1252 fail(); 1253 } 1254 1255 assertEquals("foo", removedItem); 1256 } 1257 } 1258 }); 1259 1260 items.add("foo"); 1261 listView.getSelectionModel().select(0); 1262 items.clear(); 1263 } 1264 1265 private int rt_37360_add_count = 0; 1266 private int rt_37360_remove_count = 0; 1267 @Test public void test_rt_37360() { 1268 ListView<String> stringListView = new ListView<>(); 1269 stringListView.getItems().addAll("a", "b"); 1270 1271 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1272 sm.setSelectionMode(SelectionMode.MULTIPLE); 1273 sm.getSelectedItems().addListener((ListChangeListener<String>) c -> { 1274 while (c.next()) { 1275 if (c.wasAdded()) { 1276 rt_37360_add_count += c.getAddedSize(); 1277 } 1278 if (c.wasRemoved()) { 1279 rt_37360_remove_count += c.getRemovedSize(); 1280 } 1281 } 1282 }); 1283 1284 assertEquals(0, sm.getSelectedItems().size()); 1285 assertEquals(0, rt_37360_add_count); 1286 assertEquals(0, rt_37360_remove_count); 1287 1288 sm.select(0); 1289 assertEquals(1, sm.getSelectedItems().size()); 1290 assertEquals(1, rt_37360_add_count); 1291 assertEquals(0, rt_37360_remove_count); 1292 1293 sm.select(1); 1294 assertEquals(2, sm.getSelectedItems().size()); 1295 assertEquals(2, rt_37360_add_count); 1296 assertEquals(0, rt_37360_remove_count); 1297 1298 sm.clearAndSelect(1); 1299 assertEquals(1, sm.getSelectedItems().size()); 1300 assertEquals(2, rt_37360_add_count); 1301 assertEquals(1, rt_37360_remove_count); 1302 } 1303 1304 @Test public void test_rt_38491() { 1305 ListView<String> stringListView = new ListView<>(); 1306 stringListView.getItems().addAll("a", "b"); 1307 1308 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1309 sm.setSelectionMode(SelectionMode.MULTIPLE); 1310 1311 FocusModel<String> fm = stringListView.getFocusModel(); 1312 1313 // click on row 0 1314 VirtualFlowTestUtils.clickOnRow(stringListView, 0); 1315 assertTrue(sm.isSelected(0)); 1316 assertEquals("a", sm.getSelectedItem()); 1317 assertTrue(fm.isFocused(0)); 1318 assertEquals("a", fm.getFocusedItem()); 1319 assertEquals(0, fm.getFocusedIndex()); 1320 1321 int anchor = ListCellBehavior.getAnchor(stringListView, -1); 1322 assertTrue(ListCellBehavior.hasNonDefaultAnchor(stringListView)); 1323 assertEquals(0, anchor); 1324 1325 // now add a new item at row 0. This has the effect of pushing down 1326 // the selected item into row 1. 1327 stringListView.getItems().add(0, "z"); 1328 1329 // The first bug was that selection and focus were not moving down to 1330 // be on row 1, so we test that now 1331 assertFalse(sm.isSelected(0)); 1332 assertFalse(fm.isFocused(0)); 1333 assertTrue(sm.isSelected(1)); 1334 assertEquals("a", sm.getSelectedItem()); 1335 assertTrue(fm.isFocused(1)); 1336 assertEquals("a", fm.getFocusedItem()); 1337 assertEquals(1, fm.getFocusedIndex()); 1338 1339 // The second bug was that the anchor was not being pushed down as well 1340 // (when it should). 1341 anchor = ListCellBehavior.getAnchor(stringListView, -1); 1342 assertTrue(ListCellBehavior.hasNonDefaultAnchor(stringListView)); 1343 assertEquals(1, anchor); 1344 } 1345 1346 private final ObservableList<String> rt_39256_list = FXCollections.observableArrayList(); 1347 @Test public void test_rt_39256() { 1348 ListView<String> stringListView = new ListView<>(); 1349 stringListView.getItems().addAll("a","b", "c", "d"); 1350 1351 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1352 sm.setSelectionMode(SelectionMode.MULTIPLE); 1353 1354 // rt_39256_list.addListener((ListChangeListener<String>) change -> { 1355 // while (change.next()) { 1356 // System.err.println("number of selected persons (in bound list): " + change.getList().size()); 1357 // } 1358 // }); 1359 1360 Bindings.bindContent(rt_39256_list, sm.getSelectedItems()); 1361 1362 assertEquals(0, sm.getSelectedItems().size()); 1363 assertEquals(0, rt_39256_list.size()); 1364 1365 sm.selectAll(); 1366 assertEquals(4, sm.getSelectedItems().size()); 1367 assertEquals(4, rt_39256_list.size()); 1368 1369 sm.selectAll(); 1370 assertEquals(4, sm.getSelectedItems().size()); 1371 assertEquals(4, rt_39256_list.size()); 1372 1373 sm.selectAll(); 1374 assertEquals(4, sm.getSelectedItems().size()); 1375 assertEquals(4, rt_39256_list.size()); 1376 } 1377 1378 private final ObservableList<String> rt_39482_list = FXCollections.observableArrayList(); 1379 @Test public void test_rt_39482() { 1380 ListView<String> stringListView = new ListView<>(); 1381 stringListView.getItems().addAll("a", "b", "c", "d"); 1382 1383 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1384 sm.setSelectionMode(SelectionMode.MULTIPLE); 1385 1386 sm.getSelectedItems().addListener((ListChangeListener<String>) change -> { 1387 while (change.next()) { 1388 System.out.println("sm.getSelectedItems(): " + change.getList()); 1389 } 1390 }); 1391 1392 rt_39482_list.addListener((ListChangeListener<String>) change -> { 1393 while (change.next()) { 1394 System.out.println("rt_39482_list: " + change.getList()); 1395 } 1396 }); 1397 1398 Bindings.bindContent(rt_39482_list, sm.getSelectedItems()); 1399 1400 assertEquals(0, sm.getSelectedItems().size()); 1401 assertEquals(0, rt_39482_list.size()); 1402 1403 test_rt_39482_selectRow("a", sm, 0); 1404 test_rt_39482_selectRow("b", sm, 1); 1405 test_rt_39482_selectRow("c", sm, 2); 1406 test_rt_39482_selectRow("d", sm, 3); 1407 } 1408 1409 private void test_rt_39482_selectRow(String expectedString, 1410 MultipleSelectionModel<String> sm, 1411 int rowToSelect) { 1412 System.out.println("\nSelect row " + rowToSelect); 1413 sm.selectAll(); 1414 assertEquals(4, sm.getSelectedIndices().size()); 1415 assertEquals(4, sm.getSelectedItems().size()); 1416 assertEquals(4, rt_39482_list.size()); 1417 1418 sm.clearAndSelect(rowToSelect); 1419 assertEquals(1, sm.getSelectedIndices().size()); 1420 assertEquals(1, sm.getSelectedItems().size()); 1421 assertEquals(expectedString, sm.getSelectedItem()); 1422 assertEquals(expectedString, rt_39482_list.get(0)); 1423 assertEquals(1, rt_39482_list.size()); 1424 } 1425 1426 @Test public void test_rt_39559_useSM_selectAll() { 1427 test_rt_39559(true); 1428 } 1429 1430 @Test public void test_rt_39559_useKeyboard_selectAll() { 1431 test_rt_39559(false); 1432 } 1433 1434 private void test_rt_39559(boolean useSMSelectAll) { 1435 ListView<String> stringListView = new ListView<>(); 1436 stringListView.getItems().addAll("a", "b", "c", "d"); 1437 1438 MultipleSelectionModel<String> sm = stringListView.getSelectionModel(); 1439 sm.setSelectionMode(SelectionMode.MULTIPLE); 1440 1441 StageLoader sl = new StageLoader(stringListView); 1442 KeyEventFirer keyboard = new KeyEventFirer(stringListView); 1443 1444 assertEquals(0, sm.getSelectedItems().size()); 1445 1446 sm.clearAndSelect(0); 1447 1448 if (useSMSelectAll) { 1449 sm.selectAll(); 1450 } else { 1451 keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey()); 1452 } 1453 1454 assertEquals(4, sm.getSelectedItems().size()); 1455 assertEquals(0, (int) ListCellBehavior.getAnchor(stringListView, -1)); 1456 1457 keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); 1458 1459 assertEquals(0, (int) ListCellBehavior.getAnchor(stringListView, -1)); 1460 assertEquals(2, sm.getSelectedItems().size()); 1461 assertEquals("a", sm.getSelectedItems().get(0)); 1462 assertEquals("b", sm.getSelectedItems().get(1)); 1463 1464 sl.dispose(); 1465 } 1466 1467 @Test public void test_rt_16068_firstElement_selectAndRemoveSameRow() { 1468 // select and then remove the 'a' item, selection and focus should both 1469 // stay at the first row, now 'b' 1470 test_rt_16068(0, 0, 0); 1471 } 1472 1473 @Test public void test_rt_16068_firstElement_selectRowAndRemoveLaterSibling() { 1474 // select row 'a', and remove row 'c', selection and focus should not change 1475 test_rt_16068(0, 2, 0); 1476 } 1477 1478 @Test public void test_rt_16068_middleElement_selectAndRemoveSameRow() { 1479 // select and then remove the 'b' item, selection and focus should both 1480 // move up one row to the 'a' item 1481 test_rt_16068(1, 1, 0); 1482 } 1483 1484 @Test public void test_rt_16068_middleElement_selectRowAndRemoveLaterSibling() { 1485 // select row 'b', and remove row 'c', selection and focus should not change 1486 test_rt_16068(1, 2, 1); 1487 } 1488 1489 @Test public void test_rt_16068_middleElement_selectRowAndRemoveEarlierSibling() { 1490 // select row 'b', and remove row 'a', selection and focus should move up 1491 // one row, remaining on 'b' 1492 test_rt_16068(1, 0, 0); 1493 } 1494 1495 @Test public void test_rt_16068_lastElement_selectAndRemoveSameRow() { 1496 // select and then remove the 'd' item, selection and focus should both 1497 // move up one row to the 'c' item 1498 test_rt_16068(3, 3, 2); 1499 } 1500 1501 @Test public void test_rt_16068_lastElement_selectRowAndRemoveEarlierSibling() { 1502 // select row 'd', and remove row 'a', selection and focus should move up 1503 // one row, remaining on 'd' 1504 test_rt_16068(3, 0, 2); 1505 } 1506 1507 private void test_rt_16068(int indexToSelect, int indexToRemove, int expectedIndex) { 1508 ListView<String> stringListView = new ListView<>(); 1509 stringListView.getItems().addAll("a", "b", "c", "d"); 1510 1511 MultipleSelectionModel<?> sm = stringListView.getSelectionModel(); 1512 FocusModel<?> fm = stringListView.getFocusModel(); 1513 1514 sm.select(indexToSelect); 1515 assertEquals(indexToSelect, sm.getSelectedIndex()); 1516 assertEquals(stringListView.getItems().get(indexToSelect), sm.getSelectedItem()); 1517 assertEquals(indexToSelect, fm.getFocusedIndex()); 1518 assertEquals(stringListView.getItems().get(indexToSelect), fm.getFocusedItem()); 1519 1520 stringListView.getItems().remove(indexToRemove); 1521 assertEquals(expectedIndex, sm.getSelectedIndex()); 1522 assertEquals(stringListView.getItems().get(expectedIndex), sm.getSelectedItem()); 1523 assertEquals(expectedIndex, fm.getFocusedIndex()); 1524 assertEquals(stringListView.getItems().get(expectedIndex), fm.getFocusedItem()); 1525 } 1526 1527 @Test public void test_rt_22599() { 1528 ObservableList<RT22599_DataType> initialData = FXCollections.observableArrayList( 1529 new RT22599_DataType(1, "row1"), 1530 new RT22599_DataType(2, "row2"), 1531 new RT22599_DataType(3, "row3") 1532 ); 1533 1534 ListView<RT22599_DataType> listView = new ListView<>(); 1535 listView.setItems(initialData); 1536 1537 StageLoader sl = new StageLoader(listView); 1538 1539 // testing initial state 1540 assertNotNull(listView.getSkin()); 1541 assertEquals("row1", VirtualFlowTestUtils.getCell(listView, 0).getText()); 1542 assertEquals("row2", VirtualFlowTestUtils.getCell(listView, 1).getText()); 1543 assertEquals("row3", VirtualFlowTestUtils.getCell(listView, 2).getText()); 1544 1545 // change row 0 (where "row1" currently resides), keeping same id. 1546 // Because 'set' is called, the control should update to the new content 1547 // without any user interaction 1548 RT22599_DataType data; 1549 initialData.set(0, data = new RT22599_DataType(0, "row1a")); 1550 Toolkit.getToolkit().firePulse(); 1551 assertEquals("row1a", VirtualFlowTestUtils.getCell(listView, 0).getText()); 1552 1553 // change the row 0 (where we currently have "row1a") value directly. 1554 // Because there is no associated property, this won't be observed, so 1555 // the control should still show "row1a" rather than "row1b" 1556 data.text = "row1b"; 1557 Toolkit.getToolkit().firePulse(); 1558 assertEquals("row1a", VirtualFlowTestUtils.getCell(listView, 0).getText()); 1559 1560 // call refresh() to force a refresh of all visible cells 1561 listView.refresh(); 1562 Toolkit.getToolkit().firePulse(); 1563 assertEquals("row1b", VirtualFlowTestUtils.getCell(listView, 0).getText()); 1564 1565 sl.dispose(); 1566 } 1567 1568 private static class RT22599_DataType { 1569 public int id = 0; 1570 public String text = ""; 1571 1572 public RT22599_DataType(int id, String text) { 1573 this.id = id; 1574 this.text = text; 1575 } 1576 1577 @Override public String toString() { 1578 return text; 1579 } 1580 1581 @Override public boolean equals(Object obj) { 1582 if (obj == null) return false; 1583 return id == ((RT22599_DataType)obj).id; 1584 } 1585 } 1586 1587 private int rt_39966_count = 0; 1588 @Test public void test_rt_39966() { 1589 ObservableList<String> list = FXCollections.observableArrayList("Hello World"); 1590 ListView<String> listView = new ListView<>(list); 1591 1592 StageLoader sl = new StageLoader(listView); 1593 1594 // initially there is no selection 1595 assertTrue(listView.getSelectionModel().isEmpty()); 1596 1597 listView.getSelectionModel().selectedItemProperty().addListener((value, s1, s2) -> { 1598 if (rt_39966_count == 0) { 1599 rt_39966_count++; 1600 assertFalse(listView.getSelectionModel().isEmpty()); 1601 } else { 1602 assertTrue(listView.getSelectionModel().isEmpty()); 1603 } 1604 }); 1605 1606 // our assertion two lines down always succeeds. What fails is our 1607 // assertion above within the listener. 1608 listView.getSelectionModel().select(0); 1609 assertFalse(listView.getSelectionModel().isEmpty()); 1610 1611 list.remove(0); 1612 assertTrue(listView.getSelectionModel().isEmpty()); 1613 1614 sl.dispose(); 1615 } 1616 1617 /** 1618 * Bullet 1: selected index must be updated 1619 * Corner case: last selected. Fails for core 1620 */ 1621 @Test public void test_rt_40012_selectedAtLastOnDisjointRemoveItemsAbove() { 1622 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 1623 ListView<String> listView = new ListView<>(items); 1624 SelectionModel sm = listView.getSelectionModel(); 1625 1626 int last = items.size() - 1; 1627 1628 // selecting item "5" 1629 sm.select(last); 1630 1631 // disjoint remove of 2 elements above the last selected 1632 // Removing "1" and "3" 1633 items.removeAll(items.get(1), items.get(3)); 1634 1635 // selection should move up two places such that it remains on item "5", 1636 // but in index (last - 2). 1637 int expected = last - 2; 1638 assertEquals("5", sm.getSelectedItem()); 1639 assertEquals("selected index after disjoint removes above", expected, sm.getSelectedIndex()); 1640 } 1641 1642 /** 1643 * Variant of 1: if selectedIndex is not updated, 1644 * the old index is no longer valid 1645 * for accessing the items. 1646 */ 1647 @Test public void test_rt_40012_accessSelectedAtLastOnDisjointRemoveItemsAbove() { 1648 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 1649 ListView<String> listView = new ListView<>(items); 1650 SelectionModel sm = listView.getSelectionModel(); 1651 1652 int last = items.size() - 1; 1653 1654 // selecting item "5" 1655 sm.select(last); 1656 1657 // disjoint remove of 2 elements above the last selected 1658 items.removeAll(items.get(1), items.get(3)); 1659 int selected = sm.getSelectedIndex(); 1660 if (selected > -1) { 1661 items.get(selected); 1662 } 1663 } 1664 1665 /** 1666 * Bullet 2: selectedIndex notification count 1667 * 1668 * Note that we don't use the corner case of having the last index selected 1669 * (which fails already on updating the index) 1670 */ 1671 private int rt_40012_count = 0; 1672 @Test public void test_rt_40012_selectedIndexNotificationOnDisjointRemovesAbove() { 1673 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 1674 ListView<String> listView = new ListView<>(items); 1675 SelectionModel sm = listView.getSelectionModel(); 1676 1677 int last = items.size() - 2; 1678 sm.select(last); 1679 assertEquals(last, sm.getSelectedIndex()); 1680 1681 rt_40012_count = 0; 1682 sm.selectedIndexProperty().addListener(o -> rt_40012_count++); 1683 1684 // disjoint remove of 2 elements above the last selected 1685 items.removeAll(items.get(1), items.get(3)); 1686 assertEquals("sanity: selectedIndex must be shifted by -2", last - 2, sm.getSelectedIndex()); 1687 assertEquals("must fire single event on removes above", 1, rt_40012_count); 1688 } 1689 1690 /** 1691 * Bullet 3: unchanged selectedItem must not fire change 1692 */ 1693 @Test 1694 public void test_rt_40012_selectedItemNotificationOnDisjointRemovesAbove() { 1695 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 1696 ListView<String> listView = new ListView<>(items); 1697 SelectionModel sm = listView.getSelectionModel(); 1698 1699 int last = items.size() - 2; 1700 Object lastItem = items.get(last); 1701 sm.select(last); 1702 assertEquals(lastItem, sm.getSelectedItem()); 1703 1704 rt_40012_count = 0; 1705 sm.selectedItemProperty().addListener(o -> rt_40012_count++); 1706 1707 // disjoint remove of 2 elements above the last selected 1708 items.removeAll(items.get(1), items.get(3)); 1709 assertEquals("sanity: selectedItem unchanged", lastItem, sm.getSelectedItem()); 1710 assertEquals("must not fire on unchanged selected item", 0, rt_40012_count); 1711 } 1712 1713 @Test public void test_rt_40185() { 1714 final ListView<String> lv = new ListView<>(); 1715 final ArrayList<Integer> expected = new ArrayList<>(); 1716 Collections.addAll(expected, 1, 2); 1717 1718 lv.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 1719 lv.getSelectionModel().getSelectedIndices().addListener((ListChangeListener<Integer>) change -> { 1720 while (change.next()) { 1721 if (change.wasRemoved()) { 1722 assertEquals(expected, change.getRemoved()); 1723 } 1724 } 1725 }); 1726 1727 lv.getItems().addAll("-0-","-1-","-2-"); 1728 lv.getSelectionModel().selectIndices(1, 2); 1729 lv.getSelectionModel().clearSelection(); 1730 } 1731 1732 /** 1733 * ClearAndSelect fires invalid change event if selectedIndex is unchanged. 1734 */ 1735 private int rt_40212_count = 0; 1736 @Test public void test_rt_40212() { 1737 final ListView<Integer> lv = new ListView<>(); 1738 for (int i = 0; i < 10; i++) { 1739 lv.getItems().add(i); 1740 } 1741 1742 MultipleSelectionModel<Integer> sm = lv.getSelectionModel(); 1743 sm.setSelectionMode(SelectionMode.MULTIPLE); 1744 1745 sm.selectRange(3, 5); 1746 int selected = sm.getSelectedIndex(); 1747 1748 sm.getSelectedIndices().addListener((ListChangeListener<Integer>) change -> { 1749 assertEquals("sanity: selectedIndex unchanged", selected, sm.getSelectedIndex()); 1750 while(change.next()) { 1751 assertEquals("single event on clearAndSelect already selected", 1, ++rt_40212_count); 1752 1753 boolean type = change.wasAdded() || change.wasRemoved() || change.wasPermutated() || change.wasUpdated(); 1754 assertTrue("at least one of the change types must be true", type); 1755 } 1756 }); 1757 1758 sm.clearAndSelect(selected); 1759 } 1760 1761 @Test public void test_rt_40280() { 1762 final ListView<String> view = new ListView<>(); 1763 StageLoader sl = new StageLoader(view); 1764 view.getFocusModel().getFocusedIndex(); 1765 sl.dispose(); 1766 } 1767 1768 /** 1769 * Test list change of selectedIndices on setIndices. Fails for core .. 1770 */ 1771 @Test public void test_rt_40263() { 1772 final ListView<Integer> lv = new ListView<>(); 1773 for (int i = 0; i < 10; i++) { 1774 lv.getItems().add(i); 1775 } 1776 1777 MultipleSelectionModel<Integer> sm = lv.getSelectionModel(); 1778 sm.setSelectionMode(SelectionMode.MULTIPLE); 1779 1780 int[] indices = new int[]{2, 5, 7}; 1781 ListChangeListener<Integer> l = c -> { 1782 // firstly, we expect only one change 1783 int subChanges = 0; 1784 while(c.next()) { 1785 subChanges++; 1786 } 1787 assertEquals(1, subChanges); 1788 1789 // secondly, we expect the added size to be three, as that is the 1790 // number of items selected 1791 c.reset(); 1792 c.next(); 1793 System.out.println("Added items: " + c.getAddedSubList()); 1794 assertEquals(indices.length, c.getAddedSize()); 1795 assertArrayEquals(indices, c.getAddedSubList().stream().mapToInt(i -> i).toArray()); 1796 }; 1797 sm.getSelectedIndices().addListener(l); 1798 sm.selectIndices(indices[0], indices); 1799 } 1800 1801 @Test public void test_jdk8141124() { 1802 ListView<String> listView = new ListView<>(); 1803 ObservableList<String> items = FXCollections.observableArrayList(); 1804 SortedList<String> sortedItems = new SortedList<>(items); 1805 sortedItems.setComparator(String::compareTo); 1806 listView.setItems(sortedItems); 1807 1808 MultipleSelectionModel<String> sm = listView.getSelectionModel(); 1809 1810 items.add("2"); 1811 listView.getSelectionModel().selectFirst(); 1812 assertEquals("2", sm.getSelectedItem()); 1813 assertEquals(0, sm.getSelectedIndex()); 1814 assertEquals(0, (int) sm.getSelectedIndices().get(0)); 1815 assertEquals("2", sm.getSelectedItems().get(0)); 1816 1817 items.addAll("1", "3"); 1818 assertEquals("2", sm.getSelectedItem()); 1819 assertEquals(1, sm.getSelectedIndex()); 1820 assertEquals(1, (int) sm.getSelectedIndices().get(0)); 1821 assertEquals("2", sm.getSelectedItems().get(0)); 1822 } 1823 1824 @Test public void test_jdk_8143594() { 1825 MultipleSelectionModel model = listView.getSelectionModel(); 1826 model.setSelectionMode(SelectionMode.MULTIPLE); 1827 1828 listView.getItems().addAll("Apple", "Orange", null); 1829 1830 model.select(0); 1831 model.clearAndSelect(2); 1832 model.clearAndSelect(0); 1833 model.clearAndSelect(2); 1834 } 1835 1836 @Test public void test_jdk_8145887_selectedIndices_ListIterator() { 1837 int selectIndices[] = { 4, 7, 9 }; 1838 ListView<Integer> lv = new ListView<>(); 1839 for (int i = 0; i < 10; ++i) { 1840 lv.getItems().add(i); 1841 } 1842 1843 MultipleSelectionModel msm = lv.getSelectionModel(); 1844 msm.setSelectionMode(SelectionMode.MULTIPLE); 1845 for (int i = 0 ; i < selectIndices.length; ++i) { 1846 msm.select(selectIndices[i]); 1847 } 1848 1849 ListIterator iter = lv.getSelectionModel().getSelectedIndices().listIterator(); 1850 1851 // Step 1. Initial values 1852 assertEquals(0, iter.nextIndex()); 1853 assertEquals(-1, iter.previousIndex()); 1854 assertEquals(true, iter.hasNext()); 1855 assertEquals(false, iter.hasPrevious()); 1856 1857 // Step 2. Iterate forward. 1858 assertEquals(4, iter.next()); 1859 assertEquals(1, iter.nextIndex()); 1860 assertEquals(0, iter.previousIndex()); 1861 assertEquals(true, iter.hasNext()); 1862 assertEquals(true, iter.hasPrevious()); 1863 1864 // Step 3. Iterate forward. 1865 // Values would be at similar state of Step 2. 1866 assertEquals(7, iter.next()); 1867 1868 // Step 4. Iterate forward to Last element. 1869 assertEquals(9, iter.next()); 1870 assertEquals(3, iter.nextIndex()); 1871 assertEquals(2, iter.previousIndex()); 1872 assertEquals(false, iter.hasNext()); 1873 assertEquals(true, iter.hasPrevious()); 1874 1875 // Step 5. Verify NoSuchElementException by next() 1876 try { 1877 iter.next(); 1878 } catch (Exception e) { 1879 assert(e instanceof NoSuchElementException); 1880 } 1881 1882 // Step 6. Iterate backward to Last element. 1883 assertEquals(9, iter.previous()); 1884 assertEquals(2, iter.nextIndex()); 1885 assertEquals(1, iter.previousIndex()); 1886 assertEquals(true, iter.hasNext()); 1887 assertEquals(true, iter.hasPrevious()); 1888 1889 // Step 7. Iterate forward to Last element. 1890 assertEquals(9, iter.next()); 1891 assertEquals(3, iter.nextIndex()); 1892 assertEquals(2, iter.previousIndex()); 1893 assertEquals(false, iter.hasNext()); 1894 assertEquals(true, iter.hasPrevious()); 1895 1896 // Step 8. Iterate forward to last element. 1897 // Values would be at Same state of Step 2. 1898 assertEquals(9, iter.previous()); 1899 1900 // Step 9. Iterate backward. 1901 assertEquals(7, iter.previous()); 1902 assertEquals(1, iter.nextIndex()); 1903 assertEquals(0, iter.previousIndex()); 1904 assertEquals(true, iter.hasNext()); 1905 assertEquals(true, iter.hasPrevious()); 1906 1907 // Step 10. Iterate back to first element. 1908 assertEquals(4, iter.previous()); 1909 assertEquals(0, iter.nextIndex()); 1910 assertEquals(-1, iter.previousIndex()); 1911 assertEquals(true, iter.hasNext()); 1912 assertEquals(false, iter.hasPrevious()); 1913 1914 // Step 11. Verify NoSuchElementException by previous() 1915 try { 1916 iter.previous(); 1917 } catch (Exception e) { 1918 assert(e instanceof NoSuchElementException); 1919 } 1920 } 1921 }