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