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