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