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