1 /* 2 * Copyright (c) 2010, 2015, 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 javafx.scene.control; 27 28 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertStyleClassContains; 29 import static javafx.scene.control.TableColumn.SortType.ASCENDING; 30 import static javafx.scene.control.TableColumn.SortType.DESCENDING; 31 import static org.junit.Assert.*; 32 33 import java.util.*; 34 import java.util.concurrent.Callable; 35 import java.util.concurrent.atomic.AtomicLong; 36 import java.util.function.Supplier; 37 38 import com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList; 39 import com.sun.javafx.scene.control.SelectedCellsMap; 40 import com.sun.javafx.scene.control.behavior.ListCellBehavior; 41 import com.sun.javafx.scene.control.behavior.TableCellBehavior; 42 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; 43 import com.sun.javafx.scene.control.infrastructure.KeyModifier; 44 import com.sun.javafx.scene.control.infrastructure.MouseEventFirer; 45 import com.sun.javafx.scene.control.infrastructure.StageLoader; 46 import com.sun.javafx.scene.control.skin.*; 47 import javafx.application.Platform; 48 import javafx.beans.InvalidationListener; 49 import javafx.beans.binding.Bindings; 50 import javafx.beans.binding.ObjectBinding; 51 import javafx.beans.property.*; 52 import javafx.beans.value.ChangeListener; 53 import javafx.beans.value.ObservableValue; 54 import javafx.collections.FXCollections; 55 import javafx.collections.ListChangeListener; 56 import javafx.collections.MockSetObserver; 57 import javafx.collections.ObservableList; 58 import javafx.collections.transformation.SortedList; 59 import javafx.event.Event; 60 import javafx.event.EventHandler; 61 import javafx.geometry.Orientation; 62 import javafx.scene.Group; 63 import javafx.scene.Scene; 64 import javafx.scene.control.cell.*; 65 import javafx.scene.image.ImageView; 66 import javafx.scene.input.KeyCode; 67 import javafx.scene.input.KeyEvent; 68 import javafx.scene.layout.StackPane; 69 import javafx.scene.layout.VBox; 70 import javafx.scene.paint.Color; 71 import javafx.scene.shape.Rectangle; 72 import javafx.util.Callback; 73 74 import com.sun.javafx.tk.Toolkit; 75 import org.junit.Before; 76 import org.junit.Ignore; 77 import org.junit.Test; 78 79 import com.sun.javafx.scene.control.TableColumnComparatorBase.TableColumnComparator; 80 import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils; 81 import com.sun.javafx.scene.control.test.Person; 82 import com.sun.javafx.scene.control.test.RT_22463_Person; 83 84 import static com.sun.javafx.scene.control.skin.TableColumnHeaderRetriever.*; 85 import static org.junit.Assert.assertEquals; 86 87 public class TableViewTest { 88 private TableView<String> table; 89 private TableView.TableViewSelectionModel sm; 90 private TableView.TableViewFocusModel<String> fm; 91 92 private ObservableList<Person> personTestData; 93 94 @Before public void setup() { 95 table = new TableView<>(); 96 sm = table.getSelectionModel(); 97 fm = table.getFocusModel(); 98 99 personTestData = FXCollections.observableArrayList( 100 new Person("Jacob", "Smith", "jacob.smith@example.com"), 101 new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 102 new Person("Ethan", "Williams", "ethan.williams@example.com"), 103 new Person("Emma", "Jones", "emma.jones@example.com"), 104 new Person("Michael", "Brown", "michael.brown@example.com")); 105 } 106 107 108 /********************************************************************* 109 * Tests for the constructors * 110 ********************************************************************/ 111 112 @Test public void noArgConstructorSetsTheStyleClass() { 113 assertStyleClassContains(table, "table-view"); 114 } 115 116 @Test public void noArgConstructorSetsNonNullSelectionModel() { 117 assertNotNull(sm); 118 } 119 120 @Test public void noArgConstructorSetsNonNullItems() { 121 assertNotNull(table.getItems()); 122 } 123 124 @Test public void noArgConstructorSetsNonNullSortPolicy() { 125 assertNotNull(table.getSortPolicy()); 126 } 127 128 @Test public void noArgConstructorSetsNullComparator() { 129 assertNull(table.getComparator()); 130 } 131 132 @Test public void noArgConstructorSetsNullOnSort() { 133 assertNull(table.getOnSort()); 134 } 135 136 @Test public void noArgConstructor_selectedItemIsNull() { 137 assertNull(sm.getSelectedItem()); 138 } 139 140 @Test public void noArgConstructor_selectedIndexIsNegativeOne() { 141 assertEquals(-1, sm.getSelectedIndex()); 142 } 143 144 @Test public void singleArgConstructorSetsTheStyleClass() { 145 final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi")); 146 assertStyleClassContains(b2, "table-view"); 147 } 148 149 @Test public void singleArgConstructorSetsNonNullSelectionModel() { 150 final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi")); 151 assertNotNull(b2.getSelectionModel()); 152 } 153 154 @Test public void singleArgConstructorAllowsNullItems() { 155 final TableView<String> b2 = new TableView<>(null); 156 assertNull(b2.getItems()); 157 } 158 159 @Test public void singleArgConstructorTakesItems() { 160 ObservableList<String> items = FXCollections.observableArrayList("Hi"); 161 final TableView<String> b2 = new TableView<>(items); 162 assertSame(items, b2.getItems()); 163 } 164 165 @Test public void singleArgConstructor_selectedItemIsNull() { 166 final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi")); 167 assertNull(b2.getSelectionModel().getSelectedItem()); 168 } 169 170 @Test public void singleArgConstructor_selectedIndexIsNegativeOne() { 171 final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi")); 172 assertEquals(-1, b2.getSelectionModel().getSelectedIndex()); 173 } 174 175 /********************************************************************* 176 * Tests for selection model * 177 ********************************************************************/ 178 179 @Test public void selectionModelCanBeNull() { 180 table.setSelectionModel(null); 181 assertNull(table.getSelectionModel()); 182 } 183 184 @Test public void selectionModelCanBeBound() { 185 TableView.TableViewSelectionModel<String> sm = new TableView.TableViewArrayListSelectionModel<String>(table); 186 ObjectProperty<TableView.TableViewSelectionModel<String>> other = new SimpleObjectProperty<TableView.TableViewSelectionModel<String>>(sm); 187 table.selectionModelProperty().bind(other); 188 assertSame(sm, sm); 189 } 190 191 @Test public void selectionModelCanBeChanged() { 192 TableView.TableViewSelectionModel<String> sm = new TableView.TableViewArrayListSelectionModel<String>(table); 193 table.setSelectionModel(sm); 194 assertSame(sm, sm); 195 } 196 197 @Test public void canSetSelectedItemToAnItemEvenWhenThereAreNoItems() { 198 final String randomString = new String("I AM A CRAZY RANDOM STRING"); 199 sm.select(randomString); 200 assertEquals(-1, sm.getSelectedIndex()); 201 assertSame(randomString, sm.getSelectedItem()); 202 } 203 204 @Test public void canSetSelectedItemToAnItemNotInTheDataModel() { 205 table.getItems().addAll("Apple", "Orange", "Banana"); 206 final String randomString = new String("I AM A CRAZY RANDOM STRING"); 207 sm.select(randomString); 208 assertSame(randomString, sm.getSelectedItem()); 209 assertEquals(-1, sm.getSelectedIndex()); 210 } 211 212 @Test public void settingTheSelectedItemToAnItemInItemsResultsInTheCorrectSelectedIndex() { 213 table.getItems().addAll("Apple", "Orange", "Banana"); 214 sm.select("Orange"); 215 assertEquals(1, sm.getSelectedIndex()); 216 assertSame("Orange", sm.getSelectedItem()); 217 } 218 219 @Test public void settingTheSelectedItemToANonexistantItemAndThenSettingItemsWhichContainsItResultsInCorrectSelectedIndex() { 220 sm.select("Orange"); 221 table.getItems().addAll("Apple", "Orange", "Banana"); 222 assertEquals(1, sm.getSelectedIndex()); 223 assertSame("Orange", sm.getSelectedItem()); 224 } 225 226 @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex0() { 227 table.getItems().addAll("Apple", "Orange", "Banana"); 228 sm.select(0); 229 table.getItems().clear(); 230 assertEquals(-1, sm.getSelectedIndex()); 231 } 232 233 @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex2() { 234 table.getItems().addAll("Apple", "Orange", "Banana"); 235 sm.select(2); 236 table.getItems().clear(); 237 assertEquals(-1, sm.getSelectedIndex()); 238 } 239 240 @Test public void ensureSelectedItemRemainsAccurateWhenItemsAreCleared() { 241 table.getItems().addAll("Apple", "Orange", "Banana"); 242 sm.select(2); 243 table.getItems().clear(); 244 assertNull("Selected Item: " + sm.getSelectedItem(), sm.getSelectedItem()); 245 assertEquals(-1, sm.getSelectedIndex()); 246 247 table.getItems().addAll("Kiwifruit", "Mandarin", "Pineapple"); 248 sm.select(2); 249 assertEquals("Pineapple", sm.getSelectedItem()); 250 } 251 252 @Ignore("Not fixed yet") 253 @Test public void ensureSelectionShiftsDownWhenOneNewItemIsAdded() { 254 table.getItems().addAll("Apple", "Orange", "Banana"); 255 sm.select(1); 256 assertEquals(1, sm.getSelectedIndex()); 257 assertEquals("Orange", sm.getSelectedItem()); 258 259 table.getItems().add(0, "Kiwifruit"); 260 assertEquals(2, sm.getSelectedIndex()); 261 assertEquals("Orange", sm.getSelectedItem()); 262 } 263 264 @Ignore("Not fixed yet") 265 @Test public void ensureSelectionShiftsDownWhenMultipleNewItemAreAdded() { 266 table.getItems().addAll("Apple", "Orange", "Banana"); 267 sm.select(1); 268 assertEquals(1, sm.getSelectedIndex()); 269 assertEquals("Orange", sm.getSelectedItem()); 270 271 table.getItems().addAll(0, Arrays.asList("Kiwifruit", "Pineapple", "Mandarin")); 272 assertEquals("Orange", sm.getSelectedItem()); 273 assertEquals(4, sm.getSelectedIndex()); 274 } 275 276 @Ignore("Not fixed yet") 277 @Test public void ensureSelectionShiftsDownWhenOneItemIsRemoved() { 278 table.getItems().addAll("Apple", "Orange", "Banana"); 279 sm.select(1); 280 assertEquals(1, sm.getSelectedIndex()); 281 assertEquals("Orange", sm.getSelectedItem()); 282 283 table.getItems().remove("Apple"); 284 assertEquals(0, sm.getSelectedIndex()); 285 assertEquals("Orange", sm.getSelectedItem()); 286 } 287 288 @Ignore("Not fixed yet") 289 @Test public void ensureSelectionShiftsDownWheMultipleItemsAreRemoved() { 290 table.getItems().addAll("Apple", "Orange", "Banana"); 291 sm.select(2); 292 assertEquals(2, sm.getSelectedIndex()); 293 assertEquals("Banana", sm.getSelectedItem()); 294 295 table.getItems().removeAll(Arrays.asList("Apple", "Orange")); 296 assertEquals(0, sm.getSelectedIndex()); 297 assertEquals("Banana", sm.getSelectedItem()); 298 } 299 300 @Test public void ensureSelectionIsCorrectWhenItemsChange() { 301 table.setItems(FXCollections.observableArrayList("Item 1")); 302 sm.select(0); 303 assertEquals("Item 1", sm.getSelectedItem()); 304 305 table.setItems(FXCollections.observableArrayList("Item 2")); 306 assertEquals(-1, sm.getSelectedIndex()); 307 assertNull(sm.getSelectedItem()); 308 assertEquals(0, fm.getFocusedIndex()); 309 assertEquals("Item 2", fm.getFocusedItem()); 310 } 311 312 /********************************************************************* 313 * Tests for columns * 314 ********************************************************************/ 315 316 @Test public void testColumns() { 317 TableColumn col1 = new TableColumn(); 318 319 assertNotNull(table.getColumns()); 320 assertEquals(0, table.getColumns().size()); 321 322 table.getColumns().add(col1); 323 assertEquals(1, table.getColumns().size()); 324 325 table.getColumns().remove(col1); 326 assertEquals(0, table.getColumns().size()); 327 } 328 329 @Test public void testVisibleLeafColumns() { 330 TableColumn col1 = new TableColumn(); 331 332 assertNotNull(table.getColumns()); 333 assertEquals(0, table.getColumns().size()); 334 335 table.getColumns().add(col1); 336 assertEquals(1, table.getVisibleLeafColumns().size()); 337 338 table.getColumns().remove(col1); 339 assertEquals(0, table.getVisibleLeafColumns().size()); 340 } 341 342 @Test public void testSortOrderCleanup() { 343 // ObservableList<ObservablePerson> persons = ObservablePerson.createFXPersonList(); 344 TableView table = new TableView(); 345 TableColumn<String,String> first = new TableColumn<String,String>("first"); 346 first.setCellValueFactory(new PropertyValueFactory("firstName")); 347 TableColumn<String,String> second = new TableColumn<String,String>("second"); 348 second.setCellValueFactory(new PropertyValueFactory("lastName")); 349 table.getColumns().addAll(first, second); 350 table.getSortOrder().setAll(first, second); 351 table.getColumns().remove(first); 352 assertFalse(table.getSortOrder().contains(first)); 353 } 354 355 356 /********************************************************************* 357 * Tests for new sorting API in JavaFX 8.0 * 358 ********************************************************************/ 359 360 // TODO test for sort policies returning null 361 // TODO test for changing column sortType out of order 362 // TODO test comparator returns to original when sort fails / is consumed 363 364 private static final Callback<TableView<String>, Boolean> NO_SORT_FAILED_SORT_POLICY = 365 tableView -> false; 366 367 private static final Callback<TableView<String>, Boolean> SORT_SUCCESS_ASCENDING_SORT_POLICY = 368 tableView -> { 369 if (tableView.getSortOrder().isEmpty()) return true; 370 FXCollections.sort(tableView.getItems(), new Comparator<String>() { 371 @Override public int compare(String o1, String o2) { 372 return o1.compareTo(o2); 373 } 374 }); 375 return true; 376 }; 377 378 private TableColumn<String, String> initSortTestStructure() { 379 TableColumn<String, String> col = new TableColumn<String, String>("column"); 380 col.setSortType(ASCENDING); 381 col.setCellValueFactory(param -> new ReadOnlyObjectWrapper<String>(param.getValue())); 382 table.getColumns().add(col); 383 table.getItems().addAll("Apple", "Orange", "Banana"); 384 return col; 385 } 386 387 @Ignore("This test is only valid if sort event consumption should revert changes") 388 @Test public void testSortEventCanBeConsumedToStopSortOccurring_changeSortOrderList() { 389 TableColumn<String, String> col = initSortTestStructure(); 390 table.setOnSort(event -> { 391 event.consume(); 392 }); 393 394 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 395 table.getSortOrder().add(col); 396 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 397 398 // the sort order list should be returned back to its original state 399 assertTrue(table.getSortOrder().isEmpty()); 400 } 401 402 @Test public void testSortEventCanBeNotConsumedToAllowSortToOccur_changeSortOrderList() { 403 TableColumn<String, String> col = initSortTestStructure(); 404 table.setOnSort(event -> { 405 // do not consume here - this allows the sort to happen 406 }); 407 408 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 409 table.getSortOrder().add(col); 410 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 411 412 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 413 } 414 415 @Ignore("This test is only valid if sort event consumption should revert changes") 416 @Test public void testSortEventCanBeConsumedToStopSortOccurring_changeColumnSortType_AscendingToDescending() { 417 TableColumn<String, String> col = initSortTestStructure(); 418 assertEquals(ASCENDING, col.getSortType()); 419 table.getSortOrder().add(col); 420 table.setOnSort(event -> { 421 event.consume(); 422 }); 423 424 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 425 426 // when we change from ASCENDING to DESCENDING we don't expect the sort 427 // to actually change (and in fact we expect the sort type to resort 428 // back to being ASCENDING) 429 col.setSortType(DESCENDING); 430 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 431 assertEquals(ASCENDING, col.getSortType()); 432 433 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 434 } 435 436 @Test public void testSortEventCanBeNotConsumedToAllowSortToOccur_changeColumnSortType_AscendingToDescending() { 437 TableColumn<String, String> col = initSortTestStructure(); 438 assertEquals(ASCENDING, col.getSortType()); 439 table.getSortOrder().add(col); 440 table.setOnSort(event -> { 441 // do not consume here - this allows the sort to happen 442 }); 443 444 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 445 446 col.setSortType(DESCENDING); 447 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 448 assertEquals(DESCENDING, col.getSortType()); 449 450 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 451 } 452 453 @Ignore("This test is only valid if sort event consumption should revert changes") 454 @Test public void testSortEventCanBeConsumedToStopSortOccurring_changeColumnSortType_DescendingToNull() { 455 TableColumn<String, String> col = initSortTestStructure(); 456 col.setSortType(DESCENDING); 457 assertEquals(DESCENDING, col.getSortType()); 458 table.getSortOrder().add(col); 459 table.setOnSort(event -> { 460 event.consume(); 461 }); 462 463 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 464 465 col.setSortType(null); 466 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 467 assertEquals(DESCENDING, col.getSortType()); 468 469 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 470 } 471 472 @Test public void testSortEventCanBeNotConsumedToAllowSortToOccur_changeColumnSortType_DescendingToNull() { 473 TableColumn<String, String> col = initSortTestStructure(); 474 col.setSortType(DESCENDING); 475 assertEquals(DESCENDING, col.getSortType()); 476 table.getSortOrder().add(col); 477 table.setOnSort(event -> { 478 // do not consume here - this allows the sort to happen 479 }); 480 481 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 482 483 col.setSortType(null); 484 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 485 assertNull(col.getSortType()); 486 487 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 488 } 489 490 @Ignore("This test is only valid if sort event consumption should revert changes") 491 @Test public void testSortEventCanBeConsumedToStopSortOccurring_changeColumnSortType_NullToAscending() { 492 TableColumn<String, String> col = initSortTestStructure(); 493 col.setSortType(null); 494 assertNull(col.getSortType()); 495 table.getSortOrder().add(col); 496 table.setOnSort(event -> { 497 event.consume(); 498 }); 499 500 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 501 502 col.setSortType(ASCENDING); 503 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 504 assertNull(col.getSortType()); 505 506 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 507 } 508 509 @Test public void testSortEventCanBeNotConsumedToAllowSortToOccur_changeColumnSortType_NullToAscending() { 510 TableColumn<String, String> col = initSortTestStructure(); 511 col.setSortType(null); 512 assertNull(col.getSortType()); 513 table.getSortOrder().add(col); 514 table.setOnSort(event -> { 515 // do not consume here - this allows the sort to happen 516 }); 517 518 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 519 520 col.setSortType(ASCENDING); 521 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 522 assertEquals(ASCENDING, col.getSortType()); 523 524 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 525 } 526 527 @Test public void testSortMethodWithNullSortPolicy() { 528 TableColumn<String, String> col = initSortTestStructure(); 529 table.setSortPolicy(null); 530 assertNull(table.getSortPolicy()); 531 table.sort(); 532 } 533 534 @Test public void testChangingSortPolicyUpdatesItemsList() { 535 TableColumn<String, String> col = initSortTestStructure(); 536 col.setSortType(DESCENDING); 537 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 538 table.getSortOrder().add(col); 539 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 540 table.setSortPolicy(SORT_SUCCESS_ASCENDING_SORT_POLICY); 541 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 542 } 543 544 @Test public void testChangingSortPolicyDoesNotUpdateItemsListWhenTheSortOrderListIsEmpty() { 545 TableColumn<String, String> col = initSortTestStructure(); 546 col.setSortType(DESCENDING); 547 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 548 549 table.setSortPolicy(SORT_SUCCESS_ASCENDING_SORT_POLICY); 550 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 551 } 552 553 @Test public void testFailedSortPolicyBacksOutLastChange_sortOrderAddition() { 554 TableColumn<String, String> col = initSortTestStructure(); 555 col.setSortType(DESCENDING); 556 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 557 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 558 559 table.getSortOrder().add(col); 560 561 // no sort should be run (as we have a custom sort policy), and the 562 // sortOrder list should be empty as the sortPolicy failed 563 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 564 assertTrue(table.getSortOrder().isEmpty()); 565 } 566 567 @Test public void testFailedSortPolicyBacksOutLastChange_sortOrderRemoval() { 568 TableColumn<String, String> col = initSortTestStructure(); 569 col.setSortType(DESCENDING); 570 table.getSortOrder().add(col); 571 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 572 573 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 574 575 // even though we remove the column from the sort order here, because the 576 // sort policy fails the items list should remain unchanged and the sort 577 // order list should continue to have the column in it. 578 table.getSortOrder().remove(col); 579 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 580 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getSortOrder(), col); 581 } 582 583 @Test public void testFailedSortPolicyBacksOutLastChange_sortTypeChange_ascendingToDescending() { 584 TableColumn<String, String> col = initSortTestStructure(); 585 col.setSortType(ASCENDING); 586 table.getSortOrder().add(col); 587 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 588 589 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 590 591 col.setSortType(DESCENDING); 592 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Banana", "Orange"); 593 assertEquals(ASCENDING, col.getSortType()); 594 } 595 596 @Test public void testFailedSortPolicyBacksOutLastChange_sortTypeChange_descendingToNull() { 597 TableColumn<String, String> col = initSortTestStructure(); 598 col.setSortType(DESCENDING); 599 table.getSortOrder().add(col); 600 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 601 602 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 603 604 col.setSortType(null); 605 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 606 assertEquals(DESCENDING, col.getSortType()); 607 } 608 609 @Test public void testFailedSortPolicyBacksOutLastChange_sortTypeChange_nullToAscending() { 610 TableColumn<String, String> col = initSortTestStructure(); 611 col.setSortType(null); 612 table.getSortOrder().add(col); 613 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 614 615 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 616 617 col.setSortType(ASCENDING); 618 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 619 assertNull(col.getSortType()); 620 } 621 622 @Test public void testComparatorChangesInSyncWithSortOrder_1() { 623 TableColumn<String, String> col = initSortTestStructure(); 624 assertNull(table.getComparator()); 625 assertTrue(table.getSortOrder().isEmpty()); 626 627 table.getSortOrder().add(col); 628 TableColumnComparator c = (TableColumnComparator)table.getComparator(); 629 assertNotNull(c); 630 VirtualFlowTestUtils.assertListContainsItemsInOrder(c.getColumns(), col); 631 } 632 633 @Ignore 634 @Test public void testComparatorChangesInSyncWithSortOrder_2() { 635 // same as test above 636 TableColumn<String, String> col = initSortTestStructure(); 637 assertNull(table.getComparator()); 638 assertTrue(table.getSortOrder().isEmpty()); 639 640 table.getSortOrder().add(col); 641 TableColumnComparator c = (TableColumnComparator)table.getComparator(); 642 assertNotNull(c); 643 VirtualFlowTestUtils.assertListContainsItemsInOrder(c.getColumns(), col); 644 645 // now remove column from sort order, and the comparator should go to 646 // being null 647 table.getSortOrder().remove(col); 648 assertNull(table.getComparator()); 649 } 650 651 @Test public void testFailedSortPolicyBacksOutComparatorChange_sortOrderAddition() { 652 TableColumn<String, String> col = initSortTestStructure(); 653 final TableColumnComparator oldComparator = (TableColumnComparator)table.getComparator(); 654 655 col.setSortType(DESCENDING); 656 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Apple", "Orange", "Banana"); 657 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 658 659 table.getSortOrder().add(col); 660 661 assertEquals(oldComparator, table.getComparator()); 662 } 663 664 @Test public void testFailedSortPolicyBacksOutComparatorChange_sortOrderRemoval() { 665 TableColumn<String, String> col = initSortTestStructure(); 666 TableColumnComparator oldComparator = (TableColumnComparator)table.getComparator(); 667 assertNull(oldComparator); 668 669 col.setSortType(DESCENDING); 670 table.getSortOrder().add(col); 671 VirtualFlowTestUtils.assertListContainsItemsInOrder(table.getItems(), "Orange", "Banana", "Apple"); 672 oldComparator = (TableColumnComparator)table.getComparator(); 673 VirtualFlowTestUtils.assertListContainsItemsInOrder(oldComparator.getColumns(), col); 674 675 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 676 table.getSortOrder().remove(col); 677 678 assertTrue(table.getSortOrder().contains(col)); 679 VirtualFlowTestUtils.assertListContainsItemsInOrder(oldComparator.getColumns(), col); 680 } 681 682 @Test public void testFailedSortPolicyBacksOutComparatorChange_sortTypeChange() { 683 TableColumn<String, String> col = initSortTestStructure(); 684 final TableColumnComparator oldComparator = (TableColumnComparator)table.getComparator(); 685 assertNull(oldComparator); 686 687 table.setSortPolicy(NO_SORT_FAILED_SORT_POLICY); 688 table.getSortOrder().add(col); 689 col.setSortType(ASCENDING); 690 691 assertTrue(table.getSortOrder().isEmpty()); 692 assertNull(oldComparator); 693 } 694 695 @Test public void testComparatorIsNullWhenSortOrderListIsEmpty() { 696 TableColumn<String, String> col = initSortTestStructure(); 697 698 assertNull(table.getComparator()); 699 700 table.getSortOrder().add(col); 701 assertFalse(table.getSortOrder().isEmpty()); 702 assertNotNull(table.getComparator()); 703 704 table.getSortOrder().clear(); 705 assertTrue(table.getSortOrder().isEmpty()); 706 assertNull(table.getComparator()); 707 } 708 709 710 711 /********************************************************************* 712 * Tests for specific bugs * 713 ********************************************************************/ 714 @Test public void test_rt16019() { 715 // RT-16019: NodeMemory TableView tests fail with 716 // IndexOutOfBoundsException (ObservableListWrapper.java:336) 717 TableView table = new TableView(); 718 for (int i = 0; i < 1000; i++) { 719 table.getItems().add("data " + i); 720 } 721 } 722 723 @Test public void test_rt15793() { 724 // ListView/TableView selectedIndex is 0 although the items list is empty 725 final TableView tv = new TableView(); 726 final ObservableList list = FXCollections.observableArrayList(); 727 tv.setItems(list); 728 list.add("toto"); 729 tv.getSelectionModel().select(0); 730 assertEquals(0, tv.getSelectionModel().getSelectedIndex()); 731 list.remove(0); 732 assertEquals(-1, tv.getSelectionModel().getSelectedIndex()); 733 } 734 735 @Ignore("Started failing recently, but manual tests seem to indicate the functionality is intact") 736 @Test public void test_rt17522_focusShouldMoveWhenItemAddedAtFocusIndex() { 737 final TableView lv = new TableView(); 738 StageLoader sl = new StageLoader(lv); 739 FocusModel fm = lv.getFocusModel(); 740 lv.getItems().add("row1"); 741 assertTrue(fm.isFocused(0)); 742 743 lv.getItems().add(0, "row0"); 744 assertTrue("Focus is on " + fm.getFocusedIndex(), fm.isFocused(1)); 745 assertFalse(fm.isFocused(0)); 746 747 sl.dispose(); 748 } 749 750 @Test public void test_rt17522_focusShouldMoveWhenItemAddedBeforeFocusIndex() { 751 final TableView lv = new TableView(); 752 FocusModel fm = lv.getFocusModel(); 753 lv.getItems().addAll("row1", "row2"); 754 fm.focus(1); 755 assertTrue(fm.isFocused(1)); 756 assertEquals("row2", fm.getFocusedItem()); 757 758 lv.getItems().add(1, "row0"); 759 assertTrue(fm.isFocused(2)); 760 assertEquals("row2", fm.getFocusedItem()); 761 assertFalse(fm.isFocused(1)); 762 } 763 764 @Test public void test_rt17522_focusShouldNotMoveWhenItemAddedAfterFocusIndex() { 765 final TableView lv = new TableView(); 766 FocusModel fm = lv.getFocusModel(); 767 lv.getItems().addAll("row1"); 768 fm.focus(0); 769 assertTrue(fm.isFocused(0)); 770 assertEquals("row1", fm.getFocusedItem()); 771 772 lv.getItems().add(1, "row2"); 773 assertTrue(fm.isFocused(0)); 774 assertEquals("row1", fm.getFocusedItem()); 775 assertFalse(fm.isFocused(1)); 776 } 777 778 @Test public void test_rt17522_focusShouldBeResetWhenFocusedItemIsRemoved() { 779 final TableView lv = new TableView(); 780 FocusModel fm = lv.getFocusModel(); 781 lv.getItems().add("row1"); 782 assertTrue(fm.isFocused(0)); 783 784 lv.getItems().remove("row1"); 785 assertTrue(fm.getFocusedIndex() == -1); 786 assertNull(fm.getFocusedItem()); 787 } 788 789 @Test public void test_rt17522_focusShouldMoveWhenItemRemovedBeforeFocusIndex() { 790 final TableView lv = new TableView(); 791 FocusModel fm = lv.getFocusModel(); 792 lv.getItems().addAll("row1", "row2"); 793 assertTrue(fm.isFocused(0)); 794 795 fm.focus(1); 796 assertTrue(fm.isFocused(1)); 797 assertEquals("row2", fm.getFocusedItem()); 798 799 lv.getItems().remove("row1"); 800 assertTrue(fm.isFocused(0)); 801 assertEquals("row2", fm.getFocusedItem()); 802 } 803 804 @Test public void test_rt17522_focusShouldNotMoveWhenItemRemovedAfterFocusIndex() { 805 final TableView lv = new TableView(); 806 FocusModel fm = lv.getFocusModel(); 807 lv.getItems().addAll("row1", "row2"); 808 fm.focus(0); 809 assertTrue(fm.isFocused(0)); 810 assertEquals("row1", fm.getFocusedItem()); 811 812 lv.getItems().remove("row2"); 813 assertTrue(fm.isFocused(0)); 814 assertEquals("row1", fm.getFocusedItem()); 815 } 816 817 @Test public void test_rt18385() { 818 table.getItems().addAll("row1", "row2", "row3"); 819 sm.select(1); 820 table.getItems().add("Another Row"); 821 assertEquals(1, sm.getSelectedIndices().size()); 822 assertEquals(1, sm.getSelectedItems().size()); 823 assertEquals(1, sm.getSelectedCells().size()); 824 } 825 826 @Test public void test_rt18339_onlyEditWhenTableViewIsEditable_tableEditableIsFalse_columnEditableIsFalse() { 827 TableColumn<String,String> first = new TableColumn<String,String>("first"); 828 first.setEditable(false); 829 table.getColumns().add(first); 830 table.setEditable(false); 831 table.edit(1, first); 832 assertEquals(null, table.getEditingCell()); 833 } 834 835 @Test public void test_rt18339_onlyEditWhenTableViewIsEditable_tableEditableIsFalse_columnEditableIsTrue() { 836 TableColumn<String,String> first = new TableColumn<String,String>("first"); 837 first.setEditable(true); 838 table.getColumns().add(first); 839 table.setEditable(false); 840 table.edit(1, first); 841 assertEquals(null, table.getEditingCell()); 842 } 843 844 @Test public void test_rt18339_onlyEditWhenTableViewIsEditable_tableEditableIsTrue_columnEditableIsFalse() { 845 TableColumn<String,String> first = new TableColumn<String,String>("first"); 846 first.setEditable(false); 847 table.getColumns().add(first); 848 table.setEditable(true); 849 table.edit(1, first); 850 assertEquals(null, table.getEditingCell()); 851 } 852 853 @Test public void test_rt18339_onlyEditWhenTableViewIsEditable_tableEditableIsTrue_columnEditableIsTrue() { 854 TableColumn<String,String> first = new TableColumn<String,String>("first"); 855 first.setEditable(true); 856 table.getColumns().add(first); 857 table.setEditable(true); 858 table.edit(1, first); 859 assertEquals(new TablePosition(table, 1, first), table.getEditingCell()); 860 } 861 862 @Test public void test_rt14451() { 863 table.getItems().addAll("Apple", "Orange", "Banana"); 864 sm.setSelectionMode(SelectionMode.MULTIPLE); 865 sm.selectRange(0, 2); // select from 0 (inclusive) to 2 (exclusive) 866 assertEquals(2, sm.getSelectedIndices().size()); 867 } 868 869 @Test public void test_rt21586() { 870 table.getItems().setAll("Apple", "Orange", "Banana"); 871 table.getSelectionModel().select(1); 872 assertEquals(1, table.getSelectionModel().getSelectedIndex()); 873 assertEquals("Orange", table.getSelectionModel().getSelectedItem()); 874 875 table.getItems().setAll("Kiwifruit", "Pineapple", "Grape"); 876 assertEquals(-1, table.getSelectionModel().getSelectedIndex()); 877 assertNull(table.getSelectionModel().getSelectedItem()); 878 assertEquals(0, table.getFocusModel().getFocusedIndex()); 879 assertEquals("Kiwifruit", table.getFocusModel().getFocusedItem()); 880 } 881 882 @Test public void test_rt27820_1() { 883 table.getItems().setAll("Apple", "Orange"); 884 table.getSelectionModel().select(0); 885 assertEquals(1, table.getSelectionModel().getSelectedItems().size()); 886 assertEquals("Apple", table.getSelectionModel().getSelectedItem()); 887 888 table.getItems().clear(); 889 assertEquals(0, table.getSelectionModel().getSelectedItems().size()); 890 assertNull(table.getSelectionModel().getSelectedItem()); 891 } 892 893 @Test public void test_rt27820_2() { 894 table.getItems().setAll("Apple", "Orange"); 895 table.getSelectionModel().select(1); 896 assertEquals(1, table.getSelectionModel().getSelectedItems().size()); 897 assertEquals("Orange", table.getSelectionModel().getSelectedItem()); 898 899 table.getItems().clear(); 900 assertEquals(0, table.getSelectionModel().getSelectedItems().size()); 901 assertNull(table.getSelectionModel().getSelectedItem()); 902 } 903 904 @Test public void test_rt28534() { 905 TableView<Person> table = new TableView<Person>(); 906 table.setItems(personTestData); 907 908 TableColumn firstNameCol = new TableColumn("First Name"); 909 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 910 911 TableColumn lastNameCol = new TableColumn("Last Name"); 912 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 913 914 TableColumn emailCol = new TableColumn("Email"); 915 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 916 917 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 918 919 VirtualFlowTestUtils.assertRowsNotEmpty(table, 0, 5); // rows 0 - 5 should be filled 920 VirtualFlowTestUtils.assertRowsEmpty(table, 5, -1); // rows 5+ should be empty 921 922 // now we replace the data and expect the cells that have no data 923 // to be empty 924 table.setItems(FXCollections.observableArrayList( 925 new Person("*_*Emma", "Jones", "emma.jones@example.com"), 926 new Person("_Michael", "Brown", "michael.brown@example.com"))); 927 928 VirtualFlowTestUtils.assertRowsNotEmpty(table, 0, 2); // rows 0 - 2 should be filled 929 VirtualFlowTestUtils.assertRowsEmpty(table, 2, -1); // rows 2+ should be empty 930 } 931 932 @Test public void test_rt22463() { 933 final TableView<RT_22463_Person> table = new TableView<RT_22463_Person>(); 934 table.setTableMenuButtonVisible(true); 935 TableColumn c1 = new TableColumn("Id"); 936 TableColumn c2 = new TableColumn("Name"); 937 c1.setCellValueFactory(new PropertyValueFactory<Person, Long>("id")); 938 c2.setCellValueFactory(new PropertyValueFactory<Person, String>("name")); 939 table.getColumns().addAll(c1, c2); 940 941 // before the change things display fine 942 RT_22463_Person p1 = new RT_22463_Person(); 943 p1.setId(1l); 944 p1.setName("name1"); 945 RT_22463_Person p2 = new RT_22463_Person(); 946 p2.setId(2l); 947 p2.setName("name2"); 948 table.setItems(FXCollections.observableArrayList(p1, p2)); 949 VirtualFlowTestUtils.assertCellTextEquals(table, 0, "1", "name1"); 950 VirtualFlowTestUtils.assertCellTextEquals(table, 1, "2", "name2"); 951 952 // now we change the persons but they are still equal as the ID's don't 953 // change - but the items list is cleared so the cells should update 954 RT_22463_Person new_p1 = new RT_22463_Person(); 955 new_p1.setId(1l); 956 new_p1.setName("updated name1"); 957 RT_22463_Person new_p2 = new RT_22463_Person(); 958 new_p2.setId(2l); 959 new_p2.setName("updated name2"); 960 table.getItems().clear(); 961 table.setItems(FXCollections.observableArrayList(new_p1, new_p2)); 962 VirtualFlowTestUtils.assertCellTextEquals(table, 0, "1", "updated name1"); 963 VirtualFlowTestUtils.assertCellTextEquals(table, 1, "2", "updated name2"); 964 } 965 966 @Test public void test_rt28637() { 967 ObservableList<String> items = FXCollections.observableArrayList("String1", "String2", "String3", "String4"); 968 969 final TableView<String> tableView = new TableView<String>(); 970 final MultipleSelectionModel sm = tableView.getSelectionModel(); 971 tableView.setItems(items); 972 973 tableView.getSelectionModel().select(0); 974 assertEquals("String1", sm.getSelectedItem()); 975 assertEquals(1, sm.getSelectedItems().size()); 976 assertEquals("String1", sm.getSelectedItems().get(0)); 977 assertEquals(0, sm.getSelectedIndex()); 978 979 items.remove(sm.getSelectedItem()); 980 assertEquals("String2", sm.getSelectedItem()); 981 assertEquals(1, sm.getSelectedItems().size()); 982 assertEquals("String2", sm.getSelectedItems().get(0)); 983 assertEquals(0, sm.getSelectedIndex()); 984 } 985 986 @Test public void test_rt24844() { 987 // p1 == lowest first name 988 Person p0, p1, p2, p3, p4; 989 990 TableView<Person> table = new TableView<Person>(); 991 table.setItems(FXCollections.observableArrayList( 992 p3 = new Person("Jacob", "Smith", "jacob.smith@example.com"), 993 p2 = new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 994 p1 = new Person("Ethan", "Williams", "ethan.williams@example.com"), 995 p0 = new Person("Emma", "Jones", "emma.jones@example.com"), 996 p4 = new Person("Michael", "Brown", "michael.brown@example.com"))); 997 998 TableColumn firstNameCol = new TableColumn("First Name"); 999 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1000 1001 // set dummy comparator to lock items in place until new comparator is set 1002 firstNameCol.setComparator((t, t1) -> 0); 1003 1004 table.getColumns().addAll(firstNameCol); 1005 table.getSortOrder().add(firstNameCol); 1006 1007 // ensure the existing order is as expected 1008 assertEquals(p3, table.getItems().get(0)); 1009 assertEquals(p2, table.getItems().get(1)); 1010 assertEquals(p1, table.getItems().get(2)); 1011 assertEquals(p0, table.getItems().get(3)); 1012 assertEquals(p4, table.getItems().get(4)); 1013 1014 // set a new comparator 1015 firstNameCol.setComparator(new Comparator() { 1016 Random r = new Random(); 1017 @Override public int compare(Object t, Object t1) { 1018 return t.toString().compareTo(t1.toString()); 1019 } 1020 }); 1021 1022 // ensure the new order is as expected 1023 assertEquals(p0, table.getItems().get(0)); 1024 assertEquals(p1, table.getItems().get(1)); 1025 assertEquals(p2, table.getItems().get(2)); 1026 assertEquals(p3, table.getItems().get(3)); 1027 assertEquals(p4, table.getItems().get(4)); 1028 } 1029 1030 @Test public void test_rt29331() { 1031 TableView<Person> table = new TableView<Person>(); 1032 1033 TableColumn firstNameCol = new TableColumn("First Name"); 1034 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1035 1036 TableColumn lastNameCol = new TableColumn("Last Name"); 1037 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 1038 1039 TableColumn emailCol = new TableColumn("Email"); 1040 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 1041 1042 TableColumn parentColumn = new TableColumn<>("Parent"); 1043 parentColumn.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 1044 1045 table.getColumns().addAll(parentColumn); 1046 1047 // table is setup, now hide the 'last name' column 1048 emailCol.setVisible(false); 1049 assertFalse(emailCol.isVisible()); 1050 1051 // reorder columns inside the parent column 1052 parentColumn.getColumns().setAll(emailCol, firstNameCol, lastNameCol); 1053 1054 // the email column should not become visible after this, but it does 1055 assertFalse(emailCol.isVisible()); 1056 } 1057 1058 private int rt29330_count = 0; 1059 @Test public void test_rt29330_1() { 1060 TableView<Person> table = new TableView<>(personTestData); 1061 1062 TableColumn parentColumn = new TableColumn<>("Parent"); 1063 table.getColumns().addAll(parentColumn); 1064 1065 TableColumn firstNameCol = new TableColumn("First Name"); 1066 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1067 1068 TableColumn lastNameCol = new TableColumn("Last Name"); 1069 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 1070 1071 parentColumn.getColumns().addAll(firstNameCol, lastNameCol); 1072 1073 table.setOnSort(event -> { 1074 rt29330_count++; 1075 }); 1076 1077 // test preconditions 1078 assertEquals(ASCENDING, lastNameCol.getSortType()); 1079 assertEquals(0, rt29330_count); 1080 1081 table.getSortOrder().add(lastNameCol); 1082 assertEquals(1, rt29330_count); 1083 1084 lastNameCol.setSortType(DESCENDING); 1085 assertEquals(2, rt29330_count); 1086 1087 lastNameCol.setSortType(null); 1088 assertEquals(3, rt29330_count); 1089 1090 lastNameCol.setSortType(ASCENDING); 1091 assertEquals(4, rt29330_count); 1092 } 1093 1094 @Test public void test_rt29330_2() { 1095 TableView<Person> table = new TableView<>(personTestData); 1096 1097 TableColumn firstNameCol = new TableColumn("First Name"); 1098 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1099 1100 TableColumn lastNameCol = new TableColumn("Last Name"); 1101 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 1102 1103 // this test differs from the previous one by installing the parent column 1104 // into the tableview after it has the children added into it 1105 TableColumn parentColumn = new TableColumn<>("Parent"); 1106 parentColumn.getColumns().addAll(firstNameCol, lastNameCol); 1107 table.getColumns().addAll(parentColumn); 1108 1109 table.setOnSort(event -> { 1110 rt29330_count++; 1111 }); 1112 1113 // test preconditions 1114 assertEquals(ASCENDING, lastNameCol.getSortType()); 1115 assertEquals(0, rt29330_count); 1116 1117 table.getSortOrder().add(lastNameCol); 1118 assertEquals(1, rt29330_count); 1119 1120 lastNameCol.setSortType(DESCENDING); 1121 assertEquals(2, rt29330_count); 1122 1123 lastNameCol.setSortType(null); 1124 assertEquals(3, rt29330_count); 1125 1126 lastNameCol.setSortType(ASCENDING); 1127 assertEquals(4, rt29330_count); 1128 } 1129 1130 @Test public void test_rt29313_selectedIndices() { 1131 TableView<Person> table = new TableView<>(personTestData); 1132 1133 TableSelectionModel sm = table.getSelectionModel(); 1134 1135 TableColumn firstNameCol = new TableColumn("First Name"); 1136 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1137 1138 TableColumn lastNameCol = new TableColumn("Last Name"); 1139 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 1140 1141 TableColumn emailCol = new TableColumn("Email"); 1142 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 1143 1144 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 1145 sm.setCellSelectionEnabled(true); 1146 sm.setSelectionMode(SelectionMode.MULTIPLE); 1147 1148 assertEquals(0, sm.getSelectedIndices().size()); 1149 1150 // only (0,0) should be selected, so selected indices should be [0] 1151 sm.select(0, firstNameCol); 1152 assertEquals(1, sm.getSelectedIndices().size()); 1153 1154 // now (0,0) and (1,0) should be selected, so selected indices should be [0, 1] 1155 sm.select(1, firstNameCol); 1156 assertEquals(2, sm.getSelectedIndices().size()); 1157 1158 // now (0,0), (1,0) and (1,1) should be selected, but selected indices 1159 // should remain as [0, 1], as we don't want selected indices to become 1160 // [0,1,1] (which is what RT-29313 is about) 1161 sm.select(1, lastNameCol); 1162 assertEquals(2, sm.getSelectedIndices().size()); 1163 assertEquals(0, sm.getSelectedIndices().get(0)); 1164 assertEquals(1, sm.getSelectedIndices().get(1)); 1165 } 1166 1167 @Test public void test_rt29313_selectedItems() { 1168 Person p0, p1; 1169 TableView<Person> table = new TableView<>(); 1170 table.setItems(FXCollections.observableArrayList( 1171 p0 = new Person("Jacob", "Smith", "jacob.smith@example.com"), 1172 p1 = new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 1173 new Person("Ethan", "Williams", "ethan.williams@example.com"), 1174 new Person("Emma", "Jones", "emma.jones@example.com"), 1175 new Person("Michael", "Brown", "michael.brown@example.com"))); 1176 1177 TableSelectionModel sm = table.getSelectionModel(); 1178 1179 TableColumn firstNameCol = new TableColumn("First Name"); 1180 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1181 1182 TableColumn lastNameCol = new TableColumn("Last Name"); 1183 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 1184 1185 TableColumn emailCol = new TableColumn("Email"); 1186 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 1187 1188 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 1189 sm.setCellSelectionEnabled(true); 1190 sm.setSelectionMode(SelectionMode.MULTIPLE); 1191 1192 assertEquals(0, sm.getSelectedIndices().size()); 1193 1194 // only (0,0) should be selected, so selected items should be [p0] 1195 sm.select(0, firstNameCol); 1196 assertEquals(1, sm.getSelectedItems().size()); 1197 1198 // now (0,0) and (1,0) should be selected, so selected items should be [p0, p1] 1199 sm.select(1, firstNameCol); 1200 assertEquals(2, sm.getSelectedItems().size()); 1201 1202 // now (0,0), (1,0) and (1,1) should be selected, but selected items 1203 // should remain as [p0, p1], as we don't want selected items to become 1204 // [p0,p1,p1] (which is what RT-29313 is about) 1205 sm.select(1, lastNameCol); 1206 assertEquals(2, sm.getSelectedItems().size()); 1207 assertEquals(p0, sm.getSelectedItems().get(0)); 1208 assertEquals(p1, sm.getSelectedItems().get(1)); 1209 } 1210 1211 @Test public void test_rt29566() { 1212 TableView<Person> table = new TableView<>(personTestData); 1213 1214 TableSelectionModel sm = table.getSelectionModel(); 1215 1216 TableColumn firstNameCol = new TableColumn("First Name"); 1217 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1218 1219 TableColumn lastNameCol = new TableColumn("Last Name"); 1220 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 1221 1222 TableColumn emailCol = new TableColumn("Email"); 1223 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 1224 1225 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 1226 1227 // test the state before we hide and re-add a column 1228 VirtualFlowTestUtils.assertCellTextEquals(table, 0, "Jacob", "Smith", "jacob.smith@example.com"); 1229 VirtualFlowTestUtils.assertCellTextEquals(table, 1, "Isabella", "Johnson", "isabella.johnson@example.com"); 1230 VirtualFlowTestUtils.assertCellTextEquals(table, 2, "Ethan", "Williams", "ethan.williams@example.com"); 1231 VirtualFlowTestUtils.assertCellTextEquals(table, 3, "Emma", "Jones", "emma.jones@example.com"); 1232 VirtualFlowTestUtils.assertCellTextEquals(table, 4, "Michael", "Brown", "michael.brown@example.com"); 1233 1234 // hide the last name column, and test cells again 1235 table.getColumns().remove(lastNameCol); 1236 VirtualFlowTestUtils.assertCellTextEquals(table, 0, "Jacob", "jacob.smith@example.com"); 1237 VirtualFlowTestUtils.assertCellTextEquals(table, 1, "Isabella", "isabella.johnson@example.com"); 1238 VirtualFlowTestUtils.assertCellTextEquals(table, 2, "Ethan", "ethan.williams@example.com"); 1239 VirtualFlowTestUtils.assertCellTextEquals(table, 3, "Emma", "emma.jones@example.com"); 1240 VirtualFlowTestUtils.assertCellTextEquals(table, 4, "Michael", "michael.brown@example.com"); 1241 1242 // re-add the last name column - we should go back to the original state. 1243 // However, what appears to be happening is that, for some reason, some 1244 // of the cells from the removed column do not reappear - meaning in this case 1245 // some of the last name values will not be where we expect them to be. 1246 // This is clearly not ideal! 1247 table.getColumns().add(1, lastNameCol); 1248 VirtualFlowTestUtils.assertCellTextEquals(table, 0, "Jacob", "Smith", "jacob.smith@example.com"); 1249 VirtualFlowTestUtils.assertCellTextEquals(table, 1, "Isabella", "Johnson", "isabella.johnson@example.com"); 1250 VirtualFlowTestUtils.assertCellTextEquals(table, 2, "Ethan", "Williams", "ethan.williams@example.com"); 1251 VirtualFlowTestUtils.assertCellTextEquals(table, 3, "Emma", "Jones", "emma.jones@example.com"); 1252 VirtualFlowTestUtils.assertCellTextEquals(table, 4, "Michael", "Brown", "michael.brown@example.com"); 1253 } 1254 1255 @Test public void test_rt29390() { 1256 final TableView<Person> tableView = new TableView<Person>(); 1257 tableView.setMaxHeight(50); 1258 tableView.setPrefHeight(50); 1259 tableView.setItems(FXCollections.observableArrayList( 1260 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1261 new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 1262 new Person("Ethan", "Williams", "ethan.williams@example.com"), 1263 new Person("Emma", "Jones", "emma.jones@example.com"), 1264 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1265 new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 1266 new Person("Ethan", "Williams", "ethan.williams@example.com"), 1267 new Person("Emma", "Jones", "emma.jones@example.com"), 1268 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1269 new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 1270 new Person("Ethan", "Williams", "ethan.williams@example.com"), 1271 new Person("Emma", "Jones", "emma.jones@example.com"), 1272 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1273 new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 1274 new Person("Ethan", "Williams", "ethan.williams@example.com"), 1275 new Person("Emma", "Jones", "emma.jones@example.com") 1276 )); 1277 1278 TableColumn firstNameCol = new TableColumn("First Name"); 1279 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1280 1281 tableView.getColumns().add(firstNameCol); 1282 1283 // we want the vertical scrollbar 1284 VirtualScrollBar scrollBar = VirtualFlowTestUtils.getVirtualFlowVerticalScrollbar(tableView); 1285 1286 assertNotNull(scrollBar); 1287 assertTrue(scrollBar.isVisible()); 1288 assertTrue(scrollBar.getVisibleAmount() > 0.0); 1289 assertTrue(scrollBar.getVisibleAmount() < 1.0); 1290 1291 // this next test is likely to be brittle, but we'll see...If it is the 1292 // cause of failure then it can be commented out 1293 assertEquals(0.0625, scrollBar.getVisibleAmount(), 0.0); 1294 } 1295 1296 @Test public void test_rt30400() { 1297 // create a listview that'll render cells using the check box cell factory 1298 final TableView<Person> tableView = new TableView<Person>(); 1299 tableView.setMinHeight(100); 1300 tableView.setPrefHeight(100); 1301 tableView.setItems(FXCollections.observableArrayList( 1302 new Person("Jacob", "Smith", "jacob.smith@example.com") 1303 )); 1304 1305 TableColumn firstNameCol = new TableColumn("First Name"); 1306 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1307 firstNameCol.setCellFactory(CheckBoxTableCell.forTableColumn(param -> new ReadOnlyBooleanWrapper(true))); 1308 tableView.getColumns().add(firstNameCol); 1309 1310 // because only the first row has data, all other rows should be 1311 // empty (and not contain check boxes - we just check the first four here) 1312 VirtualFlowTestUtils.assertRowsNotEmpty(tableView, 0, 1); 1313 VirtualFlowTestUtils.assertCellNotEmpty(VirtualFlowTestUtils.getCell(tableView, 0)); 1314 VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 1)); 1315 VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 2)); 1316 VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 3)); 1317 } 1318 1319 @Test public void test_rt31165() { 1320 final ObservableList names = FXCollections.observableArrayList("Adam", "Alex", "Alfred", "Albert"); 1321 1322 final TableView<Person> tableView = new TableView<Person>(); 1323 tableView.setEditable(true); 1324 tableView.setItems(FXCollections.observableArrayList( 1325 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1326 new Person("Jim", "Bob", "jim.bob@example.com") 1327 )); 1328 1329 TableColumn firstNameCol = new TableColumn("First Name"); 1330 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1331 firstNameCol.setCellFactory(ChoiceBoxTableCell.forTableColumn(names)); 1332 firstNameCol.setEditable(true); 1333 1334 tableView.getColumns().add(firstNameCol); 1335 1336 IndexedCell cell = VirtualFlowTestUtils.getCell(tableView, 1, 0); 1337 assertEquals("Jim", cell.getText()); 1338 assertFalse(cell.isEditing()); 1339 1340 tableView.edit(1, firstNameCol); 1341 1342 TablePosition editingCell = tableView.getEditingCell(); 1343 assertEquals(1, editingCell.getRow()); 1344 assertEquals(firstNameCol, editingCell.getTableColumn()); 1345 assertTrue(cell.isEditing()); 1346 1347 VirtualFlowTestUtils.getVirtualFlow(tableView).requestLayout(); 1348 Toolkit.getToolkit().firePulse(); 1349 1350 editingCell = tableView.getEditingCell(); 1351 assertEquals(1, editingCell.getRow()); 1352 assertEquals(firstNameCol, editingCell.getTableColumn()); 1353 assertTrue(cell.isEditing()); 1354 } 1355 1356 @Test public void test_rt31471() { 1357 Person jacobSmith; 1358 final TableView<Person> tableView = new TableView<Person>(); 1359 tableView.setItems(FXCollections.observableArrayList( 1360 jacobSmith = new Person("Jacob", "Smith", "jacob.smith@example.com"), 1361 new Person("Jim", "Bob", "jim.bob@example.com") 1362 )); 1363 1364 TableColumn firstNameCol = new TableColumn("First Name"); 1365 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1366 tableView.getColumns().add(firstNameCol); 1367 1368 IndexedCell cell = VirtualFlowTestUtils.getCell(tableView, 0); 1369 assertEquals(jacobSmith, cell.getItem()); 1370 1371 tableView.setFixedCellSize(50); 1372 1373 VirtualFlowTestUtils.getVirtualFlow(tableView).requestLayout(); 1374 Toolkit.getToolkit().firePulse(); 1375 1376 assertEquals(jacobSmith, cell.getItem()); 1377 assertEquals(50, cell.getHeight(), 0.00); 1378 } 1379 1380 private int rt_31200_count = 0; 1381 @Test public void test_rt_31200_tableCell() { 1382 rt_31200_count = 0; 1383 final TableView<Person> tableView = new TableView<Person>(); 1384 tableView.setItems(FXCollections.observableArrayList( 1385 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1386 new Person("Jim", "Bob", "jim.bob@example.com") 1387 )); 1388 1389 TableColumn<Person,String> firstNameCol = new TableColumn("First Name"); 1390 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1391 tableView.getColumns().add(firstNameCol); 1392 1393 firstNameCol.setCellFactory(new Callback<TableColumn<Person,String>, TableCell<Person, String>>() { 1394 @Override 1395 public TableCell<Person, String> call(TableColumn<Person,String> param) { 1396 return new TableCell<Person, String>() { 1397 ImageView view = new ImageView(); 1398 { setGraphic(view); }; 1399 1400 @Override 1401 protected void updateItem(String item, boolean empty) { 1402 if (getItem() == null ? item == null : getItem().equals(item)) { 1403 rt_31200_count++; 1404 } 1405 super.updateItem(item, empty); 1406 if (item == null || empty) { 1407 view.setImage(null); 1408 setText(null); 1409 } else { 1410 setText(item); 1411 } 1412 } 1413 }; 1414 } 1415 }); 1416 1417 StageLoader sl = new StageLoader(tableView); 1418 1419 assertEquals(14, rt_31200_count); 1420 1421 // resize the stage 1422 sl.getStage().setHeight(250); 1423 Toolkit.getToolkit().firePulse(); 1424 sl.getStage().setHeight(50); 1425 Toolkit.getToolkit().firePulse(); 1426 assertEquals(14, rt_31200_count); 1427 1428 sl.dispose(); 1429 } 1430 1431 @Test public void test_rt_31200_tableRow() { 1432 rt_31200_count = 0; 1433 final TableView<Person> tableView = new TableView<Person>(); 1434 tableView.setItems(FXCollections.observableArrayList( 1435 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1436 new Person("Jim", "Bob", "jim.bob@example.com") 1437 )); 1438 1439 TableColumn<Person,String> firstNameCol = new TableColumn("First Name"); 1440 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 1441 tableView.getColumns().add(firstNameCol); 1442 1443 tableView.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() { 1444 @Override 1445 public TableRow<Person> call(TableView<Person> param) { 1446 return new TableRow<Person>() { 1447 ImageView view = new ImageView(); 1448 { setGraphic(view); }; 1449 1450 @Override 1451 protected void updateItem(Person item, boolean empty) { 1452 if (getItem() == null ? item == null : getItem().equals(item)) { 1453 rt_31200_count++; 1454 } 1455 super.updateItem(item, empty); 1456 if (item == null || empty) { 1457 view.setImage(null); 1458 setText(null); 1459 } else { 1460 setText(item.toString()); 1461 } 1462 } 1463 }; 1464 } 1465 }); 1466 1467 StageLoader sl = new StageLoader(tableView); 1468 1469 assertEquals(14, rt_31200_count); 1470 1471 // resize the stage 1472 sl.getStage().setHeight(250); 1473 Toolkit.getToolkit().firePulse(); 1474 sl.getStage().setHeight(50); 1475 Toolkit.getToolkit().firePulse(); 1476 assertEquals(14, rt_31200_count); 1477 1478 sl.dispose(); 1479 } 1480 1481 @Test public void test_rt_31727() { 1482 TableView table = new TableView(); 1483 TableColumn<String,String> first = new TableColumn<String,String>("first"); 1484 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1485 TableColumn<String,String> second = new TableColumn<String,String>("second"); 1486 second.setCellValueFactory(new PropertyValueFactory("lastName")); 1487 table.getColumns().addAll(first, second); 1488 1489 table.setItems(FXCollections.observableArrayList( 1490 new Person("Jacob", "Smith", "jacob.smith@example.com"), 1491 new Person("Jim", "Bob", "jim.bob@example.com") 1492 )); 1493 1494 table.setEditable(true); 1495 first.setEditable(true); 1496 1497 // do a normal edit 1498 table.edit(0, first); 1499 TablePosition editingCell = table.getEditingCell(); 1500 assertNotNull(editingCell); 1501 assertEquals(0, editingCell.getRow()); 1502 assertEquals(0, editingCell.getColumn()); 1503 assertEquals(first, editingCell.getTableColumn()); 1504 assertEquals(table, editingCell.getTableView()); 1505 1506 // cancel editing 1507 table.edit(-1, null); 1508 editingCell = table.getEditingCell(); 1509 assertNull(editingCell); 1510 } 1511 1512 @Test public void test_rt_21517() { 1513 TableView table = new TableView(); 1514 TableColumn<String,String> first = new TableColumn<String,String>("first"); 1515 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1516 TableColumn<String,String> second = new TableColumn<String,String>("second"); 1517 second.setCellValueFactory(new PropertyValueFactory("lastName")); 1518 table.getColumns().addAll(first, second); 1519 1520 Person aaa,bbb,ccc; 1521 table.setItems(FXCollections.observableArrayList( 1522 aaa = new Person("AAA", "Smith", "jacob.smith@example.com"), 1523 bbb = new Person("BBB", "Bob", "jim.bob@example.com"), 1524 ccc = new Person("CCC", "Giles", "jim.bob@example.com") 1525 )); 1526 1527 final TableView.TableViewSelectionModel sm = table.getSelectionModel(); 1528 1529 // test pre-conditions 1530 assertEquals(0, sm.getSelectedCells().size()); 1531 assertEquals(0, sm.getSelectedItems().size()); 1532 assertEquals(0, sm.getSelectedIndices().size()); 1533 1534 // select the 3rd row (that is, CCC) 1535 sm.select(2); 1536 assertTrue(sm.isSelected(2)); 1537 assertEquals(2, sm.getSelectedIndex()); 1538 assertEquals(1, sm.getSelectedIndices().size()); 1539 assertTrue(sm.getSelectedIndices().contains(2)); 1540 assertEquals(ccc, sm.getSelectedItem()); 1541 assertEquals(1, sm.getSelectedItems().size()); 1542 assertTrue(sm.getSelectedItems().contains(ccc)); 1543 1544 // we also want to test visually 1545 TableRow aaaRow = (TableRow) VirtualFlowTestUtils.getCell(table, 0); 1546 assertFalse(aaaRow.isSelected()); 1547 TableRow cccRow = (TableRow) VirtualFlowTestUtils.getCell(table, 2); 1548 assertTrue(cccRow.isSelected()); 1549 1550 // sort tableview by firstname column in ascending (default) order 1551 // (so aaa continues to come first) 1552 table.getSortOrder().add(first); 1553 1554 // nothing should have changed 1555 assertTrue(sm.isSelected(2)); 1556 assertEquals(2, sm.getSelectedIndex()); 1557 assertEquals(1, sm.getSelectedIndices().size()); 1558 assertTrue(sm.getSelectedIndices().contains(2)); 1559 assertEquals(ccc, sm.getSelectedItem()); 1560 assertEquals(1, sm.getSelectedItems().size()); 1561 assertTrue(sm.getSelectedItems().contains(ccc)); 1562 aaaRow = (TableRow) VirtualFlowTestUtils.getCell(table, 0); 1563 assertFalse(aaaRow.isSelected()); 1564 cccRow = (TableRow) VirtualFlowTestUtils.getCell(table, 2); 1565 assertTrue(cccRow.isSelected()); 1566 1567 // continue to sort tableview by firstname column, but now in descending 1568 // order, (so ccc to come first) 1569 first.setSortType(TableColumn.SortType.DESCENDING); 1570 1571 // now test to ensure that CCC is still the only selected item, but now 1572 // located in index 0 1573 assertTrue(sm.isSelected(0)); 1574 assertEquals(0, sm.getSelectedIndex()); 1575 assertEquals(1, sm.getSelectedIndices().size()); 1576 assertTrue(sm.getSelectedIndices().contains(0)); 1577 assertEquals(ccc, sm.getSelectedItem()); 1578 assertEquals(1, sm.getSelectedItems().size()); 1579 assertTrue(sm.getSelectedItems().contains(ccc)); 1580 1581 // we also want to test visually 1582 aaaRow = (TableRow) VirtualFlowTestUtils.getCell(table, 1); 1583 assertFalse(aaaRow.isSelected()); 1584 cccRow = (TableRow) VirtualFlowTestUtils.getCell(table, 0); 1585 assertTrue(cccRow.isSelected()); 1586 } 1587 1588 @Test public void test_rt_30484_tableCell() { 1589 TableView<Person> table = new TableView<>(); 1590 TableColumn<Person,String> first = new TableColumn<>("first"); 1591 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1592 table.getColumns().addAll(first); 1593 1594 table.setItems(FXCollections.observableArrayList( 1595 new Person("AAA", "Smith", "jacob.smith@example.com"), 1596 new Person("BBB", "Bob", "jim.bob@example.com") 1597 )); 1598 1599 first.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() { 1600 @Override 1601 public TableCell<Person, String> call(TableColumn<Person, String> param) { 1602 return new TableCell<Person, String>() { 1603 Rectangle graphic = new Rectangle(10, 10, Color.RED); 1604 { setGraphic(graphic); }; 1605 1606 @Override protected void updateItem(String item, boolean empty) { 1607 super.updateItem(item, empty); 1608 if (item == null || empty) { 1609 graphic.setVisible(false); 1610 setText(null); 1611 } else { 1612 graphic.setVisible(true); 1613 setText(item); 1614 } 1615 } 1616 }; 1617 } 1618 }); 1619 1620 // First two rows have content, so the graphic should show. 1621 // All other rows have no content, so graphic should not show. 1622 1623 VirtualFlowTestUtils.assertGraphicIsVisible(table, 0, 0); 1624 VirtualFlowTestUtils.assertGraphicIsVisible(table, 1, 0); 1625 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 2, 0); 1626 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 3, 0); 1627 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 4, 0); 1628 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 5, 0); 1629 } 1630 1631 @Test public void test_rt_30484_tableRow() { 1632 TableView<Person> table = new TableView<>(); 1633 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1634 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1635 table.getColumns().addAll(first); 1636 1637 table.setItems(FXCollections.observableArrayList( 1638 new Person("AAA", "Smith", "jacob.smith@example.com"), 1639 new Person("BBB", "Bob", "jim.bob@example.com") 1640 )); 1641 1642 table.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() { 1643 @Override public TableRow<Person> call(TableView<Person> param) { 1644 return new TableRow<Person>() { 1645 Rectangle graphic = new Rectangle(10, 10, Color.RED); 1646 { setGraphic(graphic); }; 1647 1648 @Override protected void updateItem(Person item, boolean empty) { 1649 super.updateItem(item, empty); 1650 if (item == null || empty) { 1651 graphic.setVisible(false); 1652 setText(null); 1653 } else { 1654 graphic.setVisible(true); 1655 setText(item.toString()); 1656 } 1657 } 1658 }; 1659 } 1660 }); 1661 1662 // First two rows have content, so the graphic should show. 1663 // All other rows have no content, so graphic should not show. 1664 1665 VirtualFlowTestUtils.assertGraphicIsVisible(table, 0); 1666 VirtualFlowTestUtils.assertGraphicIsVisible(table, 1); 1667 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 2); 1668 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 3); 1669 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 4); 1670 VirtualFlowTestUtils.assertGraphicIsNotVisible(table, 5); 1671 } 1672 1673 @Test public void test_rt_32201() { 1674 final int numRows = 150; 1675 final int numColumns = 30; 1676 1677 // create data 1678 final ObservableList<List<Object>> bigData = FXCollections.observableArrayList(); 1679 for (int row = bigData.size(); row < numRows; row++) { 1680 List<Object> line = new ArrayList<>(); 1681 for (int col = 0; col <= numColumns; col++) { 1682 double value = (col == 0) ? (double)row : Math.random() * 1000; 1683 line.add(value); 1684 } 1685 bigData.add(line); 1686 } 1687 1688 TableView<List<Object>> table = new TableView<>(bigData); 1689 1690 // create columns 1691 for (int i = 0; i <= numColumns; i++) { 1692 TableColumn<List<Object>,Object> col = new TableColumn<>("Col" + i); 1693 final int coli = i; 1694 col.setCellValueFactory(p -> new ReadOnlyObjectWrapper(p.getValue().get(coli))); 1695 1696 table.getColumns().add(col); 1697 } 1698 1699 // start test 1700 assertNull(table.getComparator()); 1701 assertTrue(table.getSortOrder().isEmpty()); 1702 1703 table.getSortOrder().add(table.getColumns().get(0)); 1704 assertNotNull(table.getComparator()); 1705 assertTrue(table.getSortOrder().contains(table.getColumns().get(0))); 1706 assertEquals(1, table.getSortOrder().size()); 1707 1708 // remove column again 1709 try { 1710 table.getSortOrder().clear(); 1711 } catch (ClassCastException e) { 1712 fail("Comparator should be null as the sort order list is empty."); 1713 } 1714 assertNull(table.getComparator()); 1715 assertTrue(table.getSortOrder().isEmpty()); 1716 } 1717 1718 private int rt_31015_count = 0; 1719 @Test public void test_rt_31015() { 1720 TableView<Person> table = new TableView<>(); 1721 table.setEditable(true); 1722 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1723 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1724 table.getColumns().addAll(first); 1725 1726 table.setItems(FXCollections.observableArrayList( 1727 new Person("John", "Smith", "jacob.smith@example.com") 1728 )); 1729 1730 //Set cell factory for cells that allow editing 1731 Callback<TableColumn<Person,String>, TableCell<Person, String>> cellFactory = new Callback<TableColumn<Person,String>, TableCell<Person, String>>() { 1732 public TableCell<Person, String> call(TableColumn<Person, String> p) { 1733 return new TableCell<Person, String>() { 1734 @Override public void cancelEdit() { 1735 super.cancelEdit(); 1736 rt_31015_count++; 1737 } 1738 }; 1739 } 1740 }; 1741 first.setCellFactory(cellFactory); 1742 1743 StageLoader sl = new StageLoader(table); 1744 1745 assertEquals(0, rt_31015_count); 1746 1747 table.edit(0, first); 1748 assertEquals(0, rt_31015_count); 1749 1750 table.edit(-1, null); 1751 assertEquals(1, rt_31015_count); 1752 1753 sl.dispose(); 1754 } 1755 1756 @Test public void test_rt_31653() { 1757 TableView<Person> table = new TableView<>(); 1758 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1759 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1760 table.getColumns().addAll(first); 1761 1762 table.setItems(FXCollections.observableArrayList( 1763 new Person("John", "Smith", "jacob.smith@example.com") 1764 )); 1765 1766 TableRow<Person> rowCell = (TableRow<Person>)VirtualFlowTestUtils.getCell(table, 0); 1767 final double initialWidth = rowCell.computePrefWidth(-1); 1768 1769 first.setPrefWidth(200); 1770 1771 final double newWidth = rowCell.computePrefWidth(-1); 1772 assertEquals(200, newWidth, 0.0); 1773 assertTrue(initialWidth != newWidth); 1774 } 1775 1776 private int rt_29650_start_count = 0; 1777 private int rt_29650_commit_count = 0; 1778 private int rt_29650_cancel_count = 0; 1779 @Test public void test_rt_29650() { 1780 TableView<Person> table = new TableView<>(); 1781 table.setEditable(true); 1782 table.setItems(FXCollections.observableArrayList( 1783 new Person("John", "Smith", "jacob.smith@example.com") 1784 )); 1785 1786 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1787 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1788 Callback<TableColumn<Person, String>, TableCell<Person, String>> factory = TextFieldTableCell.forTableColumn(); 1789 first.setCellFactory(factory); 1790 table.getColumns().addAll(first); 1791 first.setOnEditStart(t -> { 1792 rt_29650_start_count++; 1793 }); 1794 first.setOnEditCommit(t -> { 1795 rt_29650_commit_count++; 1796 }); 1797 first.setOnEditCancel(t -> { 1798 rt_29650_cancel_count++; 1799 }); 1800 1801 StageLoader sl = new StageLoader(table); 1802 1803 table.edit(0, first); 1804 1805 Toolkit.getToolkit().firePulse(); 1806 1807 TableCell rootCell = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 0); 1808 TextField textField = (TextField) rootCell.getGraphic(); 1809 textField.setText("Testing!"); 1810 KeyEventFirer keyboard = new KeyEventFirer(textField); 1811 keyboard.doKeyPress(KeyCode.ENTER); 1812 1813 // TODO should the following assert be enabled? 1814 // assertEquals("Testing!", listView.getItems().get(0)); 1815 assertEquals(1, rt_29650_start_count); 1816 assertEquals(1, rt_29650_commit_count); 1817 assertEquals(0, rt_29650_cancel_count); 1818 1819 sl.dispose(); 1820 } 1821 1822 private int rt_29849_start_count = 0; 1823 @Test public void test_rt_29849() { 1824 TableView<Person> table = new TableView<>(); 1825 table.setEditable(true); 1826 table.setItems(FXCollections.observableArrayList( 1827 new Person("John", "Smith", "jacob.smith@example.com") 1828 )); 1829 1830 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1831 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1832 Callback<TableColumn<Person, String>, TableCell<Person, String>> factory = TextFieldTableCell.forTableColumn(); 1833 first.setCellFactory(factory); 1834 table.getColumns().addAll(first); 1835 first.setOnEditStart(t -> { 1836 rt_29849_start_count++; 1837 }); 1838 1839 // load the table so the default cells are created 1840 StageLoader sl = new StageLoader(table); 1841 1842 // now replace the cell factory 1843 first.setCellFactory(TextFieldTableCell.<Person>forTableColumn()); 1844 1845 Toolkit.getToolkit().firePulse(); 1846 1847 // now start an edit and count the start edit events - it should be just 1 1848 table.edit(0, first); 1849 assertEquals(1, rt_29849_start_count); 1850 1851 sl.dispose(); 1852 } 1853 1854 @Test public void test_rt_32708_removeFromColumnsList() { 1855 TableView<Person> table = new TableView<>(); 1856 table.setEditable(true); 1857 table.setItems(FXCollections.observableArrayList( 1858 new Person("John", "Smith", "jacob.smith@example.com") 1859 )); 1860 1861 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1862 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1863 TableColumn<Person,String> last = new TableColumn<Person,String>("last"); 1864 first.setCellValueFactory(new PropertyValueFactory("lastName")); 1865 TableColumn<Person,String> email = new TableColumn<Person,String>("email"); 1866 first.setCellValueFactory(new PropertyValueFactory("email")); 1867 table.getColumns().addAll(first, last, email); 1868 1869 // load the table so the default cells are created 1870 StageLoader sl = new StageLoader(table); 1871 1872 // test pre-conditions - last column should be visible 1873 VirtualFlowTestUtils.assertTableHeaderColumnExists(table, last, true); 1874 1875 // remove last column from tableview 1876 table.getColumns().remove(last); 1877 Toolkit.getToolkit().firePulse(); 1878 1879 // test post conditions - last column should not be visible 1880 VirtualFlowTestUtils.assertTableHeaderColumnExists(table, last, false); 1881 1882 sl.dispose(); 1883 } 1884 1885 @Test public void test_rt_32708_toggleVisible() { 1886 TableView<Person> table = new TableView<>(); 1887 table.setEditable(true); 1888 table.setItems(FXCollections.observableArrayList( 1889 new Person("John", "Smith", "jacob.smith@example.com") 1890 )); 1891 1892 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1893 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1894 TableColumn<Person,String> last = new TableColumn<Person,String>("last"); 1895 first.setCellValueFactory(new PropertyValueFactory("lastName")); 1896 TableColumn<Person,String> email = new TableColumn<Person,String>("email"); 1897 first.setCellValueFactory(new PropertyValueFactory("email")); 1898 table.getColumns().addAll(first, last, email); 1899 1900 // load the table so the default cells are created 1901 StageLoader sl = new StageLoader(table); 1902 1903 // test pre-conditions - last column should be visible 1904 VirtualFlowTestUtils.assertTableHeaderColumnExists(table, last, true); 1905 1906 // hide the last column from tableview 1907 last.setVisible(false); 1908 Toolkit.getToolkit().firePulse(); 1909 1910 // test post conditions - last column should not be visible 1911 VirtualFlowTestUtils.assertTableHeaderColumnExists(table, last, false); 1912 1913 sl.dispose(); 1914 } 1915 1916 // @Ignore("Test started intermittently failing, most probably due to RT-36855 changeset") 1917 @Test public void test_rt_34493() { 1918 TableView<Person> table = new TableView<>(); 1919 table.setItems(FXCollections.observableArrayList( 1920 new Person("John", "Smith", "jacob.smith@example.com") 1921 )); 1922 1923 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1924 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1925 TableColumn<Person,String> last = new TableColumn<Person,String>("last"); 1926 first.setCellValueFactory(new PropertyValueFactory("lastName")); 1927 TableColumn<Person,String> email = new TableColumn<Person,String>("email"); 1928 first.setCellValueFactory(new PropertyValueFactory("email")); 1929 table.getColumns().addAll(first, last, email); 1930 1931 // load the table 1932 StageLoader sl = new StageLoader(table); 1933 1934 // resize the last column 1935 last.impl_setWidth(400); 1936 assertEquals(400, last.getWidth(), 0.0); 1937 1938 // hide the first column 1939 table.getColumns().remove(first); 1940 Toolkit.getToolkit().firePulse(); 1941 1942 // the last column should still be 400px, not the default width or any 1943 // other value (based on the width of the content in that column) 1944 assertEquals(400, last.getWidth(), 0.0); 1945 1946 sl.dispose(); 1947 } 1948 1949 @Test public void test_rt_34685_directEditCall_cellSelectionMode() { 1950 test_rt_34685_commitCount = 0; 1951 test_rt_34685(false, true); 1952 } 1953 1954 @Test public void test_rt_34685_directEditCall_rowSelectionMode() { 1955 test_rt_34685_commitCount = 0; 1956 test_rt_34685(false, false); 1957 } 1958 1959 @Test public void test_rt_34685_mouseDoubleClick_cellSelectionMode() { 1960 test_rt_34685_commitCount = 0; 1961 test_rt_34685(true, true); 1962 } 1963 1964 @Test public void test_rt_34685_mouseDoubleClick_rowSelectionMode() { 1965 test_rt_34685_commitCount = 0; 1966 test_rt_34685(true, false); 1967 } 1968 1969 private int test_rt_34685_commitCount = 0; 1970 private void test_rt_34685(boolean useMouseToInitiateEdit, boolean cellSelectionModeEnabled) { 1971 assertEquals(0, test_rt_34685_commitCount); 1972 1973 TableView<Person> table = new TableView<>(); 1974 table.getSelectionModel().setCellSelectionEnabled(cellSelectionModeEnabled); 1975 table.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); 1976 table.setEditable(true); 1977 1978 Person person1; 1979 table.setItems(FXCollections.observableArrayList( 1980 person1 = new Person("John", "Smith", "john.smith@example.com"), 1981 new Person("Jacob", "Michaels", "jacob.michaels@example.com"), 1982 new Person("Jim", "Bob", "jim.bob@example.com") 1983 )); 1984 1985 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 1986 first.setCellValueFactory(new PropertyValueFactory("firstName")); 1987 Callback<TableColumn<Person, String>, TableCell<Person, String>> factory = TextFieldTableCell.forTableColumn(); 1988 first.setCellFactory(factory); // note that only the first name col is editable 1989 1990 EventHandler<TableColumn.CellEditEvent<Person, String>> onEditCommit = first.getOnEditCommit(); 1991 first.setOnEditCommit(event -> { 1992 test_rt_34685_commitCount++; 1993 onEditCommit.handle(event); 1994 }); 1995 1996 table.getColumns().addAll(first); 1997 1998 // get the cell at (0,0) 1999 VirtualFlowTestUtils.BLOCK_STAGE_LOADER_DISPOSE = true; 2000 TableCell cell = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 0); 2001 VirtualFlowTestUtils.BLOCK_STAGE_LOADER_DISPOSE = false; 2002 assertTrue(cell.getSkin() instanceof TableCellSkin); 2003 assertNull(cell.getGraphic()); 2004 assertEquals("John", cell.getText()); 2005 assertEquals("John", person1.getFirstName()); 2006 2007 // set the table to be editing the first cell at 0,0 2008 if (useMouseToInitiateEdit) { 2009 MouseEventFirer mouse = new MouseEventFirer(cell); 2010 mouse.fireMousePressAndRelease(2, 10, 10); // click 10 pixels in and 10 pixels down 2011 mouse.dispose(); 2012 } else { 2013 table.edit(0,first); 2014 } 2015 2016 Toolkit.getToolkit().firePulse(); 2017 assertNotNull(cell.getGraphic()); 2018 assertTrue(cell.getGraphic() instanceof TextField); 2019 2020 TextField textField = (TextField) cell.getGraphic(); 2021 assertEquals("John", textField.getText()); 2022 2023 textField.setText("Andrew"); 2024 textField.requestFocus(); 2025 Toolkit.getToolkit().firePulse(); 2026 2027 KeyEventFirer keyboard = new KeyEventFirer(textField); 2028 keyboard.doKeyPress(KeyCode.ENTER); 2029 2030 VirtualFlowTestUtils.getVirtualFlow(table).requestLayout(); 2031 Toolkit.getToolkit().firePulse(); 2032 2033 VirtualFlowTestUtils.assertTableCellTextEquals(table, 0, 0, "Andrew"); 2034 assertEquals("Andrew", cell.getText()); 2035 assertEquals("Andrew", person1.getFirstName()); 2036 assertEquals(1, test_rt_34685_commitCount); 2037 } 2038 2039 @Test public void test_rt_35224() { 2040 TableView table = new TableView(); 2041 TableColumn col1 = new TableColumn(); 2042 TableColumn col2 = new TableColumn(); 2043 table.getColumns().setAll(col1, col2); 2044 2045 StageLoader sl = new StageLoader(table); 2046 2047 Toolkit.getToolkit().firePulse(); 2048 col1.getColumns().setAll(new TableColumn(), new TableColumn()); 2049 Toolkit.getToolkit().firePulse(); 2050 col2.getColumns().setAll(new TableColumn(), new TableColumn()); 2051 Toolkit.getToolkit().firePulse(); 2052 2053 sl.dispose(); 2054 } 2055 2056 @Test public void test_rt_35141_simple_switch_two_columns_move_col1_forward_1_place() { 2057 TableView table = new TableView(); 2058 TableColumn col1 = new TableColumn(); 2059 TableColumn col2 = new TableColumn(); 2060 table.getColumns().setAll(col1, col2); 2061 2062 StageLoader sl = new StageLoader(table); 2063 2064 assertEquals(0, getColumnIndex(col1)); 2065 assertEquals(1, getColumnIndex(col2)); 2066 2067 moveColumn(col1, 1); 2068 assertEquals(1, getColumnIndex(col1)); 2069 assertEquals(0, getColumnIndex(col2)); 2070 2071 sl.dispose(); 2072 } 2073 2074 @Test public void test_rt_35141_simple_switch_two_columns_move_col2_backward_1_place() { 2075 TableView table = new TableView(); 2076 TableColumn col1 = new TableColumn(); 2077 TableColumn col2 = new TableColumn(); 2078 table.getColumns().setAll(col1, col2); 2079 2080 StageLoader sl = new StageLoader(table); 2081 2082 assertEquals(0, getColumnIndex(col1)); 2083 assertEquals(1, getColumnIndex(col2)); 2084 2085 moveColumn(col2, 0); 2086 assertEquals(1, getColumnIndex(col1)); 2087 assertEquals(0, getColumnIndex(col2)); 2088 2089 sl.dispose(); 2090 } 2091 2092 @Test public void test_rt_35141_simple_switch_three_columns_move_col1_forward_1_place() { 2093 TableView table = new TableView(); 2094 TableColumn col1 = new TableColumn(); 2095 TableColumn col2 = new TableColumn(); 2096 TableColumn col3 = new TableColumn(); 2097 table.getColumns().setAll(col1, col2, col3); 2098 2099 StageLoader sl = new StageLoader(table); 2100 2101 assertEquals(0, getColumnIndex(col1)); 2102 assertEquals(1, getColumnIndex(col2)); 2103 assertEquals(2, getColumnIndex(col3)); 2104 2105 moveColumn(col1, 1); 2106 assertEquals(1, getColumnIndex(col1)); 2107 assertEquals(0, getColumnIndex(col2)); 2108 assertEquals(2, getColumnIndex(col3)); 2109 2110 sl.dispose(); 2111 } 2112 2113 @Test public void test_rt_35141_simple_switch_three_columns_move_col2_backward_1_place() { 2114 TableView table = new TableView(); 2115 TableColumn col1 = new TableColumn(); 2116 TableColumn col2 = new TableColumn(); 2117 TableColumn col3 = new TableColumn(); 2118 table.getColumns().setAll(col1, col2, col3); 2119 2120 StageLoader sl = new StageLoader(table); 2121 2122 assertEquals(0, getColumnIndex(col1)); 2123 assertEquals(1, getColumnIndex(col2)); 2124 assertEquals(2, getColumnIndex(col3)); 2125 2126 moveColumn(col2, 0); 2127 assertEquals(1, getColumnIndex(col1)); 2128 assertEquals(0, getColumnIndex(col2)); 2129 assertEquals(2, getColumnIndex(col3)); 2130 2131 sl.dispose(); 2132 } 2133 2134 @Test public void test_rt_35141_simple_switch_three_columns_move_col2_forward_1_place() { 2135 TableView table = new TableView(); 2136 TableColumn col1 = new TableColumn(); 2137 TableColumn col2 = new TableColumn(); 2138 TableColumn col3 = new TableColumn(); 2139 table.getColumns().setAll(col1, col2, col3); 2140 2141 StageLoader sl = new StageLoader(table); 2142 2143 assertEquals(0, getColumnIndex(col1)); 2144 assertEquals(1, getColumnIndex(col2)); 2145 assertEquals(2, getColumnIndex(col3)); 2146 2147 moveColumn(col2, 2); 2148 assertEquals(0, getColumnIndex(col1)); 2149 assertEquals(2, getColumnIndex(col2)); 2150 assertEquals(1, getColumnIndex(col3)); 2151 2152 sl.dispose(); 2153 } 2154 2155 @Test public void test_rt_35141_simple_switch_three_columns_move_col3_backward_1_place() { 2156 TableView table = new TableView(); 2157 TableColumn col1 = new TableColumn(); 2158 TableColumn col2 = new TableColumn(); 2159 TableColumn col3 = new TableColumn(); 2160 table.getColumns().setAll(col1, col2, col3); 2161 2162 StageLoader sl = new StageLoader(table); 2163 2164 assertEquals(0, getColumnIndex(col1)); 2165 assertEquals(1, getColumnIndex(col2)); 2166 assertEquals(2, getColumnIndex(col3)); 2167 2168 moveColumn(col3, 1); 2169 assertEquals(0, getColumnIndex(col1)); 2170 assertEquals(2, getColumnIndex(col2)); 2171 assertEquals(1, getColumnIndex(col3)); 2172 2173 sl.dispose(); 2174 } 2175 2176 @Test public void test_rt_35141_simple_switch_three_columns_move_col0_forward_2_places() { 2177 TableView table = new TableView(); 2178 TableColumn col1 = new TableColumn(); 2179 TableColumn col2 = new TableColumn(); 2180 TableColumn col3 = new TableColumn(); 2181 table.getColumns().setAll(col1, col2, col3); 2182 2183 StageLoader sl = new StageLoader(table); 2184 2185 assertEquals(0, getColumnIndex(col1)); 2186 assertEquals(1, getColumnIndex(col2)); 2187 assertEquals(2, getColumnIndex(col3)); 2188 2189 moveColumn(col1, 2); 2190 assertEquals(2, getColumnIndex(col1)); 2191 assertEquals(0, getColumnIndex(col2)); 2192 assertEquals(1, getColumnIndex(col3)); 2193 2194 sl.dispose(); 2195 } 2196 2197 @Test public void test_rt_35141_simple_switch_three_columns_move_col3_backward_2_places() { 2198 TableView table = new TableView(); 2199 TableColumn col1 = new TableColumn(); 2200 TableColumn col2 = new TableColumn(); 2201 TableColumn col3 = new TableColumn(); 2202 table.getColumns().setAll(col1, col2, col3); 2203 2204 StageLoader sl = new StageLoader(table); 2205 2206 assertEquals(0, getColumnIndex(col1)); 2207 assertEquals(1, getColumnIndex(col2)); 2208 assertEquals(2, getColumnIndex(col3)); 2209 2210 moveColumn(col3, 0); 2211 assertEquals(1, getColumnIndex(col1)); 2212 assertEquals(2, getColumnIndex(col2)); 2213 assertEquals(0, getColumnIndex(col3)); 2214 2215 sl.dispose(); 2216 } 2217 2218 @Test public void test_rt_35141_hidden_column_move_col1_forward_1_place() { 2219 TableView table = new TableView(); 2220 TableColumn col1 = new TableColumn(); 2221 TableColumn col2 = new TableColumn(); 2222 TableColumn col3 = new TableColumn(); 2223 table.getColumns().setAll(col1, col2, col3); 2224 2225 StageLoader sl = new StageLoader(table); 2226 2227 col2.setVisible(false); 2228 2229 assertEquals(0, getColumnIndex(col1)); 2230 assertEquals(-1, getColumnIndex(col2)); 2231 assertEquals(1, getColumnIndex(col3)); 2232 2233 moveColumn(col1, 1); 2234 assertEquals(1, getColumnIndex(col1)); 2235 assertEquals(-1, getColumnIndex(col2)); 2236 assertEquals(0, getColumnIndex(col3)); 2237 2238 sl.dispose(); 2239 } 2240 2241 @Test public void test_rt_35141_hidden_column_move_col1_forward_100_places() { 2242 TableView table = new TableView(); 2243 TableColumn col1 = new TableColumn(); 2244 TableColumn col2 = new TableColumn(); 2245 TableColumn col3 = new TableColumn(); 2246 table.getColumns().setAll(col1, col2, col3); 2247 2248 StageLoader sl = new StageLoader(table); 2249 2250 col2.setVisible(false); 2251 2252 assertEquals(0, getColumnIndex(col1)); 2253 assertEquals(-1, getColumnIndex(col2)); 2254 assertEquals(1, getColumnIndex(col3)); 2255 2256 moveColumn(col1, 100); 2257 assertEquals(1, getColumnIndex(col1)); 2258 assertEquals(-1, getColumnIndex(col2)); 2259 assertEquals(0, getColumnIndex(col3)); 2260 2261 sl.dispose(); 2262 } 2263 2264 @Test public void test_rt_35141_hidden_column_move_col3_backward_1_place() { 2265 TableView table = new TableView(); 2266 TableColumn col1 = new TableColumn(); 2267 TableColumn col2 = new TableColumn(); 2268 TableColumn col3 = new TableColumn(); 2269 table.getColumns().setAll(col1, col2, col3); 2270 2271 StageLoader sl = new StageLoader(table); 2272 2273 col2.setVisible(false); 2274 2275 assertEquals(0, getColumnIndex(col1)); 2276 assertEquals(-1, getColumnIndex(col2)); 2277 assertEquals(1, getColumnIndex(col3)); 2278 2279 moveColumn(col3, 0); 2280 assertEquals(1, getColumnIndex(col1)); 2281 assertEquals(-1, getColumnIndex(col2)); 2282 assertEquals(0, getColumnIndex(col3)); 2283 2284 sl.dispose(); 2285 } 2286 2287 @Test public void test_rt_35141_multiple_hidden_columns_move_col1_to_middle() { 2288 TableView table = new TableView(); 2289 TableColumn col1 = new TableColumn(); 2290 TableColumn col2 = new TableColumn(); 2291 TableColumn col3 = new TableColumn(); 2292 TableColumn col4 = new TableColumn(); 2293 TableColumn col5 = new TableColumn(); 2294 TableColumn col6 = new TableColumn(); 2295 table.getColumns().setAll(col1, col2, col3, col4, col5, col6); 2296 2297 StageLoader sl = new StageLoader(table); 2298 2299 col2.setVisible(false); 2300 col4.setVisible(false); 2301 2302 assertEquals(0, getColumnIndex(col1)); 2303 assertEquals(-1, getColumnIndex(col2)); 2304 assertEquals(1, getColumnIndex(col3)); 2305 assertEquals(-1, getColumnIndex(col4)); 2306 assertEquals(2, getColumnIndex(col5)); 2307 assertEquals(3, getColumnIndex(col6)); 2308 2309 moveColumn(col1, 1); // 1 should represent the spot between col2 and col4 2310 assertEquals(1, getColumnIndex(col1)); 2311 assertEquals(-1, getColumnIndex(col2)); 2312 assertEquals(0, getColumnIndex(col3)); 2313 assertEquals(-1, getColumnIndex(col4)); 2314 assertEquals(2, getColumnIndex(col5)); 2315 assertEquals(3, getColumnIndex(col6)); 2316 2317 sl.dispose(); 2318 } 2319 2320 @Test public void test_rt_35141_multiple_hidden_columns_move_col1_to_end() { 2321 TableView table = new TableView(); 2322 TableColumn col1 = new TableColumn(); 2323 TableColumn col2 = new TableColumn(); 2324 TableColumn col3 = new TableColumn(); 2325 TableColumn col4 = new TableColumn(); 2326 TableColumn col5 = new TableColumn(); 2327 TableColumn col6 = new TableColumn(); 2328 table.getColumns().setAll(col1, col2, col3, col4, col5, col6); 2329 2330 StageLoader sl = new StageLoader(table); 2331 2332 col2.setVisible(false); 2333 col4.setVisible(false); 2334 2335 assertEquals(0, getColumnIndex(col1)); 2336 assertEquals(-1, getColumnIndex(col2)); 2337 assertEquals(1, getColumnIndex(col3)); 2338 assertEquals(-1, getColumnIndex(col4)); 2339 assertEquals(2, getColumnIndex(col5)); 2340 assertEquals(3, getColumnIndex(col6)); 2341 2342 moveColumn(col1, 3); // 3 should represent the end place 2343 assertEquals(3, getColumnIndex(col1)); 2344 assertEquals(-1, getColumnIndex(col2)); 2345 assertEquals(0, getColumnIndex(col3)); 2346 assertEquals(-1, getColumnIndex(col4)); 2347 assertEquals(1, getColumnIndex(col5)); 2348 assertEquals(2, getColumnIndex(col6)); 2349 2350 sl.dispose(); 2351 } 2352 2353 @Test public void test_rt_35141_multiple_hidden_columns_move_col3_to_start() { 2354 TableView table = new TableView(); 2355 TableColumn col1 = new TableColumn(); 2356 TableColumn col2 = new TableColumn(); 2357 TableColumn col3 = new TableColumn(); 2358 TableColumn col4 = new TableColumn(); 2359 TableColumn col5 = new TableColumn(); 2360 TableColumn col6 = new TableColumn(); 2361 table.getColumns().setAll(col1, col2, col3, col4, col5, col6); 2362 2363 StageLoader sl = new StageLoader(table); 2364 2365 col2.setVisible(false); 2366 col4.setVisible(false); 2367 2368 assertEquals(0, getColumnIndex(col1)); 2369 assertEquals(-1, getColumnIndex(col2)); 2370 assertEquals(1, getColumnIndex(col3)); 2371 assertEquals(-1, getColumnIndex(col4)); 2372 assertEquals(2, getColumnIndex(col5)); 2373 assertEquals(3, getColumnIndex(col6)); 2374 2375 moveColumn(col3, 0); 2376 assertEquals(1, getColumnIndex(col1)); 2377 assertEquals(-1, getColumnIndex(col2)); 2378 assertEquals(0, getColumnIndex(col3)); 2379 assertEquals(-1, getColumnIndex(col4)); 2380 assertEquals(2, getColumnIndex(col5)); 2381 assertEquals(3, getColumnIndex(col6)); 2382 2383 sl.dispose(); 2384 } 2385 2386 @Test public void test_rt_35141_multiple_hidden_columns_move_col3_to_end() { 2387 TableView table = new TableView(); 2388 TableColumn col1 = new TableColumn(); 2389 TableColumn col2 = new TableColumn(); 2390 TableColumn col3 = new TableColumn(); 2391 TableColumn col4 = new TableColumn(); 2392 TableColumn col5 = new TableColumn(); 2393 TableColumn col6 = new TableColumn(); 2394 table.getColumns().setAll(col1, col2, col3, col4, col5, col6); 2395 2396 StageLoader sl = new StageLoader(table); 2397 2398 col2.setVisible(false); 2399 col4.setVisible(false); 2400 2401 assertEquals(0, getColumnIndex(col1)); 2402 assertEquals(-1, getColumnIndex(col2)); 2403 assertEquals(1, getColumnIndex(col3)); 2404 assertEquals(-1, getColumnIndex(col4)); 2405 assertEquals(2, getColumnIndex(col5)); 2406 assertEquals(3, getColumnIndex(col6)); 2407 2408 moveColumn(col3, 3); // 3 should represent the end place 2409 assertEquals(0, getColumnIndex(col1)); 2410 assertEquals(-1, getColumnIndex(col2)); 2411 assertEquals(3, getColumnIndex(col3)); 2412 assertEquals(-1, getColumnIndex(col4)); 2413 assertEquals(1, getColumnIndex(col5)); 2414 assertEquals(2, getColumnIndex(col6)); 2415 2416 sl.dispose(); 2417 } 2418 2419 @Test public void test_rt_35141_multiple_hidden_columns_move_col6_to_start() { 2420 TableView table = new TableView(); 2421 TableColumn col1 = new TableColumn(); 2422 TableColumn col2 = new TableColumn(); 2423 TableColumn col3 = new TableColumn(); 2424 TableColumn col4 = new TableColumn(); 2425 TableColumn col5 = new TableColumn(); 2426 TableColumn col6 = new TableColumn(); 2427 table.getColumns().setAll(col1, col2, col3, col4, col5, col6); 2428 2429 StageLoader sl = new StageLoader(table); 2430 2431 col2.setVisible(false); 2432 col4.setVisible(false); 2433 2434 assertEquals(0, getColumnIndex(col1)); 2435 assertEquals(-1, getColumnIndex(col2)); 2436 assertEquals(1, getColumnIndex(col3)); 2437 assertEquals(-1, getColumnIndex(col4)); 2438 assertEquals(2, getColumnIndex(col5)); 2439 assertEquals(3, getColumnIndex(col6)); 2440 2441 moveColumn(col6, 0); 2442 assertEquals(1, getColumnIndex(col1)); 2443 assertEquals(-1, getColumnIndex(col2)); 2444 assertEquals(2, getColumnIndex(col3)); 2445 assertEquals(-1, getColumnIndex(col4)); 2446 assertEquals(3, getColumnIndex(col5)); 2447 assertEquals(0, getColumnIndex(col6)); 2448 2449 sl.dispose(); 2450 } 2451 2452 @Test public void test_rt_35141_multiple_hidden_columns_move_col6_to_middle() { 2453 TableView table = new TableView(); 2454 TableColumn col1 = new TableColumn(); 2455 TableColumn col2 = new TableColumn(); 2456 TableColumn col3 = new TableColumn(); 2457 TableColumn col4 = new TableColumn(); 2458 TableColumn col5 = new TableColumn(); 2459 TableColumn col6 = new TableColumn(); 2460 table.getColumns().setAll(col1, col2, col3, col4, col5, col6); 2461 2462 StageLoader sl = new StageLoader(table); 2463 2464 col2.setVisible(false); 2465 col4.setVisible(false); 2466 2467 assertEquals(0, getColumnIndex(col1)); 2468 assertEquals(-1, getColumnIndex(col2)); 2469 assertEquals(1, getColumnIndex(col3)); 2470 assertEquals(-1, getColumnIndex(col4)); 2471 assertEquals(2, getColumnIndex(col5)); 2472 assertEquals(3, getColumnIndex(col6)); 2473 2474 moveColumn(col6, 1); 2475 assertEquals(0, getColumnIndex(col1)); 2476 assertEquals(-1, getColumnIndex(col2)); 2477 assertEquals(2, getColumnIndex(col3)); 2478 assertEquals(-1, getColumnIndex(col4)); 2479 assertEquals(3, getColumnIndex(col5)); 2480 assertEquals(1, getColumnIndex(col6)); 2481 2482 sl.dispose(); 2483 } 2484 2485 @Test public void test_rt_34042() { 2486 Scene scene = new Scene(new Group()); 2487 SplitPane splitPane = new SplitPane(); 2488 splitPane.setOrientation(Orientation.VERTICAL); 2489 2490 //TREETABLECOLUMN 2491 TreeTableView<Person> treeTableView = new TreeTableView<>(); 2492 TreeTableColumn temp = new TreeTableColumn("First Name"); 2493 temp.setMinWidth(100); 2494 temp.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 2495 2496 TreeTableColumn temp2 = new TreeTableColumn("Last Name"); 2497 temp2.setMinWidth(100); 2498 temp2.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 2499 2500 TreeTableColumn temp3 = new TreeTableColumn("Email"); 2501 temp3.setMinWidth(200); 2502 temp3.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 2503 2504 treeTableView.getColumns().addAll(temp, temp2, temp3); 2505 2506 //TABLE 2507 TableView<Person> table = new TableView<Person>(); 2508 table.setEditable(true); 2509 table.getSelectionModel().setCellSelectionEnabled(true); 2510 TableColumn firstNameCol = new TableColumn("First Name"); 2511 firstNameCol.setMinWidth(100); 2512 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 2513 2514 TableColumn lastNameCol = new TableColumn("Last Name"); 2515 lastNameCol.setMinWidth(100); 2516 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 2517 2518 TableColumn emailCol = new TableColumn("Email"); 2519 emailCol.setMinWidth(200); 2520 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 2521 2522 table.setItems(personTestData); 2523 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 2524 2525 splitPane.getItems().add(treeTableView); 2526 splitPane.getItems().add(table); 2527 2528 ((Group) scene.getRoot()).getChildren().addAll(splitPane); 2529 2530 new StageLoader(scene); 2531 2532 TableView.TableViewSelectionModel sm = table.getSelectionModel(); 2533 sm.select(2, lastNameCol); 2534 assertFalse(sm.isSelected(2, firstNameCol)); 2535 assertTrue(sm.isSelected(2, lastNameCol)); 2536 assertFalse(sm.isSelected(2, emailCol)); 2537 2538 KeyEventFirer keyboard = new KeyEventFirer(table); 2539 keyboard.doKeyPress(KeyCode.LEFT); 2540 assertTrue(sm.isSelected(2, firstNameCol)); 2541 assertFalse(sm.isSelected(2, lastNameCol)); 2542 assertFalse(sm.isSelected(2, emailCol)); 2543 2544 keyboard.doKeyPress(KeyCode.RIGHT); 2545 assertFalse(sm.isSelected(2, firstNameCol)); 2546 assertTrue(sm.isSelected(2, lastNameCol)); 2547 assertFalse(sm.isSelected(2, emailCol)); 2548 2549 keyboard.doKeyPress(KeyCode.RIGHT); 2550 assertFalse(sm.isSelected(2, firstNameCol)); 2551 assertFalse(sm.isSelected(2, lastNameCol)); 2552 assertTrue(sm.isSelected(2, emailCol)); 2553 } 2554 2555 @Test public void test_rt35039() { 2556 final List<String> data = new ArrayList<>(); 2557 data.add("aabbaa"); 2558 data.add("bbc"); 2559 2560 final TableView<String> tableView = new TableView<>(); 2561 tableView.setItems(FXCollections.observableArrayList(data)); 2562 2563 StageLoader sl = new StageLoader(tableView); 2564 2565 // selection starts off at row -1 2566 assertNull(tableView.getSelectionModel().getSelectedItem()); 2567 2568 // select "bbc" and ensure everything is set to that 2569 tableView.getSelectionModel().select(1); 2570 assertEquals("bbc", tableView.getSelectionModel().getSelectedItem()); 2571 2572 // change the items list - but retain the same content. We expect 2573 // that "bbc" remains selected as it is still in the list 2574 tableView.setItems(FXCollections.observableArrayList(data)); 2575 assertEquals("bbc", tableView.getSelectionModel().getSelectedItem()); 2576 2577 sl.dispose(); 2578 } 2579 2580 @Test public void test_rt35763_observableList() { 2581 TableView<Person> table = new TableView(); 2582 2583 TableColumn firstNameCol = new TableColumn("First Name"); 2584 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 2585 table.getColumns().add(firstNameCol); 2586 2587 Person jacob, isabella, ethan, emma, michael; 2588 table.setItems(FXCollections.observableArrayList( 2589 jacob = new Person("Jacob", "Smith", "jacob.smith@example.com"), 2590 isabella = new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 2591 ethan = new Person("Ethan", "Williams", "ethan.williams@example.com"), 2592 emma = new Person("Emma", "Jones", "emma.jones@example.com"), 2593 michael = new Person("Michael", "Brown", "michael.brown@example.com"))); 2594 2595 assertEquals(jacob, table.getItems().get(0)); 2596 assertEquals(isabella, table.getItems().get(1)); 2597 assertEquals(ethan, table.getItems().get(2)); 2598 assertEquals(emma, table.getItems().get(3)); 2599 assertEquals(michael, table.getItems().get(4)); 2600 2601 // change sort order - expect items to be sorted 2602 table.getSortOrder().setAll(firstNameCol); 2603 2604 assertEquals(jacob, table.getItems().get(3)); 2605 assertEquals(isabella, table.getItems().get(2)); 2606 assertEquals(ethan, table.getItems().get(1)); 2607 assertEquals(emma, table.getItems().get(0)); 2608 assertEquals(michael, table.getItems().get(4)); 2609 2610 // set new items into items list - expect sortOrder list to be reset 2611 // and the items list to remain unsorted 2612 table.setItems(FXCollections.observableArrayList( 2613 jacob = new Person("Jacob", "Smith", "jacob.smith@example.com"), 2614 isabella = new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 2615 ethan = new Person("Ethan", "Williams", "ethan.williams@example.com"), 2616 emma = new Person("Emma", "Jones", "emma.jones@example.com"), 2617 michael = new Person("Michael", "Brown", "michael.brown@example.com"))); 2618 2619 assertEquals(jacob, table.getItems().get(0)); 2620 assertEquals(isabella, table.getItems().get(1)); 2621 assertEquals(ethan, table.getItems().get(2)); 2622 assertEquals(emma, table.getItems().get(3)); 2623 assertEquals(michael, table.getItems().get(4)); 2624 2625 assertTrue(table.getSortOrder().isEmpty()); 2626 } 2627 2628 @Test public void test_rt35763_sortedList() { 2629 TableView<Person> table = new TableView(); 2630 2631 TableColumn firstNameCol = new TableColumn("First Name"); 2632 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 2633 table.getColumns().add(firstNameCol); 2634 2635 Person jacob, isabella, ethan, emma, michael; 2636 SortedList<Person> sortedList = new SortedList<>(FXCollections.observableArrayList( 2637 jacob = new Person("Jacob", "Smith", "jacob.smith@example.com"), 2638 isabella = new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 2639 ethan = new Person("Ethan", "Williams", "ethan.williams@example.com"), 2640 emma = new Person("Emma", "Jones", "emma.jones@example.com"), 2641 michael = new Person("Michael", "Brown", "michael.brown@example.com"))); 2642 sortedList.comparatorProperty().bind(table.comparatorProperty()); 2643 table.setItems(sortedList); 2644 2645 assertEquals(jacob, table.getItems().get(0)); 2646 assertEquals(isabella, table.getItems().get(1)); 2647 assertEquals(ethan, table.getItems().get(2)); 2648 assertEquals(emma, table.getItems().get(3)); 2649 assertEquals(michael, table.getItems().get(4)); 2650 2651 // change sort order - expect items to be sorted 2652 table.getSortOrder().setAll(firstNameCol); 2653 2654 assertEquals(jacob, table.getItems().get(3)); 2655 assertEquals(isabella, table.getItems().get(2)); 2656 assertEquals(ethan, table.getItems().get(1)); 2657 assertEquals(emma, table.getItems().get(0)); 2658 assertEquals(michael, table.getItems().get(4)); 2659 2660 // set new items into items list - expect sortOrder list to be retained 2661 // as we're inserting a SortedList 2662 SortedList<Person> sortedList2 = new SortedList<>(FXCollections.observableArrayList( 2663 jacob = new Person("Jacob", "Smith", "jacob.smith@example.com"), 2664 isabella = new Person("Isabella", "Johnson", "isabella.johnson@example.com"), 2665 ethan = new Person("Ethan", "Williams", "ethan.williams@example.com"), 2666 emma = new Person("Emma", "Jones", "emma.jones@example.com"), 2667 michael = new Person("Michael", "Brown", "michael.brown@example.com"))); 2668 sortedList2.comparatorProperty().bind(table.comparatorProperty()); 2669 table.setItems(sortedList2); 2670 2671 assertEquals(jacob, table.getItems().get(3)); 2672 assertEquals(isabella, table.getItems().get(2)); 2673 assertEquals(ethan, table.getItems().get(1)); 2674 assertEquals(emma, table.getItems().get(0)); 2675 assertEquals(michael, table.getItems().get(4)); 2676 2677 assertEquals(1, table.getSortOrder().size()); 2678 assertEquals(firstNameCol, table.getSortOrder().get(0)); 2679 } 2680 2681 @Test(expected = IndexOutOfBoundsException.class) 2682 public void test_rt35768_negativeFrom() { 2683 readOnlyUnbackedObservableListSubListTest(-1, 0); 2684 } 2685 2686 @Test(expected = IndexOutOfBoundsException.class) 2687 public void test_rt35768_bigTo() { 2688 readOnlyUnbackedObservableListSubListTest(0, 10); 2689 } 2690 2691 @Test(expected = IndexOutOfBoundsException.class) 2692 public void test_rt35768_fromEqualsTo() { 2693 readOnlyUnbackedObservableListSubListTest(1, 1); 2694 } 2695 2696 private void readOnlyUnbackedObservableListSubListTest(int from, int to) { 2697 final SelectedCellsMap<TablePosition> selectedCellsMap = new SelectedCellsMap<TablePosition>(c -> { /* Do nothing */}) { 2698 @Override public boolean isCellSelectionEnabled() { 2699 return false; 2700 } 2701 }; 2702 ReadOnlyUnbackedObservableList<TablePosition<Object, ?>> selectedCellsSeq = new ReadOnlyUnbackedObservableList<TablePosition<Object, ?>>() { 2703 @Override public TablePosition<Object, ?> get(int i) { 2704 return selectedCellsMap.get(i); 2705 } 2706 2707 @Override public int size() { 2708 return selectedCellsMap.size(); 2709 } 2710 }; 2711 2712 // This should result in an IOOBE, but didn't until this bug was fixed 2713 selectedCellsSeq.subList(from, to); 2714 } 2715 2716 @Test public void test_rt35857() { 2717 ObservableList<String> fxList = FXCollections.observableArrayList("A", "B", "C"); 2718 final TableView<String> tableView = new TableView<String>(fxList); 2719 2720 tableView.getSelectionModel().select(0); 2721 2722 ObservableList<String> selectedItems = tableView.getSelectionModel().getSelectedItems(); 2723 assertEquals(1, selectedItems.size()); 2724 assertEquals("A", selectedItems.get(0)); 2725 2726 tableView.getItems().removeAll(selectedItems); 2727 assertEquals(2, fxList.size()); 2728 assertEquals("B", fxList.get(0)); 2729 assertEquals("C", fxList.get(1)); 2730 } 2731 2732 @Test public void test_getColumnHeaderForColumn() { 2733 TableView<Person> table = new TableView<>(); 2734 table.setItems(FXCollections.observableArrayList( 2735 new Person("John", "Smith", "jacob.smith@example.com") 2736 )); 2737 2738 TableColumn<Person,String> first = new TableColumn<Person,String>("first"); 2739 first.setCellValueFactory(new PropertyValueFactory("firstName")); 2740 TableColumn<Person,String> last = new TableColumn<Person,String>("last"); 2741 first.setCellValueFactory(new PropertyValueFactory("lastName")); 2742 2743 TableColumn name = new TableColumn("Name"); 2744 name.getColumns().addAll(first, last); 2745 2746 table.getColumns().setAll(name); 2747 2748 StageLoader sl = new StageLoader(table); 2749 2750 TableHeaderRow headerRow = VirtualFlowTestUtils.getTableHeaderRow(table); 2751 2752 TableColumnHeader nameHeader = headerRow.getColumnHeaderFor(name); 2753 TableColumnHeader firstHeader = headerRow.getColumnHeaderFor(first); 2754 TableColumnHeader lastHeader = headerRow.getColumnHeaderFor(last); 2755 assertNotNull(nameHeader); 2756 assertEquals(name, nameHeader.getTableColumn()); 2757 assertNotNull(firstHeader); 2758 assertEquals(first, firstHeader.getTableColumn()); 2759 assertNotNull(lastHeader); 2760 assertEquals(last, lastHeader.getTableColumn()); 2761 2762 sl.dispose(); 2763 } 2764 2765 @Test public void test_rt36220() { 2766 ObservableList<AtomicLong> tableItems = FXCollections.observableArrayList(); 2767 tableItems.add(new AtomicLong(0L)); 2768 2769 TableView<AtomicLong> tableView = new TableView<>(); 2770 tableView.getItems().setAll(tableItems); 2771 2772 TableColumn<AtomicLong, String> col = new TableColumn<>(); 2773 col.setCellValueFactory(obj -> new SimpleStringProperty(String.valueOf(obj.getValue().longValue()))); 2774 col.setPrefWidth(180); 2775 tableView.getColumns().add(col); 2776 2777 new StageLoader(tableView); 2778 2779 VirtualFlowTestUtils.assertTableCellTextEquals(tableView, 0, 0, "0"); 2780 2781 // 1) using this trick will prevent the first update 2782 col.setMinWidth(col.getPrefWidth() + 1); 2783 2784 long expected = System.currentTimeMillis(); 2785 tableItems.get(0).set(expected); 2786 tableView.getItems().setAll(tableItems); 2787 2788 Toolkit.getToolkit().firePulse(); 2789 2790 VirtualFlowTestUtils.assertTableCellTextEquals(tableView, 0, 0, ""+expected); 2791 } 2792 2793 @Test public void test_rt36425() { 2794 TableView<String> tableView = new TableView<>(); 2795 2796 TableColumn<String, String> tableColumn = new TableColumn<>(); 2797 tableColumn.setCellValueFactory(data -> new SimpleStringProperty(data.getValue())); 2798 tableColumn.setText("Test"); 2799 tableView.getColumns().add(tableColumn); 2800 2801 SimpleListProperty<String> data = new SimpleListProperty<>(FXCollections.observableArrayList()); 2802 tableView.itemsProperty().bind(data); 2803 data.addAll("AAA", "BBB"); 2804 2805 assertEquals("AAA", data.get(0)); 2806 assertEquals("BBB", data.get(1)); 2807 2808 tableView.getSortOrder().add(tableColumn); 2809 2810 assertTrue(tableView.getSortOrder().contains(tableColumn)); 2811 assertEquals("AAA", data.get(0)); 2812 assertEquals("BBB", data.get(1)); 2813 2814 tableColumn.setSortType(TableColumn.SortType.DESCENDING); 2815 assertEquals("AAA", data.get(1)); 2816 assertEquals("BBB", data.get(0)); 2817 } 2818 2819 private int test_rt_36353_selectedItemCount = 0; 2820 private int test_rt_36353_selectedIndexCount = 0; 2821 @Test public void test_rt36353() { 2822 ObservableList<String> data = FXCollections.observableArrayList(); 2823 data.addAll("2", "1", "3"); 2824 SortedList<String> sortedList = new SortedList<>(data); 2825 2826 TableView<String> tableView = new TableView<>(sortedList); 2827 sortedList.comparatorProperty().bind(tableView.comparatorProperty()); 2828 2829 TableColumn<String, String> tableColumn = new TableColumn<>(); 2830 tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue())); 2831 tableColumn.setText("Test"); 2832 tableView.getColumns().add(tableColumn); 2833 2834 tableView.getSelectionModel().selectedItemProperty().addListener((e, oldSelection, newSelection) -> { 2835 test_rt_36353_selectedItemCount++; 2836 }); 2837 tableView.getSelectionModel().selectedIndexProperty().addListener((e, oldIndex, newIndex) -> { 2838 test_rt_36353_selectedIndexCount++; 2839 }); 2840 2841 assertEquals(0, test_rt_36353_selectedItemCount); 2842 assertEquals(0, test_rt_36353_selectedIndexCount); 2843 2844 tableView.getSelectionModel().select(1); 2845 assertEquals(1, test_rt_36353_selectedItemCount); 2846 assertEquals(1, test_rt_36353_selectedIndexCount); 2847 assertEquals("2", sortedList.get(0)); 2848 assertEquals("1", sortedList.get(1)); 2849 assertEquals("3", sortedList.get(2)); 2850 2851 tableView.getSortOrder().add(tableColumn); 2852 assertEquals(1, test_rt_36353_selectedItemCount); 2853 assertEquals(2, test_rt_36353_selectedIndexCount); 2854 assertEquals("1", sortedList.get(0)); 2855 assertEquals("2", sortedList.get(1)); 2856 assertEquals("3", sortedList.get(2)); 2857 2858 tableColumn.setSortType(TableColumn.SortType.DESCENDING); 2859 assertEquals(1, test_rt_36353_selectedItemCount); 2860 assertEquals(3, test_rt_36353_selectedIndexCount); 2861 assertEquals("3", sortedList.get(0)); 2862 assertEquals("2", sortedList.get(1)); 2863 assertEquals("1", sortedList.get(2)); 2864 2865 tableView.getSortOrder().remove(tableColumn); 2866 assertEquals(1, test_rt_36353_selectedItemCount); 2867 assertEquals(4, test_rt_36353_selectedIndexCount); 2868 assertEquals("2", sortedList.get(0)); 2869 assertEquals("1", sortedList.get(1)); 2870 assertEquals("3", sortedList.get(2)); 2871 } 2872 2873 // This test ensures that we reuse column headers when the columns still 2874 // exist after a change to the columns list - rather than recreating new 2875 // column headers. The issue in RT-36290 was that we were creating new column 2876 // headers that were then in their initial states, allowing them to call 2877 // TableColumnHeader#updateScene(), which would resize the column based on the 2878 // data within it. 2879 @Test public void test_rt36290() { 2880 TableView<String> tableView = new TableView<>(); 2881 2882 TableColumn<String, String> tableColumn1 = new TableColumn<>(); 2883 tableColumn1.setCellValueFactory(data -> new SimpleStringProperty(data.getValue())); 2884 tableColumn1.setText("Test1"); 2885 2886 TableColumn<String, String> tableColumn2 = new TableColumn<>(); 2887 tableColumn2.setCellValueFactory(data -> new SimpleStringProperty(data.getValue())); 2888 tableColumn2.setText("Test2"); 2889 2890 tableView.getColumns().setAll(tableColumn1, tableColumn2); 2891 2892 StageLoader sl = new StageLoader(tableView); 2893 2894 final TableColumnHeader header1 = VirtualFlowTestUtils.getTableColumnHeader(tableView, tableColumn1); 2895 final TableColumnHeader header2 = VirtualFlowTestUtils.getTableColumnHeader(tableView, tableColumn2); 2896 2897 tableView.getColumns().setAll(tableColumn2, tableColumn1); 2898 Toolkit.getToolkit().firePulse(); 2899 2900 final TableColumnHeader header1_after = VirtualFlowTestUtils.getTableColumnHeader(tableView, tableColumn1); 2901 final TableColumnHeader header2_after = VirtualFlowTestUtils.getTableColumnHeader(tableView, tableColumn2); 2902 2903 assertEquals(header1, header1_after); 2904 assertEquals(header2, header2_after); 2905 2906 sl.dispose(); 2907 } 2908 2909 @Test public void test_rt25679_rowSelection() { 2910 test_rt25679(true); 2911 } 2912 2913 @Test public void test_rt25679_cellSelection() { 2914 test_rt25679(false); 2915 } 2916 2917 private void test_rt25679(boolean rowSelection) { 2918 Button focusBtn = new Button("Focus here"); 2919 2920 TableView<String> tableView = new TableView<>(FXCollections.observableArrayList("A", "B", "C")); 2921 2922 TableColumn<String, String> tableColumn = new TableColumn<>(); 2923 tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue())); 2924 tableView.getColumns().add(tableColumn); 2925 TableView.TableViewSelectionModel<String> sm = tableView.getSelectionModel(); 2926 sm.setCellSelectionEnabled(! rowSelection); 2927 2928 VBox vbox = new VBox(focusBtn, tableView); 2929 2930 StageLoader sl = new StageLoader(vbox); 2931 sl.getStage().requestFocus(); 2932 focusBtn.requestFocus(); 2933 Toolkit.getToolkit().firePulse(); 2934 2935 // test initial state 2936 assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn); 2937 assertTrue(focusBtn.isFocused()); 2938 assertEquals(-1, sm.getSelectedIndex()); 2939 assertNull(sm.getSelectedItem()); 2940 2941 // move focus to the tableView 2942 tableView.requestFocus(); 2943 2944 // ensure that there is a selection (where previously there was not one) 2945 assertEquals(sl.getStage().getScene().getFocusOwner(), tableView); 2946 assertTrue(tableView.isFocused()); 2947 2948 if (rowSelection) { 2949 assertEquals(0, sm.getSelectedIndices().size()); 2950 assertNull(sm.getSelectedItem()); 2951 assertFalse(sm.isSelected(0)); 2952 assertEquals(0, sm.getSelectedCells().size()); 2953 } else { 2954 assertFalse(sm.isSelected(0, tableColumn)); 2955 assertEquals(0, sm.getSelectedCells().size()); 2956 } 2957 2958 sl.dispose(); 2959 } 2960 2961 private int rt36556_instanceCount; 2962 @Test public void test_rt36556_scrollTo() { 2963 rt36556_instanceCount = 0; 2964 2965 TableView<String> tableView = new TableView<>(); 2966 tableView.setRowFactory(new Callback<TableView<String>, TableRow<String>>() { 2967 @Override public TableRow<String> call(TableView<String> param) { 2968 rt36556_instanceCount++; 2969 return new TableRow<>(); 2970 } 2971 }); 2972 2973 TableColumn<String, String> tableColumn = new TableColumn<>(); 2974 tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue())); 2975 2976 tableView.getColumns().add(tableColumn); 2977 2978 for (int i = 0; i < 1000; i++) { 2979 tableView.getItems().add("Row " + i); 2980 } 2981 2982 StackPane root = new StackPane(); 2983 root.getChildren().add(tableView); 2984 2985 StageLoader sl = new StageLoader(root); 2986 2987 final int cellCountAtStart = rt36556_instanceCount; 2988 2989 // start scrolling 2990 for (int i = 0; i < 1000; i++) { 2991 tableView.scrollTo(i); 2992 // Toolkit.getToolkit().firePulse(); 2993 } 2994 2995 assertEquals(cellCountAtStart, rt36556_instanceCount); 2996 sl.dispose(); 2997 } 2998 2999 @Test public void test_rt36556_mouseWheel() { 3000 rt36556_instanceCount = 0; 3001 3002 TableView<String> tableView = new TableView<>(); 3003 tableView.setRowFactory(new Callback<TableView<String>, TableRow<String>>() { 3004 @Override public TableRow<String> call(TableView<String> param) { 3005 rt36556_instanceCount++; 3006 return new TableRow<String>(); 3007 } 3008 }); 3009 3010 TableColumn<String, String> tableColumn = new TableColumn<>(); 3011 tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue())); 3012 tableView.getColumns().add(tableColumn); 3013 3014 for (int i = 0; i < 1000; i++) { 3015 tableView.getItems().add("Row " + i); 3016 } 3017 3018 StackPane root = new StackPane(); 3019 root.getChildren().add(tableView); 3020 3021 StageLoader sl = new StageLoader(root); 3022 3023 final int cellCountAtStart = rt36556_instanceCount; 3024 3025 // start scrolling - we call VirtualFlow.adjustPixels, which is what 3026 // is called when the mouse wheel is scrolled 3027 VirtualFlow flow = VirtualFlowTestUtils.getVirtualFlow(tableView); 3028 flow.adjustPixels(1000 * 24); 3029 3030 assertEquals(cellCountAtStart, rt36556_instanceCount); 3031 3032 sl.dispose(); 3033 } 3034 3035 @Test public void test_rt_36656_removeFromSortOrder() { 3036 test_rt_36656(true, false, false); 3037 } 3038 3039 @Test public void test_rt_36656_removeFromColumns() { 3040 test_rt_36656(false, true, false); 3041 } 3042 3043 @Test public void test_rt_36656_setInvisible() { 3044 test_rt_36656(false, false, true); 3045 } 3046 3047 private void test_rt_36656(boolean removeFromSortOrder, boolean removeFromColumns, boolean setInvisible) { 3048 TableView<Person> table = new TableView<Person>(); 3049 table.setItems(personTestData); 3050 3051 TableColumn firstNameCol = new TableColumn("First Name"); 3052 firstNameCol.setMinWidth(100); 3053 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 3054 3055 TableColumn lastNameCol = new TableColumn("Last Name"); 3056 lastNameCol.setMinWidth(100); 3057 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 3058 3059 TableColumn emailCol = new TableColumn("Email"); 3060 emailCol.setMinWidth(200); 3061 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 3062 3063 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 3064 3065 new StageLoader(table); 3066 3067 TableColumnHeader firstNameColHeader = VirtualFlowTestUtils.getTableColumnHeader(table, firstNameCol); 3068 TableColumnHeader lastNameColHeader = VirtualFlowTestUtils.getTableColumnHeader(table, lastNameCol); 3069 TableColumnHeader emailColHeader = VirtualFlowTestUtils.getTableColumnHeader(table, emailCol); 3070 3071 // test initial state 3072 assertEquals(-1, TableColumnHeaderRetriever.getSortPos(firstNameColHeader)); 3073 assertEquals(-1, TableColumnHeaderRetriever.getSortPos(lastNameColHeader)); 3074 assertEquals(-1, TableColumnHeaderRetriever.getSortPos(emailColHeader)); 3075 3076 // set an order including all columns 3077 table.getSortOrder().addAll(firstNameCol, lastNameCol, emailCol); 3078 assertEquals(0, TableColumnHeaderRetriever.getSortPos(firstNameColHeader)); 3079 assertEquals(1, TableColumnHeaderRetriever.getSortPos(lastNameColHeader)); 3080 assertEquals(2, TableColumnHeaderRetriever.getSortPos(emailColHeader)); 3081 3082 if (removeFromSortOrder) { 3083 // Remove lastNameCol from the table sortOrder list, so this column 3084 // is no longer part of the sort comparator 3085 table.getSortOrder().remove(lastNameCol); 3086 } else if (removeFromColumns) { 3087 // Remove lastNameCol from the table entirely. 3088 table.getColumns().remove(lastNameCol); 3089 } else if (setInvisible) { 3090 // Hide the lastNameColumn. 3091 lastNameCol.setVisible(false); 3092 } 3093 3094 // Regardless of action taken above, expect lastNameCol sortPos to be -1 3095 // and emailCol sortPos to shift from 2 to 1. 3096 assertEquals(0, TableColumnHeaderRetriever.getSortPos(firstNameColHeader)); 3097 assertEquals(-1, TableColumnHeaderRetriever.getSortPos(lastNameColHeader)); 3098 assertEquals(1, TableColumnHeaderRetriever.getSortPos(emailColHeader)); 3099 } 3100 3101 @Test public void test_rt_36670() { 3102 final ObservableList<Person> data = FXCollections.observableArrayList( 3103 new Person("Jacob", "Smith", "jacob.smith@example.com", true), 3104 new Person("Isabella", "Johnson", "isabella.johnson@example.com", false), 3105 new Person("Ethan", "Williams", "ethan.williams@example.com", true), 3106 new Person("Emma", "Jones", "emma.jones@example.com", true), 3107 new Person("Michael", "Brown", "michael.brown@example.com", false)); 3108 3109 TableColumn invitedCol = new TableColumn<>(); 3110 invitedCol.setText("Invited"); 3111 invitedCol.setMinWidth(70); 3112 invitedCol.setCellValueFactory(new PropertyValueFactory("invited")); 3113 invitedCol.setCellFactory(CheckBoxTableCell.forTableColumn(invitedCol)); 3114 3115 TableColumn firstNameCol = new TableColumn(); 3116 firstNameCol.setText("First"); 3117 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3118 3119 TableView tableView = new TableView(data); 3120 tableView.getColumns().addAll(invitedCol, firstNameCol); 3121 3122 StageLoader sl = new StageLoader(tableView); 3123 3124 // get the checkboxes 3125 CheckBox row0CheckBox = (CheckBox) VirtualFlowTestUtils.getCell(tableView, 0, 0).getGraphic(); 3126 CheckBox row1CheckBox = (CheckBox) VirtualFlowTestUtils.getCell(tableView, 1, 0).getGraphic(); 3127 CheckBox row2CheckBox = (CheckBox) VirtualFlowTestUtils.getCell(tableView, 2, 0).getGraphic(); 3128 CheckBox row3CheckBox = (CheckBox) VirtualFlowTestUtils.getCell(tableView, 3, 0).getGraphic(); 3129 CheckBox row4CheckBox = (CheckBox) VirtualFlowTestUtils.getCell(tableView, 4, 0).getGraphic(); 3130 3131 // check initial state of all checkboxes 3132 assertTrue(row0CheckBox.isSelected()); 3133 assertFalse(row1CheckBox.isSelected()); 3134 assertTrue(row2CheckBox.isSelected()); 3135 assertTrue(row3CheckBox.isSelected()); 3136 assertFalse(row4CheckBox.isSelected()); 3137 3138 // sort the table based on the invited column 3139 tableView.getSortOrder().add(invitedCol); 3140 Toolkit.getToolkit().firePulse(); 3141 3142 // The sort order has changed, with unselected items at the top and 3143 // selected items beneath them. 3144 assertFalse(row0CheckBox.isSelected()); 3145 assertFalse(row1CheckBox.isSelected()); 3146 assertTrue(row2CheckBox.isSelected()); 3147 assertTrue(row3CheckBox.isSelected()); 3148 assertTrue(row4CheckBox.isSelected()); 3149 3150 // now, select the 'Michael' row, which is row 1 3151 row1CheckBox.setSelected(true); 3152 Toolkit.getToolkit().firePulse(); 3153 3154 // only the Michael row should have changed state - but the bug 3155 // identified in RT-36670 shows that row 0 is also selected 3156 assertFalse(row0CheckBox.isSelected()); 3157 assertTrue(row1CheckBox.isSelected()); 3158 assertTrue(row2CheckBox.isSelected()); 3159 assertTrue(row3CheckBox.isSelected()); 3160 assertTrue(row4CheckBox.isSelected()); 3161 3162 sl.dispose(); 3163 } 3164 3165 @Test public void test_rt_36669() { 3166 TableView<Person> table = new TableView<>(personTestData); 3167 3168 TableColumn firstNameCol = new TableColumn("First Name"); 3169 firstNameCol.setMinWidth(100); 3170 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 3171 3172 TableColumn lastNameCol = new TableColumn("Last Name"); 3173 lastNameCol.setMinWidth(100); 3174 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 3175 3176 TableColumn emailCol = new TableColumn("Email"); 3177 emailCol.setMinWidth(200); 3178 emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 3179 3180 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 3181 table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); 3182 3183 StageLoader sl = new StageLoader(table); 3184 3185 ScrollBar vbar = VirtualFlowTestUtils.getVirtualFlowVerticalScrollbar(table); 3186 ScrollBar hbar = VirtualFlowTestUtils.getVirtualFlowHorizontalScrollbar(table); 3187 3188 // firstly test case where the TableView is tall enough to not need a vbar 3189 assertFalse(vbar.isVisible()); 3190 assertFalse(hbar.isVisible()); 3191 3192 // now make the table quite narrow and ensure that even if a vbar appears 3193 // that the hbar does not appear 3194 table.setMaxHeight(30); 3195 Toolkit.getToolkit().firePulse(); 3196 assertTrue(vbar.isVisible()); 3197 assertFalse(hbar.isVisible()); 3198 3199 sl.dispose(); 3200 } 3201 3202 private int rt_37061_index_counter = 0; 3203 private int rt_37061_item_counter = 0; 3204 @Test public void test_rt_37061() { 3205 TableView<Integer> tv = new TableView<>(); 3206 tv.getItems().add(1); 3207 tv.getSelectionModel().select(0); 3208 3209 // note we add the listeners after the selection is made, so the counters 3210 // at this point are still both at zero. 3211 tv.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> { 3212 rt_37061_index_counter++; 3213 }); 3214 3215 tv.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { 3216 rt_37061_item_counter++; 3217 }); 3218 3219 // add a new item. This does not impact the selected index or selected item 3220 // so the counters should remain at zero. 3221 tv.getItems().add(2); 3222 assertEquals(0, rt_37061_index_counter); 3223 assertEquals(0, rt_37061_item_counter); 3224 } 3225 3226 @Test public void test_rt_37058_noContent() { 3227 test_rt_37058(false); 3228 } 3229 3230 @Test public void test_rt_37058_withContent() { 3231 test_rt_37058(true); 3232 } 3233 3234 private void test_rt_37058(boolean hasContent) { 3235 // create table with a bunch of column and no rows... 3236 TableView<Integer> table = new TableView<>(); 3237 TableColumn<Integer, Integer> column = new TableColumn<>("Column"); 3238 table.getColumns().add(column); 3239 column.setPrefWidth(150); 3240 3241 if (hasContent) { 3242 table.getItems().add(1); 3243 } 3244 3245 StageLoader sl = new StageLoader(table); 3246 Toolkit.getToolkit().firePulse(); 3247 3248 assertEquals(150, column.getWidth(), 0.0); 3249 3250 sl.dispose(); 3251 } 3252 3253 @Test public void test_rt_37057_test1_MoveColumn() { 3254 // create table with a bunch of column and no rows... 3255 TableView<Integer> table = new TableView<>(); 3256 for ( int i = 1; i <= 10; i++ ) { 3257 TableColumn<Integer, Integer> column = new TableColumn<>("" + i); 3258 table.getColumns().add( column ); 3259 3260 // sneak some hidden columns in there 3261 column = new TableColumn<>("h" + i); 3262 column.setVisible( false ); 3263 table.getColumns().add( column ); 3264 } 3265 3266 StageLoader sl = new StageLoader(table); 3267 3268 TableColumn column1 = table.getVisibleLeafColumn(0); 3269 TableColumn column2 = table.getVisibleLeafColumn(1); 3270 3271 // get the headers of a few columns 3272 TableColumnHeader header1 = VirtualFlowTestUtils.getTableColumnHeader(table, column1); 3273 TableColumnHeader header2 = VirtualFlowTestUtils.getTableColumnHeader(table, column2); 3274 3275 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3276 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3277 3278 // move as per first instructions in RT-37057. Note that the moveColumn 3279 // positions seem counter-intuitive. I got these numbers by printing 3280 // the positions when in a manual test run (using the test script in 3281 // RT-37057). 3282 3283 // Drag column 1 to slot 1. As expected, the column position doesn't change. 3284 TableColumnHeaderRetriever.moveColumn(column1, 0); 3285 assertEquals(column1, table.getVisibleLeafColumn(0)); 3286 assertEquals(column2, table.getVisibleLeafColumn(1)); 3287 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3288 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3289 3290 // Drag column 1 to slot 2. As expected, the column 1 and 2 swap positions. 3291 TableColumnHeaderRetriever.moveColumn(column1, 1); 3292 assertEquals(column2, table.getVisibleLeafColumn(0)); 3293 assertEquals(column1, table.getVisibleLeafColumn(1)); 3294 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header1)); 3295 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header2)); 3296 3297 // Drag column 1 to slot 0. As expected, the column 1 and 2 swap positions. 3298 TableColumnHeaderRetriever.moveColumn(column1, 0); 3299 assertEquals(column1, table.getVisibleLeafColumn(0)); 3300 assertEquals(column2, table.getVisibleLeafColumn(1)); 3301 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3302 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3303 3304 // Drag column 1 to slot 1 again. What? Why did they swap positions this time? 3305 TableColumnHeaderRetriever.moveColumn(column1, 0); 3306 assertEquals(column1, table.getVisibleLeafColumn(0)); 3307 assertEquals(column2, table.getVisibleLeafColumn(1)); 3308 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3309 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3310 3311 sl.dispose(); 3312 } 3313 3314 @Test public void test_rt_37057_test1_MouseEvents() { 3315 // create table with a bunch of column and no rows... 3316 TableView<Integer> table = new TableView<>(); 3317 for ( int i = 1; i <= 10; i++ ) { 3318 TableColumn<Integer, Integer> column = new TableColumn<>("" + i); 3319 table.getColumns().add( column ); 3320 3321 // sneak some hidden columns in there 3322 column = new TableColumn<>("h" + i); 3323 column.setVisible( false ); 3324 column.impl_setWidth(50); 3325 column.setResizable(false); 3326 table.getColumns().add( column ); 3327 } 3328 3329 StageLoader sl = new StageLoader(table); 3330 3331 TableColumn column1 = table.getVisibleLeafColumn(0); 3332 TableColumn column2 = table.getVisibleLeafColumn(1); 3333 3334 // get the headers of a few columns 3335 TableColumnHeader header1 = VirtualFlowTestUtils.getTableColumnHeader(table, column1); 3336 TableColumnHeader header2 = VirtualFlowTestUtils.getTableColumnHeader(table, column2); 3337 3338 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3339 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3340 3341 // move as per first instructions in RT-37057. The dragOffset and sceneX 3342 // values passed into moveColumn have been derived from a manual run of 3343 // the test application attached to RT-37057 with debug output printed 3344 // in TableColumnHeader 3345 3346 // Drag column 1 to slot 1. As expected, the column position doesn't change. 3347 TableColumnHeaderRetriever.moveColumn(column1, 9, 61); 3348 assertEquals(column1, table.getVisibleLeafColumn(0)); 3349 assertEquals(column2, table.getVisibleLeafColumn(1)); 3350 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3351 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3352 3353 // Drag column 1 to slot 2. As expected, the column 1 and 2 swap positions. 3354 TableColumnHeaderRetriever.moveColumn(column1, 12, 139); 3355 assertEquals(column2, table.getVisibleLeafColumn(0)); 3356 assertEquals(column1, table.getVisibleLeafColumn(1)); 3357 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header1)); 3358 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header2)); 3359 3360 // Drag column 1 to slot 0. As expected, the column 1 and 2 swap positions. 3361 TableColumnHeaderRetriever.moveColumn(column1, 45, 21); 3362 assertEquals(column1, table.getVisibleLeafColumn(0)); 3363 assertEquals(column2, table.getVisibleLeafColumn(1)); 3364 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3365 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3366 3367 // Drag column 1 to slot 1 again. What? Why did they swap positions this time? 3368 TableColumnHeaderRetriever.moveColumn(column1, 19, 63); 3369 assertEquals(column1, table.getVisibleLeafColumn(0)); 3370 assertEquals(column2, table.getVisibleLeafColumn(1)); 3371 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3372 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3373 3374 sl.dispose(); 3375 } 3376 3377 @Test public void test_rt_37057_test2_MoveColumn() { 3378 // create table with a bunch of column and no rows... 3379 TableView<Integer> table = new TableView<>(); 3380 for ( int i = 1; i <= 10; i++ ) { 3381 TableColumn<Integer, Integer> column = new TableColumn<>("" + i); 3382 table.getColumns().add( column ); 3383 3384 // sneak some hidden columns in there 3385 column = new TableColumn<>("h" + i); 3386 column.setVisible( false ); 3387 table.getColumns().add( column ); 3388 } 3389 3390 StageLoader sl = new StageLoader(table); 3391 3392 TableColumn column1 = table.getVisibleLeafColumn(0); 3393 TableColumn column2 = table.getVisibleLeafColumn(1); 3394 TableColumn column4 = table.getVisibleLeafColumn(3); 3395 3396 // get the headers of a few columns 3397 TableColumnHeader header1 = VirtualFlowTestUtils.getTableColumnHeader(table, column1); 3398 TableColumnHeader header2 = VirtualFlowTestUtils.getTableColumnHeader(table, column2); 3399 TableColumnHeader header4 = VirtualFlowTestUtils.getTableColumnHeader(table, column4); 3400 3401 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3402 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3403 3404 // move as per second instructions in RT-37057. Note that the moveColumn 3405 // positions seem counter-intuitive. I got these numbers by printing 3406 // the positions when in a manual test run (using the test script in 3407 // RT-37057). 3408 3409 // Drag column 1 to slot 2. As expected, the column 1 and 2 swap positions 3410 TableColumnHeaderRetriever.moveColumn(column1, 1); 3411 assertEquals(column2, table.getVisibleLeafColumn(0)); 3412 assertEquals(column1, table.getVisibleLeafColumn(1)); 3413 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header1)); 3414 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header2)); 3415 3416 // Drag column 1 to slot 0. As expected, the column 1 and 2 swap positions. 3417 TableColumnHeaderRetriever.moveColumn(column1, 0); 3418 assertEquals(column1, table.getVisibleLeafColumn(0)); 3419 assertEquals(column2, table.getVisibleLeafColumn(1)); 3420 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3421 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3422 3423 // Drag column 4 to slot 1. What? It behaves like it was dragged to slot 0?! 3424 TableColumnHeaderRetriever.moveColumn(column4, 1); 3425 assertEquals(column1, table.getVisibleLeafColumn(0)); 3426 assertEquals(column4, table.getVisibleLeafColumn(1)); 3427 assertEquals(column2, table.getVisibleLeafColumn(2)); 3428 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3429 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header4)); 3430 assertEquals(2, TableColumnHeaderRetriever.getColumnIndex(header2)); 3431 3432 sl.dispose(); 3433 } 3434 3435 @Test public void test_rt_37057_test2_MouseEvents() { 3436 // create table with a bunch of column and no rows... 3437 TableView<Integer> table = new TableView<>(); 3438 for ( int i = 1; i <= 10; i++ ) { 3439 TableColumn<Integer, Integer> column = new TableColumn<>("" + i); 3440 table.getColumns().add( column ); 3441 3442 // sneak some hidden columns in there 3443 column = new TableColumn<>("h" + i); 3444 column.setVisible( false ); 3445 column.impl_setWidth(50); 3446 column.setResizable(false); 3447 table.getColumns().add( column ); 3448 } 3449 3450 StageLoader sl = new StageLoader(table); 3451 3452 TableColumn column1 = table.getVisibleLeafColumn(0); 3453 TableColumn column2 = table.getVisibleLeafColumn(1); 3454 TableColumn column4 = table.getVisibleLeafColumn(3); 3455 3456 // get the headers of a few columns 3457 TableColumnHeader header1 = VirtualFlowTestUtils.getTableColumnHeader(table, column1); 3458 TableColumnHeader header2 = VirtualFlowTestUtils.getTableColumnHeader(table, column2); 3459 TableColumnHeader header4 = VirtualFlowTestUtils.getTableColumnHeader(table, column4); 3460 3461 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3462 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3463 3464 // move as per second instructions in RT-37057. The dragOffset and sceneX 3465 // values passed into moveColumn have been derived from a manual run of 3466 // the test application attached to RT-37057 with debug output printed 3467 // in TableColumnHeader 3468 3469 // Drag column 1 to slot 2. As expected, the column 1 and 2 swap positions 3470 TableColumnHeaderRetriever.moveColumn(column1, 25, 136); 3471 assertEquals(column2, table.getVisibleLeafColumn(0)); 3472 assertEquals(column1, table.getVisibleLeafColumn(1)); 3473 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header1)); 3474 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header2)); 3475 3476 // Drag column 1 to slot 0. As expected, the column 1 and 2 swap positions. 3477 TableColumnHeaderRetriever.moveColumn(column1, 51, 23); 3478 assertEquals(column1, table.getVisibleLeafColumn(0)); 3479 assertEquals(column2, table.getVisibleLeafColumn(1)); 3480 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3481 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header2)); 3482 3483 // Drag column 4 to slot 1. What? It behaves like it was dragged to slot 0?! 3484 TableColumnHeaderRetriever.moveColumn(column4, 56, 103); 3485 assertEquals(column1, table.getVisibleLeafColumn(0)); 3486 assertEquals(column4, table.getVisibleLeafColumn(1)); 3487 assertEquals(column2, table.getVisibleLeafColumn(2)); 3488 assertEquals(0, TableColumnHeaderRetriever.getColumnIndex(header1)); 3489 assertEquals(1, TableColumnHeaderRetriever.getColumnIndex(header4)); 3490 assertEquals(2, TableColumnHeaderRetriever.getColumnIndex(header2)); 3491 3492 sl.dispose(); 3493 } 3494 3495 @Test public void test_rt_37054_noScroll() { 3496 test_rt_37054(false); 3497 } 3498 3499 @Test public void test_rt_37054_scroll() { 3500 test_rt_37054(true); 3501 } 3502 3503 private void test_rt_37054(boolean scroll) { 3504 ObjectProperty<Integer> offset = new SimpleObjectProperty<Integer>(0); 3505 3506 // create table with a bunch of rows and 1 column... 3507 TableView<Integer> table = new TableView<>(); 3508 for ( int i = 1; i <= 50; i++ ) { 3509 table.getItems().add(i); 3510 } 3511 final TableColumn<Integer, Integer> column = new TableColumn<>("Column"); 3512 table.getColumns().add( column ); 3513 column.setPrefWidth( 150 ); 3514 3515 // each cell displays x, where x = "cell row number + offset" 3516 column.setCellValueFactory( cdf -> new ObjectBinding<Integer>() { 3517 { super.bind( offset ); } 3518 3519 @Override protected Integer computeValue() { 3520 return cdf.getValue() + offset.get(); 3521 } 3522 }); 3523 3524 StackPane root = new StackPane(); 3525 root.getChildren().add( table ); 3526 3527 StageLoader sl = new StageLoader(root); 3528 3529 int index = scroll ? 0 : 25; 3530 3531 if (scroll) { 3532 // we scroll to force the table cells to update the objects they observe 3533 table.scrollTo(index); 3534 Toolkit.getToolkit().firePulse(); 3535 } 3536 3537 TableCell cell = (TableCell) VirtualFlowTestUtils.getCell(table, index + 3, 0); 3538 final int initialValue = (Integer) cell.getItem(); 3539 3540 // increment the offset value 3541 offset.setValue(offset.get() + 1); 3542 Toolkit.getToolkit().firePulse(); 3543 3544 final int incrementedValue = (Integer) cell.getItem(); 3545 assertEquals(initialValue + 1, incrementedValue); 3546 3547 sl.dispose(); 3548 } 3549 3550 @Test public void test_rt_37429() { 3551 // get the current exception handler before replacing with our own, 3552 // as ListListenerHelp intercepts the exception otherwise 3553 final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler(); 3554 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!")); 3555 3556 // table columns - 1 column; name 3557 TableColumn<String, String> nameColumn = new TableColumn<>("name"); 3558 nameColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper(param.getValue())); 3559 nameColumn.setPrefWidth(200); 3560 3561 // table 3562 TableView<String> table = new TableView<>(); 3563 table.setItems(FXCollections.observableArrayList("one", "two", "three", "four", "five")); 3564 table.getColumns().addAll(nameColumn); 3565 3566 table.getSelectionModel().getSelectedItems().addListener((ListChangeListener<String>) c -> { 3567 while (c.next()) { 3568 if(c.wasRemoved()) { 3569 // The removed list of items must be iterated or the AIOOBE will 3570 // not be thrown when getAddedSubList is called. 3571 c.getRemoved().forEach(item -> {}); 3572 } 3573 3574 if (c.wasAdded()) { 3575 c.getAddedSubList(); 3576 } 3577 } 3578 }); 3579 3580 StageLoader sl = new StageLoader(table); 3581 3582 table.getSelectionModel().select(0); 3583 table.getSortOrder().add(nameColumn); 3584 3585 sl.dispose(); 3586 3587 // reset the exception handler 3588 Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler); 3589 } 3590 3591 private int rt_37429_items_change_count = 0; 3592 private int rt_37429_cells_change_count = 0; 3593 @Test public void test_rt_37429_sortEventsShouldNotFireExtraChangeEvents() { 3594 // table columns - 1 column; name 3595 TableColumn<String, String> nameColumn = new TableColumn<>("name"); 3596 nameColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper(param.getValue())); 3597 nameColumn.setPrefWidth(200); 3598 3599 // table 3600 TableView<String> table = new TableView<>(); 3601 table.setItems(FXCollections.observableArrayList("a", "c", "b")); 3602 table.getColumns().addAll(nameColumn); 3603 3604 table.getSelectionModel().getSelectedItems().addListener((ListChangeListener<String>) c -> { 3605 while (c.next()) { 3606 rt_37429_items_change_count++; 3607 } 3608 }); 3609 table.getSelectionModel().getSelectedCells().addListener((ListChangeListener<TablePosition>) c -> { 3610 while (c.next()) { 3611 rt_37429_cells_change_count++; 3612 } 3613 }); 3614 3615 StageLoader sl = new StageLoader(table); 3616 3617 assertEquals(0, rt_37429_items_change_count); 3618 assertEquals(0, rt_37429_cells_change_count); 3619 3620 table.getSelectionModel().select(0); 3621 assertEquals(1, rt_37429_items_change_count); 3622 assertEquals(1, rt_37429_cells_change_count); 3623 3624 table.getSortOrder().add(nameColumn); 3625 assertEquals(1, rt_37429_items_change_count); 3626 assertEquals(1, rt_37429_cells_change_count); 3627 3628 nameColumn.setSortType(TableColumn.SortType.DESCENDING); 3629 assertEquals(1, rt_37429_items_change_count); 3630 assertEquals(2, rt_37429_cells_change_count); 3631 3632 nameColumn.setSortType(TableColumn.SortType.ASCENDING); 3633 assertEquals(1, rt_37429_items_change_count); 3634 assertEquals(3, rt_37429_cells_change_count); 3635 3636 sl.dispose(); 3637 } 3638 3639 private int rt_37538_count = 0; 3640 @Test public void test_rt_37538_noCNextCall() { 3641 test_rt_37538(false, false); 3642 } 3643 3644 @Test public void test_rt_37538_callCNextOnce() { 3645 test_rt_37538(true, false); 3646 } 3647 3648 @Test public void test_rt_37538_callCNextInLoop() { 3649 test_rt_37538(false, true); 3650 } 3651 3652 private void test_rt_37538(boolean callCNextOnce, boolean callCNextInLoop) { 3653 TableView<Integer> table = new TableView<>(); 3654 for ( int i = 1; i <= 50; i++ ) { 3655 table.getItems().add(i); 3656 } 3657 final TableColumn<Integer, Integer> column = new TableColumn<>("Column"); 3658 table.getColumns().add(column); 3659 column.setCellValueFactory( cdf -> new ReadOnlyObjectWrapper<Integer>(cdf.getValue())); 3660 3661 table.getSelectionModel().getSelectedItems().addListener((ListChangeListener.Change<? extends Integer> c) -> { 3662 if (callCNextOnce) { 3663 c.next(); 3664 } else if (callCNextInLoop) { 3665 while (c.next()) { 3666 // no-op 3667 } 3668 } 3669 3670 if (rt_37538_count >= 1) { 3671 Thread.dumpStack(); 3672 fail("This method should only be called once"); 3673 } 3674 3675 rt_37538_count++; 3676 }); 3677 3678 StageLoader sl = new StageLoader(table); 3679 assertEquals(0, rt_37538_count); 3680 table.getSelectionModel().select(0); 3681 assertEquals(1, rt_37538_count); 3682 sl.dispose(); 3683 } 3684 3685 @Ignore("Fix not yet developed for TableView") 3686 @Test public void test_rt_35395_testCell_fixedCellSize() { 3687 test_rt_35395(true, true); 3688 } 3689 3690 @Ignore("Fix not yet developed for TableView") 3691 @Test public void test_rt_35395_testCell_notFixedCellSize() { 3692 test_rt_35395(true, false); 3693 } 3694 3695 @Ignore("Fix not yet developed for TableView") 3696 @Test public void test_rt_35395_testRow_fixedCellSize() { 3697 test_rt_35395(false, true); 3698 } 3699 3700 @Ignore("Fix not yet developed for TableView") 3701 @Test public void test_rt_35395_testRow_notFixedCellSize() { 3702 test_rt_35395(false, false); 3703 } 3704 3705 private int rt_35395_counter; 3706 private void test_rt_35395(boolean testCell, boolean useFixedCellSize) { 3707 rt_35395_counter = 0; 3708 3709 ObservableList<String> items = FXCollections.observableArrayList(); 3710 for (int i = 0; i < 20; ++i) { 3711 items.addAll("red", "green", "blue", "purple"); 3712 } 3713 3714 TableView<String> tableView = new TableView<>(items); 3715 if (useFixedCellSize) { 3716 tableView.setFixedCellSize(24); 3717 } 3718 tableView.setRowFactory(tv -> new TableRow<String>() { 3719 @Override protected void updateItem(String color, boolean empty) { 3720 rt_35395_counter += testCell ? 0 : 1; 3721 super.updateItem(color, empty); 3722 } 3723 }); 3724 3725 TableColumn<String,String> column = new TableColumn<>("Column"); 3726 column.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue())); 3727 column.setCellFactory(tv -> new TableCell<String,String>() { 3728 @Override protected void updateItem(String color, boolean empty) { 3729 rt_35395_counter += testCell ? 1 : 0; 3730 super.updateItem(color, empty); 3731 setText(null); 3732 if (empty) { 3733 setGraphic(null); 3734 } else { 3735 Rectangle rect = new Rectangle(16, 16); 3736 rect.setStyle("-fx-fill: " + color); 3737 setGraphic(rect); 3738 } 3739 } 3740 }); 3741 tableView.getColumns().addAll(column); 3742 3743 StageLoader sl = new StageLoader(tableView); 3744 3745 Platform.runLater(() -> { 3746 rt_35395_counter = 0; 3747 items.set(10, "yellow"); 3748 Platform.runLater(() -> { 3749 Toolkit.getToolkit().firePulse(); 3750 assertEquals(1, rt_35395_counter); 3751 rt_35395_counter = 0; 3752 items.set(30, "yellow"); 3753 Platform.runLater(() -> { 3754 Toolkit.getToolkit().firePulse(); 3755 assertEquals(0, rt_35395_counter); 3756 rt_35395_counter = 0; 3757 tableView.scrollTo(5); 3758 Platform.runLater(() -> { 3759 Toolkit.getToolkit().firePulse(); 3760 assertEquals(5, rt_35395_counter); 3761 rt_35395_counter = 0; 3762 tableView.scrollTo(55); 3763 Platform.runLater(() -> { 3764 Toolkit.getToolkit().firePulse(); 3765 3766 int expected = useFixedCellSize ? 17 : 53; 3767 assertEquals(expected, rt_35395_counter); 3768 sl.dispose(); 3769 }); 3770 }); 3771 }); 3772 }); 3773 }); 3774 } 3775 3776 @Test public void test_rt_37632() { 3777 final ObservableList<String> listOne = FXCollections.observableArrayList("A", "B", "C"); 3778 final ObservableList<String> listTwo = FXCollections.observableArrayList("C"); 3779 3780 TableColumn<String,String> tableColumn = new TableColumn("column"); 3781 tableColumn.setCellValueFactory(c -> new ReadOnlyStringWrapper(c.getValue())); 3782 3783 final TableView<String> tableView = new TableView<>(); 3784 tableView.getColumns().add(tableColumn); 3785 MultipleSelectionModel<String> sm = tableView.getSelectionModel(); 3786 tableView.setItems(listOne); 3787 tableView.getSelectionModel().selectFirst(); 3788 3789 assertEquals(0, sm.getSelectedIndex()); 3790 assertEquals("A", sm.getSelectedItem()); 3791 assertEquals(1, sm.getSelectedIndices().size()); 3792 assertEquals(0, (int) sm.getSelectedIndices().get(0)); 3793 assertEquals(1, sm.getSelectedItems().size()); 3794 assertEquals("A", sm.getSelectedItems().get(0)); 3795 3796 tableView.setItems(listTwo); 3797 3798 assertEquals(-1, sm.getSelectedIndex()); 3799 assertNull(sm.getSelectedItem()); 3800 assertEquals(0, sm.getSelectedIndices().size()); 3801 assertEquals(0, sm.getSelectedItems().size()); 3802 } 3803 3804 @Test public void test_rt_38464_rowSelection_selectFirstRowOnly() { 3805 TableColumn firstNameCol = new TableColumn("First"); 3806 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3807 3808 TableColumn lastNameCol = new TableColumn("Last"); 3809 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3810 3811 TableView tableView = new TableView(personTestData); 3812 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3813 3814 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3815 sm.setCellSelectionEnabled(false); 3816 sm.setSelectionMode(SelectionMode.MULTIPLE); 3817 3818 sm.select(0); 3819 3820 assertTrue(sm.isSelected(0)); 3821 assertTrue(sm.isSelected(0, firstNameCol)); 3822 assertTrue(sm.isSelected(0, lastNameCol)); 3823 3824 assertEquals(1, sm.getSelectedIndices().size()); 3825 assertEquals(1, sm.getSelectedItems().size()); 3826 assertEquals(1, sm.getSelectedCells().size()); 3827 } 3828 3829 @Test public void test_rt_38464_rowSelection_selectFirstRowAndThenCallNoOpMethods() { 3830 TableColumn firstNameCol = new TableColumn("First"); 3831 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3832 3833 TableColumn lastNameCol = new TableColumn("Last"); 3834 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3835 3836 TableView tableView = new TableView(personTestData); 3837 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3838 3839 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3840 sm.setCellSelectionEnabled(false); 3841 sm.setSelectionMode(SelectionMode.MULTIPLE); 3842 3843 sm.select(0); // select first row 3844 sm.select(0); // this should be a no-op 3845 sm.select(0, firstNameCol); // so should this, as we are in row selection mode 3846 sm.select(0, lastNameCol); // and same here 3847 3848 assertTrue(sm.isSelected(0)); 3849 assertTrue(sm.isSelected(0, firstNameCol)); 3850 assertTrue(sm.isSelected(0, lastNameCol)); 3851 3852 assertEquals(1, sm.getSelectedIndices().size()); 3853 assertEquals(1, sm.getSelectedItems().size()); 3854 assertEquals(1, sm.getSelectedCells().size()); 3855 } 3856 3857 3858 @Test public void test_rt_38464_cellSelection_selectFirstRowOnly() { 3859 TableColumn firstNameCol = new TableColumn("First"); 3860 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3861 3862 TableColumn lastNameCol = new TableColumn("Last"); 3863 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3864 3865 TableView tableView = new TableView(personTestData); 3866 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3867 3868 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3869 sm.setCellSelectionEnabled(true); 3870 sm.setSelectionMode(SelectionMode.MULTIPLE); 3871 3872 // select first row. This should be translated into selection of all 3873 // cells in this row, but does not result in the row itself being 3874 // considered selected. 3875 sm.select(0); 3876 3877 assertFalse(sm.isSelected(0)); 3878 assertTrue(sm.isSelected(0, firstNameCol)); 3879 assertTrue(sm.isSelected(0, lastNameCol)); 3880 3881 assertEquals(1, sm.getSelectedIndices().size()); 3882 assertEquals(1, sm.getSelectedItems().size()); 3883 assertEquals(2, sm.getSelectedCells().size()); 3884 } 3885 3886 @Test public void test_rt_38464_cellSelection_selectFirstRowAndThenCallNoOpMethods() { 3887 TableColumn firstNameCol = new TableColumn("First"); 3888 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3889 3890 TableColumn lastNameCol = new TableColumn("Last"); 3891 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3892 3893 TableView tableView = new TableView(personTestData); 3894 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3895 3896 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3897 sm.setCellSelectionEnabled(true); 3898 sm.setSelectionMode(SelectionMode.MULTIPLE); 3899 3900 // select first row. This should be translated into selection of all 3901 // cells in this row, but does not result in the row itself being 3902 // considered selected. 3903 sm.select(0); // select first row 3904 sm.select(0, firstNameCol); // This line and the next should be no-ops 3905 sm.select(0, lastNameCol); 3906 3907 assertFalse(sm.isSelected(0)); 3908 assertTrue(sm.isSelected(0, firstNameCol)); 3909 assertTrue(sm.isSelected(0, lastNameCol)); 3910 3911 assertEquals(1, sm.getSelectedIndices().size()); 3912 assertEquals(1, sm.getSelectedItems().size()); 3913 assertEquals(2, sm.getSelectedCells().size()); 3914 } 3915 3916 @Test public void test_rt38464_selectCellMultipleTimes() { 3917 TableColumn firstNameCol = new TableColumn("First"); 3918 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3919 3920 TableColumn lastNameCol = new TableColumn("Last"); 3921 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3922 3923 TableView tableView = new TableView(personTestData); 3924 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3925 3926 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3927 sm.setCellSelectionEnabled(true); 3928 sm.setSelectionMode(SelectionMode.MULTIPLE); 3929 3930 // default selection when in cell selection mode 3931 assertEquals(0, sm.getSelectedCells().size()); 3932 assertEquals(0, sm.getSelectedItems().size()); 3933 assertEquals(0, sm.getSelectedIndices().size()); 3934 3935 // select the first cell 3936 sm.select(0, firstNameCol); 3937 assertEquals(1, sm.getSelectedCells().size()); 3938 assertEquals(1, sm.getSelectedItems().size()); 3939 assertEquals(1, sm.getSelectedIndices().size()); 3940 3941 // select the first cell....again 3942 sm.select(0, firstNameCol); 3943 assertEquals(1, sm.getSelectedCells().size()); 3944 assertEquals(1, sm.getSelectedItems().size()); 3945 assertEquals(1, sm.getSelectedIndices().size()); 3946 } 3947 3948 @Test public void test_rt38464_selectCellThenRow() { 3949 TableColumn firstNameCol = new TableColumn("First"); 3950 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3951 3952 TableColumn lastNameCol = new TableColumn("Last"); 3953 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3954 3955 TableView tableView = new TableView(personTestData); 3956 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3957 3958 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3959 sm.setCellSelectionEnabled(true); 3960 sm.setSelectionMode(SelectionMode.MULTIPLE); 3961 3962 // default selection when in cell selection mode 3963 assertEquals(0, sm.getSelectedCells().size()); 3964 assertEquals(0, sm.getSelectedItems().size()); 3965 assertEquals(0, sm.getSelectedIndices().size()); 3966 3967 // select the first cell 3968 sm.select(0, firstNameCol); 3969 assertEquals(1, sm.getSelectedCells().size()); 3970 assertEquals(1, sm.getSelectedItems().size()); 3971 assertEquals(1, sm.getSelectedIndices().size()); 3972 3973 // select the first row 3974 sm.select(0); 3975 3976 // we go to 2 here as all cells in the row become selected. What we do 3977 // not expect is to go to 3, as that would mean duplication 3978 assertEquals(2, sm.getSelectedCells().size()); 3979 assertEquals(1, sm.getSelectedItems().size()); 3980 assertEquals(1, sm.getSelectedIndices().size()); 3981 } 3982 3983 @Test public void test_rt38464_selectRowThenCell() { 3984 TableColumn firstNameCol = new TableColumn("First"); 3985 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 3986 3987 TableColumn lastNameCol = new TableColumn("Last"); 3988 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 3989 3990 TableView tableView = new TableView(personTestData); 3991 tableView.getColumns().addAll(firstNameCol, lastNameCol); 3992 3993 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 3994 sm.setCellSelectionEnabled(true); 3995 sm.setSelectionMode(SelectionMode.MULTIPLE); 3996 3997 // default selection when in cell selection mode 3998 assertEquals(0, sm.getSelectedCells().size()); 3999 assertEquals(0, sm.getSelectedItems().size()); 4000 assertEquals(0, sm.getSelectedIndices().size()); 4001 4002 // select the first row 4003 sm.select(0); 4004 4005 // we go to 2 here as all cells in the row become selected. 4006 assertEquals(2, sm.getSelectedCells().size()); 4007 assertEquals(1, sm.getSelectedItems().size()); 4008 assertEquals(1, sm.getSelectedIndices().size()); 4009 4010 // select the first cell - no change is expected 4011 sm.select(0, firstNameCol); 4012 assertEquals(2, sm.getSelectedCells().size()); 4013 assertEquals(1, sm.getSelectedItems().size()); 4014 assertEquals(1, sm.getSelectedIndices().size()); 4015 } 4016 4017 @Test public void test_rt38464_selectTests_cellSelection_singleSelection_selectsOneRow() { 4018 test_rt38464_selectTests(true, true, true); 4019 } 4020 4021 @Test public void test_rt38464_selectTests_cellSelection_singleSelection_selectsTwoRows() { 4022 test_rt38464_selectTests(true, true, false); 4023 } 4024 4025 @Test public void test_rt38464_selectTests_cellSelection_multipleSelection_selectsOneRow() { 4026 test_rt38464_selectTests(true, false, true); 4027 } 4028 4029 @Test public void test_rt38464_selectTests_cellSelection_multipleSelection_selectsTwoRows() { 4030 test_rt38464_selectTests(true, false, false); 4031 } 4032 4033 @Test public void test_rt38464_selectTests_rowSelection_singleSelection_selectsOneRow() { 4034 test_rt38464_selectTests(false, true, true); 4035 } 4036 4037 @Test public void test_rt38464_selectTests_rowSelection_singleSelection_selectsTwoRows() { 4038 test_rt38464_selectTests(false, true, false); 4039 } 4040 4041 @Test public void test_rt38464_selectTests_rowSelection_multipleSelection_selectsOneRow() { 4042 test_rt38464_selectTests(false, false, true); 4043 } 4044 4045 @Test public void test_rt38464_selectTests_rowSelection_multipleSelection_selectsTwoRows() { 4046 test_rt38464_selectTests(false, false, false); 4047 } 4048 4049 private void test_rt38464_selectTests(boolean cellSelection, boolean singleSelection, boolean selectsOneRow) { 4050 TableColumn firstNameCol = new TableColumn("First"); 4051 firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName")); 4052 4053 TableColumn lastNameCol = new TableColumn("Last"); 4054 lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName")); 4055 4056 TableView tableView = new TableView(personTestData); 4057 tableView.getColumns().addAll(firstNameCol, lastNameCol); 4058 4059 TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel(); 4060 sm.setCellSelectionEnabled(cellSelection); 4061 sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE); 4062 4063 // default selection when in cell selection mode 4064 assertEquals(0, sm.getSelectedCells().size()); 4065 assertEquals(0, sm.getSelectedItems().size()); 4066 assertEquals(0, sm.getSelectedIndices().size()); 4067 4068 if (selectsOneRow) { 4069 sm.select(0); 4070 } else { 4071 // select the first two rows 4072 sm.selectIndices(0, 1); 4073 } 4074 4075 final int expectedCells = singleSelection ? 1 : 4076 selectsOneRow && cellSelection ? 2 : 4077 selectsOneRow && !cellSelection ? 1 : 4078 !selectsOneRow && cellSelection ? 4 : 4079 /* !selectsOneRow && !cellSelection */ 2; 4080 4081 final int expectedItems = singleSelection ? 1 : 4082 selectsOneRow ? 1 : 2; 4083 4084 assertEquals(expectedCells, sm.getSelectedCells().size()); 4085 assertEquals(expectedItems, sm.getSelectedItems().size()); 4086 assertEquals(expectedItems, sm.getSelectedIndices().size()); 4087 4088 // we expect the table column of all selected cells, in this instance, 4089 // to be null as we have not explicitly stated a column, nor have we clicked 4090 // on a column. The only alternative is to use the first column. 4091 for (TablePosition<?,?> tp : sm.getSelectedCells()) { 4092 if (cellSelection) { 4093 assertNotNull(tp.getTableColumn()); 4094 } else { 4095 assertNull(tp.getTableColumn()); 4096 } 4097 } 4098 } 4099 4100 private int rt_37853_cancelCount; 4101 private int rt_37853_commitCount; 4102 @Test public void test_rt_37853() { 4103 TableColumn<String,String> first = new TableColumn<>("first"); 4104 first.setEditable(true); 4105 first.setCellFactory(TextFieldTableCell.forTableColumn()); 4106 table.getColumns().add(first); 4107 table.setEditable(true); 4108 4109 for (int i = 0; i < 10; i++) { 4110 table.getItems().add("" + i); 4111 } 4112 4113 StageLoader sl = new StageLoader(table); 4114 4115 first.setOnEditCancel(editEvent -> rt_37853_cancelCount++); 4116 first.setOnEditCommit(editEvent -> rt_37853_commitCount++); 4117 4118 assertEquals(0, rt_37853_cancelCount); 4119 assertEquals(0, rt_37853_commitCount); 4120 4121 table.edit(1, first); 4122 assertNotNull(table.getEditingCell()); 4123 4124 table.getItems().clear(); 4125 assertEquals(1, rt_37853_cancelCount); 4126 assertEquals(0, rt_37853_commitCount); 4127 4128 sl.dispose(); 4129 } 4130 4131 4132 /************************************************************************** 4133 * 4134 * Tests (and related code) for RT-38892 4135 * 4136 *************************************************************************/ 4137 4138 private final Supplier<TableColumn<Person,String>> columnCallable = () -> { 4139 TableColumn<Person,String> column = new TableColumn<>("Last Name"); 4140 column.setCellValueFactory(new PropertyValueFactory<Person,String>("lastName")); 4141 return column; 4142 }; 4143 4144 private TableColumn<Person, String> test_rt_38892_firstNameCol; 4145 private TableColumn<Person, String> test_rt_38892_lastNameCol; 4146 4147 private TableView<Person> init_test_rt_38892() { 4148 ObservableList<Person> data = FXCollections.observableArrayList( 4149 new Person("Jacob", "Smith", ""), 4150 new Person("Isabella", "Johnson", ""), 4151 new Person("Ethan", "Williams", ""), 4152 new Person("Emma", "Jones", ""), 4153 new Person("Michael", "Brown", "") 4154 ); 4155 4156 TableView<Person> table = new TableView<>(); 4157 table.getSelectionModel().setCellSelectionEnabled(true); 4158 table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 4159 table.setItems(data); 4160 4161 test_rt_38892_firstNameCol = new TableColumn<>("First Name"); 4162 test_rt_38892_firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName")); 4163 test_rt_38892_lastNameCol = columnCallable.get(); 4164 table.getColumns().addAll(test_rt_38892_firstNameCol, test_rt_38892_lastNameCol); 4165 4166 return table; 4167 } 4168 4169 @Test public void test_rt_38892_focusMovesToLeftWhenPossible() { 4170 TableView<Person> table = init_test_rt_38892(); 4171 4172 TableView.TableViewFocusModel<Person> fm = table.getFocusModel(); 4173 fm.focus(0, test_rt_38892_lastNameCol); 4174 4175 // assert pre-conditions 4176 assertEquals(0, fm.getFocusedIndex()); 4177 assertEquals(0, fm.getFocusedCell().getRow()); 4178 assertEquals(test_rt_38892_lastNameCol, fm.getFocusedCell().getTableColumn()); 4179 assertEquals(1, fm.getFocusedCell().getColumn()); 4180 4181 // now remove column where focus is and replace it with a new column. 4182 // We expect focus to move to the left one cell. 4183 table.getColumns().remove(1); 4184 table.getColumns().add(columnCallable.get()); 4185 4186 assertEquals(0, fm.getFocusedIndex()); 4187 assertEquals(0, fm.getFocusedCell().getRow()); 4188 assertEquals(test_rt_38892_firstNameCol, fm.getFocusedCell().getTableColumn()); 4189 assertEquals(0, fm.getFocusedCell().getColumn()); 4190 } 4191 4192 @Test public void test_rt_38892_removeLeftMostColumn() { 4193 TableView<Person> table = init_test_rt_38892(); 4194 4195 TableView.TableViewFocusModel<Person> fm = table.getFocusModel(); 4196 fm.focus(0, test_rt_38892_firstNameCol); 4197 4198 // assert pre-conditions 4199 assertEquals(0, fm.getFocusedIndex()); 4200 assertEquals(0, fm.getFocusedCell().getRow()); 4201 assertEquals(test_rt_38892_firstNameCol, fm.getFocusedCell().getTableColumn()); 4202 assertEquals(0, fm.getFocusedCell().getColumn()); 4203 4204 // now remove column where focus is and replace it with a new column. 4205 // In the current (non-specified) behavior, this results in focus being 4206 // shifted to a cell in the remaining column, even when we add a new column 4207 // as we index based on the column, not on its index. 4208 table.getColumns().remove(0); 4209 TableColumn<Person,String> newColumn = columnCallable.get(); 4210 table.getColumns().add(0, newColumn); 4211 4212 assertEquals(0, fm.getFocusedIndex()); 4213 assertEquals(0, fm.getFocusedCell().getRow()); 4214 assertEquals(test_rt_38892_lastNameCol, fm.getFocusedCell().getTableColumn()); 4215 assertEquals(1, fm.getFocusedCell().getColumn()); 4216 } 4217 4218 @Test public void test_rt_38892_removeSelectionFromCellsInRemovedColumn() { 4219 TableView<Person> table = init_test_rt_38892(); 4220 4221 TableView.TableViewSelectionModel sm = table.getSelectionModel(); 4222 sm.select(0, test_rt_38892_firstNameCol); 4223 sm.select(1, test_rt_38892_lastNameCol); // this should go 4224 sm.select(2, test_rt_38892_firstNameCol); 4225 sm.select(3, test_rt_38892_lastNameCol); // so should this 4226 sm.select(4, test_rt_38892_firstNameCol); 4227 4228 assertEquals(5, sm.getSelectedCells().size()); 4229 4230 table.getColumns().remove(1); 4231 4232 assertEquals(3, sm.getSelectedCells().size()); 4233 assertTrue(sm.isSelected(0, test_rt_38892_firstNameCol)); 4234 assertFalse(sm.isSelected(1, test_rt_38892_lastNameCol)); 4235 assertTrue(sm.isSelected(2, test_rt_38892_firstNameCol)); 4236 assertFalse(sm.isSelected(3, test_rt_38892_lastNameCol)); 4237 assertTrue(sm.isSelected(4, test_rt_38892_firstNameCol)); 4238 } 4239 4240 @Test public void test_rt_38787_remove_b() { 4241 // selection moves to "a" 4242 test_rt_38787("a", 0, "b"); 4243 } 4244 4245 @Test public void test_rt_38787_remove_b_c() { 4246 // selection moves to "a" 4247 test_rt_38787("a", 0, "b", "c"); 4248 } 4249 4250 @Test public void test_rt_38787_remove_c_d() { 4251 // selection stays on "b" 4252 test_rt_38787("b", 1, "c", "d"); 4253 } 4254 4255 @Test public void test_rt_38787_remove_a() { 4256 // selection moves to "b", now in index 0 4257 test_rt_38787("b", 0, "a"); 4258 } 4259 4260 @Test public void test_rt_38787_remove_z() { 4261 // selection shouldn't move as 'z' doesn't exist 4262 test_rt_38787("b", 1, "z"); 4263 } 4264 4265 private void test_rt_38787(String expectedItem, int expectedIndex, String... itemsToRemove) { 4266 TableView<String> stringTableView = new TableView<>(); 4267 stringTableView.getItems().addAll("a","b","c","d"); 4268 4269 TableColumn<String,String> column = new TableColumn<>("Column"); 4270 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4271 stringTableView.getColumns().add(column); 4272 4273 MultipleSelectionModel<String> sm = stringTableView.getSelectionModel(); 4274 sm.select("b"); 4275 4276 // test pre-conditions 4277 assertEquals(1, sm.getSelectedIndex()); 4278 assertEquals(1, (int)sm.getSelectedIndices().get(0)); 4279 assertEquals("b", sm.getSelectedItem()); 4280 assertEquals("b", sm.getSelectedItems().get(0)); 4281 assertFalse(sm.isSelected(0)); 4282 assertTrue(sm.isSelected(1)); 4283 assertFalse(sm.isSelected(2)); 4284 4285 // removing items 4286 stringTableView.getItems().removeAll(itemsToRemove); 4287 4288 // testing against expectations 4289 assertEquals(expectedIndex, sm.getSelectedIndex()); 4290 assertEquals(expectedIndex, (int)sm.getSelectedIndices().get(0)); 4291 assertEquals(expectedItem, sm.getSelectedItem()); 4292 assertEquals(expectedItem, sm.getSelectedItems().get(0)); 4293 } 4294 4295 private int rt_38341_indices_count = 0; 4296 private int rt_38341_items_count = 0; 4297 @Test public void test_rt_38341() { 4298 TableView<String> stringTableView = new TableView<>(); 4299 stringTableView.getItems().addAll("a","b","c","d"); 4300 4301 TableColumn<String,String> column = new TableColumn<>("Column"); 4302 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4303 stringTableView.getColumns().add(column); 4304 4305 MultipleSelectionModel<String> sm = stringTableView.getSelectionModel(); 4306 sm.getSelectedIndices().addListener((ListChangeListener<Integer>) c -> { 4307 rt_38341_indices_count++; 4308 }); 4309 sm.getSelectedItems().addListener((ListChangeListener<String>) c -> rt_38341_items_count++); 4310 4311 assertEquals(0, rt_38341_indices_count); 4312 assertEquals(0, rt_38341_items_count); 4313 4314 // expand the first child of root, and select it (note: root isn't visible) 4315 sm.select(1); 4316 assertEquals(1, sm.getSelectedIndex()); 4317 assertEquals(1, sm.getSelectedIndices().size()); 4318 assertEquals(1, (int)sm.getSelectedIndices().get(0)); 4319 assertEquals(1, sm.getSelectedItems().size()); 4320 assertEquals("b", sm.getSelectedItem()); 4321 assertEquals("b", sm.getSelectedItems().get(0)); 4322 4323 assertEquals(1, rt_38341_indices_count); 4324 assertEquals(1, rt_38341_items_count); 4325 4326 // now delete it 4327 stringTableView.getItems().remove(1); 4328 4329 // selection should move to the childs parent in index 0 4330 assertEquals(0, sm.getSelectedIndex()); 4331 assertEquals(1, sm.getSelectedIndices().size()); 4332 assertEquals(0, (int)sm.getSelectedIndices().get(0)); 4333 assertEquals(1, sm.getSelectedItems().size()); 4334 assertEquals("a", sm.getSelectedItem()); 4335 assertEquals("a", sm.getSelectedItems().get(0)); 4336 4337 // we also expect there to be an event in the selection model for 4338 // selected indices and selected items 4339 assertEquals(2, rt_38341_indices_count); 4340 assertEquals(2, rt_38341_items_count); 4341 } 4342 4343 @Test public void test_rt_39132() { 4344 TableView<String> tableView = new TableView<>(); 4345 4346 ObservableList items = FXCollections.observableArrayList("one", "two", "three"); 4347 tableView.setItems(items); 4348 4349 TableColumn<String,String> column = new TableColumn<>("Column"); 4350 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4351 tableView.getColumns().add(column); 4352 4353 MultipleSelectionModel sm = tableView.getSelectionModel(); 4354 sm.select(0); 4355 4356 assertEquals(0, sm.getSelectedIndex()); 4357 assertEquals("one", sm.getSelectedItem()); 4358 4359 items.add(0, "new item"); 4360 assertEquals(1, sm.getSelectedIndex()); 4361 assertEquals("one", sm.getSelectedItem()); 4362 } 4363 4364 private int rt_38943_index_count = 0; 4365 private int rt_38943_item_count = 0; 4366 @Test public void test_rt_38943() { 4367 TableView<String> tableView = new TableView<>(FXCollections.observableArrayList("one", "two", "three")); 4368 4369 TableColumn<String,String> column = new TableColumn<>("Column"); 4370 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4371 tableView.getColumns().add(column); 4372 4373 MultipleSelectionModel sm = tableView.getSelectionModel(); 4374 4375 sm.selectedIndexProperty().addListener((observable, oldValue, newValue) -> rt_38943_index_count++); 4376 sm.selectedItemProperty().addListener((observable, oldValue, newValue) -> rt_38943_item_count++); 4377 4378 assertEquals(-1, sm.getSelectedIndex()); 4379 assertNull(sm.getSelectedItem()); 4380 assertEquals(0, rt_38943_index_count); 4381 assertEquals(0, rt_38943_item_count); 4382 4383 sm.select(0); 4384 assertEquals(0, sm.getSelectedIndex()); 4385 assertEquals("one", sm.getSelectedItem()); 4386 assertEquals(1, rt_38943_index_count); 4387 assertEquals(1, rt_38943_item_count); 4388 4389 sm.clearSelection(0); 4390 assertEquals(-1, sm.getSelectedIndex()); 4391 assertNull(sm.getSelectedItem()); 4392 assertEquals(2, rt_38943_index_count); 4393 assertEquals(2, rt_38943_item_count); 4394 } 4395 4396 @Test public void test_rt_38884() { 4397 TableView<String> table = new TableView<>(); 4398 ObservableList<String> items = table.getItems(); 4399 4400 table.getSelectionModel().getSelectedItems().addListener((ListChangeListener.Change<? extends String> c) -> { 4401 while (c.next()) { 4402 if (c.wasRemoved()) { 4403 assertTrue(c.getRemovedSize() > 0); 4404 4405 List<? extends String> removed = c.getRemoved(); 4406 String removedItem = null; 4407 try { 4408 removedItem = removed.get(0); 4409 } catch (Exception e) { 4410 fail(); 4411 } 4412 4413 assertEquals("foo", removedItem); 4414 } 4415 } 4416 }); 4417 4418 items.add("foo"); 4419 table.getSelectionModel().select(0); 4420 items.clear(); 4421 } 4422 4423 private int rt_37360_add_count = 0; 4424 private int rt_37360_remove_count = 0; 4425 @Test public void test_rt_37360() { 4426 TableView<String> stringTableView = new TableView<>(); 4427 stringTableView.getItems().addAll("a","b"); 4428 4429 TableColumn<String,String> column = new TableColumn<>("Column"); 4430 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4431 stringTableView.getColumns().add(column); 4432 4433 MultipleSelectionModel<String> sm = stringTableView.getSelectionModel(); 4434 sm.setSelectionMode(SelectionMode.MULTIPLE); 4435 sm.getSelectedItems().addListener((ListChangeListener<String>) c -> { 4436 while (c.next()) { 4437 if (c.wasAdded()) { 4438 rt_37360_add_count += c.getAddedSize(); 4439 } 4440 if (c.wasRemoved()) { 4441 rt_37360_remove_count += c.getRemovedSize(); 4442 } 4443 } 4444 }); 4445 4446 assertEquals(0, sm.getSelectedItems().size()); 4447 assertEquals(0, rt_37360_add_count); 4448 assertEquals(0, rt_37360_remove_count); 4449 4450 sm.select(0); 4451 assertEquals(1, sm.getSelectedItems().size()); 4452 assertEquals(1, rt_37360_add_count); 4453 assertEquals(0, rt_37360_remove_count); 4454 4455 sm.select(1); 4456 assertEquals(2, sm.getSelectedItems().size()); 4457 assertEquals(2, rt_37360_add_count); 4458 assertEquals(0, rt_37360_remove_count); 4459 4460 sm.clearAndSelect(1); 4461 assertEquals(1, sm.getSelectedItems().size()); 4462 assertEquals(2, rt_37360_add_count); 4463 assertEquals(1, rt_37360_remove_count); 4464 } 4465 4466 @Test public void test_rt_38491() { 4467 TableView<String> stringTableView = new TableView<>(); 4468 stringTableView.getItems().addAll("a","b", "c", "d"); 4469 4470 TableColumn<String,String> column = new TableColumn<>("Column"); 4471 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4472 stringTableView.getColumns().add(column); 4473 4474 TableSelectionModel<String> sm = stringTableView.getSelectionModel(); 4475 sm.setSelectionMode(SelectionMode.MULTIPLE); 4476 4477 TableView.TableViewFocusModel fm = stringTableView.getFocusModel(); 4478 4479 StageLoader sl = new StageLoader(stringTableView); 4480 4481 // click on row 0 4482 sm.select(0, column); 4483 assertTrue(sm.isSelected(0)); 4484 assertEquals("a", sm.getSelectedItem()); 4485 assertTrue(fm.isFocused(0)); 4486 assertEquals("a", fm.getFocusedItem()); 4487 assertEquals(0, fm.getFocusedCell().getRow()); 4488 assertEquals(column, fm.getFocusedCell().getTableColumn()); 4489 4490 TablePosition anchor = TableCellBehavior.getAnchor(stringTableView, null); 4491 assertTrue(TableCellBehavior.hasNonDefaultAnchor(stringTableView)); 4492 assertEquals(0, anchor.getRow()); 4493 assertEquals(column, anchor.getTableColumn()); 4494 4495 // now add a new item at row 0. This has the effect of pushing down 4496 // the selected item into row 1. 4497 stringTableView.getItems().add(0, "z"); 4498 4499 Toolkit.getToolkit().firePulse(); 4500 4501 // The first bug was that selection and focus were not moving down to 4502 // be on row 1, so we test that now 4503 assertFalse(sm.isSelected(0)); 4504 assertFalse(fm.isFocused(0)); 4505 assertTrue(sm.isSelected(1)); 4506 assertEquals("a", sm.getSelectedItem()); 4507 assertTrue(fm.isFocused(1)); 4508 assertEquals("a", fm.getFocusedItem()); 4509 assertEquals(1, fm.getFocusedCell().getRow()); 4510 assertEquals(column, fm.getFocusedCell().getTableColumn()); 4511 4512 // The second bug was that the anchor was not being pushed down as well 4513 // (when it should). 4514 anchor = TableCellBehavior.getAnchor(stringTableView, null); 4515 assertTrue(TableCellBehavior.hasNonDefaultAnchor(stringTableView)); 4516 assertEquals(1, anchor.getRow()); 4517 assertEquals(column, anchor.getTableColumn()); 4518 4519 sl.dispose(); 4520 } 4521 4522 private final ObservableList<String> rt_39256_list = FXCollections.observableArrayList(); 4523 @Test public void test_rt_39256() { 4524 TableView<String> stringTableView = new TableView<>(); 4525 stringTableView.getItems().addAll("a","b", "c", "d"); 4526 4527 TableColumn<String,String> column = new TableColumn<>("Column"); 4528 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4529 stringTableView.getColumns().add(column); 4530 4531 TableSelectionModel<String> sm = stringTableView.getSelectionModel(); 4532 sm.setSelectionMode(SelectionMode.MULTIPLE); 4533 4534 // rt_39256_list.addListener((ListChangeListener<String>) change -> { 4535 // while (change.next()) { 4536 // System.err.println("number of selected persons (in bound list): " + change.getList().size()); 4537 // } 4538 // }); 4539 4540 Bindings.bindContent(rt_39256_list, sm.getSelectedItems()); 4541 4542 assertEquals(0, sm.getSelectedItems().size()); 4543 assertEquals(0, rt_39256_list.size()); 4544 4545 sm.selectAll(); 4546 assertEquals(4, sm.getSelectedItems().size()); 4547 assertEquals(4, rt_39256_list.size()); 4548 4549 sm.selectAll(); 4550 assertEquals(4, sm.getSelectedItems().size()); 4551 assertEquals(4, rt_39256_list.size()); 4552 4553 sm.selectAll(); 4554 assertEquals(4, sm.getSelectedItems().size()); 4555 assertEquals(4, rt_39256_list.size()); 4556 } 4557 4558 @Test public void test_rt_39256_noTableView() { 4559 ObservableList<String> listOne = FXCollections.observableArrayList(); 4560 ObservableList<String> listTwo = FXCollections.observableArrayList(); 4561 4562 // listOne.addListener((ListChangeListener<String>) change -> { 4563 // while (change.next()) { 4564 // System.out.println("number of strings in bound list - listOne: " + change.getList().size() + ", change: " + change); 4565 // } 4566 // }); 4567 // 4568 // listTwo.addListener((ListChangeListener<String>) change -> { 4569 // while (change.next()) { 4570 // System.out.println("number of strings in unbound list - listTwo: " + change.getList().size() + ", change: " + change); 4571 // } 4572 // }); 4573 4574 Bindings.bindContent(listOne, listTwo); 4575 4576 assertEquals(0, listOne.size()); 4577 assertEquals(0, listTwo.size()); 4578 4579 System.out.println("Test One:"); 4580 listTwo.setAll("a", "b", "c", "d"); 4581 assertEquals(4, listOne.size()); 4582 assertEquals(4, listTwo.size()); 4583 4584 System.out.println("\nTest Two:"); 4585 listTwo.setAll("e", "f", "g", "h"); 4586 assertEquals(4, listOne.size()); 4587 assertEquals(4, listTwo.size()); 4588 4589 System.out.println("\nTest Three:"); 4590 listTwo.setAll("i", "j", "k", "l"); 4591 assertEquals(4, listOne.size()); 4592 assertEquals(4, listTwo.size()); 4593 } 4594 4595 private final ObservableList<String> rt_39482_list = FXCollections.observableArrayList(); 4596 @Test public void test_rt_39482() { 4597 TableView<String> stringTableView = new TableView<>(); 4598 stringTableView.getItems().addAll("a","b", "c", "d"); 4599 4600 TableColumn<String,String> column = new TableColumn<>("Column"); 4601 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4602 stringTableView.getColumns().add(column); 4603 4604 TableView.TableViewSelectionModel<String> sm = stringTableView.getSelectionModel(); 4605 sm.setSelectionMode(SelectionMode.MULTIPLE); 4606 4607 sm.getSelectedItems().addListener((ListChangeListener<String>) change -> { 4608 while (change.next()) { 4609 System.out.println("sm.getSelectedItems(): " + change.getList()); 4610 } 4611 }); 4612 4613 rt_39482_list.addListener((ListChangeListener<String>) change -> { 4614 while (change.next()) { 4615 System.out.println("rt_39482_list: " + change.getList()); 4616 } 4617 }); 4618 4619 Bindings.bindContent(rt_39482_list, sm.getSelectedItems()); 4620 4621 assertEquals(0, sm.getSelectedItems().size()); 4622 assertEquals(0, rt_39482_list.size()); 4623 4624 test_rt_39482_selectRow("a", sm, 0, column); 4625 test_rt_39482_selectRow("b", sm, 1, column); 4626 test_rt_39482_selectRow("c", sm, 2, column); 4627 test_rt_39482_selectRow("d", sm, 3, column); 4628 } 4629 4630 private void test_rt_39482_selectRow(String expectedString, 4631 TableView.TableViewSelectionModel<String> sm, 4632 int rowToSelect, 4633 TableColumn<String,String> columnToSelect) { 4634 System.out.println("\nSelect row " + rowToSelect); 4635 sm.selectAll(); 4636 assertEquals(4, sm.getSelectedCells().size()); 4637 assertEquals(4, sm.getSelectedIndices().size()); 4638 assertEquals(4, sm.getSelectedItems().size()); 4639 assertEquals(4, rt_39482_list.size()); 4640 4641 sm.clearAndSelect(rowToSelect, columnToSelect); 4642 assertEquals(1, sm.getSelectedCells().size()); 4643 assertEquals(1, sm.getSelectedIndices().size()); 4644 assertEquals(1, sm.getSelectedItems().size()); 4645 assertEquals(expectedString, sm.getSelectedItem()); 4646 assertEquals(expectedString, rt_39482_list.get(0)); 4647 assertEquals(1, rt_39482_list.size()); 4648 } 4649 4650 @Test public void test_rt_39559_useSM_selectAll() { 4651 test_rt_39559(true); 4652 } 4653 4654 @Test public void test_rt_39559_useKeyboard_selectAll() { 4655 test_rt_39559(false); 4656 } 4657 4658 private void test_rt_39559(boolean useSMSelectAll) { 4659 TableView<String> stringTableView = new TableView<>(); 4660 stringTableView.getItems().addAll("a","b", "c", "d"); 4661 4662 TableColumn<String,String> column = new TableColumn<>("Column"); 4663 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4664 stringTableView.getColumns().add(column); 4665 4666 TableView.TableViewSelectionModel<String> sm = stringTableView.getSelectionModel(); 4667 sm.setSelectionMode(SelectionMode.MULTIPLE); 4668 4669 StageLoader sl = new StageLoader(stringTableView); 4670 KeyEventFirer keyboard = new KeyEventFirer(stringTableView); 4671 4672 assertEquals(0, sm.getSelectedItems().size()); 4673 4674 sm.clearAndSelect(0); 4675 4676 if (useSMSelectAll) { 4677 sm.selectAll(); 4678 } else { 4679 keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey()); 4680 } 4681 4682 assertEquals(4, sm.getSelectedItems().size()); 4683 assertEquals(0, ((TablePosition) TableCellBehavior.getAnchor(stringTableView, null)).getRow()); 4684 4685 keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); 4686 4687 assertEquals(0, ((TablePosition) TableCellBehavior.getAnchor(stringTableView, null)).getRow()); 4688 assertEquals(2, sm.getSelectedItems().size()); 4689 assertEquals("a", sm.getSelectedItems().get(0)); 4690 assertEquals("b", sm.getSelectedItems().get(1)); 4691 4692 sl.dispose(); 4693 } 4694 4695 @Test public void test_rt_16068_firstElement_selectAndRemoveSameRow() { 4696 // select and then remove the 'a' item, selection and focus should both 4697 // stay at the first row, now 'b' 4698 test_rt_16068(0, 0, 0); 4699 } 4700 4701 @Test public void test_rt_16068_firstElement_selectRowAndRemoveLaterSibling() { 4702 // select row 'a', and remove row 'c', selection and focus should not change 4703 test_rt_16068(0, 2, 0); 4704 } 4705 4706 @Test public void test_rt_16068_middleElement_selectAndRemoveSameRow() { 4707 // select and then remove the 'b' item, selection and focus should both 4708 // move up one row to the 'a' item 4709 test_rt_16068(1, 1, 0); 4710 } 4711 4712 @Test public void test_rt_16068_middleElement_selectRowAndRemoveLaterSibling() { 4713 // select row 'b', and remove row 'c', selection and focus should not change 4714 test_rt_16068(1, 2, 1); 4715 } 4716 4717 @Test public void test_rt_16068_middleElement_selectRowAndRemoveEarlierSibling() { 4718 // select row 'b', and remove row 'a', selection and focus should move up 4719 // one row, remaining on 'b' 4720 test_rt_16068(1, 0, 0); 4721 } 4722 4723 @Test public void test_rt_16068_lastElement_selectAndRemoveSameRow() { 4724 // select and then remove the 'd' item, selection and focus should both 4725 // move up one row to the 'c' item 4726 test_rt_16068(3, 3, 2); 4727 } 4728 4729 @Test public void test_rt_16068_lastElement_selectRowAndRemoveEarlierSibling() { 4730 // select row 'd', and remove row 'a', selection and focus should move up 4731 // one row, remaining on 'd' 4732 test_rt_16068(3, 0, 2); 4733 } 4734 4735 private void test_rt_16068(int indexToSelect, int indexToRemove, int expectedIndex) { 4736 TableView<String> stringTableView = new TableView<>(); 4737 stringTableView.getItems().addAll("a","b", "c", "d"); 4738 4739 TableColumn<String,String> column = new TableColumn<>("Column"); 4740 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4741 stringTableView.getColumns().add(column); 4742 4743 TableView.TableViewSelectionModel<?> sm = stringTableView.getSelectionModel(); 4744 FocusModel<?> fm = stringTableView.getFocusModel(); 4745 4746 sm.select(indexToSelect); 4747 assertEquals(indexToSelect, sm.getSelectedIndex()); 4748 assertEquals(stringTableView.getItems().get(indexToSelect), sm.getSelectedItem()); 4749 assertEquals(indexToSelect, fm.getFocusedIndex()); 4750 assertEquals(stringTableView.getItems().get(indexToSelect), fm.getFocusedItem()); 4751 4752 stringTableView.getItems().remove(indexToRemove); 4753 assertEquals(expectedIndex, sm.getSelectedIndex()); 4754 assertEquals(stringTableView.getItems().get(expectedIndex), sm.getSelectedItem()); 4755 assertEquals(expectedIndex, fm.getFocusedIndex()); 4756 assertEquals(stringTableView.getItems().get(expectedIndex), fm.getFocusedItem()); 4757 } 4758 4759 private int test_rt_39822_count = 0; 4760 @Test public void test_rt_39822() { 4761 // get the current exception handler before replacing with our own, 4762 // as ListListenerHelp intercepts the exception otherwise 4763 final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler(); 4764 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> { 4765 e.printStackTrace(); 4766 4767 if (test_rt_39822_count == 0) { 4768 test_rt_39822_count++; 4769 if (! (e instanceof IllegalStateException)) { 4770 fail("Incorrect exception type - expecting IllegalStateException"); 4771 } 4772 } else { 4773 // don't care 4774 test_rt_39822_count++; 4775 } 4776 }); 4777 4778 TableView<String> table = new TableView<>(); 4779 TableColumn<String, String> col1 = new TableColumn<>("Foo"); 4780 table.getColumns().addAll(col1, col1); // add column twice 4781 4782 StageLoader sl = null; 4783 try { 4784 sl = new StageLoader(table); 4785 } finally { 4786 if (sl != null) { 4787 sl.dispose(); 4788 } 4789 4790 // reset the exception handler 4791 Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler); 4792 } 4793 } 4794 4795 private int test_rt_39842_count = 0; 4796 @Test public void test_rt_39842_selectLeftDown() { 4797 test_rt_39842(true, false); 4798 } 4799 4800 @Test public void test_rt_39842_selectLeftUp() { 4801 test_rt_39842(true, true); 4802 } 4803 4804 @Test public void test_rt_39842_selectRightDown() { 4805 test_rt_39842(false, false); 4806 } 4807 4808 @Test public void test_rt_39842_selectRightUp() { 4809 test_rt_39842(false, true); 4810 } 4811 4812 private void test_rt_39842(boolean selectToLeft, boolean selectUpwards) { 4813 test_rt_39842_count = 0; 4814 4815 TableColumn firstNameCol = new TableColumn("First Name"); 4816 firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 4817 4818 TableColumn lastNameCol = new TableColumn("Last Name"); 4819 lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 4820 4821 TableView<Person> table = new TableView<>(); 4822 table.setItems(personTestData); 4823 table.getColumns().addAll(firstNameCol, lastNameCol); 4824 4825 sm = table.getSelectionModel(); 4826 sm.setCellSelectionEnabled(true); 4827 sm.setSelectionMode(SelectionMode.MULTIPLE); 4828 sm.getSelectedCells().addListener((ListChangeListener) c -> test_rt_39842_count++); 4829 4830 StageLoader sl = new StageLoader(table); 4831 4832 assertEquals(0, test_rt_39842_count); 4833 4834 if (selectToLeft) { 4835 if (selectUpwards) { 4836 sm.selectRange(3, lastNameCol, 0, firstNameCol); 4837 } else { 4838 sm.selectRange(0, lastNameCol, 3, firstNameCol); 4839 } 4840 } else { 4841 if (selectUpwards) { 4842 sm.selectRange(3, firstNameCol, 0, lastNameCol); 4843 } else { 4844 sm.selectRange(0, firstNameCol, 3, lastNameCol); 4845 } 4846 } 4847 4848 // test model state 4849 assertEquals(8, sm.getSelectedCells().size()); 4850 assertEquals(1, test_rt_39842_count); 4851 4852 // test visual state 4853 for (int row = 0; row <= 3; row++) { 4854 for (int column = 0; column <= 1; column++) { 4855 IndexedCell cell = VirtualFlowTestUtils.getCell(table, row, column); 4856 assertTrue(cell.isSelected()); 4857 } 4858 } 4859 4860 sl.dispose(); 4861 } 4862 4863 @Test public void test_rt_22599() { 4864 ObservableList<RT22599_DataType> initialData = FXCollections.observableArrayList( 4865 new RT22599_DataType(1, "row1"), 4866 new RT22599_DataType(2, "row2"), 4867 new RT22599_DataType(3, "row3") 4868 ); 4869 4870 TableColumn<RT22599_DataType, String> col = new TableColumn<>("Header"); 4871 col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().text)); 4872 4873 TableView<RT22599_DataType> table = new TableView<>(); 4874 table.setItems(initialData); 4875 table.getColumns().addAll(col); 4876 4877 StageLoader sl = new StageLoader(table); 4878 4879 // testing initial state 4880 assertNotNull(table.getSkin()); 4881 assertEquals("row1", VirtualFlowTestUtils.getCell(table, 0, 0).getText()); 4882 assertEquals("row2", VirtualFlowTestUtils.getCell(table, 1, 0).getText()); 4883 assertEquals("row3", VirtualFlowTestUtils.getCell(table, 2, 0).getText()); 4884 4885 // change row 0 (where "row1" currently resides), keeping same id. 4886 // Because 'set' is called, the control should update to the new content 4887 // without any user interaction 4888 RT22599_DataType data; 4889 initialData.set(0, data = new RT22599_DataType(0, "row1a")); 4890 Toolkit.getToolkit().firePulse(); 4891 assertEquals("row1a", VirtualFlowTestUtils.getCell(table, 0, 0).getText()); 4892 4893 // change the row 0 (where we currently have "row1a") value directly. 4894 // Because there is no associated property, this won't be observed, so 4895 // the control should still show "row1a" rather than "row1b" 4896 data.text = "row1b"; 4897 Toolkit.getToolkit().firePulse(); 4898 assertEquals("row1a", VirtualFlowTestUtils.getCell(table, 0, 0).getText()); 4899 4900 // call refresh() to force a refresh of all visible cells 4901 table.refresh(); 4902 Toolkit.getToolkit().firePulse(); 4903 assertEquals("row1b", VirtualFlowTestUtils.getCell(table, 0, 0).getText()); 4904 4905 sl.dispose(); 4906 } 4907 4908 private static class RT22599_DataType { 4909 public int id = 0; 4910 public String text = ""; 4911 4912 public RT22599_DataType(int id, String text) { 4913 this.id = id; 4914 this.text = text; 4915 } 4916 4917 @Override public boolean equals(Object obj) { 4918 if (obj == null) return false; 4919 return id == ((RT22599_DataType)obj).id; 4920 } 4921 } 4922 4923 private int rt_39966_count = 0; 4924 @Test public void test_rt_39966() { 4925 ObservableList<String> initialData = FXCollections.observableArrayList("Hello World"); 4926 4927 TableColumn<String, String> col = new TableColumn<>("Header"); 4928 col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue())); 4929 4930 TableView<String> table = new TableView<>(initialData); 4931 table.getColumns().addAll(col); 4932 4933 StageLoader sl = new StageLoader(table); 4934 4935 // initially there is no selection 4936 assertTrue(table.getSelectionModel().isEmpty()); 4937 4938 table.getSelectionModel().selectedItemProperty().addListener((value, s1, s2) -> { 4939 if (rt_39966_count == 0) { 4940 rt_39966_count++; 4941 assertFalse(table.getSelectionModel().isEmpty()); 4942 } else { 4943 assertTrue(table.getSelectionModel().isEmpty()); 4944 } 4945 }); 4946 4947 // our assertion two lines down always succeeds. What fails is our 4948 // assertion above within the listener. 4949 table.getSelectionModel().select(0); 4950 assertFalse(table.getSelectionModel().isEmpty()); 4951 4952 initialData.remove(0); 4953 assertTrue(table.getSelectionModel().isEmpty()); 4954 4955 sl.dispose(); 4956 } 4957 4958 /** 4959 * Bullet 1: selected index must be updated 4960 * Corner case: last selected. Fails for core 4961 */ 4962 @Test public void test_rt_40012_selectedAtLastOnDisjointRemoveItemsAbove() { 4963 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 4964 TableView<String> stringTableView = new TableView<>(items); 4965 TableView.TableViewSelectionModel<?> sm = stringTableView.getSelectionModel(); 4966 4967 TableColumn<String,String> column = new TableColumn<>("Column"); 4968 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4969 stringTableView.getColumns().add(column); 4970 4971 int last = items.size() - 1; 4972 4973 // selecting item "5" 4974 sm.select(last); 4975 4976 // disjoint remove of 2 elements above the last selected 4977 // Removing "1" and "3" 4978 items.removeAll(items.get(1), items.get(3)); 4979 4980 // selection should move up two places such that it remains on item "5", 4981 // but in index (last - 2). 4982 int expected = last - 2; 4983 assertEquals("5", sm.getSelectedItem()); 4984 assertEquals("selected index after disjoint removes above", expected, sm.getSelectedIndex()); 4985 } 4986 4987 /** 4988 * Variant of 1: if selectedIndex is not updated, 4989 * the old index is no longer valid 4990 * for accessing the items. 4991 */ 4992 @Test public void test_rt_40012_accessSelectedAtLastOnDisjointRemoveItemsAbove() { 4993 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 4994 TableView<String> stringTableView = new TableView<>(items); 4995 TableView.TableViewSelectionModel<?> sm = stringTableView.getSelectionModel(); 4996 4997 TableColumn<String,String> column = new TableColumn<>("Column"); 4998 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 4999 stringTableView.getColumns().add(column); 5000 5001 int last = items.size() - 1; 5002 5003 // selecting item "5" 5004 sm.select(last); 5005 5006 // disjoint remove of 2 elements above the last selected 5007 items.removeAll(items.get(1), items.get(3)); 5008 int selected = sm.getSelectedIndex(); 5009 if (selected > -1) { 5010 items.get(selected); 5011 } 5012 } 5013 5014 /** 5015 * Bullet 2: selectedIndex notification count 5016 * 5017 * Note that we don't use the corner case of having the last index selected 5018 * (which fails already on updating the index) 5019 */ 5020 private int rt_40012_count = 0; 5021 @Test public void test_rt_40012_selectedIndexNotificationOnDisjointRemovesAbove() { 5022 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 5023 TableView<String> stringTableView = new TableView<>(items); 5024 TableView.TableViewSelectionModel<?> sm = stringTableView.getSelectionModel(); 5025 5026 TableColumn<String,String> column = new TableColumn<>("Column"); 5027 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 5028 stringTableView.getColumns().add(column); 5029 5030 int last = items.size() - 2; 5031 sm.select(last); 5032 assertEquals(last, sm.getSelectedIndex()); 5033 5034 rt_40012_count = 0; 5035 sm.selectedIndexProperty().addListener(o -> rt_40012_count++); 5036 5037 // disjoint remove of 2 elements above the last selected 5038 items.removeAll(items.get(1), items.get(3)); 5039 assertEquals("sanity: selectedIndex must be shifted by -2", last - 2, sm.getSelectedIndex()); 5040 assertEquals("must fire single event on removes above", 1, rt_40012_count); 5041 } 5042 5043 /** 5044 * Bullet 3: unchanged selectedItem must not fire change 5045 */ 5046 @Test 5047 public void test_rt_40012_selectedItemNotificationOnDisjointRemovesAbove() { 5048 ObservableList<String> items = FXCollections.observableArrayList("0", "1", "2", "3", "4", "5"); 5049 TableView<String> stringTableView = new TableView<>(items); 5050 TableView.TableViewSelectionModel<?> sm = stringTableView.getSelectionModel(); 5051 5052 TableColumn<String,String> column = new TableColumn<>("Column"); 5053 column.setCellValueFactory(cdf -> new ReadOnlyStringWrapper(cdf.getValue())); 5054 stringTableView.getColumns().add(column); 5055 5056 int last = items.size() - 2; 5057 Object lastItem = items.get(last); 5058 sm.select(last); 5059 assertEquals(lastItem, sm.getSelectedItem()); 5060 5061 rt_40012_count = 0; 5062 sm.selectedItemProperty().addListener(o -> rt_40012_count++); 5063 5064 // disjoint remove of 2 elements above the last selected 5065 items.removeAll(items.get(1), items.get(3)); 5066 assertEquals("sanity: selectedItem unchanged", lastItem, sm.getSelectedItem()); 5067 assertEquals("must not fire on unchanged selected item", 0, rt_40012_count); 5068 } 5069 }