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