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.TableCellBehavior;
  29 import com.sun.javafx.scene.control.behavior.TreeTableCellBehavior;
  30 import javafx.beans.property.ReadOnlyStringWrapper;
  31 import javafx.collections.FXCollections;
  32 import javafx.collections.ListChangeListener;
  33 import javafx.collections.ObservableList;
  34 import javafx.scene.input.KeyCode;
  35 import java.util.List;
  36 import java.util.function.Function;
  37 
  38 import com.sun.javafx.PlatformUtil;
  39 import com.sun.javafx.util.Utils;
  40 import com.sun.javafx.scene.control.behavior.TreeTableViewAnchorRetriever;
  41 import com.sun.javafx.scene.control.infrastructure.ControlTestUtils;
  42 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
  43 import com.sun.javafx.scene.control.infrastructure.KeyModifier;
  44 import com.sun.javafx.scene.control.infrastructure.StageLoader;
  45 import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
  46 import com.sun.javafx.tk.Toolkit;
  47 import org.junit.After;
  48 import org.junit.Before;
  49 import org.junit.Ignore;
  50 import org.junit.Test;
  51 import static org.junit.Assert.assertEquals;
  52 import static org.junit.Assert.assertFalse;
  53 import static org.junit.Assert.assertNotSame;
  54 import static org.junit.Assert.assertNull;
  55 import static org.junit.Assert.assertTrue;
  56 import static org.junit.Assert.fail;
  57 
  58 public class TreeTableViewKeyInputTest {
  59     private TreeTableView<String> tableView;
  60     private TreeTableView.TreeTableViewSelectionModel<String> sm;
  61     private TreeTableView.TreeTableViewFocusModel<String> fm;
  62     
  63     private KeyEventFirer keyboard;
  64     
  65     private StageLoader stageLoader;
  66     
  67     private TreeTableColumn<String, String> col0;
  68     private TreeTableColumn<String, String> col1;
  69     private TreeTableColumn<String, String> col2;
  70     private TreeTableColumn<String, String> col3;
  71     private TreeTableColumn<String, String> col4;
  72     
  73     private final TreeItem<String> root = new TreeItem<String>("Root");                     // 0
  74         private final TreeItem<String> child1 = new TreeItem<String>("Child 1");            // 1
  75         private final TreeItem<String> child2 = new TreeItem<String>("Child 2");            // 2
  76         private final TreeItem<String> child3 = new TreeItem<String>("Child 3");            // 3
  77             private final TreeItem<String> subchild1 = new TreeItem<String>("Subchild 1");  // 4
  78             private final TreeItem<String> subchild2 = new TreeItem<String>("Subchild 2");  // 5
  79             private final TreeItem<String> subchild3 = new TreeItem<String>("Subchild 3");  // 6
  80         private final TreeItem<String> child4 = new TreeItem<String>("Child 4");            // 7
  81         private final TreeItem<String> child5 = new TreeItem<String>("Child 5");            // 8
  82         private final TreeItem<String> child6 = new TreeItem<String>("Child 6");            // 9
  83         private final TreeItem<String> child7 = new TreeItem<String>("Child 7");            // 10
  84         private final TreeItem<String> child8 = new TreeItem<String>("Child 8");            // 11
  85         private final TreeItem<String> child9 = new TreeItem<String>("Child 9");            // 12
  86         private final TreeItem<String> child10 = new TreeItem<String>("Child 10");          // 13
  87     
  88     @Before public void setup() {
  89         // reset tree structure
  90         root.getChildren().clear();
  91         root.setExpanded(true);
  92         root.getChildren().setAll(child1, child2, child3, child4, child5, child6, child7, child8, child9, child10 );
  93         child1.getChildren().clear();
  94         child1.setExpanded(false);
  95         child2.getChildren().clear();
  96         child2.setExpanded(false);
  97         child3.getChildren().clear();
  98         child3.setExpanded(true);
  99         child3.getChildren().setAll(subchild1, subchild2, subchild3);
 100         child4.getChildren().clear();
 101         child4.setExpanded(false);
 102         child5.getChildren().clear();
 103         child5.setExpanded(false);
 104         child6.getChildren().clear();
 105         child6.setExpanded(false);
 106         child7.getChildren().clear();
 107         child7.setExpanded(false);
 108         child8.getChildren().clear();
 109         child8.setExpanded(false);
 110         child9.getChildren().clear();
 111         child9.setExpanded(false);
 112         child10.getChildren().clear();
 113         child10.setExpanded(false);
 114         
 115         tableView = new TreeTableView<String>();
 116         sm = tableView.getSelectionModel();
 117         fm = tableView.getFocusModel();
 118         
 119         sm.setSelectionMode(SelectionMode.MULTIPLE);
 120         sm.setCellSelectionEnabled(false);
 121         
 122         tableView.setRoot(root);
 123 
 124         col0 = new TreeTableColumn<String, String>("col0");
 125         col1 = new TreeTableColumn<String, String>("col1");
 126         col2 = new TreeTableColumn<String, String>("col2");
 127         col3 = new TreeTableColumn<String, String>("col3");
 128         col4 = new TreeTableColumn<String, String>("col4");
 129         tableView.getColumns().setAll(col0, col1, col2, col3, col4);
 130         
 131         keyboard = new KeyEventFirer(tableView);
 132         
 133         stageLoader = new StageLoader(tableView);
 134         stageLoader.getStage().show();
 135     }
 136     
 137     @After public void tearDown() {
 138         tableView.getSkin().dispose();
 139         stageLoader.dispose();
 140     }
 141     
 142     /***************************************************************************
 143      * Util methods
 144      **************************************************************************/
 145     
 146     private String debug() {
 147         StringBuilder sb = new StringBuilder("Selected Cells: [");
 148         
 149         List<TreeTablePosition<String,?>> cells = sm.getSelectedCells();
 150         for (TreeTablePosition<String,?> tp : cells) {
 151             sb.append("(");
 152             sb.append(tp.getRow());
 153             sb.append(",");
 154             sb.append(tp.getColumn());
 155             sb.append("), ");
 156         }
 157         
 158         sb.append("] \nFocus: (" + fm.getFocusedCell().getRow() + ", " + fm.getFocusedCell().getColumn() + ")");
 159         
 160         TreeTablePosition anchor = getAnchor();
 161         sb.append(" \nAnchor: (" + (anchor == null ? "null" : anchor.getRow()) + 
 162                 ", " + (anchor == null ? "null" : anchor.getColumn()) + ")");
 163         return sb.toString();
 164     }
 165     
 166     // Returns true if ALL indices are selected
 167     private boolean isSelected(int... indices) {
 168         for (int index : indices) {
 169             if (! sm.isSelected(index)) {
 170                 System.out.println("Index " + index + " is not selected, but it is expected to be (selected indices: " + sm.getSelectedIndices() + ")");
 171                 return false;
 172             }
 173         }
 174         return true;
 175     }
 176     
 177     // Returns true if ALL indices are NOT selected
 178     private boolean isNotSelected(int... indices) {
 179         for (int index : indices) {
 180             if (sm.isSelected(index)) {
 181                 System.out.println("Index " + index + " is selected, but it is not expected to be");
 182                 return false;
 183             }
 184         }
 185         return true;
 186     }
 187     
 188     private TreeTablePosition getAnchor() {
 189         return TreeTableViewAnchorRetriever.getAnchor(tableView);
 190     }
 191     
 192     private boolean isAnchor(int row) {
 193         TreeTablePosition tp = new TreeTablePosition(tableView, row, null);
 194         return getAnchor() != null && getAnchor().equals(tp);
 195     }
 196     
 197     private boolean isAnchor(int row, int col) {
 198         TreeTablePosition tp = new TreeTablePosition(tableView, row, tableView.getColumns().get(col));
 199         return getAnchor() != null && getAnchor().equals(tp);
 200     }
 201     
 202     private int getItemCount() {
 203         return root.getChildren().size() + child3.getChildren().size();
 204     }
 205     
 206     
 207     
 208     /***************************************************************************
 209      * 
 210      * 
 211      * Tests taken from TableViewKeyInputTest
 212      * (scroll down further for the TreeViewKeyInputTests)
 213      * 
 214      * 
 215      **************************************************************************/    
 216     
 217     
 218     /***************************************************************************
 219      * General tests
 220      **************************************************************************/    
 221     
 222     @Test public void testInitialState() {
 223         assertEquals(-1, sm.getSelectedIndex());
 224         assertEquals(0, sm.getSelectedCells().size());
 225         assertEquals(0, sm.getSelectedIndices().size());
 226         assertEquals(0, sm.getSelectedItems().size());
 227     }
 228     
 229     
 230     /***************************************************************************
 231      * Tests for row-based single selection
 232      **************************************************************************/
 233     
 234     @Test public void testDownArrowChangesSelection() {
 235         sm.clearAndSelect(0);
 236         keyboard.doDownArrowPress();
 237         assertFalse(sm.isSelected(0));
 238         assertTrue(sm.isSelected(1));
 239     }
 240     
 241     @Test public void testDownArrowDoesNotChangeSelectionWhenAtLastIndex() {
 242         int endIndex = tableView.getExpandedItemCount() - 1;
 243         sm.clearAndSelect(endIndex);
 244         assertTrue(sm.isSelected(endIndex));
 245         keyboard.doDownArrowPress();
 246         assertTrue(sm.isSelected(endIndex));
 247     }
 248     
 249     @Test public void testUpArrowDoesNotChangeSelectionWhenAt0Index() {
 250         sm.clearAndSelect(0);
 251         keyboard.doUpArrowPress();
 252         assertTrue(sm.isSelected(0));
 253         assertEquals(1, sm.getSelectedCells().size());
 254         assertEquals(1, sm.getSelectedIndices().size());
 255         assertEquals(1, sm.getSelectedItems().size());
 256     }
 257     
 258     @Test public void testUpArrowChangesSelection() {
 259         sm.clearAndSelect(1);
 260         keyboard.doUpArrowPress();
 261         assertFalse(sm.isSelected(1));
 262         assertTrue(sm.isSelected(0));
 263     }
 264     
 265     @Test public void testLeftArrowDoesNotChangeState() {
 266         keyboard.doLeftArrowPress();
 267         testInitialState();
 268     }
 269     
 270 //    @Test public void testRightArrowDoesNotChangeState() {
 271 //        keyboard.doRightArrowPress();
 272 //        testInitialState();
 273 //    }
 274     
 275     /* test 19
 276     @Test public void testCtrlDownMovesFocusButLeavesSelectionAlone() {
 277         assertTrue(fm.isFocused(0));
 278         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 279         assertTrue(fm.isFocused(1));
 280         assertTrue(sm.isSelected(0));
 281         assertFalse(sm.isSelected(1));
 282     } */
 283     
 284     // test 20
 285     @Test public void testCtrlUpDoesNotMoveFocus() {
 286         sm.clearAndSelect(0);
 287         assertTrue(fm.isFocused(0));
 288         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 289         assertTrue(fm.isFocused(0));
 290         assertTrue(sm.isSelected(0));
 291     }
 292     
 293     // test 21
 294     @Test public void testCtrlLeftDoesNotMoveFocus() {
 295         sm.clearAndSelect(0);
 296         assertTrue(fm.isFocused(0));
 297         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
 298         assertTrue(fm.isFocused(0));
 299         assertTrue(sm.isSelected(0));
 300     }
 301     
 302     // test 22
 303     @Test public void testCtrlRightDoesNotMoveFocus() {
 304         sm.clearAndSelect(0);
 305         assertTrue(fm.isFocused(0));
 306         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
 307         assertTrue(fm.isFocused(0));
 308         assertTrue(sm.isSelected(0));
 309     }
 310     
 311     /* test 23
 312     @Test public void testCtrlUpMovesFocus() {
 313         sm.clearAndSelect(1);
 314         assertTrue(fm.isFocused(1));
 315         assertTrue(sm.isSelected(1));
 316         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 317         assertTrue(fm.isFocused(0));
 318         assertTrue(sm.isSelected(1));
 319     } */
 320     
 321     // test 24
 322     @Test public void testCtrlDownDoesNotMoveFocusWhenAtLastIndex() {
 323         int endIndex = tableView.getExpandedItemCount() - 1;
 324         sm.clearAndSelect(endIndex);
 325         assertTrue(fm.isFocused(endIndex));
 326         assertTrue(sm.isSelected(endIndex));
 327         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 328         assertTrue(fm.isFocused(endIndex));
 329         assertTrue(sm.isSelected(endIndex));
 330     }
 331     
 332     /* test 25
 333     @Test public void testCtrlDownArrowWithSpaceChangesAnchor() {
 334         sm.clearAndSelect(0);
 335         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 336         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 337         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey());  // select 2
 338         assertTrue(isSelected(0, 2));
 339         assertTrue(isNotSelected(1));
 340         assertTrue(isAnchor(2));
 341     } */
 342     
 343     /* test 26
 344     @Test public void testCtrlUpArrowWithSpaceChangesAnchor() {
 345         sm.clearAndSelect(2);
 346         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 347         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 348         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey());  // select 0
 349         assertTrue(isSelected(0, 2));
 350         assertTrue(isNotSelected(1));
 351         assertTrue(isAnchor(0));
 352     } */
 353     
 354     // test 44
 355     @Test public void testHomeKey() {
 356         sm.clearAndSelect(3);
 357         keyboard.doKeyPress(KeyCode.HOME);
 358         assertTrue(isSelected(0));
 359         assertTrue(isNotSelected(1,2,3));
 360     }
 361     
 362     // test 45
 363     @Test public void testEndKey() {
 364         sm.clearAndSelect(3);
 365         keyboard.doKeyPress(KeyCode.END);
 366         assertTrue(isSelected(tableView.getExpandedItemCount() - 1));
 367         assertTrue(isNotSelected(1,2,3));
 368     }
 369     
 370     /* test 53
 371     @Test public void testCtrlHome() {
 372         sm.clearAndSelect(5);
 373         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey());
 374         assertTrue(isSelected(5));
 375         assertTrue(fm.isFocused(0));
 376     } */
 377     
 378     /* test 54
 379     @Test public void testCtrlEnd() {
 380         sm.clearAndSelect(5);
 381         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey());
 382         assertTrue(isSelected(5));
 383         assertTrue(fm.isFocused(tableView.getItems().size() - 1));
 384     } */
 385     
 386     /* test 68
 387     @Test public void testCtrlSpaceToClearSelection() {
 388         sm.clearAndSelect(5);
 389         assertTrue(isSelected(5));
 390         assertTrue(fm.isFocused(5));
 391         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey());
 392         assertTrue(isNotSelected(5));
 393         assertTrue(debug(), fm.isFocused(5));
 394         assertTrue(isAnchor(5));
 395     } */
 396     
 397     
 398     
 399     /***************************************************************************
 400      * Tests for row-based multiple selection
 401      **************************************************************************/
 402     
 403     @Test public void testShiftDownArrowIncreasesSelection() {
 404         sm.clearAndSelect(0);
 405         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 406         assertTrue(sm.isSelected(0));
 407         assertTrue(sm.isSelected(1));
 408     }
 409     
 410     @Test public void testShiftDownArrowDoesNotChangeSelectionWhenAtLastIndex() {
 411         int endIndex = tableView.getExpandedItemCount() - 1;
 412         sm.clearAndSelect(endIndex);
 413         assertTrue(sm.isSelected(endIndex));
 414         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 415         assertTrue(sm.isSelected(endIndex));
 416     }
 417     
 418     @Test public void testShiftUpArrowIncreasesSelection() {
 419         sm.clearAndSelect(1);
 420         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 421         assertTrue(sm.isSelected(0));
 422         assertTrue(sm.isSelected(1));
 423     }
 424     
 425     @Test public void testShiftUpArrowWhenAt0Index() {
 426         sm.clearAndSelect(0);
 427         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 428         assertTrue(sm.isSelected(0));
 429     }
 430     
 431     @Test public void testShiftLeftArrowWhenAt0Index() {
 432         sm.clearAndSelect(0);
 433         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 434         assertTrue(sm.isSelected(0));
 435         assertFalse(sm.isSelected(1));
 436     }
 437     
 438     @Test public void testShiftRightArrowWhenAt0Index() {
 439         sm.clearAndSelect(0);
 440         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 441         assertTrue(sm.isSelected(0));
 442         assertFalse(sm.isSelected(1));
 443     }
 444     
 445     @Test public void testShiftDownTwiceThenShiftUp() {
 446         sm.clearAndSelect(0);
 447         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 448         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 449         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 450         assertTrue(debug(), isSelected(0, 1));
 451         assertTrue(debug(), isNotSelected(2));
 452     }
 453     
 454     @Test public void testShiftUpTwiceThenShiftDownFrom0Index() {
 455         sm.clearAndSelect(0);
 456         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 457         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 458         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 459         assertTrue(sm.isSelected(0));
 460         assertTrue(sm.isSelected(1));
 461         assertFalse(sm.isSelected(2));
 462     }
 463     
 464     @Test public void testShiftLeftTwiceThenShiftRight() {
 465         sm.clearAndSelect(0);
 466         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 467         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 468         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 469         assertTrue(sm.isSelected(0));
 470         assertFalse(sm.isSelected(1));
 471         assertFalse(sm.isSelected(2));
 472     }
 473     
 474     @Test public void testShiftRightTwiceThenShiftLeft() {
 475         sm.clearAndSelect(0);
 476         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 477         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 478         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 479         assertTrue(sm.isSelected(0));
 480         assertFalse(sm.isSelected(1));
 481         assertFalse(sm.isSelected(2));
 482     }
 483     
 484     @Test public void testShiftUpTwiceThenShiftDown() {
 485         sm.clearAndSelect(2);                           // select 2
 486         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // also select 1
 487         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // also select 0
 488         keyboard.doDownArrowPress(KeyModifier.SHIFT);   // deselect 0
 489         assertFalse(debug(), sm.isSelected(0));
 490         assertTrue(sm.isSelected(1));
 491         assertTrue(sm.isSelected(2));
 492         assertFalse(sm.isSelected(3));
 493     }
 494     
 495     // test 18 from Jindra's testcases.rtf file
 496     @Test public void testShiftDownTwiceThenShiftUpWhenAtLastIndex() {
 497         int endIndex = tableView.getExpandedItemCount() - 1;
 498         sm.clearAndSelect(endIndex);
 499         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 500         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 501         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 502         assertTrue(sm.isSelected(endIndex));
 503         assertTrue(sm.isSelected(endIndex - 1));
 504         assertFalse(sm.isSelected(endIndex - 2));
 505     }
 506     
 507     // test 27
 508     @Test public void testCtrlDownArrowWithSpaceChangesAnchor_extended() {
 509         sm.clearAndSelect(0);
 510         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 511         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 512         keyboard.doKeyPress(KeyCode.SPACE, 
 513                 KeyModifier.getShortcutKey(),
 514                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 2
 515         
 516         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 517         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 518         keyboard.doKeyPress(KeyCode.SPACE, 
 519                 KeyModifier.getShortcutKey(),
 520                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // deselect 0
 521         assertTrue(isSelected(2));
 522         assertTrue(isNotSelected(0, 1));
 523         assertTrue(isAnchor(0));
 524     } 
 525     
 526     // test 28
 527     @Test public void testCtrlUpArrowWithSpaceChangesAnchor_extended() {
 528         sm.clearAndSelect(2);
 529         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 530         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 531         keyboard.doKeyPress(KeyCode.SPACE, 
 532                 KeyModifier.getShortcutKey(),
 533                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 0
 534         
 535         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 536         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 537         keyboard.doKeyPress(KeyCode.SPACE, 
 538                 KeyModifier.getShortcutKey(),
 539                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // deselect 2
 540         assertTrue(isSelected(0));
 541         assertTrue(isNotSelected(1, 2));
 542         assertTrue(isAnchor(2));
 543     }
 544     
 545     // test 29
 546     @Test public void testCtrlDownArrowWithSpaceChangesAnchor_extended2() {
 547         sm.clearAndSelect(0);
 548         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 549         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 550         keyboard.doKeyPress(KeyCode.SPACE, 
 551                 KeyModifier.getShortcutKey(),
 552                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 2
 553         
 554         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 555         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 556         keyboard.doKeyPress(KeyCode.SPACE, 
 557                 KeyModifier.getShortcutKey(),
 558                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 4
 559         assertTrue(isSelected(0, 2, 4));
 560         assertTrue(isNotSelected(1, 3, 5));
 561         assertTrue(isAnchor(4));
 562     }
 563     
 564     // test 30
 565     @Test public void testCtrlUpArrowWithSpaceChangesAnchor_extended2() {
 566         sm.clearAndSelect(4);
 567         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 568         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 569         keyboard.doKeyPress(KeyCode.SPACE, 
 570                 KeyModifier.getShortcutKey(),
 571                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 2
 572         
 573         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 574         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 575         keyboard.doKeyPress(KeyCode.SPACE, 
 576                 KeyModifier.getShortcutKey(),
 577                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 0
 578         assertTrue(isSelected(0, 2, 4));
 579         assertTrue(isNotSelected(1, 3));
 580         assertTrue(isAnchor(0));
 581     }
 582     
 583     // test 31
 584     @Test public void testCtrlDownArrowThenShiftSpaceToSelectRange() {
 585         sm.clearAndSelect(0);
 586         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 587         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 588         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 0,1,2
 589         assertTrue(isSelected(0, 1, 2));
 590         assertTrue(isNotSelected(3));
 591         assertTrue(isAnchor(0));
 592     }
 593     
 594     // test 32
 595     @Test public void testCtrlUpArrowThenShiftSpaceToSelectRange() {
 596         sm.clearAndSelect(2);
 597         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 598         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 599         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 0,1,2
 600         assertTrue(isSelected(0, 1, 2));
 601         assertTrue(isNotSelected(3));
 602         assertTrue(debug(), isAnchor(2));
 603     }
 604     
 605     // test 33
 606     @Test public void testCtrlDownArrowThenSpaceToChangeSelection() {
 607         sm.clearAndSelect(0);
 608         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 609         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 610         keyboard.doKeyPress(KeyCode.SPACE, 
 611                 KeyModifier.getShortcutKey(),
 612                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 2, keeping 0 selected
 613         assertTrue(isSelected(0, 2));
 614         assertTrue(isNotSelected(1, 3));
 615         assertTrue(isAnchor(2));
 616         
 617         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 618         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 619         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 2,3,4
 620         assertTrue(isSelected(2, 3, 4));
 621         assertTrue(isNotSelected(0, 1));
 622         assertTrue(isAnchor(2));
 623     }
 624     
 625     // test 34
 626     @Test public void testCtrlUpArrowThenSpaceToChangeSelection() {
 627         sm.clearAndSelect(4);
 628         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 629         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 630         keyboard.doKeyPress(KeyCode.SPACE, 
 631                 KeyModifier.getShortcutKey(),
 632                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 2, keeping 4 selected
 633         assertTrue(isSelected(2, 4));
 634         assertTrue(isNotSelected(0, 1, 3));
 635         assertTrue(isAnchor(2));
 636         
 637         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 638         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 639         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 0,1,2
 640         assertTrue(isSelected(0, 1, 2));
 641         assertTrue(isNotSelected(3, 4));
 642         assertTrue(debug(), isAnchor(2));
 643     }
 644     
 645     // test 35
 646     @Test public void testCtrlDownTwiceThenShiftDown() {
 647         sm.clearAndSelect(0);
 648         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 649         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 650         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);  // select 0,1,2,3
 651         assertTrue(isSelected(0, 1, 2, 3));
 652     }
 653     
 654     // test 36
 655     @Test public void testCtrlUpTwiceThenShiftDown() {
 656         sm.clearAndSelect(3);
 657         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 658         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 659         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 660         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);  // select 1,2,3
 661         assertTrue(isSelected(1, 2, 3));
 662         assertTrue(isNotSelected(0));
 663     }
 664     
 665     // test 37
 666     @Test public void testCtrlDownThriceThenShiftUp() {
 667         sm.clearAndSelect(0);
 668         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 669         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 670         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 671         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);  // select 0,1,2
 672         assertTrue(isSelected(0, 1, 2));
 673         assertTrue(isNotSelected(3, 4));
 674     }
 675     
 676     // test 38
 677     @Test public void testCtrlUpTwiceThenShiftUp() {
 678         sm.clearAndSelect(3);
 679         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 680         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 681         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);  // select 0,1,2,3
 682         assertTrue(isSelected(0, 1, 2, 3));
 683         assertTrue(isNotSelected(4));
 684     }
 685     
 686     // test 39
 687     @Test public void testCtrlDownTwiceThenSpace_extended() {
 688         sm.clearAndSelect(0);
 689         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 690         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 691         keyboard.doKeyPress(KeyCode.SPACE, 
 692                 KeyModifier.getShortcutKey(),
 693                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 0,2
 694         assertTrue(isSelected(0, 2));
 695         assertTrue(isNotSelected(1, 3));
 696         assertTrue(isAnchor(2));
 697         
 698         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 699         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 700         keyboard.doDownArrowPress(KeyModifier.SHIFT);   // select 2,3,4,5
 701         assertTrue(isSelected(2, 3, 4, 5));
 702         assertTrue(isNotSelected(0, 1));
 703         assertTrue(isAnchor(2));
 704     }
 705     
 706     // test 40
 707     @Test public void testCtrlUpTwiceThenSpace_extended() {
 708         sm.clearAndSelect(5);
 709         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 710         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 711         keyboard.doKeyPress(KeyCode.SPACE, 
 712                 KeyModifier.getShortcutKey(),
 713                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 3,5
 714         assertTrue(isSelected(3,5));
 715         assertTrue(isNotSelected(0,1,2,4));
 716         assertTrue(isAnchor(3));
 717         
 718         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 719         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 720         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 721         keyboard.doDownArrowPress(KeyModifier.SHIFT);   // select 1,2,3
 722         assertTrue(isSelected(1,2,3));
 723         assertTrue(isNotSelected(0,4,5));
 724         assertTrue(isAnchor(3));
 725     }
 726     
 727     // test 41
 728     @Test public void testCtrlDownTwiceThenSpace_extended2() {
 729         sm.clearAndSelect(0);
 730         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 731         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 732         keyboard.doKeyPress(KeyCode.SPACE, 
 733                 KeyModifier.getShortcutKey(),
 734                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 0,2
 735         assertTrue(isSelected(0,2));
 736         assertTrue(isNotSelected(1,3,4));
 737         assertTrue(isAnchor(2));
 738         
 739         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 740         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 741         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 5
 742         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // select 2,3,4
 743         assertTrue(isSelected(2,3,4));
 744         assertTrue(isNotSelected(0,1,5));
 745         assertTrue(isAnchor(2));
 746     }
 747     
 748     // test 50
 749     @Test public void testCtrlDownThenShiftHome() {
 750         sm.clearAndSelect(0);
 751         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 752         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 753         keyboard.doKeyPress(KeyCode.SPACE, 
 754                 KeyModifier.getShortcutKey(),
 755                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 0,2
 756         assertTrue(isSelected(0,2));
 757         assertTrue(isNotSelected(1,3,4));
 758         assertTrue(isAnchor(2));
 759         
 760         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 761         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 762         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
 763         assertTrue(isSelected(0,1,2));
 764         assertTrue(isNotSelected(3,4));
 765         assertTrue(debug(),isAnchor(2));
 766     }
 767     
 768     // test 51
 769     @Test public void testCtrlUpThenShiftEnd() {
 770         sm.clearAndSelect(5);
 771         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 772         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 773         keyboard.doKeyPress(KeyCode.SPACE, 
 774                 KeyModifier.getShortcutKey(),
 775                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 3,5
 776         assertTrue(isSelected(3,5));
 777         assertTrue(isNotSelected(1,2,4));
 778         assertTrue(isAnchor(3));
 779         
 780         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 781         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 782         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
 783         assertTrue(isSelected(3,4,5,6,7,8,9));
 784         assertTrue(isNotSelected(0,1,2));
 785         assertTrue(debug(),isAnchor(3));
 786     }
 787     
 788     // test 42
 789     @Test public void testCtrlUpTwiceThenSpace_extended2() {
 790         sm.clearAndSelect(5);
 791         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 792         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 793         keyboard.doKeyPress(KeyCode.SPACE, 
 794                 KeyModifier.getShortcutKey(),
 795                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 3,5
 796         assertTrue(isSelected(3,5));
 797         assertTrue(isNotSelected(0,1,2,4));
 798         assertTrue(isAnchor(3));
 799         
 800         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 801         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 802         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // select 0,1,2,3
 803         assertTrue(isSelected(0,1,2,3));
 804         assertTrue(isNotSelected(4,5));
 805         assertTrue(isAnchor(3));
 806     }
 807     
 808     // test 46
 809     @Test public void testHomeKey_withSelectedItems() {
 810         sm.clearSelection();
 811         sm.selectRange(4, 11);
 812         keyboard.doKeyPress(KeyCode.HOME);
 813         assertTrue(isSelected(0));
 814         assertTrue(isNotSelected(1,2,3,4,5,6,7,8,9,10,11));
 815     }
 816     
 817     // test 47
 818     @Test public void testEndKey_withSelectedItems() {
 819         sm.clearSelection();
 820         sm.selectRange(4, 11);
 821         keyboard.doKeyPress(KeyCode.END);
 822         assertTrue(isSelected(tableView.getExpandedItemCount() - 1));
 823         assertTrue(isNotSelected(1,2,3,4,5,6,7,8));
 824     }
 825     
 826     // test 48
 827     @Test public void testShiftHome() {
 828         sm.clearAndSelect(3);
 829         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
 830         assertTrue(isSelected(0,1,2,3));
 831         assertTrue(isNotSelected(4,5));
 832         assertTrue(debug(), isAnchor(3));
 833     }
 834     
 835     // test 49
 836     @Test public void testShiftEnd() {
 837         sm.clearAndSelect(3);
 838         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
 839         assertTrue(isSelected(3,4,5,6,7,8,9));
 840         assertTrue(isNotSelected(0,1,2));
 841         assertTrue(debug(), isAnchor(3));
 842     }
 843     
 844     // test 52
 845     @Test public void testShiftHomeThenShiftEnd() {
 846         sm.clearAndSelect(5);
 847         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
 848         assertTrue(isSelected(0,1,2,3,4,5));
 849         assertTrue(isAnchor(5));
 850         
 851         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
 852         assertTrue(isSelected(5,6,7,8,9));
 853         assertTrue(isAnchor(5));
 854     }
 855     
 856     // test 65
 857     @Test public void testShiftPageUp() {
 858         sm.clearAndSelect(0);
 859         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 860         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 861         keyboard.doKeyPress(KeyCode.SPACE, 
 862                 KeyModifier.getShortcutKey(),
 863                 (Utils.isMac()  ? KeyModifier.CTRL : null));
 864         assertTrue(isSelected(0,2));
 865         assertTrue(isAnchor(2));
 866         
 867         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 868         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 869         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
 870         assertTrue(isSelected(0,1,2));
 871         assertTrue(isAnchor(2));
 872     }
 873     
 874     // test 67
 875     @Test public void testCtrlAToSelectAll() {
 876         sm.clearAndSelect(5);
 877         keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey());
 878         assertTrue(isSelected(0,1,2,3,4,5,6,7,8,9));
 879     }
 880     
 881     
 882     /***************************************************************************
 883      * Tests for cell-based multiple selection
 884      **************************************************************************/    
 885     
 886     @Ignore("Bug persists")
 887     @Test public void testSelectionPathDeviationWorks1() {
 888         // select horizontally, then select two items vertically, then go back
 889         // in opposite direction
 890         sm.setCellSelectionEnabled(true);
 891         sm.clearAndSelect(1, col0);
 892         
 893         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col2)
 894         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col3)
 895         keyboard.doDownArrowPress(KeyModifier.SHIFT);    // select (2, col3)
 896         keyboard.doDownArrowPress(KeyModifier.SHIFT);    // select (3, col3)
 897         assertTrue(sm.isSelected(1, col2));
 898         assertTrue(sm.isSelected(2, col2));
 899         assertTrue(sm.isSelected(3, col2));
 900         
 901         keyboard.doUpArrowPress(KeyModifier.SHIFT);    // deselect (3, col3)
 902         assertTrue(sm.isSelected(1, col2));
 903         assertTrue(sm.isSelected(2, col2));
 904         assertFalse(sm.isSelected(3, col2));
 905         
 906         keyboard.doUpArrowPress(KeyModifier.SHIFT);    // deselect (2, col3)
 907         assertTrue(sm.isSelected(1, col2));
 908         assertFalse(sm.isSelected(2, col2));
 909         assertFalse(sm.isSelected(3, col2));
 910         
 911         keyboard.doUpArrowPress(KeyModifier.SHIFT);    // deselect (1, col3)
 912         assertFalse(debug(), sm.isSelected(1, col2));
 913         assertFalse(sm.isSelected(2, col2));
 914         assertFalse(sm.isSelected(3, col2));
 915         
 916         keyboard.doLeftArrowPress(KeyModifier.SHIFT);    // deselect (1, col2)
 917         assertFalse(sm.isSelected(1, col1));
 918     }
 919     
 920     
 921     /***************************************************************************
 922      * Tests for discontinuous multiple row selection (RT-18951)
 923      **************************************************************************/    
 924     
 925     // Test 1
 926     @Test public void test_rt18591_row_1() {
 927         sm.clearAndSelect(0);
 928         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 929         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 930         keyboard.doKeyPress(KeyCode.SPACE, 
 931                 KeyModifier.getShortcutKey(),
 932                 (Utils.isMac()  ? KeyModifier.CTRL : null));
 933         assertTrue(isSelected(0,2));
 934         assertTrue(isAnchor(2));
 935         
 936         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 937         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 938         assertTrue(isSelected(0,2,3,4));
 939         assertTrue(isAnchor(2));
 940     }
 941     
 942     // Test 2
 943     @Test public void test_rt18591_row_2() {
 944         sm.clearAndSelect(5);
 945         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 946         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 947         keyboard.doKeyPress(KeyCode.SPACE, 
 948                 KeyModifier.getShortcutKey(),
 949                 (Utils.isMac()  ? KeyModifier.CTRL : null));
 950         assertTrue(isSelected(3,5));
 951         assertTrue(isAnchor(3));
 952         
 953         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 954         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 955         assertTrue(isSelected(1,2,3,5));
 956         assertTrue(isAnchor(3));
 957     }
 958     
 959     // Test 3
 960     @Test public void test_rt18591_row_3() {
 961         // same as test 1 above
 962         sm.clearAndSelect(0);
 963         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 964         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 965         keyboard.doKeyPress(KeyCode.SPACE, 
 966                 KeyModifier.getShortcutKey(),
 967                 (Utils.isMac()  ? KeyModifier.CTRL : null));
 968         assertTrue(isSelected(0,2));
 969         assertTrue(isAnchor(2));
 970         
 971         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 972         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 973         assertTrue(isSelected(0,2,3,4));
 974         assertTrue(isAnchor(2));
 975         // end of similarities
 976         
 977         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 978         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 979         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 980         assertTrue(isSelected(0,1,2,3,4));
 981         assertTrue(isAnchor(2));
 982     }
 983     
 984     // Test 4
 985     @Test public void test_rt18591_row_4() {
 986         // same as test 2 above
 987         sm.clearAndSelect(5);
 988         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 989         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 990         keyboard.doKeyPress(KeyCode.SPACE, 
 991                 KeyModifier.getShortcutKey(),
 992                 (Utils.isMac()  ? KeyModifier.CTRL : null));
 993         assertTrue(isSelected(3,5));
 994         assertTrue(isAnchor(3));
 995         
 996         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 997         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
 998         assertTrue(isSelected(1,2,3,5));
 999         assertTrue(isAnchor(3));
1000         // end of similarities
1001         
1002         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1003         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1004         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1005         assertTrue(isSelected(1,2,3,4,5));
1006         assertTrue(isAnchor(3));
1007     }
1008     
1009     // Test 5 (need Page down support)
1010 //    @Test public void test_5() {
1011 //        // same as test 1 above
1012 //        sm.clearAndSelect(0);
1013 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1014 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1015 //        keyboard.doKeyPress(KeyCode.SPACE, 
1016 //                KeyModifier.getShortcutKey(),
1017 //                (Utils.isMac()  ? KeyModifier.CTRL : null));
1018 //        assertTrue(isSelected(0,2));
1019 //        assertTrue(isAnchor(2));
1020 //        // end of similarities
1021 //        
1022 //        keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1023 //        assertTrue(isSelected(0,2,/*until end of page */));
1024 //        assertTrue(isAnchor(2));
1025 //    }
1026     
1027     // Test 6
1028     @Test public void test_rt18591_row_6() {
1029         sm.clearAndSelect(10);
1030         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1031         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1032         keyboard.doKeyPress(KeyCode.SPACE, 
1033                 KeyModifier.getShortcutKey(),
1034                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1035         assertTrue(debug(), isSelected(8,10));
1036         assertTrue(isAnchor(8));
1037         
1038         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1039         assertTrue(isSelected(0,1,2,3,4,5,6,7,8,10));
1040         assertTrue(isAnchor(8));
1041     }
1042     
1043 //    // Test 7
1044 //    @Test public void test_rt18591_row_7() {
1045 //        sm.clearAndSelect(0);
1046 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1047 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1048 //        keyboard.doKeyPress(KeyCode.SPACE, 
1049 //                KeyModifier.getShortcutKey(),
1050 //                (Utils.isMac()  ? KeyModifier.CTRL : null));
1051 //        assertTrue(isSelected(0,2));
1052 //        assertTrue(isAnchor(2));
1053 //        
1054 //        keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1055 //        keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1056 //        assertTrue(isSelected(0,2,3,4,5,6,7,8,10)); // this isn't right
1057 //        assertTrue(isAnchor(8));
1058 //        
1059 //        // NOT COMPLETE
1060 //    }
1061 //    
1062 //    // Test 8
1063 //    @Test public void test_rt18591_row_8() {
1064 //        // NOT COMPLETE
1065 //    }
1066     
1067     // Test 9
1068     @Test public void test_rt18591_row_9() {
1069         sm.clearAndSelect(0);
1070         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1071         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1072         keyboard.doKeyPress(KeyCode.SPACE, 
1073                 KeyModifier.getShortcutKey(),
1074                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1075         assertTrue(isSelected(0,2));
1076         assertTrue(isAnchor(2));
1077         
1078         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1079         assertTrue(isSelected(0,2,3,4,5,6,7,8,9));
1080         assertTrue(isAnchor(2));
1081     }
1082     
1083     // Test 10
1084     @Test public void test_rt18591_row_10() {
1085         sm.clearAndSelect(8);
1086         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1087         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1088         keyboard.doKeyPress(KeyCode.SPACE, 
1089                 KeyModifier.getShortcutKey(),
1090                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1091         assertTrue(isSelected(6,8));
1092         assertTrue(isAnchor(6));
1093         
1094         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1095         assertTrue(isSelected(0,1,2,3,4,5,6,8));
1096         assertTrue(isAnchor(6));
1097     }
1098     
1099     // Test 11
1100     @Test public void test_rt18591_row_11() {
1101         sm.clearAndSelect(5);
1102         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1103         assertTrue(isSelected(0,1,2,3,4,5));
1104         assertTrue(isAnchor(5));
1105         
1106         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1107         assertTrue(isSelected(0,1,2,3,4,5,6,7,8,9));
1108         assertTrue(isAnchor(5));
1109     }
1110     
1111     // Test 12
1112     @Test public void test_rt18591_row_12() {
1113         sm.clearAndSelect(0);
1114         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1115         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1116         keyboard.doKeyPress(KeyCode.SPACE, 
1117                 KeyModifier.getShortcutKey(),
1118                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1119         assertTrue(isSelected(0,2));
1120         assertTrue(isAnchor(2));
1121         
1122         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1123         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1124         assertTrue(isSelected(0,2,3,4));
1125         assertTrue(isAnchor(2));
1126         
1127         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1128         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1129         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1130         assertTrue(isSelected(0,1,2,3,4));
1131         assertTrue(isAnchor(2));
1132         
1133         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1134         keyboard.doKeyPress(KeyCode.SPACE, 
1135                 KeyModifier.getShortcutKey(),
1136                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1137         assertTrue(isSelected(1,2,3,4));
1138         assertTrue(isAnchor(0));
1139         assertTrue(fm.isFocused(0));
1140     }
1141     
1142     
1143     /***************************************************************************
1144      * Tests for discontinuous multiple cell selection (RT-18951)
1145      **************************************************************************/  
1146     
1147     // Test 1
1148     @Test public void test_rt18591_cell_1() {
1149         sm.setSelectionMode(SelectionMode.MULTIPLE);
1150         sm.setCellSelectionEnabled(true);
1151         sm.select(0, col0);
1152         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
1153         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
1154         keyboard.doKeyPress(KeyCode.SPACE, 
1155                 KeyModifier.getShortcutKey(),
1156                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1157         assertTrue(sm.isSelected(0,col0));
1158         assertTrue(sm.isSelected(0,col2));
1159         assertTrue(isAnchor(0,2));
1160         
1161         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1162         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1163         assertTrue(sm.isSelected(0,col0));
1164         assertTrue(sm.isSelected(0,col2));
1165         assertTrue(sm.isSelected(0,col3));
1166         assertTrue(sm.isSelected(0,col4));
1167         assertTrue(isAnchor(0,2));
1168     }
1169     
1170     // Test 2
1171     @Test public void test_rt18591_cell_2() {
1172         sm.setSelectionMode(SelectionMode.MULTIPLE);
1173         sm.setCellSelectionEnabled(true);
1174         sm.select(0, col4);
1175         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
1176         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
1177         keyboard.doKeyPress(KeyCode.SPACE, 
1178                 KeyModifier.getShortcutKey(),
1179                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1180         assertTrue(sm.isSelected(0,col4));
1181         assertTrue(sm.isSelected(0,col2));
1182         assertTrue(isAnchor(0,2));
1183         
1184         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1185         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1186         assertTrue(sm.isSelected(0,col0));
1187         assertTrue(sm.isSelected(0,col1));
1188         assertTrue(sm.isSelected(0,col2));
1189         assertTrue(sm.isSelected(0,col4));
1190         assertTrue(isAnchor(0,2));
1191     }
1192     
1193     // Test 3
1194     @Test public void test_rt18591_cell_3() {
1195         sm.setSelectionMode(SelectionMode.MULTIPLE);
1196         sm.setCellSelectionEnabled(true);
1197         sm.select(0, col0);
1198         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
1199         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
1200         keyboard.doKeyPress(KeyCode.SPACE, 
1201                 KeyModifier.getShortcutKey(),
1202                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1203         assertTrue(sm.isSelected(0,col0));
1204         assertTrue(sm.isSelected(0,col2));
1205         assertTrue(isAnchor(0,2));
1206         
1207         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1208         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1209         assertTrue(sm.isSelected(0,col0));
1210         assertTrue(sm.isSelected(0,col2));
1211         assertTrue(sm.isSelected(0,col3));
1212         assertTrue(sm.isSelected(0,col4));
1213         assertTrue(isAnchor(0,2));
1214         
1215         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1216         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1217         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1218         assertTrue(sm.isSelected(0,col0));
1219         assertTrue(sm.isSelected(0,col1));
1220         assertTrue(sm.isSelected(0,col2));
1221         assertTrue(sm.isSelected(0,col3));
1222         assertTrue(sm.isSelected(0,col4));
1223         assertTrue(isAnchor(0,2));
1224     }
1225     
1226     // Test 4
1227     @Test public void test_rt18591_cell_4() {
1228         sm.setSelectionMode(SelectionMode.MULTIPLE);
1229         sm.setCellSelectionEnabled(true);
1230         sm.select(0, col4);
1231         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
1232         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
1233         keyboard.doKeyPress(KeyCode.SPACE, 
1234                 KeyModifier.getShortcutKey(),
1235                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1236         assertTrue(sm.isSelected(0,col4));
1237         assertTrue(sm.isSelected(0,col2));
1238         assertTrue(isAnchor(0,2));
1239         
1240         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1241         keyboard.doLeftArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1242         assertTrue(sm.isSelected(0,col0));
1243         assertTrue(sm.isSelected(0,col1));
1244         assertTrue(sm.isSelected(0,col2));
1245         assertTrue(sm.isSelected(0,col4));
1246         assertTrue(isAnchor(0,2));
1247         
1248         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1249         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1250         keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1251         assertTrue(sm.isSelected(0,col0));
1252         assertTrue(sm.isSelected(0,col1));
1253         assertTrue(sm.isSelected(0,col2));
1254         assertTrue(sm.isSelected(0,col3));
1255         assertTrue(sm.isSelected(0,col4));
1256         assertTrue(isAnchor(0,2));
1257     }
1258     
1259     // Test 5
1260     @Test public void test_rt18591_cell_5() {
1261         sm.setSelectionMode(SelectionMode.MULTIPLE);
1262         sm.setCellSelectionEnabled(true);
1263         sm.select(0, col1);
1264         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1265         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1266         keyboard.doKeyPress(KeyCode.SPACE, 
1267                 KeyModifier.getShortcutKey(),
1268                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1269         assertTrue(sm.isSelected(0,col1));
1270         assertTrue(sm.isSelected(2,col1));
1271         assertTrue(isAnchor(2,1));
1272         
1273         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1274         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1275         assertTrue(sm.isSelected(0,col1));
1276         assertTrue(sm.isSelected(2,col1));
1277         assertTrue(sm.isSelected(3,col1));
1278         assertTrue(sm.isSelected(4,col1));
1279         assertTrue(isAnchor(2,1));
1280     }
1281     
1282     // Test 6
1283     @Test public void test_rt18591_cell_6() {
1284         sm.setSelectionMode(SelectionMode.MULTIPLE);
1285         sm.setCellSelectionEnabled(true);
1286         sm.select(5, col1);
1287         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1288         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1289         keyboard.doKeyPress(KeyCode.SPACE, 
1290                 KeyModifier.getShortcutKey(),
1291                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1292         assertTrue(sm.isSelected(5,col1));
1293         assertTrue(sm.isSelected(3,col1));
1294         assertTrue(isAnchor(3,1));
1295         
1296         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1297         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1298         assertTrue(sm.isSelected(1,col1));
1299         assertTrue(sm.isSelected(2,col1));
1300         assertTrue(sm.isSelected(3,col1));
1301         assertTrue(sm.isSelected(5,col1));
1302         assertTrue(isAnchor(3,1));
1303     }
1304     
1305     // Test 7
1306     @Test public void test_rt18591_cell_7() {
1307         sm.setSelectionMode(SelectionMode.MULTIPLE);
1308         sm.setCellSelectionEnabled(true);
1309         sm.select(0, col1);
1310         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1311         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1312         keyboard.doKeyPress(KeyCode.SPACE, 
1313                 KeyModifier.getShortcutKey(),
1314                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1315         assertTrue(sm.isSelected(0,col1));
1316         assertTrue(sm.isSelected(2,col1));
1317         assertTrue(isAnchor(2,1));
1318         
1319         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1320         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1321         assertTrue(sm.isSelected(0,col1));
1322         assertTrue(sm.isSelected(2,col1));
1323         assertTrue(sm.isSelected(3,col1));
1324         assertTrue(sm.isSelected(4,col1));
1325         assertTrue(isAnchor(2,1));
1326         
1327         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1328         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1329         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1330         assertTrue(sm.isSelected(0,col1));
1331         assertTrue(sm.isSelected(1,col1));
1332         assertTrue(sm.isSelected(2,col1));
1333         assertTrue(sm.isSelected(3,col1));
1334         assertTrue(sm.isSelected(4,col1));
1335         assertTrue(isAnchor(2,1));
1336     }
1337     
1338     // Test 8
1339     @Test public void test_rt18591_cell_8() {
1340         sm.setSelectionMode(SelectionMode.MULTIPLE);
1341         sm.setCellSelectionEnabled(true);
1342         sm.select(5, col1);
1343         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1344         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1345         keyboard.doKeyPress(KeyCode.SPACE, 
1346                 KeyModifier.getShortcutKey(),
1347                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1348         assertTrue(sm.isSelected(5,col1));
1349         assertTrue(sm.isSelected(3,col1));
1350         assertTrue(isAnchor(3,1));
1351         
1352         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1353         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1354         assertTrue(sm.isSelected(1,col1));
1355         assertTrue(sm.isSelected(2,col1));
1356         assertTrue(sm.isSelected(3,col1));
1357         assertTrue(sm.isSelected(5,col1));
1358         assertTrue(isAnchor(3,1));
1359         
1360         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1361         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1362         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1363         assertTrue(sm.isSelected(1,col1));
1364         assertTrue(sm.isSelected(2,col1));
1365         assertTrue(sm.isSelected(3,col1));
1366         assertTrue(sm.isSelected(4,col1));
1367         assertTrue(sm.isSelected(5,col1));
1368         assertTrue(isAnchor(3,1));
1369     }
1370     
1371     // Skipped tests 9 - 12 as they require Page Up/Down support
1372     
1373     // Test 13
1374     @Test public void test_rt18591_cell_13() {
1375         sm.setSelectionMode(SelectionMode.MULTIPLE);
1376         sm.setCellSelectionEnabled(true);
1377         sm.select(0, col1);
1378         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1379         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1380         keyboard.doKeyPress(KeyCode.SPACE, 
1381                 KeyModifier.getShortcutKey(),
1382                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1383         assertTrue(sm.isSelected(0,col1));
1384         assertTrue(sm.isSelected(2,col1));
1385         assertTrue(isAnchor(2,1));
1386         
1387         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1388         assertTrue(sm.isSelected(0,col1));
1389         for (int i = 2; i < tableView.getExpandedItemCount(); i++) {
1390             assertTrue(debug(),sm.isSelected(i,col1));
1391         }
1392         assertTrue(isAnchor(2,1));
1393     }
1394     
1395     // Test 14
1396     @Test public void test_rt18591_cell_14() {
1397         int n = tableView.getExpandedItemCount() - 1;
1398         sm.setSelectionMode(SelectionMode.MULTIPLE);
1399         sm.setCellSelectionEnabled(true);
1400         sm.select(n, col1);
1401         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1402         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1403         keyboard.doKeyPress(KeyCode.SPACE, 
1404                 KeyModifier.getShortcutKey(),
1405                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1406         assertTrue(sm.isSelected(n,col1));
1407         assertTrue(sm.isSelected(n - 2,col1));
1408         assertTrue(isAnchor(n - 2,1));
1409         
1410         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1411         assertTrue(sm.isSelected(n,col1));
1412         for (int i = 0; i < n - 2; i++) {
1413             assertTrue(sm.isSelected(i,col1));
1414         }
1415         assertTrue(isAnchor(n - 2,1));
1416     }
1417     
1418     // Test 15
1419     @Test public void test_rt18591_cell_15() {
1420         sm.setSelectionMode(SelectionMode.MULTIPLE);
1421         sm.setCellSelectionEnabled(true);
1422         sm.select(5, col1);
1423 
1424         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1425         for (int i = 0; i <= 5; i++) {
1426             assertTrue(sm.isSelected(i,col1));
1427         }
1428         assertTrue(debug(), isAnchor(5,1));
1429         
1430         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1431         for (int i = 0; i < tableView.getExpandedItemCount() - 1; i++) {
1432             assertTrue(sm.isSelected(i,col1));
1433         }
1434         assertTrue(isAnchor(5,1));
1435     }
1436     
1437     // Test 16
1438     @Test public void test_rt18591_cell_16() {
1439         sm.setSelectionMode(SelectionMode.MULTIPLE);
1440         sm.setCellSelectionEnabled(true);
1441         sm.select(0, col1);
1442         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1443         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1444         keyboard.doKeyPress(KeyCode.SPACE, 
1445                 KeyModifier.getShortcutKey(),
1446                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1447         assertTrue(sm.isSelected(0,col1));
1448         assertTrue(sm.isSelected(2,col1));
1449         assertTrue(isAnchor(2,1));
1450         
1451         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1452         keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1453         assertTrue(sm.isSelected(0,col1));
1454         assertTrue(sm.isSelected(2,col1));
1455         assertTrue(sm.isSelected(3,col1));
1456         assertTrue(sm.isSelected(4,col1));
1457         assertTrue(isAnchor(2,1));
1458         
1459         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1460         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1461         keyboard.doUpArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1462         assertTrue(sm.isSelected(0,col1));
1463         assertTrue(sm.isSelected(1,col1));
1464         assertTrue(sm.isSelected(2,col1));
1465         assertTrue(sm.isSelected(3,col1));
1466         assertTrue(sm.isSelected(4,col1));
1467         assertTrue(isAnchor(2,1));
1468         
1469         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1470         keyboard.doKeyPress(KeyCode.SPACE, 
1471                 KeyModifier.getShortcutKey(),
1472                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1473         assertFalse(sm.isSelected(0,col1));
1474         assertTrue(sm.isSelected(1,col1));
1475         assertTrue(sm.isSelected(2,col1));
1476         assertTrue(sm.isSelected(3,col1));
1477         assertTrue(sm.isSelected(4,col1));
1478         assertTrue(isAnchor(0,1));
1479         assertTrue(fm.isFocused(0,col1));
1480     }
1481     
1482 //    // Test 17
1483 //    @Test public void test_rt18591_cell_17() {
1484 //        sm.setSelectionMode(SelectionMode.MULTIPLE);
1485 //        sm.setCellSelectionEnabled(true);
1486 //        sm.select(3, col1);
1487 //        keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
1488 //        keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
1489 //        keyboard.doKeyPress(KeyCode.SPACE, 
1490 //                KeyModifier.getShortcutKey(),
1491 //                (Utils.isMac()  ? KeyModifier.CTRL : null));
1492 //        assertTrue(sm.isSelected(3,col1));
1493 //        assertTrue(sm.isSelected(3,col3));
1494 //        assertTrue(isAnchor(3,3));
1495 //        
1496 //        keyboard.doRightArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1497 //        assertTrue(sm.isSelected(3,col1));
1498 //        assertTrue(sm.isSelected(3,col3));
1499 //        assertTrue(sm.isSelected(3,col4));
1500 //        assertTrue(isAnchor(3,3));
1501 //        
1502 //        keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1503 //        keyboard.doDownArrowPress(KeyModifier.SHIFT, KeyModifier.getShortcutKey());
1504 //        assertTrue(sm.isSelected(3,col1));
1505 //        assertTrue(sm.isSelected(3,col3));
1506 //        assertTrue(sm.isSelected(3,col4));
1507 //        assertTrue(sm.isSelected(4,col3));
1508 //        assertTrue(sm.isSelected(5,col3));
1509 //        assertTrue(isAnchor(3,3));
1510 //    }
1511     
1512     
1513     /***************************************************************************
1514      * Tests for specific bug reports
1515      **************************************************************************/
1516     
1517     @Test public void test_rt18488_selectToLeft() {
1518         sm.setCellSelectionEnabled(true);
1519         sm.clearAndSelect(1, col4);
1520         
1521         keyboard.doLeftArrowPress(KeyModifier.SHIFT);   // select (1, col4)
1522         keyboard.doLeftArrowPress(KeyModifier.SHIFT);   // select (1, col3)
1523         keyboard.doLeftArrowPress(KeyModifier.SHIFT);   // select (1, col2)
1524         keyboard.doLeftArrowPress(KeyModifier.SHIFT);   // select (1, col1)
1525         assertTrue(sm.isSelected(1, col4));
1526         assertTrue(sm.isSelected(1, col3));
1527         assertTrue(sm.isSelected(1, col2));
1528         assertTrue(sm.isSelected(1, col1));
1529         assertTrue(sm.isSelected(1, col0));
1530         
1531         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // deselect (1, col1)
1532         assertTrue(sm.isSelected(1, col4));
1533         assertTrue(sm.isSelected(1, col3));
1534         assertTrue(sm.isSelected(1, col2));
1535         assertTrue(debug(), sm.isSelected(1, col1));
1536         assertFalse(sm.isSelected(1, col0));
1537     }
1538     
1539     @Test public void test_rt18488_selectToRight() {
1540         sm.setCellSelectionEnabled(true);
1541         sm.clearAndSelect(1, col0);
1542         
1543         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col2)
1544         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col3)
1545         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col4)
1546         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col5)
1547         assertTrue(sm.isSelected(1, col4));
1548         assertTrue(sm.isSelected(1, col3));
1549         assertTrue(sm.isSelected(1, col2));
1550         assertTrue(sm.isSelected(1, col1));
1551         assertTrue(sm.isSelected(1, col0));
1552         
1553         keyboard.doLeftArrowPress(KeyModifier.SHIFT);   // deselect (1, col5)
1554         assertFalse(sm.isSelected(1, col4));
1555         assertTrue(sm.isSelected(1, col3));
1556         assertTrue(sm.isSelected(1, col2));
1557         assertTrue(sm.isSelected(1, col1));
1558         assertTrue(sm.isSelected(1, col0));
1559     }
1560     
1561     @Test public void test_rt18488_comment1() {
1562         sm.setCellSelectionEnabled(true);
1563         sm.clearAndSelect(1, col0);
1564         
1565         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col2)
1566         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col3)
1567         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col4)
1568         keyboard.doRightArrowPress(KeyModifier.SHIFT);   // select (1, col5)
1569         keyboard.doDownArrowPress(KeyModifier.SHIFT);    // select (2, col5)
1570         
1571         assertTrue(sm.isSelected(2, col4));
1572         assertTrue(sm.isSelected(1, col4));
1573         assertTrue(sm.isSelected(1, col3));
1574         assertTrue(sm.isSelected(1, col2));
1575         assertTrue(sm.isSelected(1, col1));
1576         assertTrue(sm.isSelected(1, col0));
1577         
1578         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // deselect (2, col5)
1579         assertFalse(sm.isSelected(2, col4));
1580         assertTrue(sm.isSelected(1, col4));
1581         assertTrue(sm.isSelected(1, col3));
1582         assertTrue(sm.isSelected(1, col2));
1583         assertTrue(sm.isSelected(1, col1));
1584         assertTrue(sm.isSelected(1, col0));
1585     }
1586     
1587     @Test public void test_rt18536_positive_horizontal() {
1588         // Test shift selection when focus is elsewhere (so as to select a range)
1589         sm.setCellSelectionEnabled(true);
1590         sm.clearAndSelect(1, col0);
1591         
1592         // move focus by holding down ctrl button
1593         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col2)
1594         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col3)
1595         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col4)
1596         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col5)
1597         assertTrue(fm.isFocused(1, col4));
1598         
1599         // press shift + space to select all cells between (1, col1) and (1, col5)
1600         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
1601         assertTrue(sm.isSelected(1, col4));
1602         assertTrue(debug(), sm.isSelected(1, col3));
1603         assertTrue(sm.isSelected(1, col2));
1604         assertTrue(sm.isSelected(1, col1));
1605         assertTrue(sm.isSelected(1, col0));
1606     }
1607     
1608     @Test public void test_rt18536_negative_horizontal() {
1609         // Test shift selection when focus is elsewhere (so as to select a range)
1610         sm.setCellSelectionEnabled(true);
1611         sm.clearAndSelect(1, col4);
1612         
1613         // move focus by holding down ctrl button
1614         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col4)
1615         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col3)
1616         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col2)
1617         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col1)
1618         assertTrue(fm.isFocused(1, col0));
1619         
1620         // press shift + space to select all cells between (1, col1) and (1, col5)
1621         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
1622         assertTrue(debug(), sm.isSelected(1, col4));
1623         assertTrue(sm.isSelected(1, col3));
1624         assertTrue(sm.isSelected(1, col2));
1625         assertTrue(sm.isSelected(1, col1));
1626         assertTrue(sm.isSelected(1, col0));
1627     }
1628 
1629     //
1630     @Test public void test_rt18536_positive_vertical() {
1631         // Test shift selection when focus is elsewhere (so as to select a range)
1632         sm.setCellSelectionEnabled(true);
1633         sm.clearAndSelect(1, col4);
1634         
1635         // move focus by holding down ctrl button
1636         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // move focus to (2, col5)
1637         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // move focus to (3, col5)
1638         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // move focus to (4, col5)
1639         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // move focus to (5, col5)
1640         assertTrue(fm.isFocused(5, col4));
1641         
1642         // press shift + space to select all cells between (1, col5) and (5, col5)
1643         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
1644         assertTrue(sm.isSelected(1, col4));
1645         assertTrue(sm.isSelected(2, col4));
1646         assertTrue(sm.isSelected(3, col4));
1647         assertTrue(sm.isSelected(4, col4));
1648         assertTrue(sm.isSelected(5, col4));
1649     }
1650     
1651     //
1652     @Test public void test_rt18536_negative_vertical() {
1653         // Test shift selection when focus is elsewhere (so as to select a range)
1654         sm.setCellSelectionEnabled(true);
1655         sm.clearAndSelect(5, col4);
1656         
1657         // move focus by holding down ctrl button
1658         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());   // move focus to (4, col5)
1659         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());   // move focus to (3, col5)
1660         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());   // move focus to (2, col5)
1661         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());   // move focus to (1, col5)
1662         assertTrue(fm.isFocused(1, col4));
1663         
1664         // press shift + space to select all cells between (1, col5) and (5, col5)
1665         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
1666         assertTrue(sm.isSelected(1, col4));
1667         assertTrue(sm.isSelected(2, col4));
1668         assertTrue(sm.isSelected(3, col4));
1669         assertTrue(sm.isSelected(4, col4));
1670         assertTrue(sm.isSelected(5, col4));
1671     }
1672     
1673     //
1674     @Test public void test_rt18642() {
1675         sm.setCellSelectionEnabled(false);
1676         sm.clearAndSelect(1);                          // select 1
1677         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 2
1678         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 3
1679         keyboard.doKeyPress(KeyCode.SPACE, 
1680                 KeyModifier.getShortcutKey(),
1681                 (Utils.isMac()  ? KeyModifier.CTRL : null)); // set anchor, and also select, 3
1682         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 4
1683         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 5
1684         keyboard.doKeyPress(KeyCode.SPACE, 
1685                 KeyModifier.getShortcutKey(),
1686                 (Utils.isMac()  ? KeyModifier.CTRL : null)); // set anchor, and also select, 5
1687         
1688         assertTrue(isSelected(1, 3, 5));
1689         assertTrue(isNotSelected(0, 2, 4));
1690         
1691         // anchor is at 5, so shift+UP should select rows 4 and 5 only
1692         keyboard.doUpArrowPress(KeyModifier.SHIFT);   
1693         assertTrue(isSelected(4, 5));
1694         assertTrue(isNotSelected(0, 1, 2, 3));
1695     }
1696     
1697     
1698     
1699     
1700     
1701     /***************************************************************************
1702      * 
1703      * 
1704      * Tests taken from TreeViewKeyInputTest
1705      * 
1706      * 
1707      **************************************************************************/  
1708     
1709     /***************************************************************************
1710      * Tests for row-based single selection
1711      **************************************************************************/
1712     
1713     // test 19
1714     @Test public void testCtrlDownMovesFocusButLeavesSelectionAlone() {
1715         sm.clearAndSelect(0);
1716         assertTrue(fm.isFocused(0));
1717         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1718         assertTrue(fm.isFocused(1));
1719         assertTrue(sm.isSelected(0));
1720         assertFalse(sm.isSelected(1));
1721     }
1722     
1723     // test 23
1724     @Test public void testCtrlUpMovesFocus() {
1725         sm.clearAndSelect(1);
1726         assertTrue(fm.isFocused(1));
1727         assertTrue(sm.isSelected(1));
1728         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1729         assertTrue(fm.isFocused(0));
1730         assertTrue(sm.isSelected(1));
1731     }
1732     
1733     // test 25
1734     @Test public void testCtrlDownArrowWithSpaceChangesAnchor() {
1735         sm.clearAndSelect(0);
1736         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
1737         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
1738         keyboard.doKeyPress(KeyCode.SPACE, 
1739                 KeyModifier.getShortcutKey(),
1740                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 2
1741         assertTrue(isSelected(0, 2));
1742         assertTrue(isNotSelected(1));
1743         assertTrue(isAnchor(2));
1744     }
1745     
1746     // test 26
1747     @Test public void testCtrlUpArrowWithSpaceChangesAnchor() {
1748         sm.clearAndSelect(2);
1749         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
1750         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
1751         keyboard.doKeyPress(KeyCode.SPACE, 
1752                 KeyModifier.getShortcutKey(),
1753                 (Utils.isMac()  ? KeyModifier.CTRL : null));  // select 0
1754         assertTrue(isSelected(0, 2));
1755         assertTrue(isNotSelected(1));
1756         assertTrue(isAnchor(0));
1757     }
1758     
1759     // test 53
1760     @Test public void testCtrlHome() {
1761         sm.clearAndSelect(5);
1762         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey());
1763         assertTrue(isSelected(5));
1764         assertTrue(fm.isFocused(0));
1765     }
1766     
1767     // test 54
1768     @Test public void testCtrlEnd() {
1769         sm.clearAndSelect(5);
1770         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey());
1771         assertTrue(isSelected(5));
1772         assertTrue(fm.isFocused(getItemCount()));
1773     }
1774     
1775     // test 68
1776     @Test public void testCtrlSpaceToClearSelection() {
1777         sm.clearAndSelect(5);
1778         assertTrue(isSelected(5));
1779         assertTrue(fm.isFocused(5));
1780         keyboard.doKeyPress(KeyCode.SPACE, 
1781                 KeyModifier.getShortcutKey(),
1782                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1783         assertTrue(isNotSelected(5));
1784         assertTrue(debug(), fm.isFocused(5));
1785         assertTrue(isAnchor(5));
1786     }
1787     
1788     /***************************************************************************
1789      * Tests for discontinuous multiple selection (RT-18952)
1790      **************************************************************************/  
1791     
1792     // Test 1
1793     @Test public void test_rt18952_1() {
1794         sm.clearAndSelect(0);
1795         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1796         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1797         keyboard.doKeyPress(KeyCode.SPACE, 
1798                 KeyModifier.getShortcutKey(),
1799                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1800         assertTrue(isSelected(0,2));
1801         assertTrue(isAnchor(2));
1802         
1803         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1804         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1805         assertTrue(debug(),isSelected(0,2,3,4));
1806         assertTrue(isAnchor(2));
1807     }
1808     
1809     // Test 2
1810     @Test public void test_rt18952_2() {
1811         sm.clearAndSelect(5);
1812         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1813         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1814         keyboard.doKeyPress(KeyCode.SPACE, 
1815                 KeyModifier.getShortcutKey(),
1816                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1817         assertTrue(isSelected(3,5));
1818         assertTrue(isAnchor(3));
1819         
1820         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1821         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1822         assertTrue(isSelected(1,2,3,5));
1823         assertTrue(isAnchor(3));
1824     }
1825     
1826     // Test 3
1827     @Test public void test_rt18952_3() {
1828         sm.clearAndSelect(0);
1829         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1830         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1831         keyboard.doKeyPress(KeyCode.SPACE, 
1832                 KeyModifier.getShortcutKey(),
1833                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1834         assertTrue(isSelected(0,2));
1835         assertTrue(isAnchor(2));
1836         
1837         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1838         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1839         assertTrue(isSelected(0,2,3,4));
1840         assertTrue(isAnchor(2));
1841         
1842         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1843         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1844         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1845         assertTrue(isSelected(0,1,2,3,4));
1846         assertTrue(isAnchor(2));
1847     }
1848     
1849     // Test 4
1850     @Test public void test_rt18952_4() {
1851         sm.clearAndSelect(5);
1852         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1853         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1854         keyboard.doKeyPress(KeyCode.SPACE, 
1855                 KeyModifier.getShortcutKey(),
1856                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1857         assertTrue(isSelected(3,5));
1858         assertTrue(isAnchor(3));
1859         
1860         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1861         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1862         assertTrue(isSelected(1,2,3,5));
1863         assertTrue(isAnchor(3));
1864         
1865         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1866         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1867         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1868         assertTrue(isSelected(1,2,3,4,5));
1869         assertTrue(isAnchor(3));
1870     }
1871     
1872     // TODO skipped some tests here (5-8)
1873     
1874     // Test 9
1875     @Test public void test_rt18952_9() {
1876         sm.clearAndSelect(0);
1877         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1878         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1879         keyboard.doKeyPress(KeyCode.SPACE, 
1880                 KeyModifier.getShortcutKey(),
1881                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1882         assertTrue(isSelected(0,2));
1883         assertTrue(isAnchor(2));
1884         
1885         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1886         assertTrue(isSelected(0,2,3,4,5,6,7,8,9));
1887         assertTrue(isAnchor(2));
1888     }
1889     
1890     // Test 10
1891     @Test public void test_rt18952_10() {
1892         sm.clearAndSelect(9);
1893         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1894         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1895         keyboard.doKeyPress(KeyCode.SPACE, 
1896                 KeyModifier.getShortcutKey(),
1897                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1898         assertTrue(isSelected(7,9));
1899         assertTrue(isAnchor(7));
1900         
1901         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1902         assertTrue(isSelected(0,1,2,3,4,5,6,7,9));
1903         assertTrue(isAnchor(7));
1904     }
1905     
1906     // Test 11
1907     @Test public void test_rt18952_11() {
1908         sm.clearAndSelect(5);
1909         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1910         assertTrue(isSelected(0,1,2,3,4,5));
1911         assertTrue(isAnchor(5));
1912         
1913         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1914         assertTrue(isSelected(0,1,2,3,4,5,6,7,8,9));
1915         assertTrue(isAnchor(5));
1916     }
1917     
1918     // Test 12
1919     @Test public void test_rt18952_12() {
1920         sm.clearAndSelect(0);
1921         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1922         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
1923         keyboard.doKeyPress(KeyCode.SPACE,
1924                 KeyModifier.getShortcutKey(),
1925                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1926         assertTrue(isSelected(0,2));
1927         assertTrue(isAnchor(2));
1928         
1929         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1930         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1931         assertTrue(isSelected(0,2,3,4));
1932         assertTrue(isAnchor(2));
1933         
1934         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1935         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1936         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1937         assertTrue(isSelected(0,1,2,3,4));
1938         assertTrue(isAnchor(2));
1939 
1940         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
1941         keyboard.doKeyPress(KeyCode.SPACE, 
1942                 KeyModifier.getShortcutKey(),
1943                 (Utils.isMac()  ? KeyModifier.CTRL : null));
1944         assertTrue(isSelected(1,2,3,4));
1945         assertTrue(fm.isFocused(0));
1946         assertTrue(isAnchor(0));
1947     }
1948     
1949     
1950     
1951     /***************************************************************************
1952      * Tests for editing
1953      **************************************************************************/
1954     
1955 //    // test 43 (part 1)
1956 //    @Test public void testF2EntersEditModeAndEscapeCancelsEdit_part1() {
1957 //        tableView.setEditable(true);
1958 //        
1959 //        sm.clearAndSelect(0);
1960 //        assertNull(tableView.getEditingItem());
1961 //        keyboard.doKeyPress(KeyCode.F2);
1962 //        assertEquals(root, tableView.getEditingItem());
1963 //        
1964 //        keyboard.doKeyPress(KeyCode.ESCAPE);
1965 //        assertNull(tableView.getEditingItem());
1966 //    }
1967 //    
1968 //    // test 43 (part 2)
1969 //    @Test public void testF2EntersEditModeAndEscapeCancelsEdit_part2() {
1970 //        tableView.setEditable(true);
1971 //        
1972 //        sm.clearAndSelect(0);
1973 //        keyboard.doKeyPress(KeyCode.F2);
1974 //        
1975 //        
1976 //    }
1977     
1978     
1979     /***************************************************************************
1980      * Tests for Tree(Table)View-specific functionality
1981      **************************************************************************/ 
1982     
1983     // Test 1 (TreeView test cases)
1984     @Test public void testRightArrowExpandsBranch() {
1985         sm.clearAndSelect(0);
1986         root.setExpanded(false);
1987         assertFalse(root.isExpanded());
1988         keyboard.doRightArrowPress();
1989         assertTrue(root.isExpanded());
1990     }
1991     
1992     // Test 2 (TreeView test cases)
1993     @Test public void testRightArrowOnExpandedBranch() {
1994         sm.clearAndSelect(0);
1995         keyboard.doRightArrowPress();
1996         assertTrue(isNotSelected(0));
1997         assertTrue(isSelected(1));
1998     }
1999     
2000     // Test 3 (TreeView test cases)
2001     @Test public void testRightArrowOnLeafNode() {
2002         sm.clearAndSelect(1);
2003         keyboard.doRightArrowPress();
2004         assertTrue(isNotSelected(0));
2005         assertTrue(isSelected(1));
2006         assertTrue(isNotSelected(2));
2007     }
2008     
2009     // Test 4 (TreeView test cases)
2010     @Test public void testLeftArrowCollapsesBranch() {
2011         sm.clearAndSelect(0);
2012         assertTrue(root.isExpanded());
2013         keyboard.doLeftArrowPress();
2014         assertFalse(root.isExpanded());
2015     }
2016     
2017     // Test 5 (TreeView test cases)
2018     @Test public void testLeftArrowOnLeafMovesSelectionToParent() {
2019         sm.clearAndSelect(2);
2020         assertTrue(root.isExpanded());
2021         keyboard.doLeftArrowPress();
2022         assertTrue(root.isExpanded());
2023         assertTrue(isSelected(0));
2024         assertTrue(isNotSelected(2));
2025     }
2026     
2027     // Test 6 (TreeView test cases)
2028     @Test public void testLeftArrowMultipleTimes() {
2029         sm.clearAndSelect(5);
2030         keyboard.doLeftArrowPress();
2031         assertTrue(child3.isExpanded());
2032         assertTrue(isSelected(3));
2033         assertTrue(isNotSelected(5));
2034         
2035         keyboard.doLeftArrowPress();
2036         assertFalse(child3.isExpanded());
2037         assertTrue(isSelected(3));
2038         
2039         keyboard.doLeftArrowPress();
2040         assertTrue(isSelected(0));
2041         assertTrue(root.isExpanded());
2042         
2043         keyboard.doLeftArrowPress();
2044         assertTrue(isSelected(0));
2045         assertFalse(root.isExpanded());
2046     }
2047     
2048     // Test 7 (TreeView test cases)
2049     @Test public void testDownArrowTwice() {
2050         sm.clearAndSelect(0);
2051         keyboard.doDownArrowPress();
2052         keyboard.doDownArrowPress();
2053         assertTrue(isSelected(2));
2054         assertTrue(isNotSelected(0));
2055     }
2056     
2057     // Test 8 (TreeView test cases)
2058     @Test public void testDownArrowFourTimes() {
2059         // adding children to child2, but not expanding it
2060         child2.getChildren().addAll(new TreeItem("another child"), new TreeItem("And another!"));
2061         child2.setExpanded(false);
2062         
2063         child3.setExpanded(true);
2064         sm.clearAndSelect(0);
2065         keyboard.doDownArrowPress();
2066         keyboard.doDownArrowPress();
2067         keyboard.doDownArrowPress();
2068         keyboard.doDownArrowPress();
2069         assertTrue(isSelected(4));
2070         assertTrue(isNotSelected(0));
2071     }
2072     
2073     // Test 9 (TreeView test cases)
2074     @Test public void testUpArrow() {
2075         sm.clearAndSelect(1);
2076         keyboard.doUpArrowPress();
2077         assertTrue(isSelected(0));
2078         assertTrue(isNotSelected(1));
2079     }
2080     
2081     // Test 9 (TreeView test cases)
2082     @Test public void testUpArrowFourTimes() {
2083         // adding children to child2, but not expanding it
2084         child2.getChildren().addAll(new TreeItem("another child"), new TreeItem("And another!"));
2085         child2.setExpanded(false);
2086         
2087         sm.clearAndSelect(5);
2088         keyboard.doUpArrowPress();
2089         keyboard.doUpArrowPress();
2090         keyboard.doUpArrowPress();
2091         keyboard.doUpArrowPress();
2092         
2093         assertTrue(isSelected(1));
2094         assertTrue(isNotSelected(5));
2095     }
2096     
2097     // Test 20 (TreeView test cases)
2098     // NOTE: this used to be isSelected but changed when we removed functionality
2099     // for KeyCode.SLASH. Rather than remove the test I'm now testing to make
2100     // sure it does nothing.
2101     @Test public void testCtrlForwardSlashToSelectAll() {
2102         sm.clearAndSelect(1);
2103         keyboard.doKeyPress(KeyCode.SLASH, KeyModifier.getShortcutKey());
2104         assertTrue(isSelected(1));
2105         assertTrue(isNotSelected(0,2,3,4,5,6,7,8,9));
2106     }
2107     
2108     // Test 21 (TreeView test cases)
2109     // NOTE: this used to be isNotSelected but changed when we removed functionality
2110     // for KeyCode.BACK_SLASH. Rather than remove the test I'm now testing to make
2111     // sure it does nothing.
2112     @Test public void testCtrlBackSlashToClearSelection() {
2113         sm.selectAll();
2114         fm.focus(1);
2115         keyboard.doKeyPress(KeyCode.BACK_SLASH, KeyModifier.getShortcutKey());
2116         assertTrue(debug(), isSelected(0,1,2,3,4,5,6,7,8,9));
2117         assertTrue(fm.isFocused(1));
2118     }
2119     
2120     // Test 24 (TreeView test cases)
2121     @Ignore("Not yet working")
2122     @Test public void testExpandCollapseImpactOnSelection() {
2123         sm.clearAndSelect(5);
2124         assertTrue(child3.isExpanded());
2125         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2126         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2127         assertTrue(isSelected(3,4,5));
2128         
2129         keyboard.doLeftArrowPress();
2130         assertFalse(child3.isExpanded());
2131         assertTrue(isSelected(3));
2132         
2133         keyboard.doRightArrowPress();
2134         assertTrue(child3.isExpanded());
2135         assertTrue(isSelected(3,4,5));
2136     }
2137     
2138     // Test 54 (TreeView test cases)
2139     @Test public void testAsteriskExpandsAllBranchesFromRoot() {
2140         // adding children to child2, but not expanding it
2141         child2.getChildren().addAll(new TreeItem("another child"), new TreeItem("And another!"));
2142         child2.setExpanded(false);
2143         
2144         sm.clearAndSelect(0);
2145         assertFalse(child2.isExpanded());
2146         assertTrue(child3.isExpanded());
2147         keyboard.doKeyPress(KeyCode.MULTIPLY);
2148         
2149         assertTrue(child2.isExpanded());
2150         assertTrue(child3.isExpanded());
2151     }
2152     
2153     // Test 57 (TreeView test cases)
2154     @Test public void testMinusCollapsesBranch() {
2155         sm.clearAndSelect(3);
2156         assertTrue(child3.isExpanded());
2157         keyboard.doKeyPress(KeyCode.SUBTRACT);
2158         assertFalse(child3.isExpanded());
2159     }
2160     
2161     // Test 58 (TreeView test cases)
2162     @Test public void testPlusCollapsesBranch() {
2163         sm.clearAndSelect(3);
2164         child3.setExpanded(false);
2165         assertFalse(child3.isExpanded());
2166         keyboard.doKeyPress(KeyCode.ADD);
2167         assertTrue(child3.isExpanded());
2168     }
2169     
2170     
2171     /***************************************************************************
2172      * Tests for specific bug reports
2173      **************************************************************************/
2174     
2175 //    @Test public void test_rt18642() {
2176 //        sm.clearAndSelect(1);                          // select 1
2177 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 2
2178 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 3
2179 //        keyboard.doKeyPress(KeyCode.SPACE, 
2180 //                KeyModifier.getShortcutKey(),
2181 //                (Utils.isMac()  ? KeyModifier.CTRL : null)); // set anchor, and also select, 3
2182 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 4
2183 //        keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 5
2184 //        keyboard.doKeyPress(KeyCode.SPACE, 
2185 //                KeyModifier.getShortcutKey(),
2186 //                (Utils.isMac()  ? KeyModifier.CTRL : null)); // set anchor, and also select, 5
2187 //        
2188 //        assertTrue(isSelected(1, 3, 5));
2189 //        assertTrue(isNotSelected(0, 2, 4));
2190 //        
2191 //        // anchor is at 5, so shift+UP should select rows 4 and 5 only
2192 //        keyboard.doUpArrowPress(KeyModifier.SHIFT);   
2193 //        assertTrue(isSelected(4, 5));
2194 //        assertTrue(isNotSelected(0, 1, 2, 3));
2195 //    }
2196     
2197     @Test public void test_rt14451_1() {
2198         sm.clearAndSelect(5);                          
2199 
2200         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
2201         assertTrue(debug(), isSelected(0,1,2,3,4,5));
2202         assertTrue(isNotSelected(6,7,8,9));
2203         
2204         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
2205         assertTrue(isNotSelected(0,1,2,3,4));
2206         assertTrue(isSelected(5,6,7,8,9));
2207         
2208         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
2209         assertTrue(isSelected(0,1,2,3,4,5));
2210         assertTrue(debug(), isNotSelected(6,7,8,9));
2211     } 
2212     
2213     @Test public void test_rt14451_2() {
2214         sm.clearAndSelect(5);                          
2215 
2216         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
2217         assertTrue(isNotSelected(0,1,2,3,4));
2218         assertTrue(isSelected(5,6,7,8,9));
2219         
2220         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
2221         assertTrue(isSelected(0,1,2,3,4,5));
2222         assertTrue(debug(), isNotSelected(6,7,8,9));
2223         
2224         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
2225         assertTrue(isNotSelected(0,1,2,3,4));
2226         assertTrue(isSelected(5,6,7,8,9));
2227     } 
2228     
2229     @Test public void test_rt26835_1() {
2230         sm.clearAndSelect(5);                          
2231         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey()); 
2232         assertTrue(fm.isFocused(0));
2233     } 
2234     
2235     @Test public void test_rt26835_2() {
2236         sm.clearAndSelect(5);                          
2237         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey()); 
2238         assertTrue(debug(), fm.isFocused(getItemCount()));
2239     } 
2240     
2241     @Test public void test_rt27175() {
2242         sm.clearAndSelect(5);                          
2243         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey()); 
2244         assertTrue(debug(), fm.isFocused(0));
2245         assertTrue(isSelected(0,1,2,3,4,5));
2246     } 
2247     
2248     @Test public void test_rt28065() {
2249         sm.setSelectionMode(SelectionMode.MULTIPLE);
2250         
2251         tableView.getSelectionModel().select(0);
2252         assertEquals(0, tableView.getSelectionModel().getSelectedIndex());
2253         assertEquals(root, tableView.getSelectionModel().getSelectedItem());
2254         assertEquals(0, tableView.getFocusModel().getFocusedIndex());
2255         assertEquals(root, tableView.getFocusModel().getFocusedItem());
2256         
2257         keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey());
2258         assertEquals(0, tableView.getSelectionModel().getSelectedIndex());
2259         assertEquals(root, tableView.getSelectionModel().getSelectedItem());
2260         assertEquals(0, tableView.getFocusModel().getFocusedIndex());
2261         assertEquals(root, tableView.getFocusModel().getFocusedItem());
2262     }
2263     
2264     @Test public void test_rt27583_cellSelection_1() {
2265         sm.setCellSelectionEnabled(true);
2266         sm.setSelectionMode(SelectionMode.MULTIPLE);
2267         
2268         sm.select(0, col0);
2269         assertTrue(fm.isFocused(0, col0));
2270         
2271         // focus should not go out the top of the table
2272         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2273         assertTrue(fm.isFocused(1, col0));
2274         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2275         assertTrue(fm.isFocused(0, col0));
2276         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2277         assertTrue(debug(), fm.isFocused(0, col0));
2278         
2279     }
2280     
2281     @Test public void test_rt27583_cellSelection_2() {
2282         sm.setCellSelectionEnabled(true);
2283         sm.setSelectionMode(SelectionMode.MULTIPLE);
2284         
2285         sm.select(10, col0);
2286         assertTrue(fm.isFocused(10, col0));
2287         
2288         // focus should not go out the bottom of the table
2289         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2290         assertTrue(fm.isFocused(11, col0));
2291         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2292         assertTrue(fm.isFocused(12, col0));
2293         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2294         assertTrue(fm.isFocused(13, col0));
2295         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2296         assertTrue(debug(), fm.isFocused(13, col0));
2297     }
2298     
2299     @Test public void test_rt27583_rowSelection_1() {
2300         sm.setCellSelectionEnabled(false);
2301         sm.setSelectionMode(SelectionMode.MULTIPLE);
2302         
2303         sm.select(0);
2304         assertTrue(fm.isFocused(0));
2305         
2306         // focus should not go out the top of the table
2307         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2308         assertTrue(fm.isFocused(1));
2309         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2310         assertTrue(fm.isFocused(0));
2311         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2312         assertTrue(debug(), fm.isFocused(0));
2313         
2314     }
2315     
2316     @Test public void test_rt27583_rowSelection_2() {
2317         sm.setCellSelectionEnabled(false);
2318         sm.setSelectionMode(SelectionMode.MULTIPLE);
2319         
2320         sm.select(10);
2321         assertTrue(fm.isFocused(10));
2322         
2323         // focus should not go out the bottom of the table
2324         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2325         assertTrue(fm.isFocused(11));
2326         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2327         assertTrue(fm.isFocused(12));
2328         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2329         assertTrue(fm.isFocused(13));
2330         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2331         assertTrue(debug(), fm.isFocused(13));
2332     }
2333     
2334     @Test public void test_rt29930() {
2335         sm.setCellSelectionEnabled(false);
2336         sm.setSelectionMode(SelectionMode.MULTIPLE);
2337         
2338         sm.clearAndSelect(0);
2339         
2340         keyboard.doDownArrowPress(KeyModifier.SHIFT); // select rows [0,1]
2341         keyboard.doDownArrowPress(KeyModifier.SHIFT); // select rows [0,1,2]
2342         assertTrue(isSelected(0,1,2));
2343         assertEquals(2, fm.getFocusedIndex());
2344         assertEquals(0, getAnchor().getRow());
2345         
2346         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null); // set new anchor point
2347         assertTrue(isSelected(0,1));
2348         assertEquals(2, fm.getFocusedIndex());
2349         assertEquals(2, getAnchor().getRow());
2350         
2351         keyboard.doDownArrowPress(KeyModifier.SHIFT); // select rows [2,3]
2352         assertTrue(isSelected(2,3));
2353         assertTrue(debug(), isNotSelected(0,1));
2354         assertEquals(3, fm.getFocusedIndex());
2355         assertEquals(2, getAnchor().getRow());
2356     }
2357 
2358     private int rt29849_start_count = 0;
2359     private int rt29849_cancel_count = 0;
2360     @Test public void test_rt29849() {
2361         tableView.setEditable(true);
2362         col0.setEditable(true);
2363 
2364         col0.setCellValueFactory(param -> new ReadOnlyStringWrapper("DUMMY TEXT"));
2365 
2366         col0.setOnEditStart(t -> {
2367             rt29849_start_count++;
2368         });
2369         col0.setOnEditCancel(t -> {
2370             rt29849_cancel_count++;
2371         });
2372 
2373         // initially the counts should be zero
2374         assertEquals(0, rt29849_start_count);
2375         assertEquals(0, rt29849_cancel_count);
2376 
2377         IndexedCell cell = VirtualFlowTestUtils.getCell(tableView, 0, 0);
2378         assertTrue(cell.isEditable());
2379         assertFalse(cell.isEditing());
2380         assertEquals(0, cell.getIndex());
2381 
2382         // do an edit, start count should be one, cancel still zero
2383         tableView.edit(0, col0);
2384         assertTrue(cell.isEditing());
2385         assertEquals(1, rt29849_start_count);
2386         assertEquals(0, rt29849_cancel_count);
2387 
2388         // cancel edit, now both counts should be 1
2389         keyboard.doKeyPress(KeyCode.ESCAPE);
2390         assertFalse(cell.isEditing());
2391         assertEquals(1, rt29849_start_count);
2392         assertEquals(1, rt29849_cancel_count);
2393     }
2394 
2395     private int rt31577_count = 0;
2396     @Test public void test_rt31577() {
2397         final TableSelectionModel sm = tableView.getSelectionModel();
2398         sm.setCellSelectionEnabled(false);
2399         sm.setSelectionMode(SelectionMode.SINGLE);
2400         sm.clearSelection();
2401 
2402         // the actual bug is that the selectedItem property does not fire an
2403         // event when the selected items list changes (due to deselection).
2404         // It actually does always contain the right value - it just doesn't
2405         // let anyone know it!
2406         sm.selectedItemProperty().addListener(observable -> {
2407             rt31577_count++;
2408         });
2409 
2410         assertTrue(sm.getSelectedItems().isEmpty());
2411         assertFalse(sm.isSelected(1));
2412         assertEquals(0, rt31577_count);
2413 
2414         // select the first row
2415         keyboard.doKeyPress(KeyCode.KP_DOWN);
2416         assertEquals(1, sm.getSelectedItems().size());
2417         assertTrue(sm.isSelected(0));
2418         assertTrue(sm.getSelectedItems().contains(root));
2419         assertEquals(root, sm.getSelectedItem());
2420         assertEquals(1, rt31577_count);
2421 
2422         // deselect the row
2423         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.CTRL,
2424                 Utils.isMac() ? KeyModifier.getShortcutKey() : null);
2425         assertTrue(sm.getSelectedItems().isEmpty());
2426         assertFalse(sm.isSelected(1));
2427         assertNull(sm.getSelectedItem());
2428         assertEquals(2, rt31577_count);
2429     }
2430 
2431     @Test public void test_rt32383_pageDown() {
2432         // this test requires a lot of data
2433         for (int i = 0; i < 100; i++) {
2434             root.getChildren().add(new TreeItem<String>("Row " + i));
2435         }
2436 
2437         final MultipleSelectionModel sm = tableView.getSelectionModel();
2438         sm.setSelectionMode(SelectionMode.SINGLE);
2439         sm.clearAndSelect(0);
2440 
2441         final TreeItem<String> initialFocusOwner = fm.getFocusedItem();
2442 
2443         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.getShortcutKey());
2444         Toolkit.getToolkit().firePulse();
2445         final TreeItem<String> newFocusOwner = fm.getFocusedItem();
2446         assertNotSame(initialFocusOwner, newFocusOwner);
2447 
2448         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.getShortcutKey());
2449         Toolkit.getToolkit().firePulse();
2450         final TreeItem<String> nextFocusOwner = fm.getFocusedItem();
2451         assertNotSame(initialFocusOwner, nextFocusOwner);
2452         assertNotSame(newFocusOwner, nextFocusOwner);
2453     }
2454 
2455     @Test public void test_rt32383_pageUp() {
2456         // this test requires a lot of data
2457         for (int i = 0; i < 100; i++) {
2458             root.getChildren().add(new TreeItem<String>("Row " + i));
2459         }
2460 
2461         final int lastIndex = 99;
2462 
2463         final MultipleSelectionModel sm = tableView.getSelectionModel();
2464         sm.setSelectionMode(SelectionMode.SINGLE);
2465         sm.clearAndSelect(lastIndex);
2466 
2467         // need to make sure we scroll down to the bottom!
2468         tableView.scrollTo(lastIndex);
2469         Toolkit.getToolkit().firePulse();
2470 
2471         final TreeItem<String> initialFocusOwner = fm.getFocusedItem();
2472 
2473         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey());
2474         Toolkit.getToolkit().firePulse();
2475         final TreeItem<String> newFocusOwner = fm.getFocusedItem();
2476         assertNotSame(initialFocusOwner, newFocusOwner);
2477 
2478         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey());
2479         Toolkit.getToolkit().firePulse();
2480         final TreeItem<String> nextFocusOwner = fm.getFocusedItem();
2481         assertNotSame(initialFocusOwner, nextFocusOwner);
2482         assertNotSame(newFocusOwner, nextFocusOwner);
2483     }
2484 
2485     @Test public void test_rt27710_pageDown_singleSelection_cell() {
2486         // this test requires a lot of data
2487         for (int i = 0; i < 100; i++) {
2488             root.getChildren().add(new TreeItem<String>("Row " + i));
2489         }
2490 
2491         col0.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
2492 
2493         final TableSelectionModel sm = tableView.getSelectionModel();
2494         sm.setSelectionMode(SelectionMode.SINGLE);
2495         sm.setCellSelectionEnabled(true);
2496         sm.clearAndSelect(0, col0);
2497 
2498         final TreeItem<String> initialFocusOwner = fm.getFocusedItem();
2499 
2500         // because single selection is enabled, shift+pgDown should result in
2501         // the same result as ctrl+pgDown
2502         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2503         Toolkit.getToolkit().firePulse();
2504         final TreeItem<String> newFocusOwner = fm.getFocusedItem();
2505         assertNotSame(initialFocusOwner, newFocusOwner);
2506 
2507         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2508         Toolkit.getToolkit().firePulse();
2509         final TreeItem<String> nextFocusOwner = fm.getFocusedItem();
2510         assertNotSame(initialFocusOwner, nextFocusOwner);
2511         assertNotSame(newFocusOwner, nextFocusOwner);
2512     }
2513 
2514     @Test public void test_rt27710_pageUp_singleSelection_cell() {
2515         // this test requires a lot of data
2516         for (int i = 0; i < 100; i++) {
2517             root.getChildren().add(new TreeItem<String>("Row " + i));
2518         }
2519 
2520         col0.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
2521 
2522         final int lastIndex = 99;
2523 
2524         final TableSelectionModel sm = tableView.getSelectionModel();
2525         sm.setSelectionMode(SelectionMode.SINGLE);
2526         sm.setCellSelectionEnabled(true);
2527         sm.clearAndSelect(lastIndex, col0);
2528 
2529         // need to make sure we scroll down to the bottom!
2530         tableView.scrollTo(lastIndex);
2531         Toolkit.getToolkit().firePulse();
2532 
2533         final TreeItem<String> initialFocusOwner = fm.getFocusedItem();
2534 
2535         // because single selection is enabled, shift+pgUp should result in
2536         // the same result as ctrl+pgUp
2537         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2538         Toolkit.getToolkit().firePulse();
2539         final TreeItem<String> newFocusOwner = fm.getFocusedItem();
2540         assertNotSame(initialFocusOwner, newFocusOwner);
2541 
2542         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2543         Toolkit.getToolkit().firePulse();
2544         final TreeItem<String> nextFocusOwner = fm.getFocusedItem();
2545         assertNotSame(initialFocusOwner, nextFocusOwner);
2546         assertNotSame(newFocusOwner, nextFocusOwner);
2547     }
2548 
2549     @Test public void test_rt19053_pageUp() {
2550         final int items = 8;
2551         root.getChildren().clear();
2552         for (int i = 0; i < items; i++) {
2553             root.getChildren().add(new TreeItem<>("Row " + i));
2554         }
2555 
2556         final int middleIndex = items / 2;
2557 
2558         final MultipleSelectionModel sm = tableView.getSelectionModel();
2559         tableView.setShowRoot(false);
2560         sm.setSelectionMode(SelectionMode.SINGLE);
2561         sm.clearAndSelect(middleIndex);
2562 
2563         assertEquals(middleIndex, sm.getSelectedIndex());
2564 
2565         final Object initialSelectionOwner = sm.getSelectedItem();
2566 
2567         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2568         Toolkit.getToolkit().firePulse();
2569         final Object newSelectionOwner = sm.getSelectedItem();
2570         assertNotSame(initialSelectionOwner + " == " + newSelectionOwner, initialSelectionOwner, newSelectionOwner);
2571 
2572         // selection should go all the way to the top, but this bug
2573         // shows that instead it seems to stop midway - where the anchor is
2574         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2575         Toolkit.getToolkit().firePulse();
2576         assertEquals(0, fm.getFocusedIndex());
2577         assertEquals(0, sm.getSelectedIndex());
2578         final Object nextSelectionOwner =  sm.getSelectedItem();
2579         assertNotSame(initialSelectionOwner, nextSelectionOwner);
2580         assertNotSame(newSelectionOwner, nextSelectionOwner);
2581     }
2582 
2583     @Test public void test_rt19053_pageDown() {
2584         final int items = 8;
2585         root.getChildren().clear();
2586         for (int i = 0; i < items; i++) {
2587             root.getChildren().add(new TreeItem<>("Row " + i));
2588         }
2589 
2590         final int middleIndex = items / 2;
2591 
2592         final MultipleSelectionModel sm = tableView.getSelectionModel();
2593         tableView.setShowRoot(false);
2594         sm.setSelectionMode(SelectionMode.SINGLE);
2595         sm.clearAndSelect(middleIndex);
2596 
2597         assertEquals(middleIndex, sm.getSelectedIndex());
2598 
2599         final Object initialSelectionOwner = sm.getSelectedItem();
2600 
2601         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2602         Toolkit.getToolkit().firePulse();
2603         final Object newSelectionOwner = sm.getSelectedItem();
2604         assertNotSame(initialSelectionOwner, newSelectionOwner);
2605 
2606         // selection should go all the way to the bottom, but this bug
2607         // shows that instead it seems to stop midway - where the anchor is
2608         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2609         Toolkit.getToolkit().firePulse();
2610         assertEquals(items - 1, fm.getFocusedIndex());
2611         assertEquals(items - 1, sm.getSelectedIndex());
2612         final Object nextSelectionOwner =  sm.getSelectedItem();
2613         assertNotSame(initialSelectionOwner, nextSelectionOwner);
2614         assertNotSame(newSelectionOwner, nextSelectionOwner);
2615     }
2616 
2617     @Test public void test_rt21375_scenario_1a_down() {
2618         sm.clearSelection();
2619 
2620         final int items = 8;
2621         root.getChildren().clear();
2622         for (int i = 0; i < items; i++) {
2623             root.getChildren().add(new TreeItem<>("Row " + i));
2624         }
2625 
2626         final MultipleSelectionModel sm = tableView.getSelectionModel();
2627         sm.setSelectionMode(SelectionMode.MULTIPLE);
2628         sm.clearAndSelect(0);
2629 
2630         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2631         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2632         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);
2633         Toolkit.getToolkit().firePulse();
2634         assertTrue(isSelected(0,1,2,3));
2635         assertEquals(4, sm.getSelectedItems().size());
2636     }
2637 
2638     @Test public void test_rt21375_scenario_1b_down() {
2639         final int items = 8;
2640         root.getChildren().clear();
2641         for (int i = 0; i < items; i++) {
2642             root.getChildren().add(new TreeItem<>("Row " + i));
2643         }
2644 
2645         final MultipleSelectionModel sm = tableView.getSelectionModel();
2646         sm.setSelectionMode(SelectionMode.MULTIPLE);
2647         sm.clearAndSelect(0);
2648 
2649         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2650         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2651         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2652         Toolkit.getToolkit().firePulse();
2653         assertTrue(isSelected(0,1,2,3));
2654         assertEquals(4, sm.getSelectedItems().size());
2655     }
2656 
2657     @Test public void test_rt21375_scenario_2_down() {
2658         final int items = 8;
2659         root.getChildren().clear();
2660         for (int i = 0; i < items; i++) {
2661             root.getChildren().add(new TreeItem<>("Row " + i));
2662         }
2663 
2664         final MultipleSelectionModel sm = tableView.getSelectionModel();
2665         sm.setSelectionMode(SelectionMode.MULTIPLE);
2666         sm.clearAndSelect(0);
2667 
2668         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
2669         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
2670         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
2671         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
2672         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.SHIFT);
2673         Toolkit.getToolkit().firePulse();
2674         assertTrue(isSelected(2,3,4));
2675         assertEquals(3, sm.getSelectedItems().size());
2676     }
2677 
2678     @Test public void test_rt21375_scenario_3_down() {
2679         final int items = 8;
2680         root.getChildren().clear();
2681         for (int i = 0; i < items; i++) {
2682             root.getChildren().add(new TreeItem<>("Row " + i));
2683         }
2684 
2685         final MultipleSelectionModel sm = tableView.getSelectionModel();
2686         sm.setSelectionMode(SelectionMode.MULTIPLE);
2687         sm.clearAndSelect(0);
2688 
2689         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
2690         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
2691         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
2692         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
2693         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2694         Toolkit.getToolkit().firePulse();
2695         assertTrue(isSelected(0,2,3,4));
2696         assertEquals(4, sm.getSelectedItems().size());
2697     }
2698 
2699     @Test public void test_rt21375_scenario_1a_up() {
2700         sm.clearSelection();
2701 
2702         final int items = 8;
2703         root.getChildren().clear();
2704         for (int i = 0; i < items; i++) {
2705             root.getChildren().add(new TreeItem<>("Row " + i));
2706         }
2707 
2708         final MultipleSelectionModel sm = tableView.getSelectionModel();
2709         sm.setSelectionMode(SelectionMode.MULTIPLE);
2710         sm.clearAndSelect(7);
2711 
2712         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
2713         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
2714         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
2715         Toolkit.getToolkit().firePulse();
2716         assertTrue(isSelected(7,6,5,4));
2717         assertEquals(4, sm.getSelectedItems().size());
2718     }
2719 
2720     @Test public void test_rt21375_scenario_1b_up() {
2721         sm.clearSelection();
2722 
2723         final int items = 8;
2724         root.getChildren().clear();
2725         for (int i = 0; i < items; i++) {
2726             root.getChildren().add(new TreeItem<>("Row " + i));
2727         }
2728 
2729         final MultipleSelectionModel sm = tableView.getSelectionModel();
2730         sm.setSelectionMode(SelectionMode.MULTIPLE);
2731         sm.clearAndSelect(7);
2732 
2733         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
2734         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
2735         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2736         Toolkit.getToolkit().firePulse();
2737         assertTrue(isSelected(7,6,5,4));
2738         assertEquals(4, sm.getSelectedItems().size());
2739     }
2740 
2741     @Test public void test_rt21375_scenario_2_up() {
2742         final int items = 8;
2743         root.getChildren().clear();
2744         for (int i = 0; i < items; i++) {
2745             root.getChildren().add(new TreeItem<>("Row " + i));
2746         }
2747 
2748         final MultipleSelectionModel sm = tableView.getSelectionModel();
2749         sm.setSelectionMode(SelectionMode.MULTIPLE);
2750         sm.clearAndSelect(7);
2751 
2752         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
2753         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
2754         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
2755         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
2756         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.SHIFT);
2757         Toolkit.getToolkit().firePulse();
2758         assertTrue(isSelected(5,4,3));
2759         assertEquals(3, sm.getSelectedItems().size());
2760     }
2761 
2762     @Test public void test_rt21375_scenario_3_up() {
2763         final int items = 8;
2764         root.getChildren().clear();
2765         for (int i = 0; i < items; i++) {
2766             root.getChildren().add(new TreeItem<>("Row " + i));
2767         }
2768 
2769         final MultipleSelectionModel sm = tableView.getSelectionModel();
2770         sm.setSelectionMode(SelectionMode.MULTIPLE);
2771         sm.clearAndSelect(7);
2772 
2773         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
2774         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
2775         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
2776         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
2777         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2778         Toolkit.getToolkit().firePulse();
2779         assertTrue(isSelected(7,5,4,3));
2780         assertEquals(4, sm.getSelectedItems().size());
2781     }
2782 
2783     @Test public void test_rt33301_multipleSelection_down() {
2784         final int items = 4;
2785         root.getChildren().clear();
2786         for (int i = 0; i < items; i++) {
2787             root.getChildren().add(new TreeItem<>("Row " + i));
2788         }
2789 
2790         final TableFocusModel fm = tableView.getFocusModel();
2791         final TableSelectionModel sm = tableView.getSelectionModel();
2792         sm.setSelectionMode(SelectionMode.MULTIPLE);
2793         sm.setCellSelectionEnabled(false);
2794         sm.clearAndSelect(2);
2795 
2796         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
2797         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
2798         Toolkit.getToolkit().firePulse();
2799         assertTrue(isNotSelected(0,1));
2800         assertTrue(isSelected(2,3,4));
2801         assertEquals(3, sm.getSelectedItems().size());
2802         assertTrue(fm.isFocused(4));
2803 
2804         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
2805         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
2806         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
2807         Toolkit.getToolkit().firePulse();
2808         assertTrue(isNotSelected(0,1));
2809         assertTrue(isSelected(2,3,4));
2810         assertEquals(3, sm.getSelectedItems().size());
2811         assertTrue("Focus index incorrectly at: " + fm.getFocusedIndex(), fm.isFocused(4));
2812     }
2813 
2814     @Test public void test_rt33301_multipleSelection_up() {
2815         final int items = 4;
2816         root.getChildren().clear();
2817         for (int i = 0; i < items; i++) {
2818             root.getChildren().add(new TreeItem<>("Row " + i));
2819         }
2820 
2821         final TableFocusModel fm = tableView.getFocusModel();
2822         final TableSelectionModel sm = tableView.getSelectionModel();
2823         sm.setSelectionMode(SelectionMode.MULTIPLE);
2824         sm.setCellSelectionEnabled(false);
2825         sm.clearAndSelect(2);
2826 
2827         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
2828         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
2829         Toolkit.getToolkit().firePulse();
2830         assertTrue(isNotSelected(3,4));
2831         assertTrue(isSelected(0,1,2));
2832         assertEquals(3, sm.getSelectedItems().size());
2833         assertTrue(fm.isFocused(0));
2834 
2835         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
2836         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
2837         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
2838         Toolkit.getToolkit().firePulse();
2839         assertTrue(isNotSelected(3,4));
2840         assertTrue(isSelected(0,1,2));
2841         assertEquals(3, sm.getSelectedItems().size());
2842         assertTrue(fm.isFocused(0));
2843     }
2844 
2845     @Test public void test_rt33301_singleSelection_down() {
2846         final int items = 4;
2847         root.getChildren().clear();
2848         for (int i = 0; i < items; i++) {
2849             root.getChildren().add(new TreeItem<>("Row " + i));
2850         }
2851 
2852         final TableFocusModel fm = tableView.getFocusModel();
2853         final TableSelectionModel sm = tableView.getSelectionModel();
2854         sm.setSelectionMode(SelectionMode.SINGLE);
2855         sm.setCellSelectionEnabled(false);
2856         sm.clearAndSelect(2);
2857 
2858         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
2859         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
2860         Toolkit.getToolkit().firePulse();
2861         assertTrue(isNotSelected(0,1,2,3));
2862         assertTrue(isSelected(4));
2863         assertEquals(1, sm.getSelectedItems().size());
2864         assertTrue(fm.isFocused(4));
2865 
2866         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
2867         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
2868         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
2869         Toolkit.getToolkit().firePulse();
2870         assertTrue(isNotSelected(0,1,2,3));
2871         assertTrue(isSelected(4));
2872         assertEquals(1, sm.getSelectedItems().size());
2873         assertTrue(fm.isFocused(4));
2874     }
2875 
2876     @Test public void test_rt33301_singleSelection_up() {
2877         final int items = 4;
2878         root.getChildren().clear();
2879         for (int i = 0; i < items; i++) {
2880             root.getChildren().add(new TreeItem<>("Row " + i));
2881         }
2882 
2883         final TableFocusModel fm = tableView.getFocusModel();
2884         final TableSelectionModel sm = tableView.getSelectionModel();
2885         sm.setSelectionMode(SelectionMode.SINGLE);
2886         sm.setCellSelectionEnabled(false);
2887         sm.clearAndSelect(2);
2888 
2889         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
2890         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
2891         Toolkit.getToolkit().firePulse();
2892         assertTrue(isNotSelected(1,2,3,4));
2893         assertTrue(isSelected(0));
2894         assertEquals(1, sm.getSelectedItems().size());
2895         assertTrue(fm.isFocused(0));
2896 
2897         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
2898         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
2899         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
2900         Toolkit.getToolkit().firePulse();
2901         assertTrue(isNotSelected(1,2,3,4));
2902         assertTrue(isSelected(0));
2903         assertEquals(1, sm.getSelectedItems().size());
2904         assertTrue(fm.isFocused(0));
2905     }
2906 
2907     private int rt_33559_count = 0;
2908     @Test public void test_rt33559() {
2909         final int items = 4;
2910         root.getChildren().clear();
2911         root.setExpanded(false);
2912         for (int i = 0; i < items; i++) {
2913             root.getChildren().add(new TreeItem<>("Row " + i));
2914         }
2915 
2916         final MultipleSelectionModel sm = tableView.getSelectionModel();
2917         sm.setSelectionMode(SelectionMode.SINGLE);
2918         sm.clearAndSelect(0);
2919 
2920         tableView.getSelectionModel().getSelectedItems().addListener((ListChangeListener) c -> {
2921             while (c.next()) {
2922                 rt_33559_count++;
2923             }
2924         });
2925 
2926         assertEquals(0, rt_33559_count);
2927         keyboard.doKeyPress(KeyCode.RIGHT); // expand root
2928         assertEquals(0, rt_33559_count);
2929     }
2930 
2931     @Test public void test_rt20915() {
2932         final FocusModel fm = tableView.getFocusModel();
2933         final MultipleSelectionModel sm = tableView.getSelectionModel();
2934         sm.clearAndSelect(0);
2935 
2936         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2937         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2938         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
2939         Toolkit.getToolkit().firePulse();
2940         assertTrue(isNotSelected(1,2,3));
2941         assertTrue(isSelected(0));
2942         assertEquals(1, sm.getSelectedItems().size());
2943         assertTrue(fm.isFocused(3));
2944 
2945         keyboard.doKeyPress(KeyCode.SPACE,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2946         Toolkit.getToolkit().firePulse();
2947         assertTrue(isSelected(0,1,2,3));
2948         assertEquals(4, sm.getSelectedItems().size());
2949         assertTrue(fm.isFocused(3));
2950     }
2951 
2952     @Test public void test_rt34200() {
2953         final int items = 100;
2954         root.getChildren().clear();
2955         root.setExpanded(true);
2956         for (int i = 0; i < items; i++) {
2957             root.getChildren().add(new TreeItem<>("Row " + i));
2958         }
2959 
2960         sm.clearAndSelect(99);
2961         tableView.scrollTo(99);
2962         assertEquals(99, getAnchor().getRow());
2963         assertEquals(99, fm.getFocusedIndex());
2964 
2965         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2966         Toolkit.getToolkit().firePulse();
2967         assertEquals(99, getAnchor().getRow());
2968         assertTrue(fm.getFocusedIndex() < 99);
2969     }
2970 
2971     @Test public void test_rt34369_cellSelection() {
2972         final int items = 100;
2973         root.getChildren().clear();
2974         root.setExpanded(true);
2975         for (int i = 0; i < items; i++) {
2976             root.getChildren().add(new TreeItem<>("Row " + i));
2977         }
2978 
2979         sm.setCellSelectionEnabled(true);
2980 
2981         sm.clearAndSelect(99, col0);
2982         tableView.scrollTo(99);
2983         assertEquals(99, getAnchor().getRow());
2984         assertEquals(col0, getAnchor().getTableColumn());
2985         assertEquals(99, fm.getFocusedIndex());
2986 
2987         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2988         Toolkit.getToolkit().firePulse();
2989         assertEquals(99, getAnchor().getRow());
2990         assertEquals(col0, getAnchor().getTableColumn());
2991         assertTrue(fm.getFocusedIndex() < 99);
2992     }
2993 
2994     @Test public void test_rt34369_rowSelection() {
2995         final int items = 100;
2996         root.getChildren().clear();
2997         root.setExpanded(true);
2998         for (int i = 0; i < items; i++) {
2999             root.getChildren().add(new TreeItem<>("Row " + i));
3000         }
3001 
3002         sm.setCellSelectionEnabled(false);
3003 
3004         sm.clearAndSelect(99);
3005         tableView.scrollTo(99);
3006         assertEquals(99, getAnchor().getRow());
3007         assertEquals(99, fm.getFocusedIndex());
3008 
3009         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
3010         Toolkit.getToolkit().firePulse();
3011         assertEquals(99, getAnchor().getRow());
3012         assertTrue(fm.getFocusedIndex() < 99);
3013     }
3014 
3015     @Test public void test_rt33894() {
3016         final int items = 5;
3017         root.getChildren().clear();
3018         root.setExpanded(true);
3019         for (int i = 0; i < items; i++) {
3020             root.getChildren().add(new TreeItem<>("Row " + i));
3021         }
3022 
3023         sm.clearAndSelect(1);
3024         assertEquals(1, getAnchor().getRow());
3025         assertEquals(1, fm.getFocusedIndex());
3026         assertEquals(1, sm.getSelectedIndex());
3027 
3028         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3029         Toolkit.getToolkit().firePulse();
3030         assertEquals(1, getAnchor().getRow());
3031         assertEquals(2, fm.getFocusedIndex());
3032         assertEquals(1, sm.getSelectedIndex());
3033 
3034         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
3035         Toolkit.getToolkit().firePulse();
3036         assertEquals(2, getAnchor().getRow());
3037         assertEquals(2, fm.getFocusedIndex());
3038         assertEquals(2, sm.getSelectedIndex());
3039         assertTrue(isSelected(1, 2));
3040 
3041         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3042         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3043         Toolkit.getToolkit().firePulse();
3044         assertEquals(2, getAnchor().getRow());
3045         assertEquals(0, fm.getFocusedIndex());
3046         assertEquals(2, sm.getSelectedIndex());
3047         assertTrue(isSelected(1, 2));
3048 
3049         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
3050         Toolkit.getToolkit().firePulse();
3051         assertEquals(0, getAnchor().getRow());
3052         assertEquals(0, fm.getFocusedIndex());
3053         assertEquals(0, sm.getSelectedIndex());
3054         assertTrue(isSelected(0, 1, 2));
3055     }
3056 
3057     @Test public void test_rt34425() {
3058         final int items = 5;
3059         root.getChildren().clear();
3060         root.setExpanded(true);
3061         for (int i = 0; i < items; i++) {
3062             root.getChildren().add(new TreeItem<>("Row " + i));
3063         }
3064 
3065         sm.clearAndSelect(1);
3066         assertEquals(1, getAnchor().getRow());
3067         assertEquals(1, fm.getFocusedIndex());
3068         assertEquals(1, sm.getSelectedIndex());
3069 
3070         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3071         Toolkit.getToolkit().firePulse();
3072         assertEquals(1, getAnchor().getRow());
3073         assertEquals(2, fm.getFocusedIndex());
3074         assertEquals(1, sm.getSelectedIndex());
3075 
3076         keyboard.doKeyPress(KeyCode.SPACE);
3077         Toolkit.getToolkit().firePulse();
3078         assertEquals(2, getAnchor().getRow());
3079         assertEquals(2, fm.getFocusedIndex());
3080         assertEquals(2, sm.getSelectedIndex());
3081         assertTrue(isSelected(1, 2));
3082     }
3083 
3084     @Test public void test_rt33613_up_oneColumn() {
3085         final int items = 10;
3086         root.getChildren().clear();
3087         root.setExpanded(true);
3088         for (int i = 0; i < items; i++) {
3089             root.getChildren().add(new TreeItem<>("Row " + i));
3090         }
3091 
3092         sm.setCellSelectionEnabled(true);
3093 
3094         sm.clearAndSelect(6, col0);
3095         assertEquals(6, getAnchor().getRow());
3096         assertEquals(0, getAnchor().getColumn());
3097         assertEquals(6, fm.getFocusedIndex());
3098         assertEquals(6, sm.getSelectedIndex());
3099 
3100         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3101         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3102         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3103         Toolkit.getToolkit().firePulse();
3104         assertEquals(6, getAnchor().getRow());
3105         assertEquals(0, getAnchor().getColumn());
3106         assertEquals(3, fm.getFocusedIndex());
3107         assertEquals(6, sm.getSelectedIndex());
3108 
3109         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
3110         Toolkit.getToolkit().firePulse();
3111         assertEquals(6, getAnchor().getRow());
3112         assertEquals(0, getAnchor().getColumn());
3113         assertEquals(3, fm.getFocusedIndex());
3114         assertEquals(3, sm.getSelectedIndex());
3115     }
3116 
3117     @Test public void test_rt33613_up_multipleColumn_right() {
3118         final int items = 10;
3119         root.getChildren().clear();
3120         root.setExpanded(true);
3121         for (int i = 0; i < items; i++) {
3122             root.getChildren().add(new TreeItem<>("Row " + i));
3123         }
3124 
3125         sm.setCellSelectionEnabled(true);
3126 
3127         sm.clearAndSelect(6, col0);
3128         assertEquals(6, getAnchor().getRow());
3129         assertEquals(0, getAnchor().getColumn());
3130         assertTrue(fm.isFocused(6, col0));
3131         assertTrue(sm.isSelected(6, col0));
3132 
3133         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3134         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3135         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3136         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.getShortcutKey());
3137         Toolkit.getToolkit().firePulse();
3138         assertEquals(6, getAnchor().getRow());
3139         assertEquals(0, getAnchor().getColumn());
3140         assertTrue(fm.isFocused(3, col1));
3141         assertTrue(sm.isSelected(6, col0));
3142         assertFalse(sm.isSelected(3, col1));
3143 
3144         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
3145         Toolkit.getToolkit().firePulse();
3146         assertEquals(6, getAnchor().getRow());
3147         assertEquals(0, getAnchor().getColumn());
3148         assertTrue(fm.isFocused(3, col1));
3149         assertTrue(sm.isSelected(3, col1));
3150         assertTrue(sm.isSelected(6, col0));
3151     }
3152 
3153     @Test public void test_rt33613_up_multipleColumn_left() {
3154         final int items = 10;
3155         root.getChildren().clear();
3156         root.setExpanded(true);
3157         for (int i = 0; i < items; i++) {
3158             root.getChildren().add(new TreeItem<>("Row " + i));
3159         }
3160 
3161         sm.setCellSelectionEnabled(true);
3162 
3163         sm.clearAndSelect(6, col1);
3164         assertEquals(6, getAnchor().getRow());
3165         assertEquals(1, getAnchor().getColumn());
3166         assertTrue(fm.isFocused(6, col1));
3167         assertTrue(sm.isSelected(6, col1));
3168 
3169         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3170         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3171         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
3172         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.getShortcutKey());
3173         Toolkit.getToolkit().firePulse();
3174         assertEquals(6, getAnchor().getRow());
3175         assertEquals(1, getAnchor().getColumn());
3176         assertTrue(fm.isFocused(3, col0));
3177         assertTrue(sm.isSelected(6, col1));
3178         assertFalse(sm.isSelected(3, col0));
3179 
3180         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
3181         Toolkit.getToolkit().firePulse();
3182         assertEquals(6, getAnchor().getRow());
3183         assertEquals(1, getAnchor().getColumn());
3184         assertTrue(fm.isFocused(3, col0));
3185         assertTrue(sm.isSelected(3, col0));
3186         assertTrue(sm.isSelected(6, col1));
3187     }
3188 
3189     @Test public void test_rt33613_down_oneColumn() {
3190         final int items = 10;
3191         root.getChildren().clear();
3192         root.setExpanded(true);
3193         for (int i = 0; i < items; i++) {
3194             root.getChildren().add(new TreeItem<>("Row " + i));
3195         }
3196 
3197         sm.setCellSelectionEnabled(true);
3198 
3199         sm.clearAndSelect(3, col0);
3200         assertEquals(3, getAnchor().getRow());
3201         assertEquals(0, getAnchor().getColumn());
3202         assertEquals(3, fm.getFocusedIndex());
3203         assertEquals(3, sm.getSelectedIndex());
3204 
3205         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3206         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3207         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3208         Toolkit.getToolkit().firePulse();
3209         assertEquals(3, getAnchor().getRow());
3210         assertEquals(0, getAnchor().getColumn());
3211         assertEquals(6, fm.getFocusedIndex());
3212         assertEquals(3, sm.getSelectedIndex());
3213 
3214         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
3215         Toolkit.getToolkit().firePulse();
3216         assertEquals(3, getAnchor().getRow());
3217         assertEquals(0, getAnchor().getColumn());
3218         assertEquals(6, fm.getFocusedIndex());
3219         assertEquals(6, sm.getSelectedIndex());
3220     }
3221 
3222     @Test public void test_rt33613_down_multipleColumn_right() {
3223         final int items = 10;
3224         root.getChildren().clear();
3225         root.setExpanded(true);
3226         for (int i = 0; i < items; i++) {
3227             root.getChildren().add(new TreeItem<>("Row " + i));
3228         }
3229 
3230         sm.setCellSelectionEnabled(true);
3231 
3232         sm.clearAndSelect(3, col0);
3233         assertEquals(3, getAnchor().getRow());
3234         assertEquals(0, getAnchor().getColumn());
3235         assertTrue(fm.isFocused(3, col0));
3236         assertTrue(sm.isSelected(3, col0));
3237 
3238         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3239         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3240         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3241         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.getShortcutKey());
3242         Toolkit.getToolkit().firePulse();
3243         assertEquals(3, getAnchor().getRow());
3244         assertEquals(0, getAnchor().getColumn());
3245         assertTrue(fm.isFocused(6, col1));
3246         assertTrue(sm.isSelected(3, col0));
3247         assertFalse(sm.isSelected(6, col1));
3248 
3249         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
3250         Toolkit.getToolkit().firePulse();
3251         assertEquals(3, getAnchor().getRow());
3252         assertEquals(0, getAnchor().getColumn());
3253         assertTrue(fm.isFocused(6, col1));
3254         assertTrue(sm.isSelected(6, col1));
3255         assertTrue(sm.isSelected(3, col0));
3256     }
3257 
3258     @Test public void test_rt33613_down_multipleColumn_left() {
3259         final int items = 10;
3260         root.getChildren().clear();
3261         root.setExpanded(true);
3262         for (int i = 0; i < items; i++) {
3263             root.getChildren().add(new TreeItem<>("Row " + i));
3264         }
3265 
3266         sm.setCellSelectionEnabled(true);
3267 
3268         sm.clearAndSelect(3, col1);
3269         assertEquals(3, getAnchor().getRow());
3270         assertEquals(1, getAnchor().getColumn());
3271         assertTrue(fm.isFocused(3, col1));
3272         assertTrue(sm.isSelected(3, col1));
3273 
3274         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3275         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3276         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3277         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.getShortcutKey());
3278         Toolkit.getToolkit().firePulse();
3279         assertEquals(3, getAnchor().getRow());
3280         assertEquals(1, getAnchor().getColumn());
3281         assertTrue(fm.isFocused(6, col0));
3282         assertTrue(sm.isSelected(3, col1));
3283         assertFalse(sm.isSelected(6, col0));
3284 
3285         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);
3286         Toolkit.getToolkit().firePulse();
3287         assertEquals(3, getAnchor().getRow());
3288         assertEquals(1, getAnchor().getColumn());
3289         assertTrue(fm.isFocused(6, col0));
3290         assertTrue(sm.isSelected(6, col0));
3291         assertTrue(sm.isSelected(3, col1));
3292     }
3293 
3294     @Test public void test_rt18439() {
3295         final int items = 10;
3296         root.getChildren().clear();
3297         root.setExpanded(true);
3298         for (int i = 0; i < items; i++) {
3299             root.getChildren().add(new TreeItem<>("Row " + i));
3300         }
3301 
3302         sm.setCellSelectionEnabled(true);
3303         sm.setSelectionMode(SelectionMode.MULTIPLE);
3304 
3305         sm.clearAndSelect(0, col0);
3306 
3307         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 1
3308         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 2
3309         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 3
3310         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 4
3311         assertEquals(0, getAnchor().getRow());
3312         assertEquals(debug(), 0, getAnchor().getColumn());              // anchor does not move
3313         assertTrue(fm.isFocused(0, col4));
3314         assertTrue(sm.isSelected(0, col0));
3315         assertTrue(sm.isSelected(0, col1));
3316         assertTrue(sm.isSelected(0, col2));
3317         assertTrue(sm.isSelected(0, col3));
3318         assertTrue(sm.isSelected(0, col4));
3319 
3320         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 1
3321         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 2
3322         assertEquals(0, getAnchor().getRow());
3323         assertEquals(0, getAnchor().getColumn());             // anchor does not move
3324         assertTrue(fm.isFocused(2, col4));
3325         assertTrue(sm.isSelected(0, col0));
3326         assertTrue(sm.isSelected(0, col1));
3327         assertTrue(sm.isSelected(0, col2));
3328         assertTrue(sm.isSelected(0, col3));
3329         assertTrue(sm.isSelected(0, col4));
3330         assertTrue(sm.isSelected(1, col4));
3331         assertTrue(sm.isSelected(2, col4));
3332 
3333         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 3
3334         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 2
3335         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 1
3336         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 0
3337         assertEquals(0, getAnchor().getRow());
3338         assertEquals(0, getAnchor().getColumn());             // anchor does not move
3339         assertTrue(fm.isFocused(2, col0));
3340         assertTrue(sm.isSelected(0, col0));
3341         assertTrue(sm.isSelected(0, col1));
3342         assertTrue(sm.isSelected(0, col2));
3343         assertTrue(sm.isSelected(0, col3));
3344         assertTrue(sm.isSelected(0, col4));
3345         assertTrue(sm.isSelected(1, col4));
3346         assertTrue(sm.isSelected(2, col4));
3347         assertTrue(sm.isSelected(2, col3));
3348         assertTrue(sm.isSelected(2, col2));
3349         assertTrue(sm.isSelected(2, col1));
3350         assertTrue(sm.isSelected(2, col0));
3351 
3352         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 1
3353         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 0
3354         assertEquals(0, getAnchor().getRow());
3355         assertEquals(0, getAnchor().getColumn());           // anchor does not move
3356         assertTrue(fm.isFocused(0, col0));
3357         assertFalse(sm.isSelected(0, col0));                // we've gone right around - this cell is now unselected
3358         assertTrue(sm.isSelected(0, col1));
3359         assertTrue(sm.isSelected(0, col2));
3360         assertTrue(sm.isSelected(0, col3));
3361         assertTrue(sm.isSelected(0, col4));
3362         assertTrue(sm.isSelected(1, col4));
3363         assertTrue(sm.isSelected(2, col4));
3364         assertTrue(sm.isSelected(2, col3));
3365         assertTrue(sm.isSelected(2, col2));
3366         assertTrue(sm.isSelected(2, col1));
3367         assertTrue(sm.isSelected(2, col0));
3368         assertTrue(sm.isSelected(1, col0));
3369     }
3370 
3371     // this is an extension of the previous test, where we had a bug where going up resulted in all cells between the
3372     // anchor (at (0,0)) and the first selected cell in column 0 were being selected. This wasn't visible in the previous
3373     // test as we only went down two rows, so when we went up everything looked as expected
3374     @Test public void test_rt18439_startAt_row0_col0_clockwise() {
3375         final int items = 10;
3376         root.getChildren().clear();
3377         root.setExpanded(true);
3378         for (int i = 0; i < items; i++) {
3379             root.getChildren().add(new TreeItem<>("Row " + i));
3380         }
3381 
3382         sm.setCellSelectionEnabled(true);
3383         sm.setSelectionMode(SelectionMode.MULTIPLE);
3384 
3385         sm.clearAndSelect(0, col0);
3386 
3387         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 1
3388         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 2
3389         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 3
3390         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 4
3391 
3392         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 1
3393         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 2
3394         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 3
3395         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 4
3396 
3397         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 3
3398         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 2
3399         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 1
3400         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 0
3401 
3402         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 3
3403         assertEquals(0, getAnchor().getRow());
3404         assertEquals(0, getAnchor().getColumn());           // anchor does not move
3405         assertTrue(fm.isFocused(3, col0));
3406         assertTrue(sm.isSelected(0, col0));
3407         assertTrue(sm.isSelected(0, col1));
3408         assertTrue(sm.isSelected(0, col2));
3409         assertTrue(sm.isSelected(0, col3));
3410         assertTrue(sm.isSelected(0, col4));
3411         assertTrue(sm.isSelected(1, col4));
3412         assertTrue(sm.isSelected(2, col4));
3413         assertTrue(sm.isSelected(3, col4));
3414         assertTrue(sm.isSelected(4, col4));
3415         assertTrue(sm.isSelected(4, col3));
3416         assertTrue(sm.isSelected(4, col2));
3417         assertTrue(sm.isSelected(4, col1));
3418         assertTrue(sm.isSelected(4, col0));
3419         assertTrue(sm.isSelected(3, col0));
3420 
3421         // critical part - these cells should not be selected!
3422         assertFalse(sm.isSelected(1, col0));
3423         assertFalse(sm.isSelected(2, col0));
3424     }
3425 
3426     @Test public void test_rt18439_startAt_row0_col4_clockwise() {
3427         final int items = 10;
3428         root.getChildren().clear();
3429         root.setExpanded(true);
3430         for (int i = 0; i < items; i++) {
3431             root.getChildren().add(new TreeItem<>("Row " + i));
3432         }
3433 
3434         sm.setCellSelectionEnabled(true);
3435         sm.setSelectionMode(SelectionMode.MULTIPLE);
3436 
3437         sm.clearAndSelect(0, col4);
3438 
3439         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 1
3440         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 2
3441         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 3
3442         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 4
3443 
3444         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 3
3445         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 2
3446         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 1
3447         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 0
3448 
3449         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 3
3450         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 2
3451         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 1
3452         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 0
3453 
3454         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 1
3455         assertEquals(0, getAnchor().getRow());
3456         assertEquals(4, getAnchor().getColumn());           // anchor does not move
3457         assertTrue(fm.isFocused(0, col1));
3458         assertTrue(sm.isSelected(0, col4));
3459         assertTrue(sm.isSelected(1, col4));
3460         assertTrue(sm.isSelected(2, col4));
3461         assertTrue(sm.isSelected(3, col4));
3462         assertTrue(sm.isSelected(4, col4));
3463         assertTrue(sm.isSelected(4, col3));
3464         assertTrue(sm.isSelected(4, col2));
3465         assertTrue(sm.isSelected(4, col1));
3466         assertTrue(sm.isSelected(4, col0));
3467         assertTrue(sm.isSelected(3, col0));
3468         assertTrue(sm.isSelected(2, col0));
3469         assertTrue(sm.isSelected(1, col0));
3470         assertTrue(sm.isSelected(0, col0));
3471         assertTrue(sm.isSelected(0, col1));
3472 
3473         // critical part - these cells should not be selected!
3474         assertFalse(sm.isSelected(0, col2));
3475         assertFalse(sm.isSelected(0, col3));
3476     }
3477 
3478     @Test public void test_rt18439_startAt_row4_col4_clockwise() {
3479         final int items = 10;
3480         root.getChildren().clear();
3481         root.setExpanded(true);
3482         for (int i = 0; i < items; i++) {
3483             root.getChildren().add(new TreeItem<>("Row " + i));
3484         }
3485 
3486         sm.setCellSelectionEnabled(true);
3487         sm.setSelectionMode(SelectionMode.MULTIPLE);
3488 
3489         sm.clearAndSelect(4, col4);
3490 
3491         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 3
3492         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 2
3493         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 1
3494         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 0
3495 
3496         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 3
3497         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 2
3498         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 1
3499         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);   // row 0
3500 
3501         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 1
3502         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 2
3503         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 3
3504         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 4
3505 
3506         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 1
3507         assertEquals(4, getAnchor().getRow());
3508         assertEquals(4, getAnchor().getColumn());           // anchor does not move
3509         assertTrue(fm.isFocused(1, col4));
3510         assertTrue(sm.isSelected(4, col4));
3511         assertTrue(sm.isSelected(4, col2));
3512         assertTrue(sm.isSelected(4, col2));
3513         assertTrue(sm.isSelected(4, col1));
3514         assertTrue(sm.isSelected(4, col0));
3515         assertTrue(sm.isSelected(3, col0));
3516         assertTrue(sm.isSelected(2, col0));
3517         assertTrue(sm.isSelected(1, col0));
3518         assertTrue(sm.isSelected(0, col0));
3519         assertTrue(sm.isSelected(0, col1));
3520         assertTrue(sm.isSelected(0, col2));
3521         assertTrue(sm.isSelected(0, col3));
3522         assertTrue(sm.isSelected(0, col4));
3523         assertTrue(sm.isSelected(1, col4));
3524 
3525         // critical part - these cells should not be selected!
3526         assertFalse(sm.isSelected(2, col4));
3527         assertFalse(sm.isSelected(3, col4));
3528     }
3529 
3530     @Test public void test_rt18439_startAt_row4_col0_clockwise() {
3531         final int items = 10;
3532         root.getChildren().clear();
3533         root.setExpanded(true);
3534         for (int i = 0; i < items; i++) {
3535             root.getChildren().add(new TreeItem<>("Row " + i));
3536         }
3537 
3538         sm.setCellSelectionEnabled(true);
3539         sm.setSelectionMode(SelectionMode.MULTIPLE);
3540 
3541         sm.clearAndSelect(4, col0);
3542 
3543         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 3
3544         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 2
3545         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 1
3546         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // row 0
3547 
3548         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT);   // col 1
3549         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT);   // col 2
3550         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT);   // col 3
3551         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT);   // col 4
3552 
3553         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 1
3554         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 2
3555         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 3
3556         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // row 4
3557 
3558         keyboard.doKeyPress(KeyCode.LEFT, KeyModifier.SHIFT); // col 3
3559         assertEquals(4, getAnchor().getRow());
3560         assertEquals(0, getAnchor().getColumn());           // anchor does not move
3561         assertTrue(fm.isFocused(4, col3));
3562         assertTrue(sm.isSelected(4, col0));
3563         assertTrue(sm.isSelected(3, col0));
3564         assertTrue(sm.isSelected(2, col0));
3565         assertTrue(sm.isSelected(1, col0));
3566         assertTrue(sm.isSelected(0, col0));
3567         assertTrue(sm.isSelected(0, col1));
3568         assertTrue(sm.isSelected(0, col2));
3569         assertTrue(sm.isSelected(0, col3));
3570         assertTrue(sm.isSelected(0, col4));
3571         assertTrue(sm.isSelected(1, col4));
3572         assertTrue(sm.isSelected(2, col4));
3573         assertTrue(sm.isSelected(3, col4));
3574         assertTrue(sm.isSelected(4, col4));
3575         assertTrue(sm.isSelected(4, col3));
3576 
3577         // critical part - these cells should not be selected!
3578         assertFalse(sm.isSelected(4, col2));
3579         assertFalse(sm.isSelected(4, col1));
3580     }
3581 
3582     @Test public void test_rt34461_cellSelection() {
3583         final int items = 10;
3584         root.getChildren().clear();
3585         root.setExpanded(true);
3586         for (int i = 0; i < items; i++) {
3587             root.getChildren().add(new TreeItem<>("Row " + i));
3588         }
3589 
3590         sm.setCellSelectionEnabled(true);
3591         sm.setSelectionMode(SelectionMode.MULTIPLE);
3592 
3593         sm.clearAndSelect(0, col0);
3594         assertEquals(0, getAnchor().getRow());
3595         assertEquals(0, getAnchor().getColumn());
3596         assertTrue(fm.isFocused(0, col0));
3597         assertTrue(sm.isSelected(0, col0));
3598         assertFalse(sm.isSelected(1, col0));
3599 
3600         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3601         assertEquals(0, getAnchor().getRow());
3602         assertEquals(0, getAnchor().getColumn());
3603         assertTrue(fm.isFocused(1, col0));
3604         assertTrue(sm.isSelected(0, col0));
3605         assertFalse(sm.isSelected(1, col0));
3606 
3607         keyboard.doKeyPress(KeyCode.SPACE);
3608         assertEquals(1, getAnchor().getRow());      // new anchor point
3609         assertEquals(0, getAnchor().getColumn());
3610         assertTrue(fm.isFocused(1, col0));
3611         assertTrue(sm.isSelected(0, col0));
3612         assertTrue(sm.isSelected(1, col0));
3613 
3614         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);
3615         assertEquals(1, getAnchor().getRow());
3616         assertEquals(0, getAnchor().getColumn());
3617         assertTrue(fm.isFocused(2, col0));
3618         assertFalse(sm.isSelected(0, col0));    // selection moves off here as the anchor point moved with the space
3619         assertTrue(sm.isSelected(1, col0));
3620         assertTrue(sm.isSelected(2, col0));
3621     }
3622 
3623     @Test public void test_rt34461_rowSelection() {
3624         final int items = 10;
3625         root.getChildren().clear();
3626         root.setExpanded(true);
3627         for (int i = 0; i < items; i++) {
3628             root.getChildren().add(new TreeItem<>("Row " + i));
3629         }
3630 
3631         sm.setCellSelectionEnabled(false);
3632         sm.setSelectionMode(SelectionMode.MULTIPLE);
3633 
3634         sm.clearAndSelect(0);
3635         assertEquals(0, getAnchor().getRow());
3636         assertEquals(-1, getAnchor().getColumn());
3637         assertTrue(fm.isFocused(0));
3638         assertTrue(sm.isSelected(0));
3639         assertFalse(sm.isSelected(1));
3640 
3641         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
3642         assertEquals(0, getAnchor().getRow());
3643         assertEquals(-1, getAnchor().getColumn());
3644         assertTrue(fm.isFocused(1));
3645         assertTrue(sm.isSelected(0));
3646         assertFalse(sm.isSelected(1));
3647 
3648         keyboard.doKeyPress(KeyCode.SPACE);
3649         assertEquals(1, getAnchor().getRow());      // new anchor point
3650         assertEquals(-1, getAnchor().getColumn());
3651         assertTrue(fm.isFocused(1));
3652         assertTrue(sm.isSelected(0));
3653         assertTrue(sm.isSelected(1));
3654 
3655         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);
3656         assertEquals(1, getAnchor().getRow());
3657         assertEquals(-1, getAnchor().getColumn());
3658         assertTrue(fm.isFocused(2));
3659         assertFalse(sm.isSelected(0));    // selection moves off here as the anchor point moved with the space
3660         assertTrue(sm.isSelected(1));
3661         assertTrue(sm.isSelected(2));
3662     }
3663 
3664     @Test public void test_rt34407_down_down_up() {
3665         final int items = 100;
3666         root.getChildren().clear();
3667         root.setExpanded(true);
3668         for (int i = 0; i < items; i++) {
3669             root.getChildren().add(new TreeItem<>("Row " + i));
3670         }
3671         tableView.setPrefHeight(130); // roughly room for four rows
3672 
3673         StageLoader sl = new StageLoader(tableView);
3674         sm.setCellSelectionEnabled(false);
3675         sm.setSelectionMode(SelectionMode.MULTIPLE);
3676 
3677         sm.clearAndSelect(0);
3678         fm.focus(0);
3679         assertEquals(0, getAnchor().getRow());
3680         assertEquals(-1, getAnchor().getColumn());
3681         assertTrue(fm.isFocused(0));
3682         assertTrue(sm.isSelected(0));
3683         assertFalse(sm.isSelected(1));
3684 
3685         // we expect the final Page-up to return us back to this selected index and with the same number of selected indices
3686         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
3687         final int leadSelectedIndex = sm.getSelectedIndex();
3688         final int selectedIndicesCount = sm.getSelectedIndices().size();
3689         assertEquals(3, leadSelectedIndex);
3690         assertEquals(3, fm.getFocusedIndex());
3691         assertEquals(4, selectedIndicesCount);
3692 
3693         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
3694         assertEquals(leadSelectedIndex * 2, sm.getSelectedIndex());
3695         assertEquals(leadSelectedIndex * 2, fm.getFocusedIndex());
3696         assertEquals(selectedIndicesCount * 2 - 1, sm.getSelectedIndices().size());
3697 
3698         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
3699         assertEquals(leadSelectedIndex, sm.getSelectedIndex());
3700         assertEquals(leadSelectedIndex, fm.getFocusedIndex());
3701         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
3702 
3703         sl.dispose();
3704     }
3705 
3706     @Test public void test_rt34407_up_up_down() {
3707         final int items = 100;
3708         root.getChildren().clear();
3709         root.setExpanded(true);
3710         for (int i = 0; i < items; i++) {
3711             root.getChildren().add(new TreeItem<>("Row " + i));
3712         }
3713         tableView.setPrefHeight(160); // roughly room for four rows
3714 
3715         StageLoader sl = new StageLoader(tableView);
3716         sm.setCellSelectionEnabled(false);
3717         sm.setSelectionMode(SelectionMode.MULTIPLE);
3718 
3719         sm.clearAndSelect(99);
3720         fm.focus(99);
3721         tableView.scrollTo(99);
3722         Toolkit.getToolkit().firePulse();
3723 
3724         assertEquals(99, getAnchor().getRow());
3725         assertEquals(-1, getAnchor().getColumn());
3726         assertTrue(fm.isFocused(99));
3727         assertTrue(sm.isSelected(99));
3728         assertFalse(sm.isSelected(98));
3729 
3730         // we expect the final Page-down to return us back to this selected index and with the same number of selected indices
3731         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
3732         final int leadSelectedIndex = sm.getSelectedIndex();
3733         final int selectedIndicesCount = sm.getSelectedIndices().size();
3734         final int diff = 99 - leadSelectedIndex;
3735         assertEquals(99 - diff, leadSelectedIndex);
3736         assertEquals(99 - diff, fm.getFocusedIndex());
3737         assertEquals(4, selectedIndicesCount);
3738 
3739         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
3740         assertEquals(99 - diff * 2 - 1, sm.getSelectedIndex());
3741         assertEquals(selectedIndicesCount * 2, sm.getSelectedIndices().size());
3742 
3743         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
3744         assertEquals(leadSelectedIndex, sm.getSelectedIndex());
3745         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
3746 
3747         sl.dispose();
3748     }
3749 
3750     @Test public void test_rt34768() {
3751         tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
3752         TreeTableColumn<String, String> firstNameCol = new TreeTableColumn<>("First Name");
3753         tableView.getColumns().setAll(firstNameCol);
3754         tableView.setRoot(null);
3755 
3756         // no need for an assert here - we're testing for an AIOOBE
3757         keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey());
3758     }
3759 
3760     @Test public void test_rt35853_multipleSelection_rowSelection_shiftDown() {
3761         final int items = 10;
3762         root.getChildren().clear();
3763         root.setExpanded(true);
3764         for (int i = 0; i < items; i++) {
3765             root.getChildren().add(new TreeItem<>("Row " + i));
3766         }
3767 
3768         sm.setSelectionMode(SelectionMode.MULTIPLE);
3769 
3770         sm.clearAndSelect(5);
3771         assertEquals(5, getAnchor().getRow());
3772         assertTrue(fm.isFocused(5));
3773         assertTrue(sm.isSelected(5));
3774 
3775         sm.selectedIndexProperty().addListener(observable -> {
3776             // we expect only one selected index change event, from 5 to 4
3777             assertEquals(4, sm.getSelectedIndex());
3778         });
3779 
3780         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
3781         assertEquals(5, getAnchor().getRow());
3782         assertTrue(fm.isFocused(4));
3783         assertTrue(sm.isSelected(4));
3784         assertTrue(sm.isSelected(5));
3785     }
3786 
3787     @Test public void test_rt35853_multipleSelection_rowSelection_noShiftDown() {
3788         final int items = 10;
3789         root.getChildren().clear();
3790         root.setExpanded(true);
3791         for (int i = 0; i < items; i++) {
3792             root.getChildren().add(new TreeItem<>("Row " + i));
3793         }
3794 
3795         sm.setSelectionMode(SelectionMode.MULTIPLE);
3796 
3797         sm.clearAndSelect(5);
3798         assertEquals(5, getAnchor().getRow());
3799         assertTrue(fm.isFocused(5));
3800         assertTrue(sm.isSelected(5));
3801 
3802         sm.selectedIndexProperty().addListener(observable -> {
3803             // we expect only one selected index change event, from 5 to 4
3804             assertEquals(4, sm.getSelectedIndex());
3805         });
3806 
3807         keyboard.doKeyPress(KeyCode.UP);
3808         assertEquals(4, getAnchor().getRow());
3809         assertTrue(fm.isFocused(4));
3810         assertTrue(sm.isSelected(4));
3811         assertFalse(sm.isSelected(5));
3812     }
3813 
3814     @Test public void test_rt35853_singleSelection_rowSelection_shiftDown() {
3815         final int items = 10;
3816         root.getChildren().clear();
3817         root.setExpanded(true);
3818         for (int i = 0; i < items; i++) {
3819             root.getChildren().add(new TreeItem<>("Row " + i));
3820         }
3821 
3822         sm.setSelectionMode(SelectionMode.SINGLE);
3823 
3824         sm.clearAndSelect(5);
3825         assertEquals(5, getAnchor().getRow());
3826         assertTrue(fm.isFocused(5));
3827         assertTrue(sm.isSelected(5));
3828 
3829         sm.selectedIndexProperty().addListener(observable -> {
3830             // we expect only one selected index change event, from 5 to 4
3831             assertEquals(4, sm.getSelectedIndex());
3832         });
3833 
3834         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
3835         assertEquals(4, getAnchor().getRow());
3836         assertTrue(fm.isFocused(4));
3837         assertTrue(sm.isSelected(4));
3838         assertFalse(sm.isSelected(5));
3839     }
3840 
3841     @Test public void test_rt35853_singleSelection_rowSelection_noShiftDown() {
3842         final int items = 10;
3843         root.getChildren().clear();
3844         root.setExpanded(true);
3845         for (int i = 0; i < items; i++) {
3846             root.getChildren().add(new TreeItem<>("Row " + i));
3847         }
3848 
3849         sm.setSelectionMode(SelectionMode.SINGLE);
3850 
3851         sm.clearAndSelect(5);
3852         assertEquals(5, getAnchor().getRow());
3853         assertTrue(fm.isFocused(5));
3854         assertTrue(sm.isSelected(5));
3855 
3856         sm.selectedIndexProperty().addListener(observable -> {
3857             // we expect only one selected index change event, from 5 to 4
3858             assertEquals(4, sm.getSelectedIndex());
3859         });
3860 
3861         keyboard.doKeyPress(KeyCode.UP);
3862         assertEquals(4, getAnchor().getRow());
3863         assertTrue(fm.isFocused(4));
3864         assertTrue(sm.isSelected(4));
3865         assertFalse(sm.isSelected(5));
3866     }
3867 
3868     @Test public void test_rt35853_multipleSelection_cellSelection_shiftDown() {
3869         final int items = 10;
3870         root.getChildren().clear();
3871         root.setExpanded(true);
3872         for (int i = 0; i < items; i++) {
3873             root.getChildren().add(new TreeItem<>("Row " + i));
3874         }
3875 
3876         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
3877         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
3878         tableView.getColumns().setAll(col);
3879 
3880         sm.setSelectionMode(SelectionMode.MULTIPLE);
3881         sm.setCellSelectionEnabled(true);
3882 
3883         sm.clearAndSelect(5, col);
3884         assertEquals(5, getAnchor().getRow());
3885         assertTrue(fm.isFocused(5, col));
3886         assertTrue(sm.isSelected(5, col));
3887 
3888         sm.selectedIndexProperty().addListener(observable -> {
3889             // we expect only one selected index change event, from 5 to 4
3890             assertEquals(4, sm.getSelectedIndex());
3891         });
3892 
3893         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
3894         assertEquals(5, getAnchor().getRow());
3895         assertTrue(fm.isFocused(4, col));
3896         assertTrue(sm.isSelected(4, col));
3897         assertTrue(sm.isSelected(5, col));
3898     }
3899 
3900     @Test public void test_rt35853_multipleSelection_cellSelection_noShiftDown() {
3901         final int items = 10;
3902         root.getChildren().clear();
3903         root.setExpanded(true);
3904         for (int i = 0; i < items; i++) {
3905             root.getChildren().add(new TreeItem<>("Row " + i));
3906         }
3907 
3908         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
3909         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
3910         tableView.getColumns().setAll(col);
3911 
3912         sm.setSelectionMode(SelectionMode.MULTIPLE);
3913         sm.setCellSelectionEnabled(true);
3914 
3915         sm.clearAndSelect(5, col);
3916         assertEquals(5, getAnchor().getRow());
3917         assertTrue(fm.isFocused(5, col));
3918         assertTrue(sm.isSelected(5, col));
3919 
3920         sm.selectedIndexProperty().addListener(observable -> {
3921             // we expect only one selected index change event, from 5 to 4
3922             assertEquals(4, sm.getSelectedIndex());
3923         });
3924 
3925         keyboard.doKeyPress(KeyCode.UP);
3926         assertEquals(4, getAnchor().getRow());
3927         assertTrue(fm.isFocused(4, col));
3928         assertTrue(sm.isSelected(4, col));
3929         assertFalse(sm.isSelected(5, col));
3930     }
3931 
3932     @Test public void test_rt35853_singleSelection_cellSelection_shiftDown() {
3933         final int items = 10;
3934         root.getChildren().clear();
3935         root.setExpanded(true);
3936         for (int i = 0; i < items; i++) {
3937             root.getChildren().add(new TreeItem<>("Row " + i));
3938         }
3939 
3940         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
3941         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
3942         tableView.getColumns().setAll(col);
3943 
3944         sm.setSelectionMode(SelectionMode.SINGLE);
3945         sm.setCellSelectionEnabled(true);
3946 
3947         sm.clearAndSelect(5, col);
3948         assertEquals(5, getAnchor().getRow());
3949         assertTrue(fm.isFocused(5, col));
3950         assertTrue(sm.isSelected(5, col));
3951 
3952         sm.selectedIndexProperty().addListener(observable -> {
3953             // we expect only one selected index change event, from 5 to 4
3954             assertEquals(4, sm.getSelectedIndex());
3955         });
3956 
3957         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
3958         assertEquals(4, getAnchor().getRow());
3959         assertTrue(fm.isFocused(4, col));
3960         assertTrue(sm.isSelected(4, col));
3961         assertFalse(sm.isSelected(5, col));
3962     }
3963 
3964     @Test public void test_rt35853_singleSelection_cellSelection_noShiftDown() {
3965         final int items = 10;
3966         root.getChildren().clear();
3967         root.setExpanded(true);
3968         for (int i = 0; i < items; i++) {
3969             root.getChildren().add(new TreeItem<>("Row " + i));
3970         }
3971 
3972         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
3973         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
3974         tableView.getColumns().setAll(col);
3975 
3976         sm.setSelectionMode(SelectionMode.SINGLE);
3977         sm.setCellSelectionEnabled(true);
3978 
3979         sm.clearAndSelect(5, col);
3980         assertEquals(5, getAnchor().getRow());
3981         assertTrue(fm.isFocused(5, col));
3982         assertTrue(sm.isSelected(5, col));
3983 
3984         sm.selectedIndexProperty().addListener(observable -> {
3985             // we expect only one selected index change event, from 5 to 4
3986             assertEquals(4, sm.getSelectedIndex());
3987         });
3988 
3989         keyboard.doKeyPress(KeyCode.UP);
3990         assertEquals(4, getAnchor().getRow());
3991         assertTrue(fm.isFocused(4, col));
3992         assertTrue(sm.isSelected(4, col));
3993         assertFalse(sm.isSelected(5, col));
3994     }
3995 
3996     @Test public void test_rt36800_rowSelection() {
3997         test_rt36800(false);
3998     }
3999 
4000     @Test public void test_rt36800_cellSelection() {
4001         test_rt36800(true);
4002     }
4003 
4004     private void test_rt36800(boolean cellSelection) {
4005         final int items = 10;
4006         root.getChildren().clear();
4007         root.setExpanded(true);
4008         for (int i = 0; i < items; i++) {
4009             root.getChildren().add(new TreeItem<>("Row " + i));
4010         }
4011 
4012         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4013         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4014         tableView.getColumns().setAll(col);
4015 
4016         sm.setSelectionMode(SelectionMode.SINGLE);
4017         sm.setCellSelectionEnabled(cellSelection);
4018 
4019         if (cellSelection) {
4020             sm.clearAndSelect(5, col);
4021             assertEquals(5, getAnchor().getRow());
4022             assertEquals(col, getAnchor().getTableColumn());
4023             assertTrue(fm.isFocused(5, col));
4024             assertTrue(sm.isSelected(5, col));
4025         } else {
4026             sm.clearAndSelect(5);
4027             assertEquals(5, getAnchor().getRow());
4028             assertTrue(fm.isFocused(5));
4029             assertTrue(sm.isSelected(5));
4030         }
4031 
4032         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 4
4033         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 3
4034         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 2
4035         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 1
4036         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 0
4037 
4038         ControlTestUtils.runWithExceptionHandler(() -> {
4039             keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // bug time?
4040         });
4041 
4042         if (cellSelection) {
4043             assertEquals(0, getAnchor().getRow());
4044             assertEquals(col, getAnchor().getTableColumn());
4045             assertTrue(fm.isFocused(0, col));
4046             assertTrue(sm.isSelected(0, col));
4047             assertFalse(sm.isSelected(1, col));
4048             assertFalse(sm.isSelected(2, col));
4049             assertFalse(sm.isSelected(3, col));
4050             assertFalse(sm.isSelected(4, col));
4051             assertFalse(sm.isSelected(5, col));
4052         } else {
4053             assertEquals(0, getAnchor().getRow());
4054             assertTrue(fm.isFocused(0));
4055             assertTrue(sm.isSelected(0));
4056             assertFalse(sm.isSelected(1));
4057             assertFalse(sm.isSelected(2));
4058             assertFalse(sm.isSelected(3));
4059             assertFalse(sm.isSelected(4));
4060             assertFalse(sm.isSelected(5));
4061         }
4062     }
4063 
4064     @Test public void test_rt_37130_pageUpAtTop() {
4065         final int items = 100;
4066         root.getChildren().clear();
4067         root.setExpanded(true);
4068         for (int i = 0; i < items; i++) {
4069             root.getChildren().add(new TreeItem<>("Row " + i));
4070         }
4071 
4072         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4073         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4074         tableView.getColumns().setAll(col);
4075 
4076         sm.setSelectionMode(SelectionMode.MULTIPLE);
4077         sm.setCellSelectionEnabled(true);
4078 
4079         StageLoader sl = new StageLoader(tableView);
4080 
4081         sm.select(5, col);
4082         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
4083         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
4084 
4085         sl.dispose();
4086     }
4087 
4088     @Test public void test_rt_37130_pageUpAtBottom() {
4089         final int items = 100;
4090         root.getChildren().clear();
4091         root.setExpanded(true);
4092         for (int i = 0; i < items; i++) {
4093             root.getChildren().add(new TreeItem<>("Row " + i));
4094         }
4095 
4096         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4097         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4098         tableView.getColumns().setAll(col);
4099 
4100         sm.setSelectionMode(SelectionMode.MULTIPLE);
4101         sm.setCellSelectionEnabled(true);
4102 
4103         StageLoader sl = new StageLoader(tableView);
4104 
4105         sm.select(95, col);
4106         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
4107         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
4108 
4109         sl.dispose();
4110     }
4111 
4112     @Test public void test_rt_37130_pageDownAtTop() {
4113         final int items = 100;
4114         root.getChildren().clear();
4115         root.setExpanded(true);
4116         for (int i = 0; i < items; i++) {
4117             root.getChildren().add(new TreeItem<>("Row " + i));
4118         }
4119 
4120         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4121         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4122         tableView.getColumns().setAll(col);
4123 
4124         sm.setSelectionMode(SelectionMode.MULTIPLE);
4125         sm.setCellSelectionEnabled(true);
4126 
4127         StageLoader sl = new StageLoader(tableView);
4128 
4129         sm.select(5, col);
4130         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
4131         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
4132 
4133         sl.dispose();
4134     }
4135 
4136     @Test public void test_rt_37130_pageDownAtBottom() {
4137         final int items = 100;
4138         root.getChildren().clear();
4139         root.setExpanded(true);
4140         for (int i = 0; i < items; i++) {
4141             root.getChildren().add(new TreeItem<>("Row " + i));
4142         }
4143 
4144         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4145         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4146         tableView.getColumns().setAll(col);
4147 
4148         sm.setSelectionMode(SelectionMode.MULTIPLE);
4149         sm.setCellSelectionEnabled(true);
4150 
4151         StageLoader sl = new StageLoader(tableView);
4152 
4153         sm.select(95, col);
4154         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
4155         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
4156 
4157         sl.dispose();
4158     }
4159 
4160 //    @Test public void test_rt_38326() {
4161 //        int argCount = 4;
4162 //        int testCount = (int) Math.pow(2, argCount);
4163 //        for (int test = 0; test < testCount; test++) {
4164 //            boolean moveUp                                      = (test & 0b1000) == 0b1000;
4165 //            boolean singleSelection                             = (test & 0b0100) == 0b0100;
4166 //            boolean cellSelection                               = (test & 0b0010) == 0b0010;
4167 //            boolean updateItemsListBeforeSelectionModelChanges  = (test & 0b0001) == 0b0001;
4168 //
4169 //            StringBuilder sb = new StringBuilder("@Test public void test_rt_38326_focusLostOnShortcutKeyNav_");
4170 //            sb.append(moveUp ? "moveUp_" : "moveDown_");
4171 //            sb.append(singleSelection ? "singleSelection_" : "multipleSelection_");
4172 //            sb.append(cellSelection ? "cellSelection_" : "rowSelection_");
4173 //            sb.append(updateItemsListBeforeSelectionModelChanges ? "updateItemsListBeforeSelectionModelChanges" : "updateItemsListAfterSelectionModelChanges");
4174 //            sb.append("() {\n    ");
4175 //            sb.append("test_rt_38326(");
4176 //            sb.append(moveUp + ", ");
4177 //            sb.append(singleSelection + ", ");
4178 //            sb.append(cellSelection + ", ");
4179 //            sb.append(updateItemsListBeforeSelectionModelChanges);
4180 //            sb.append(");\n}");
4181 //
4182 //            System.out.println(sb);
4183 //        }
4184 //    }
4185 
4186     // -- tests generated by above commented out code
4187     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
4188         test_rt_38326(false, false, false, false);
4189     }
4190     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
4191         test_rt_38326(false, false, false, true);
4192     }
4193     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
4194         test_rt_38326(false, false, true, false);
4195     }
4196     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
4197         test_rt_38326(false, false, true, true);
4198     }
4199     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
4200         test_rt_38326(false, true, false, false);
4201     }
4202     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
4203         test_rt_38326(false, true, false, true);
4204     }
4205     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
4206         test_rt_38326(false, true, true, false);
4207     }
4208     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
4209         test_rt_38326(false, true, true, true);
4210     }
4211     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
4212         test_rt_38326(true, false, false, false);
4213     }
4214     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
4215         test_rt_38326(true, false, false, true);
4216     }
4217     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
4218         test_rt_38326(true, false, true, false);
4219     }
4220     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
4221         test_rt_38326(true, false, true, true);
4222     }
4223     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
4224         test_rt_38326(true, true, false, false);
4225     }
4226     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
4227         test_rt_38326(true, true, false, true);
4228     }
4229     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
4230         test_rt_38326(true, true, true, false);
4231     }
4232     @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
4233         test_rt_38326(true, true, true, true);
4234     }
4235 
4236     private void test_rt_38326(boolean moveUp, boolean singleSelection, boolean cellSelection, boolean updateItemsListBeforeSelectionModelChanges) {
4237         final int items = 10;
4238         ObservableList<TreeItem<String>> itemsList = FXCollections.observableArrayList();
4239         for (int i = 0; i < items; i++) {
4240             itemsList.add(new TreeItem<>("Row " + i));
4241         }
4242 
4243         root.setExpanded(true);
4244 
4245         if (updateItemsListBeforeSelectionModelChanges) {
4246             root.getChildren().clear();
4247             root.getChildren().addAll(itemsList);
4248         }
4249 
4250         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4251         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4252 
4253         TreeTableColumn<String, String> col2 = new TreeTableColumn<>("Column 2");
4254         col2.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4255 
4256         tableView.getColumns().setAll(col, col2);
4257 
4258         TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel();
4259         sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
4260         sm.setCellSelectionEnabled(cellSelection);
4261 
4262         if (! updateItemsListBeforeSelectionModelChanges) {
4263             root.getChildren().clear();
4264             root.getChildren().addAll(itemsList);
4265         }
4266 
4267         StageLoader sl = new StageLoader(tableView);
4268 
4269         // test the initial state to ensure it is as we expect
4270         assertFalse(sm.isSelected(0));
4271         assertFalse(sm.isSelected(0, col));
4272         assertFalse(sm.isSelected(0, col2));
4273         assertEquals(0, sm.getSelectedIndices().size());
4274         assertEquals(0, sm.getSelectedItems().size());
4275         assertEquals(0, sm.getSelectedCells().size());
4276 
4277         final int startRow = 5;
4278         sm.clearSelection();
4279         sm.select(startRow, col);
4280         assertEquals(1, sm.getSelectedCells().size());
4281         assertEquals(startRow, sm.getSelectedCells().get(0).getRow());
4282         assertEquals(col, sm.getSelectedCells().get(0).getTableColumn());
4283         assertEquals(startRow, tableView.getFocusModel().getFocusedCell().getRow());
4284         assertEquals(col, tableView.getFocusModel().getFocusedCell().getTableColumn());
4285 
4286         keyboard.doKeyPress(moveUp ? KeyCode.UP : KeyCode.DOWN, KeyModifier.getShortcutKey());
4287         assertEquals(moveUp ? startRow-1 : startRow+1, tableView.getFocusModel().getFocusedCell().getRow());
4288         assertEquals(col, tableView.getFocusModel().getFocusedCell().getTableColumn());
4289 
4290         sl.dispose();
4291     }
4292 
4293     private int rt_39088_indices_event_count = 0;
4294     private int rt_39088_items_event_count = 0;
4295     @Test public void test_rt_39088() {
4296         ObservableList<TreeItem<String>> itemsList = FXCollections.observableArrayList();
4297         for (int i = 0; i < 4; i++) {
4298             itemsList.add(new TreeItem<>("Row " + i));
4299         }
4300 
4301         root.setExpanded(true);
4302         root.getChildren().setAll(itemsList);
4303 
4304         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4305         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4306 
4307         tableView.getColumns().setAll(col);
4308 
4309         TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel();
4310         sm.setSelectionMode(SelectionMode.MULTIPLE);
4311         sm.setCellSelectionEnabled(false);
4312 
4313         ObservableList<Integer> indices = sm.getSelectedIndices();
4314         ObservableList<TreeItem<String>> items = sm.getSelectedItems();
4315 
4316         indices.addListener((ListChangeListener<Integer>) change -> rt_39088_indices_event_count++);
4317         items.addListener((ListChangeListener<TreeItem<String>>) change -> rt_39088_items_event_count++);
4318 
4319         StageLoader sl = new StageLoader(tableView);
4320 
4321         assertEquals(0, rt_39088_indices_event_count);
4322         assertEquals(0, rt_39088_items_event_count);
4323         assertEquals(0, indices.size());
4324         assertEquals(0, items.size());
4325 
4326         sm.select(3);
4327         assertEquals(1, rt_39088_indices_event_count);
4328         assertEquals(1, rt_39088_items_event_count);
4329         assertEquals(1, indices.size());
4330         assertEquals(1, items.size());
4331 
4332         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
4333         assertEquals(2, rt_39088_indices_event_count);
4334         assertEquals(2, rt_39088_items_event_count);
4335         assertEquals(2, indices.size());
4336         assertEquals(2, items.size());
4337 
4338         // this is where the test fails...
4339         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
4340         assertEquals(3, rt_39088_indices_event_count);
4341         assertEquals(3, rt_39088_items_event_count);
4342         assertEquals(3, indices.size());
4343         assertEquals(3, items.size());
4344 
4345         sl.dispose();
4346     }
4347 
4348     @Test public void test_rt_27709_singleSelection_cellSelection() {
4349         test_rt_27709(SelectionMode.SINGLE, true, false);
4350     }
4351 
4352     @Test public void test_rt_27709_multipleSelection_cellSelection() {
4353         test_rt_27709(SelectionMode.MULTIPLE, true, false);
4354     }
4355 
4356     @Test public void test_rt_27709_singleSelection_rowSelection() {
4357         test_rt_27709(SelectionMode.SINGLE, false, false);
4358     }
4359 
4360     @Test public void test_rt_27709_multipleSelection_rowSelection() {
4361         test_rt_27709(SelectionMode.MULTIPLE, false, false);
4362     }
4363 
4364     @Test public void test_rt_27709_singleSelection_cellSelection_resetSelection() {
4365         test_rt_27709(SelectionMode.SINGLE, true, true);
4366     }
4367 
4368     @Test public void test_rt_27709_multipleSelection_cellSelection_resetSelection() {
4369         test_rt_27709(SelectionMode.MULTIPLE, true, true);
4370     }
4371 
4372     @Test public void test_rt_27709_singleSelection_rowSelection_resetSelection() {
4373         test_rt_27709(SelectionMode.SINGLE, false, true);
4374     }
4375 
4376     @Test public void test_rt_27709_multipleSelection_rowSelection_resetSelection() {
4377         test_rt_27709(SelectionMode.MULTIPLE, false, true);
4378     }
4379 
4380     private void test_rt_27709(SelectionMode mode, boolean cellSelectionMode, boolean resetSelection) {
4381         root.getChildren().clear();
4382         for (int i = 0; i < 10; i++) {
4383             root.getChildren().add(new TreeItem<>("Row " + i));
4384         }
4385 
4386         root.setExpanded(true);
4387         tableView.setShowRoot(false);
4388 
4389         TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
4390         col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4391 
4392         tableView.getColumns().setAll(col);
4393 
4394         TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel();
4395         sm.setSelectionMode(mode);
4396         sm.setCellSelectionEnabled(cellSelectionMode);
4397 
4398         ObservableList<Integer> indices = sm.getSelectedIndices();
4399         ObservableList<TreeTablePosition<String,?>> cells = sm.getSelectedCells();
4400 
4401         StageLoader sl = new StageLoader(tableView);
4402 
4403         int expectedSize = mode == SelectionMode.SINGLE ? 1 : 10;
4404         int lookupIndex = mode == SelectionMode.SINGLE ? 0 : 9;
4405 
4406         sm.select(0, col);
4407         assertEquals(1, indices.size());
4408         assertEquals(1, cells.size());
4409 
4410         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
4411         assertEquals(expectedSize, indices.size());
4412         assertEquals(expectedSize, cells.size());
4413         assertEquals(9, (int) indices.get(lookupIndex));
4414         assertEquals(9, cells.get(lookupIndex).getRow());
4415 
4416         if (resetSelection) {
4417             sm.clearAndSelect(9, col);
4418             TreeTablePosition<?,?> anchor = TreeTableCellBehavior.getAnchor(tableView, null);
4419             assertEquals(9, anchor.getRow());
4420             assertEquals(col, anchor.getTableColumn());
4421         } else {
4422             expectedSize = 1;
4423         }
4424 
4425         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
4426         assertEquals(expectedSize, indices.size());
4427         assertEquals(expectedSize, cells.size());
4428         assertTrue(sm.isSelected(0, col));
4429 
4430         if (resetSelection) {
4431             sm.clearAndSelect(0, col);
4432 
4433             TreeTablePosition<?,?> anchor = TreeTableCellBehavior.getAnchor(tableView, null);
4434             assertEquals(0, anchor.getRow());
4435             assertEquals(col, anchor.getTableColumn());
4436         } else {
4437             expectedSize = mode == SelectionMode.SINGLE ? 1 : 10;
4438         }
4439 
4440         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
4441         assertEquals(expectedSize, indices.size());
4442         assertEquals(expectedSize, cells.size());
4443         assertTrue(sm.isSelected(9, col));
4444 
4445         sl.dispose();
4446     }
4447 
4448     @Test public void test_rt_18440_goLeft() {
4449         test_rt_18440(KeyCode.LEFT, 3, false, colIndex -> {
4450             keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
4451             return colIndex - 1;
4452         });
4453     }
4454 
4455     @Test public void test_rt_18440_goLeft_toEnd() {
4456         test_rt_18440(KeyCode.LEFT, 3, true, colIndex -> {
4457             keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
4458             return colIndex - 1;
4459         });
4460     }
4461 
4462     @Test public void test_rt_18440_goRight() {
4463         test_rt_18440(KeyCode.RIGHT, 0, false, colIndex -> {
4464             keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
4465             return colIndex + 1;
4466         });
4467     }
4468 
4469     @Test public void test_rt_18440_goRight_toEnd() {
4470         test_rt_18440(KeyCode.RIGHT, 0, true, colIndex -> {
4471             keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
4472             return colIndex + 1;
4473         });
4474     }
4475 
4476     private void test_rt_18440(KeyCode direction, int startColumn, boolean goToEnd, Function<Integer, Integer> r) {
4477         root.getChildren().clear();
4478         for (int i = 0; i < 10; i++) {
4479             root.getChildren().add(new TreeItem<>("Row " + i));
4480         }
4481 
4482         root.setExpanded(true);
4483         tableView.setShowRoot(false);
4484         tableView.setRoot(root);
4485 
4486         tableView.getColumns().clear();
4487         for (int i = 0; i < 4; i++) {
4488             TreeTableColumn<String, String> col = new TreeTableColumn<>("Column " + i);
4489             col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4490             tableView.getColumns().add(col);
4491         }
4492 
4493         TreeTableView.TreeTableViewFocusModel fm = tableView.getFocusModel();
4494         TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel();
4495         sm.setSelectionMode(SelectionMode.MULTIPLE);
4496         sm.setCellSelectionEnabled(true);
4497 
4498         ObservableList<Integer> indices = sm.getSelectedIndices();
4499         ObservableList<TreeItem<String>> items = sm.getSelectedItems();
4500 
4501         StageLoader sl = new StageLoader(tableView);
4502 
4503         assertEquals(0, indices.size());
4504         assertEquals(0, items.size());
4505 
4506         sm.select(0, tableView.getColumns().get(startColumn));
4507         assertEquals(0, sm.getSelectedIndex());
4508         assertEquals(tableView.getColumns().get(startColumn), sm.getSelectedCells().get(0).getTableColumn());
4509         assertEquals(0, fm.getFocusedIndex());
4510         assertEquals(tableView.getColumns().get(startColumn), fm.getFocusedCell().getTableColumn());
4511 
4512         int expectedColumn = r.apply(startColumn);
4513         assertEquals(0, sm.getSelectedIndex());
4514         assertEquals(tableView.getColumns().get(startColumn), sm.getSelectedCells().get(0).getTableColumn());
4515         assertEquals(0, fm.getFocusedIndex());
4516         assertEquals(tableView.getColumns().get(expectedColumn), fm.getFocusedCell().getTableColumn());
4517 
4518         expectedColumn = r.apply(expectedColumn);
4519         assertEquals(0, sm.getSelectedIndex());
4520         assertEquals(tableView.getColumns().get(startColumn), sm.getSelectedCells().get(0).getTableColumn());
4521         assertEquals(0, fm.getFocusedIndex());
4522         assertEquals(tableView.getColumns().get(expectedColumn), fm.getFocusedCell().getTableColumn());
4523 
4524         if (goToEnd) {
4525             expectedColumn = r.apply(expectedColumn);
4526             assertEquals(0, sm.getSelectedIndex());
4527             assertEquals(tableView.getColumns().get(startColumn), sm.getSelectedCells().get(0).getTableColumn());
4528             assertEquals(0, fm.getFocusedIndex());
4529             assertEquals(tableView.getColumns().get(expectedColumn), fm.getFocusedCell().getTableColumn());
4530         }
4531 
4532         expectedColumn = direction == KeyCode.RIGHT ? 3 : 0;
4533         keyboard.doKeyPress(direction, KeyModifier.SHIFT);
4534         assertEquals(0, sm.getSelectedIndex());
4535         assertEquals(debug(), 4, sm.getSelectedCells().size());
4536         assertEquals(0, fm.getFocusedIndex());
4537         assertEquals(tableView.getColumns().get(expectedColumn), fm.getFocusedCell().getTableColumn());
4538 
4539         sl.dispose();
4540     }
4541 
4542     @Test public void test_rt_24865_moveDownwards() {
4543         root.getChildren().clear();
4544         for (int i = 0; i < 100; i++) {
4545             root.getChildren().add(new TreeItem<>("Row " + i));
4546         }
4547 
4548         root.setExpanded(true);
4549         tableView.setShowRoot(false);
4550         tableView.setRoot(root);
4551 
4552         Toolkit.getToolkit().firePulse();
4553 
4554         ObservableList<Integer> indices = sm.getSelectedIndices();
4555 
4556         sm.select(0);
4557         assertTrue(isSelected(0));
4558         assertTrue(fm.isFocused(0));
4559         assertEquals(1, indices.size());
4560         assertEquals(0, ((TreeTablePosition) TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4561 
4562         keyboard.doDownArrowPress(KeyModifier.SHIFT);
4563         keyboard.doDownArrowPress(KeyModifier.SHIFT);
4564         keyboard.doDownArrowPress(KeyModifier.SHIFT);
4565         assertTrue(isSelected(0, 1, 2, 3));
4566         assertTrue(fm.isFocused(3));
4567         assertEquals(4, indices.size());
4568         assertEquals(0, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4569 
4570         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
4571         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
4572         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
4573         assertTrue(isSelected(0, 1, 2, 3));
4574         assertTrue(isNotSelected(4, 5, 6, 7, 8, 9));
4575         assertTrue(fm.isFocused(6));
4576         assertEquals(4, indices.size());
4577         assertEquals(0, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4578 
4579         // main point of test: selection between the last index (3) and the focus
4580         // index (6) should now be true
4581         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
4582         final int selectedRowCount = indices.size();
4583         for (int i = 0; i < selectedRowCount; i++) {
4584             assertTrue(isSelected(i));
4585         }
4586         assertTrue(fm.isFocused(selectedRowCount - 1));
4587         assertEquals(0, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4588 
4589         keyboard.doDownArrowPress(KeyModifier.SHIFT);
4590         int newSelectedRowCount = selectedRowCount + 1;
4591         for (int i = 0; i < newSelectedRowCount; i++) {
4592             assertTrue(isSelected(i));
4593         }
4594         assertTrue(fm.isFocused(newSelectedRowCount - 1));
4595         assertEquals(0, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4596     }
4597 
4598     @Test public void test_rt_24865_moveUpwards() {
4599         root.getChildren().clear();
4600         for (int i = 0; i < 100; i++) {
4601             root.getChildren().add(new TreeItem<>("Row " + i));
4602         }
4603 
4604         root.setExpanded(true);
4605         tableView.setShowRoot(false);
4606         tableView.setRoot(root);
4607 
4608         Toolkit.getToolkit().firePulse();
4609 
4610         ObservableList<Integer> indices = sm.getSelectedIndices();
4611 
4612         sm.select(50);
4613         tableView.scrollTo(50);
4614 
4615         Toolkit.getToolkit().firePulse();
4616 
4617         assertTrue(isSelected(50));
4618         assertTrue(fm.isFocused(50));
4619         assertEquals(1, indices.size());
4620         assertEquals(50, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4621 
4622         keyboard.doUpArrowPress(KeyModifier.SHIFT);
4623         keyboard.doUpArrowPress(KeyModifier.SHIFT);
4624         keyboard.doUpArrowPress(KeyModifier.SHIFT);
4625         assertTrue(isSelected(50, 49, 48, 47));
4626         assertTrue(fm.isFocused(47));
4627         assertEquals(4, indices.size());
4628         assertEquals(50, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4629 
4630         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
4631         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
4632         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
4633         assertTrue(isSelected(50, 49, 48, 47));
4634         assertTrue(isNotSelected(46, 45, 44, 43, 42, 41));
4635         assertTrue(fm.isFocused(44));
4636         assertEquals(4, indices.size());
4637         assertEquals(50, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4638 
4639         // main point of test: selection between the last index (47) and the focus
4640         // index (44) should now be true
4641         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
4642         final int selectedRowCount = indices.size();
4643         for (int i = 0; i < selectedRowCount; i++) {
4644             assertTrue(isSelected(50 - i));
4645         }
4646         assertTrue(fm.isFocused(50 - selectedRowCount + 1));
4647         assertEquals(50, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4648 
4649         keyboard.doUpArrowPress(KeyModifier.SHIFT);
4650         int newSelectedRowCount = selectedRowCount + 1;
4651         for (int i = 0; i < newSelectedRowCount; i++) {
4652             assertTrue(isSelected(50 - i));
4653         }
4654         assertTrue(fm.isFocused(50 - newSelectedRowCount + 1));
4655         assertEquals(50, ((TreeTablePosition)TreeTableCellBehavior.getAnchor(tableView, null)).getRow());
4656     }
4657 
4658     @Test public void test_rt_39792_goLeft_goPastEnd() {
4659         test_rt_39792(3, colIndex -> {
4660             keyboard.doLeftArrowPress(KeyModifier.SHIFT);
4661             return colIndex - 1;
4662         });
4663     }
4664 
4665     @Test public void test_rt_39792_goRight_goPastEnd() {
4666         test_rt_39792(0, colIndex -> {
4667             keyboard.doRightArrowPress(KeyModifier.SHIFT);
4668             return colIndex + 1;
4669         });
4670     }
4671 
4672     private void test_rt_39792(int startColumn, Function<Integer, Integer> r) {
4673         root.getChildren().clear();
4674         for (int i = 0; i < 10; i++) {
4675             root.getChildren().add(new TreeItem<>("Row " + i));
4676         }
4677 
4678         root.setExpanded(true);
4679         tableView.setShowRoot(false);
4680         tableView.setRoot(root);
4681 
4682         tableView.getColumns().clear();
4683         for (int i = 0; i < 4; i++) {
4684             TreeTableColumn<String, String> col = new TreeTableColumn<>("Column " + i);
4685             col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
4686             tableView.getColumns().add(col);
4687         }
4688 
4689         TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel();
4690         sm.setSelectionMode(SelectionMode.MULTIPLE);
4691         sm.setCellSelectionEnabled(true);
4692 
4693         ObservableList<Integer> indices = sm.getSelectedIndices();
4694         ObservableList<TreeItem<String>> items = sm.getSelectedItems();
4695 
4696         StageLoader sl = new StageLoader(tableView);
4697 
4698         assertEquals(0, indices.size());
4699         assertEquals(0, items.size());
4700 
4701         sm.select(0, tableView.getColumns().get(startColumn));
4702         assertEquals(1, sm.getSelectedCells().size());
4703 
4704         int expectedColumn = r.apply(startColumn);
4705         assertEquals(2, sm.getSelectedCells().size());
4706 
4707         expectedColumn = r.apply(expectedColumn);
4708         assertEquals(3, sm.getSelectedCells().size());
4709 
4710         expectedColumn = r.apply(expectedColumn);
4711         assertEquals(4, sm.getSelectedCells().size());
4712 
4713         // this should not cause any issue, but it does - as noted in RT-39792
4714         /*expectedColumn = */r.apply(expectedColumn);
4715         assertEquals(4, sm.getSelectedCells().size());
4716 
4717         sl.dispose();
4718     }
4719 }