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 com.sun.javafx.scene.control.behavior.TreeTableViewAnchorRetriever; 29 import com.sun.javafx.scene.control.infrastructure.*; 30 import com.sun.javafx.scene.control.test.Person; 31 32 import static org.junit.Assert.*; 33 34 import com.sun.javafx.tk.Toolkit; 35 import javafx.collections.FXCollections; 36 import javafx.collections.ListChangeListener; 37 import javafx.collections.ObservableList; 38 import javafx.scene.Node; 39 import javafx.scene.Scene; 40 import javafx.scene.control.cell.TreeItemPropertyValueFactory; 41 42 import javafx.scene.layout.VBox; 43 import org.junit.After; 44 45 import org.junit.Before; 46 import org.junit.Ignore; 47 import org.junit.Test; 48 49 //@Ignore("Disabling tests as they fail with OOM in continuous builds") 50 public class TreeTableViewMouseInputTest { 51 private TreeTableView<String> tableView; 52 private TreeTableView.TreeTableViewSelectionModel<?> sm; 53 private TreeTableView.TreeTableViewFocusModel<?> fm; 54 55 private final TreeTableColumn<String, String> col0 = new TreeTableColumn<String, String>("col0"); 56 private final TreeTableColumn<String, String> col1 = new TreeTableColumn<String, String>("col1"); 57 private final TreeTableColumn<String, String> col2 = new TreeTableColumn<String, String>("col2"); 58 private final TreeTableColumn<String, String> col3 = new TreeTableColumn<String, String>("col3"); 59 private final TreeTableColumn<String, String> col4 = new TreeTableColumn<String, String>("col4"); 60 61 private TreeItem<String> root; // 0 62 private TreeItem<String> child1; // 1 63 private TreeItem<String> child2; // 2 64 private TreeItem<String> child3; // 3 65 private TreeItem<String> subchild1; // 4 66 private TreeItem<String> subchild2; // 5 67 private TreeItem<String> subchild3; // 6 68 private TreeItem<String> child4; // 7 69 private TreeItem<String> child5; // 8 70 private TreeItem<String> child6; // 9 71 private TreeItem<String> child7; // 10 72 private TreeItem<String> child8; // 11 73 private TreeItem<String> child9; // 12 74 private TreeItem<String> child10; // 13 75 76 @Before public void setup() { 77 root = new TreeItem<String>("Root"); // 0 78 child1 = new TreeItem<String>("Child 1"); // 1 79 child2 = new TreeItem<String>("Child 2"); // 2 80 child3 = new TreeItem<String>("Child 3"); // 3 81 subchild1 = new TreeItem<String>("Subchild 1"); // 4 82 subchild2 = new TreeItem<String>("Subchild 2"); // 5 83 subchild3 = new TreeItem<String>("Subchild 3"); // 6 84 child4 = new TreeItem<String>("Child 4"); // 7 85 child5 = new TreeItem<String>("Child 5"); // 8 86 child6 = new TreeItem<String>("Child 6"); // 9 87 child7 = new TreeItem<String>("Child 7"); // 10 88 child8 = new TreeItem<String>("Child 8"); // 11 89 child9 = new TreeItem<String>("Child 9"); // 12 90 child10 = new TreeItem<String>("Child 10"); // 13 91 92 // reset tree structure 93 root.getChildren().clear(); 94 root.setExpanded(true); 95 root.getChildren().setAll(child1, child2, child3, child4, child5, child6, child7, child8, child9, child10 ); 96 child1.getChildren().clear(); 97 child1.setExpanded(false); 98 child2.getChildren().clear(); 99 child2.setExpanded(false); 100 child3.getChildren().clear(); 101 child3.setExpanded(true); 102 child3.getChildren().setAll(subchild1, subchild2, subchild3); 103 child4.getChildren().clear(); 104 child4.setExpanded(false); 105 child5.getChildren().clear(); 106 child5.setExpanded(false); 107 child6.getChildren().clear(); 108 child6.setExpanded(false); 109 child7.getChildren().clear(); 110 child7.setExpanded(false); 111 child8.getChildren().clear(); 112 child8.setExpanded(false); 113 child9.getChildren().clear(); 114 child9.setExpanded(false); 115 child10.getChildren().clear(); 116 child10.setExpanded(false); 117 118 tableView = new TreeTableView<String>(); 119 sm = tableView.getSelectionModel(); 120 fm = tableView.getFocusModel(); 121 122 sm.setSelectionMode(SelectionMode.MULTIPLE); 123 sm.setCellSelectionEnabled(false); 124 125 tableView.setRoot(root); 126 tableView.getColumns().setAll(col0, col1, col2, col3, col4); 127 } 128 129 @After public void tearDown() { 130 if (tableView.getSkin() != null) { 131 tableView.getSkin().dispose(); 132 } 133 sm = null; 134 } 135 136 /*************************************************************************** 137 * Util methods 138 **************************************************************************/ 139 140 private String debug() { 141 StringBuilder sb = new StringBuilder("Selected Cells: ["); 142 143 ObservableList<? extends TreeTablePosition<?, ?>> cells = sm.getSelectedCells(); 144 for (TreeTablePosition<?,?> tp : cells) { 145 sb.append("("); 146 sb.append(tp.getRow()); 147 sb.append(","); 148 sb.append(tp.getColumn()); 149 sb.append("), "); 150 } 151 152 sb.append("] \nFocus: (" + fm.getFocusedCell().getRow() + ", " + fm.getFocusedCell().getColumn() + ")"); 153 154 TreeTablePosition anchor = getAnchor(); 155 sb.append(" \nAnchor: (" + (anchor == null ? "null" : anchor.getRow()) + 156 ", " + (anchor == null ? "null" : anchor.getColumn()) + ")"); 157 return sb.toString(); 158 } 159 160 // Returns true if ALL indices are selected 161 private boolean isSelected(int... indices) { 162 for (int index : indices) { 163 if (! sm.isSelected(index)) return false; 164 } 165 return true; 166 } 167 168 // Returns true if ALL indices are NOT selected 169 private boolean isNotSelected(int... indices) { 170 for (int index : indices) { 171 if (sm.isSelected(index)) return false; 172 } 173 return true; 174 } 175 176 private TreeTablePosition getAnchor() { 177 return TreeTableViewAnchorRetriever.getAnchor(tableView); 178 } 179 180 private boolean isAnchor(int row) { 181 TreeTablePosition tp = new TreeTablePosition(tableView, row, null); 182 return getAnchor() != null && getAnchor().equals(tp); 183 } 184 185 private boolean isAnchor(int row, int col) { 186 TreeTablePosition tp = new TreeTablePosition(tableView, row, tableView.getColumns().get(col)); 187 return getAnchor() != null && getAnchor().equals(tp); 188 } 189 190 private int getItemCount() { 191 return root.getChildren().size() + child3.getChildren().size(); 192 } 193 194 195 196 /*************************************************************************** 197 * Tests for specific bug reports 198 **************************************************************************/ 199 200 @Test public void test_rt29833_mouse_select_upwards() { 201 sm.setCellSelectionEnabled(false); 202 sm.setSelectionMode(SelectionMode.MULTIPLE); 203 204 sm.clearAndSelect(9); 205 206 // select all from 9 - 7 207 VirtualFlowTestUtils.clickOnRow(tableView, 7, KeyModifier.SHIFT); 208 assertTrue(debug(), isSelected(7,8,9)); 209 210 // select all from 9 - 7 - 5 211 VirtualFlowTestUtils.clickOnRow(tableView, 5, KeyModifier.SHIFT); 212 assertTrue(debug(),isSelected(5,6,7,8,9)); 213 } 214 215 @Test public void test_rt29833_mouse_select_downwards() { 216 sm.setCellSelectionEnabled(false); 217 sm.setSelectionMode(SelectionMode.MULTIPLE); 218 219 sm.clearAndSelect(5); 220 221 // select all from 5 - 7 222 VirtualFlowTestUtils.clickOnRow(tableView, 7, KeyModifier.SHIFT); 223 assertTrue(debug(), isSelected(5,6,7)); 224 225 // select all from 5 - 7 - 9 226 VirtualFlowTestUtils.clickOnRow(tableView, 9, KeyModifier.SHIFT); 227 assertTrue(debug(),isSelected(5,6,7,8,9)); 228 } 229 230 private int rt30394_count = 0; 231 // @Ignore("Ignoring due to RT-37166") 232 @Test public void test_rt30394() { 233 sm.setCellSelectionEnabled(false); 234 sm.setSelectionMode(SelectionMode.MULTIPLE); 235 sm.clearSelection(); 236 237 final TableFocusModel fm = tableView.getFocusModel(); 238 fm.focus(-1); 239 240 fm.focusedIndexProperty().addListener((observable, oldValue, newValue) -> { 241 rt30394_count++; 242 assertEquals(0, fm.getFocusedIndex()); 243 }); 244 245 // test pre-conditions 246 assertEquals(0,rt30394_count); 247 assertFalse(fm.isFocused(0)); 248 249 // select the first row with the shift key held down. The focus event 250 // should only fire once - for focus on 0 (never -1 as this bug shows). 251 VirtualFlowTestUtils.clickOnRow(tableView, 0, KeyModifier.SHIFT); 252 Toolkit.getToolkit().firePulse(); 253 assertEquals(1, rt30394_count); 254 assertTrue(fm.isFocused(0)); 255 } 256 257 @Test public void test_rt32119() { 258 sm.setSelectionMode(SelectionMode.MULTIPLE); 259 sm.clearSelection(); 260 261 // select rows 2, 3, and 4 262 VirtualFlowTestUtils.clickOnRow(tableView, 2); 263 VirtualFlowTestUtils.clickOnRow(tableView, 4, KeyModifier.SHIFT); 264 assertFalse(sm.isSelected(1)); 265 assertTrue(sm.isSelected(2)); 266 assertTrue(sm.isSelected(3)); 267 assertTrue(sm.isSelected(4)); 268 assertFalse(sm.isSelected(5)); 269 270 // now shift click on the 2nd row - this should make only row 2 be 271 // selected. The bug is that row 4 remains selected also. 272 VirtualFlowTestUtils.clickOnRow(tableView, 2, KeyModifier.SHIFT); 273 assertFalse(sm.isSelected(1)); 274 assertTrue(sm.isSelected(2)); 275 assertFalse(sm.isSelected(3)); 276 assertFalse(sm.isSelected(4)); 277 assertFalse(sm.isSelected(5)); 278 } 279 280 @Test public void test_rt31020() { 281 sm.setSelectionMode(SelectionMode.MULTIPLE); 282 sm.clearSelection(); 283 284 // set all the columns to be very narrow (so the mouse click happens 285 // to the right of them all, out in no-mans land 286 tableView.setMinWidth(200); 287 tableView.setPrefWidth(200); 288 tableView.getColumns().clear(); 289 col0.setMaxWidth(10); 290 tableView.getColumns().add(col0); 291 292 // select rows 1, 2, 3, 4, and 5 293 VirtualFlowTestUtils.clickOnRow(tableView, 1, true); 294 VirtualFlowTestUtils.clickOnRow(tableView, 5, true, KeyModifier.SHIFT); 295 assertTrue(sm.isSelected(1)); 296 assertTrue(sm.isSelected(2)); 297 assertTrue(sm.isSelected(3)); 298 assertTrue(sm.isSelected(4)); 299 assertTrue(sm.isSelected(5)); 300 } 301 302 @Test public void test_rt21444_up_cell() { 303 final int items = 8; 304 root.getChildren().clear(); 305 for (int i = 0; i < items; i++) { 306 root.getChildren().add(new TreeItem<>("Row " + i)); 307 } 308 309 final int selectRow = 3; 310 311 tableView.setShowRoot(false); 312 final MultipleSelectionModel<TreeItem<String>> sm = tableView.getSelectionModel(); 313 sm.setSelectionMode(SelectionMode.MULTIPLE); 314 sm.clearAndSelect(selectRow); 315 316 assertEquals(selectRow, sm.getSelectedIndex()); 317 assertEquals("Row 3", sm.getSelectedItem().getValue()); 318 319 VirtualFlowTestUtils.clickOnRow(tableView, selectRow - 1, KeyModifier.SHIFT); 320 assertEquals(2, sm.getSelectedItems().size()); 321 assertEquals("Row 2", sm.getSelectedItem().getValue()); 322 assertEquals("Row 2", sm.getSelectedItems().get(0).getValue()); 323 } 324 325 @Test public void test_rt21444_down_cell() { 326 final int items = 8; 327 root.getChildren().clear(); 328 for (int i = 0; i < items; i++) { 329 root.getChildren().add(new TreeItem<>("Row " + i)); 330 } 331 332 final int selectRow = 3; 333 334 tableView.setShowRoot(false); 335 final MultipleSelectionModel<TreeItem<String>> sm = tableView.getSelectionModel(); 336 sm.setSelectionMode(SelectionMode.MULTIPLE); 337 sm.clearAndSelect(selectRow); 338 339 assertEquals(selectRow, sm.getSelectedIndex()); 340 assertEquals("Row 3", sm.getSelectedItem().getValue()); 341 342 VirtualFlowTestUtils.clickOnRow(tableView, selectRow + 1, KeyModifier.SHIFT); 343 assertEquals("Row 4", sm.getSelectedItem().getValue()); 344 } 345 346 @Test public void test_rt21444_up_row() { 347 final int items = 8; 348 root.getChildren().clear(); 349 for (int i = 0; i < items; i++) { 350 root.getChildren().add(new TreeItem<>("Row " + i)); 351 } 352 353 final int selectRow = 3; 354 355 tableView.setShowRoot(false); 356 final MultipleSelectionModel<TreeItem<String>> sm = tableView.getSelectionModel(); 357 sm.setSelectionMode(SelectionMode.MULTIPLE); 358 sm.clearAndSelect(selectRow); 359 360 assertEquals(selectRow, sm.getSelectedIndex()); 361 assertEquals("Row 3", sm.getSelectedItem().getValue()); 362 363 VirtualFlowTestUtils.clickOnRow(tableView, selectRow - 1, true, KeyModifier.SHIFT); 364 assertEquals(2, sm.getSelectedItems().size()); 365 assertEquals("Row 2", sm.getSelectedItem().getValue()); 366 assertEquals("Row 2", sm.getSelectedItems().get(0).getValue()); 367 } 368 369 @Test public void test_rt21444_down_row() { 370 final int items = 8; 371 root.getChildren().clear(); 372 for (int i = 0; i < items; i++) { 373 root.getChildren().add(new TreeItem<>("Row " + i)); 374 } 375 376 final int selectRow = 3; 377 378 tableView.setShowRoot(false); 379 final MultipleSelectionModel<TreeItem<String>> sm = tableView.getSelectionModel(); 380 sm.setSelectionMode(SelectionMode.MULTIPLE); 381 sm.clearAndSelect(selectRow); 382 383 assertEquals(selectRow, sm.getSelectedIndex()); 384 assertEquals("Row 3", sm.getSelectedItem().getValue()); 385 386 VirtualFlowTestUtils.clickOnRow(tableView, selectRow + 1, true, KeyModifier.SHIFT); 387 assertEquals("Row 4", sm.getSelectedItem().getValue()); 388 } 389 390 @Test public void test_rt32560_cell() { 391 final int items = 8; 392 root.getChildren().clear(); 393 for (int i = 0; i < items; i++) { 394 root.getChildren().add(new TreeItem<>("Row " + i)); 395 } 396 397 final MultipleSelectionModel sm = tableView.getSelectionModel(); 398 sm.setSelectionMode(SelectionMode.MULTIPLE); 399 sm.clearAndSelect(0); 400 401 assertEquals(0, sm.getSelectedIndex()); 402 assertEquals(root, sm.getSelectedItem()); 403 assertEquals(0, fm.getFocusedIndex()); 404 405 VirtualFlowTestUtils.clickOnRow(tableView, 5, KeyModifier.SHIFT); 406 assertEquals(5, sm.getSelectedIndex()); 407 assertEquals(5, fm.getFocusedIndex()); 408 assertEquals(6, sm.getSelectedItems().size()); 409 410 VirtualFlowTestUtils.clickOnRow(tableView, 0, KeyModifier.SHIFT); 411 assertEquals(0, sm.getSelectedIndex()); 412 assertEquals(0, fm.getFocusedIndex()); 413 assertEquals(1, sm.getSelectedItems().size()); 414 } 415 416 @Test public void test_rt32560_row() { 417 final int items = 8; 418 root.getChildren().clear(); 419 for (int i = 0; i < items; i++) { 420 root.getChildren().add(new TreeItem<>("Row " + i)); 421 } 422 423 // StageLoader sl = new StageLoader(tableView); 424 425 tableView.setShowRoot(true); 426 final MultipleSelectionModel sm = tableView.getSelectionModel(); 427 sm.setSelectionMode(SelectionMode.MULTIPLE); 428 sm.clearAndSelect(0); 429 430 assertEquals(0, sm.getSelectedIndex()); 431 assertEquals(root, sm.getSelectedItem()); 432 assertEquals(0, fm.getFocusedIndex()); 433 434 VirtualFlowTestUtils.clickOnRow(tableView, 5, true, KeyModifier.SHIFT); 435 assertEquals(5, sm.getSelectedIndex()); 436 assertEquals(5, fm.getFocusedIndex()); 437 assertEquals(sm.getSelectedItems().toString(), 6, sm.getSelectedItems().size()); 438 439 VirtualFlowTestUtils.clickOnRow(tableView, 0, true, KeyModifier.SHIFT); 440 assertEquals(0, sm.getSelectedIndex()); 441 assertEquals(0, fm.getFocusedIndex()); 442 assertEquals(debug(), 1, sm.getSelectedItems().size()); 443 444 // sl.dispose(); 445 } 446 447 @Test public void test_rt_32963() { 448 final int items = 8; 449 root.getChildren().clear(); 450 root.setExpanded(true); 451 for (int i = 0; i < items; i++) { 452 root.getChildren().add(new TreeItem<>("Row " + i)); 453 } 454 tableView.setRoot(root); 455 456 tableView.setShowRoot(true); 457 final MultipleSelectionModel sm = tableView.getSelectionModel(); 458 sm.setSelectionMode(SelectionMode.MULTIPLE); 459 sm.clearAndSelect(0); 460 461 assertEquals(9, tableView.getExpandedItemCount()); 462 463 assertEquals(0, sm.getSelectedIndex()); 464 assertEquals(0, fm.getFocusedIndex()); 465 assertEquals(root, sm.getSelectedItem()); 466 assertEquals(1, sm.getSelectedItems().size()); 467 468 VirtualFlowTestUtils.clickOnRow(tableView, 5, KeyModifier.SHIFT); 469 assertEquals("Actual selected index: " + sm.getSelectedIndex(), 5, sm.getSelectedIndex()); 470 assertEquals("Actual focused index: " + fm.getFocusedIndex(), 5, fm.getFocusedIndex()); 471 assertTrue("Selected indices: " + sm.getSelectedIndices(), sm.getSelectedIndices().contains(0)); 472 assertTrue("Selected items: " + sm.getSelectedItems(), sm.getSelectedItems().contains(root)); 473 assertEquals(6, sm.getSelectedItems().size()); 474 } 475 476 @Ignore("Test doesn't work - mouse event not firing as expected") 477 @Test public void test_rt_33101() { 478 final int items = 8; 479 root.setValue("New Root"); 480 root.getChildren().clear(); 481 root.setExpanded(true); 482 for (int i = 0; i < items; i++) { 483 root.getChildren().add(new TreeItem<>("Row " + i)); 484 } 485 tableView.setRoot(root); 486 487 StageLoader sl = new StageLoader(tableView); 488 489 tableView.setShowRoot(true); 490 final MultipleSelectionModel sm = tableView.getSelectionModel(); 491 sm.setSelectionMode(SelectionMode.MULTIPLE); 492 sm.clearAndSelect(0); 493 494 TreeTableRow rootRow = (TreeTableRow) VirtualFlowTestUtils.getCell(tableView, 0); 495 Node disclosureNode = rootRow.getDisclosureNode(); 496 497 assertTrue(root.isExpanded()); 498 assertEquals("New Root", rootRow.getTreeItem().getValue()); 499 assertNotNull(disclosureNode); 500 assertTrue(disclosureNode.isVisible()); 501 assertTrue(disclosureNode.getScene() != null); 502 assertEquals(9, tableView.getExpandedItemCount()); 503 504 MouseEventFirer mouse = new MouseEventFirer(disclosureNode); 505 mouse.fireMousePressAndRelease(); 506 assertFalse(root.isExpanded()); 507 assertEquals(1, tableView.getExpandedItemCount()); 508 509 mouse.fireMousePressAndRelease(); 510 assertTrue(root.isExpanded()); 511 assertEquals(9, tableView.getExpandedItemCount()); 512 513 mouse.dispose(); 514 sl.dispose(); 515 } 516 517 private int rt_30626_count = 0; 518 @Test public void test_rt_30626() { 519 final int items = 8; 520 root.getChildren().clear(); 521 root.setExpanded(true); 522 for (int i = 1; i < items; i++) { 523 root.getChildren().add(new TreeItem<>("Row " + i)); 524 } 525 tableView.setRoot(root); 526 527 tableView.setShowRoot(true); 528 final MultipleSelectionModel sm = tableView.getSelectionModel(); 529 sm.setSelectionMode(SelectionMode.MULTIPLE); 530 sm.clearAndSelect(0); 531 532 tableView.getSelectionModel().getSelectedItems().addListener((ListChangeListener) c -> { 533 while (c.next()) { 534 rt_30626_count++; 535 } 536 }); 537 538 Cell cell = VirtualFlowTestUtils.getCell(tableView, 1, 0); 539 MouseEventFirer mouse = new MouseEventFirer(cell); 540 541 assertEquals(0, rt_30626_count); 542 mouse.fireMousePressAndRelease(); 543 assertEquals(1, rt_30626_count); 544 545 mouse.fireMousePressAndRelease(); 546 assertEquals(1, rt_30626_count); 547 } 548 549 @Test public void test_rt_33897_rowSelection() { 550 final int items = 8; 551 root.getChildren().clear(); 552 root.setExpanded(true); 553 for (int i = 0; i < items; i++) { 554 root.getChildren().add(new TreeItem<>("Row " + i)); 555 } 556 tableView.setRoot(root); 557 558 final TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel(); 559 sm.setSelectionMode(SelectionMode.MULTIPLE); 560 sm.setCellSelectionEnabled(false); 561 562 VirtualFlowTestUtils.clickOnRow(tableView, 1); 563 assertEquals(1, sm.getSelectedCells().size()); 564 565 TreeTablePosition pos = sm.getSelectedCells().get(0); 566 assertEquals(1, pos.getRow()); 567 assertNotNull(pos.getTableColumn()); 568 } 569 570 @Test public void test_rt_33897_cellSelection() { 571 final int items = 8; 572 root.getChildren().clear(); 573 root.setExpanded(true); 574 for (int i = 0; i < items; i++) { 575 root.getChildren().add(new TreeItem<>("Row " + i)); 576 } 577 tableView.setRoot(root); 578 579 final TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel(); 580 sm.setSelectionMode(SelectionMode.MULTIPLE); 581 sm.setCellSelectionEnabled(true); 582 583 VirtualFlowTestUtils.clickOnRow(tableView, 1); 584 assertEquals(1, sm.getSelectedCells().size()); 585 586 TreeTablePosition pos = sm.getSelectedCells().get(0); 587 assertEquals(1, pos.getRow()); 588 assertNotNull(pos.getTableColumn()); 589 } 590 591 @Test public void test_rt_34649() { 592 final int items = 8; 593 root.getChildren().clear(); 594 root.setExpanded(true); 595 for (int i = 0; i < items; i++) { 596 root.getChildren().add(new TreeItem<>("Row " + i)); 597 } 598 tableView.setRoot(root); 599 600 final MultipleSelectionModel sm = tableView.getSelectionModel(); 601 final FocusModel fm = tableView.getFocusModel(); 602 sm.setSelectionMode(SelectionMode.SINGLE); 603 604 assertFalse(sm.isSelected(4)); 605 assertFalse(fm.isFocused(4)); 606 VirtualFlowTestUtils.clickOnRow(tableView, 4, true, KeyModifier.getShortcutKey()); 607 assertTrue(sm.isSelected(4)); 608 assertTrue(fm.isFocused(4)); 609 610 VirtualFlowTestUtils.clickOnRow(tableView, 4, true, KeyModifier.getShortcutKey()); 611 assertFalse(sm.isSelected(4)); 612 assertTrue(fm.isFocused(4)); 613 } 614 615 @Test public void test_rt_35338() { 616 root.getChildren().clear(); 617 tableView.setRoot(root); 618 tableView.getColumns().setAll(col0); 619 620 col0.setWidth(20); 621 tableView.setMinWidth(1000); 622 tableView.setMinWidth(1000); 623 624 TreeTableRow row = (TreeTableRow) VirtualFlowTestUtils.getCell(tableView, 4); 625 assertNotNull(row); 626 assertNull(row.getItem()); 627 assertEquals(4, row.getIndex()); 628 629 MouseEventFirer mouse = new MouseEventFirer(row); 630 mouse.fireMousePressAndRelease(1, 100, 10); 631 mouse.dispose(); 632 } 633 634 @Test public void test_rt_36509() { 635 final int items = 8; 636 root.getChildren().clear(); 637 root.setExpanded(false); 638 for (int i = 0; i < items; i++) { 639 root.getChildren().add(new TreeItem<>("Row " + i)); 640 } 641 tableView.setRoot(root); 642 643 // expand 644 assertFalse(root.isExpanded()); 645 VirtualFlowTestUtils.clickOnRow(tableView, 0, 2); 646 assertTrue(root.isExpanded()); 647 648 // collapse 649 VirtualFlowTestUtils.clickOnRow(tableView, 0, 2); 650 assertFalse(root.isExpanded()); 651 652 // expand again 653 VirtualFlowTestUtils.clickOnRow(tableView, 0, 2); 654 assertTrue(root.isExpanded()); 655 } 656 657 @Test public void test_rt_37069() { 658 final int items = 8; 659 root.getChildren().clear(); 660 root.setExpanded(false); 661 for (int i = 0; i < items; i++) { 662 root.getChildren().add(new TreeItem<>("Row " + i)); 663 } 664 tableView.setRoot(root); 665 tableView.setFocusTraversable(false); 666 667 Button btn = new Button("Button"); 668 VBox vbox = new VBox(btn, tableView); 669 670 StageLoader sl = new StageLoader(vbox); 671 sl.getStage().requestFocus(); 672 btn.requestFocus(); 673 Toolkit.getToolkit().firePulse(); 674 Scene scene = sl.getStage().getScene(); 675 676 assertTrue(btn.isFocused()); 677 assertFalse(tableView.isFocused()); 678 679 ScrollBar vbar = VirtualFlowTestUtils.getVirtualFlowVerticalScrollbar(tableView); 680 MouseEventFirer mouse = new MouseEventFirer(vbar); 681 mouse.fireMousePressAndRelease(); 682 683 assertTrue(btn.isFocused()); 684 assertFalse(tableView.isFocused()); 685 686 sl.dispose(); 687 } 688 689 @Test public void test_rt_38306_selectFirstRow() { 690 test_rt_38306(false); 691 } 692 693 @Test public void test_rt_38306_selectFirstTwoRows() { 694 test_rt_38306(true); 695 } 696 697 private void test_rt_38306(boolean selectTwoRows) { 698 TreeItem<Person> root = new TreeItem<>(); 699 root.getChildren().addAll( 700 new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")), 701 new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")), 702 new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")), 703 new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")), 704 new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com")) 705 ); 706 707 TreeTableView<Person> table = new TreeTableView<>(); 708 table.setRoot(root); 709 root.setExpanded(true); 710 table.setShowRoot(false); 711 712 TreeTableView.TreeTableViewSelectionModel sm = table.getSelectionModel(); 713 sm.setCellSelectionEnabled(true); 714 sm.setSelectionMode(SelectionMode.MULTIPLE); 715 716 TreeTableColumn firstNameCol = new TreeTableColumn("First Name"); 717 firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName")); 718 719 TreeTableColumn lastNameCol = new TreeTableColumn("Last Name"); 720 lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName")); 721 722 TreeTableColumn emailCol = new TreeTableColumn("Email"); 723 emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email")); 724 725 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 726 727 sm.select(0, firstNameCol); 728 729 assertTrue(sm.isSelected(0, firstNameCol)); 730 assertEquals(1, sm.getSelectedCells().size()); 731 732 TreeTableCell cell_0_0 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 0); 733 TreeTableCell cell_0_1 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 1); 734 TreeTableCell cell_0_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 2); 735 736 TreeTableCell cell_1_0 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 0); 737 TreeTableCell cell_1_1 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 1); 738 TreeTableCell cell_1_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 2); 739 740 MouseEventFirer mouse = selectTwoRows ? 741 new MouseEventFirer(cell_1_2) : new MouseEventFirer(cell_0_2); 742 743 mouse.fireMousePressAndRelease(KeyModifier.SHIFT); 744 745 assertTrue(sm.isSelected(0, firstNameCol)); 746 assertTrue(sm.isSelected(0, lastNameCol)); 747 assertTrue(sm.isSelected(0, emailCol)); 748 749 if (selectTwoRows) { 750 assertTrue(sm.isSelected(1, firstNameCol)); 751 assertTrue(sm.isSelected(1, lastNameCol)); 752 assertTrue(sm.isSelected(1, emailCol)); 753 } 754 755 assertEquals(selectTwoRows ? 6 : 3, sm.getSelectedCells().size()); 756 757 assertTrue(cell_0_0.isSelected()); 758 assertTrue(cell_0_1.isSelected()); 759 assertTrue(cell_0_2.isSelected()); 760 761 if (selectTwoRows) { 762 assertTrue(cell_1_0.isSelected()); 763 assertTrue(cell_1_1.isSelected()); 764 assertTrue(cell_1_2.isSelected()); 765 } 766 } 767 768 @Test public void test_rt_38464_rowSelection() { 769 ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList( 770 new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")), 771 new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")), 772 new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")), 773 new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")), 774 new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com"))); 775 776 TreeTableView<Person> table = new TreeTableView<>(); 777 778 TreeItem<Person> root = new TreeItem<Person>(new Person("Root", null, null)); 779 root.setExpanded(true); 780 table.setRoot(root); 781 table.setShowRoot(false); 782 root.getChildren().setAll(persons); 783 784 TreeTableColumn firstNameCol = new TreeTableColumn("First Name"); 785 firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName")); 786 787 TreeTableColumn lastNameCol = new TreeTableColumn("Last Name"); 788 lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName")); 789 790 TreeTableColumn emailCol = new TreeTableColumn("Email"); 791 emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email")); 792 793 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 794 795 sm = table.getSelectionModel(); 796 sm.setCellSelectionEnabled(false); 797 sm.setSelectionMode(SelectionMode.MULTIPLE); 798 799 sm.clearSelection(); 800 sm.select(0, lastNameCol); 801 802 assertTrue(sm.isSelected(0, lastNameCol)); 803 assertEquals(1, sm.getSelectedCells().size()); 804 805 TreeTableCell cell_4_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 4, 1); 806 807 MouseEventFirer mouse = new MouseEventFirer(cell_4_2); 808 mouse.fireMousePressAndRelease(KeyModifier.SHIFT); 809 810 // we are in row selection mode, so all cells in the selected rows should 811 // be selected. We test this per-cell, but also per-row. 812 for (int row = 0; row < 5; row++) { 813 // test that the selection model is accurate 814 assertTrue(sm.isSelected(row, firstNameCol)); 815 assertTrue(sm.isSelected(row, lastNameCol)); 816 assertTrue(sm.isSelected(row, emailCol)); 817 assertTrue(sm.isSelected(row)); 818 819 // and assert that the visuals are accurate 820 // (TableCells should not be selected, but TableRows should be) 821 for (int column = 0; column < 3; column++) { 822 if (row == 4 && column == 2) { 823 // bizarrely cell (4,2), i.e. the bottom-right cell consisting 824 // of Michael Brown's email address, doesn't exist. 825 continue; 826 } 827 TreeTableCell cell = (TreeTableCell) VirtualFlowTestUtils.getCell(table, row, column); 828 assertFalse("cell[row: " + row + ", column: " + column + "] is selected, but shouldn't be", cell.isSelected()); 829 } 830 TreeTableRow cell = (TreeTableRow) VirtualFlowTestUtils.getCell(table, row); 831 assertTrue(cell.isSelected()); 832 } 833 } 834 835 @Test public void test_rt_38464_cellSelection() { 836 ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList( 837 new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")), 838 new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")), 839 new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")), 840 new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")), 841 new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com"))); 842 843 TreeTableView<Person> table = new TreeTableView<>(); 844 845 TreeItem<Person> root = new TreeItem<>(new Person("Root", null, null)); 846 root.setExpanded(true); 847 table.setRoot(root); 848 table.setShowRoot(false); 849 root.getChildren().setAll(persons); 850 851 TreeTableColumn firstNameCol = new TreeTableColumn("First Name"); 852 firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName")); 853 854 TreeTableColumn lastNameCol = new TreeTableColumn("Last Name"); 855 lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName")); 856 857 TreeTableColumn emailCol = new TreeTableColumn("Email"); 858 emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email")); 859 860 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 861 862 sm = table.getSelectionModel(); 863 sm.setCellSelectionEnabled(true); 864 sm.setSelectionMode(SelectionMode.MULTIPLE); 865 866 sm.clearSelection(); 867 sm.select(0, emailCol); 868 table.getFocusModel().focus(0, emailCol); 869 870 assertTrue(sm.isSelected(0, emailCol)); 871 assertEquals(1, sm.getSelectedCells().size()); 872 873 TreeTableCell cell_4_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 4, 2); 874 assertEquals(emailCol, cell_4_2.getTableColumn()); 875 876 new MouseEventFirer(cell_4_2).fireMousePressAndRelease(KeyModifier.SHIFT); 877 878 for (int row = 0; row < 5; row++) { 879 // test that the selection model is accurate 880 assertFalse(sm.isSelected(row, firstNameCol)); 881 assertFalse(sm.isSelected(row, lastNameCol)); 882 assertTrue(sm.isSelected(row, emailCol)); 883 assertFalse(sm.isSelected(row)); 884 885 // and assert that the visuals are accurate 886 // (some TableCells should be selected, but TableRows should not be) 887 for (int column = 0; column < 3; column++) { 888 if (row == 4 && column == 2) { 889 // bizarrely cell (4,2), i.e. the bottom-right cell consisting 890 // of Michael Brown's email address, doesn't exist. 891 continue; 892 } 893 TreeTableCell cell = (TreeTableCell) VirtualFlowTestUtils.getCell(table, row, column); 894 assertEquals(column == 2 ? true : false, cell.isSelected()); 895 } 896 TreeTableRow cell = (TreeTableRow) VirtualFlowTestUtils.getCell(table, row); 897 assertFalse(cell.isSelected()); 898 } 899 } 900 901 @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_cellSelection_singleSelection() { 902 test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(true, true); 903 } 904 905 @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_cellSelection_multipleSelection() { 906 test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(true, false); 907 } 908 909 @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_rowSelection_singleSelection() { 910 test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(false, true); 911 } 912 913 @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_rowSelection_multipleSelection() { 914 test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(false, false); 915 } 916 917 private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean cellSelection, boolean singleSelection) { 918 ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList( 919 new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")), 920 new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")), 921 new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")), 922 new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")), 923 new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com"))); 924 925 TreeTableView<Person> table = new TreeTableView<>(); 926 927 TreeItem<Person> root = new TreeItem<Person>(new Person("Root", null, null)); 928 root.setExpanded(true); 929 table.setRoot(root); 930 table.setShowRoot(false); 931 root.getChildren().setAll(persons); 932 933 TreeTableColumn firstNameCol = new TreeTableColumn("First Name"); 934 firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName")); 935 936 TreeTableColumn lastNameCol = new TreeTableColumn("Last Name"); 937 lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName")); 938 939 TreeTableColumn emailCol = new TreeTableColumn("Email"); 940 emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email")); 941 942 table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 943 944 TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel(); 945 sm.setCellSelectionEnabled(cellSelection); 946 sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE); 947 948 TreeTableCell cell_0_0 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 0); 949 TreeTableCell cell_0_1 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 1); 950 TreeTableCell cell_0_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 2); 951 952 sm.clearSelection(); 953 954 // click on cell (0,0). 955 new MouseEventFirer(cell_0_0).fireMousePressAndRelease(); 956 957 if (cellSelection) { 958 // Because we are in cell selection mode, this has the effect of 959 // selecting just the one cell. 960 assertFalse(sm.isSelected(0)); 961 assertTrue(sm.isSelected(0, firstNameCol)); 962 assertFalse(sm.isSelected(0, lastNameCol)); 963 assertFalse(sm.isSelected(0, emailCol)); 964 assertEquals(1, sm.getSelectedCells().size()); 965 assertEquals(0, sm.getSelectedCells().get(0).getRow()); 966 assertEquals(firstNameCol, sm.getSelectedCells().get(0).getTableColumn()); 967 } else { 968 // Because we are in row selection mode, this has 969 // the effect of selecting all cells and the backing row. However, the 970 // selected cell will be (0, firstNameCol) only 971 assertTrue(sm.isSelected(0)); 972 assertTrue(sm.isSelected(0, firstNameCol)); 973 assertTrue(sm.isSelected(0, lastNameCol)); 974 assertTrue(sm.isSelected(0, emailCol)); 975 assertEquals(1, sm.getSelectedCells().size()); 976 assertEquals(0, sm.getSelectedCells().get(0).getRow()); 977 assertEquals(firstNameCol, sm.getSelectedCells().get(0).getTableColumn()); 978 } 979 980 // click on cell (0,1). 981 new MouseEventFirer(cell_0_1).fireMousePressAndRelease(); 982 983 if (cellSelection) { 984 // Everything should remain the same, except the 985 // column of the single selected cell should change to lastNameCol. 986 assertFalse(sm.isSelected(0)); 987 assertFalse(sm.isSelected(0, firstNameCol)); 988 assertTrue(sm.isSelected(0, lastNameCol)); 989 assertFalse(sm.isSelected(0, emailCol)); 990 assertEquals(1, sm.getSelectedCells().size()); 991 TreeTablePosition<?,?> cell = sm.getSelectedCells().get(0); 992 assertEquals(0, cell.getRow()); 993 assertEquals(lastNameCol, cell.getTableColumn()); 994 } else { 995 // Everything should remain the same, except the 996 // column of the single selected cell should change to lastNameCol. 997 assertTrue(sm.isSelected(0)); 998 assertTrue(sm.isSelected(0, firstNameCol)); 999 assertTrue(sm.isSelected(0, lastNameCol)); 1000 assertTrue(sm.isSelected(0, emailCol)); 1001 assertEquals(1, sm.getSelectedCells().size()); 1002 TreeTablePosition<?,?> cell = sm.getSelectedCells().get(0); 1003 assertEquals(0, cell.getRow()); 1004 assertEquals(lastNameCol, cell.getTableColumn()); 1005 } 1006 } 1007 }