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.InvalidationListener;
  31 import javafx.beans.Observable;
  32 import javafx.beans.property.ReadOnlyStringWrapper;
  33 import javafx.collections.FXCollections;
  34 import javafx.collections.ListChangeListener;
  35 import javafx.collections.ObservableList;
  36 import javafx.event.EventHandler;
  37 import javafx.scene.input.KeyCode;
  38 import java.util.List;
  39 import com.sun.javafx.PlatformUtil;
  40 import com.sun.javafx.util.Utils;
  41 import com.sun.javafx.scene.control.behavior.ListViewAnchorRetriever;
  42 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
  43 import com.sun.javafx.scene.control.infrastructure.KeyModifier;
  44 import com.sun.javafx.scene.control.infrastructure.StageLoader;
  45 import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
  46 import com.sun.javafx.tk.Toolkit;
  47 import javafx.scene.layout.HBox;
  48 import org.junit.After;
  49 import org.junit.Before;
  50 import org.junit.Ignore;
  51 import org.junit.Test;
  52 import static org.junit.Assert.assertEquals;
  53 import static org.junit.Assert.assertFalse;
  54 import static org.junit.Assert.assertNotSame;
  55 import static org.junit.Assert.assertNull;
  56 import static org.junit.Assert.assertTrue;
  57 import static org.junit.Assert.fail;
  58 
  59 public class ListViewKeyInputTest {
  60     private ListView<String> listView;
  61     private MultipleSelectionModel<String> sm;
  62     private FocusModel<String> fm;
  63     
  64     private KeyEventFirer keyboard;
  65     
  66     private StageLoader stageLoader;
  67     
  68     @Before public void setup() {
  69         listView = new ListView<>();
  70         sm = listView.getSelectionModel();
  71         fm = listView.getFocusModel();
  72         
  73         sm.setSelectionMode(SelectionMode.MULTIPLE);
  74         
  75         keyboard = new KeyEventFirer(listView);
  76         stageLoader = new StageLoader(listView);
  77 
  78         listView.getItems().setAll("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
  79     }
  80     
  81     @After public void tearDown() {
  82         listView.getSkin().dispose();
  83         stageLoader.dispose();
  84     }
  85     
  86     
  87     /***************************************************************************
  88      * Util methods
  89      **************************************************************************/
  90     
  91     private String debug() {
  92         StringBuilder sb = new StringBuilder("Selected Indices: [");
  93         
  94         List<Integer> indices = sm.getSelectedIndices();
  95         for (Integer index : indices) {
  96             sb.append(index);
  97             sb.append(", ");
  98         }
  99         
 100         sb.append("] \nFocus: " + fm.getFocusedIndex());
 101         sb.append(" \nAnchor: " + getAnchor());
 102         return sb.toString();
 103     }
 104     
 105     // Returns true if ALL indices are selected
 106     private boolean isSelected(int... indices) {
 107         for (int index : indices) {
 108             if (! sm.isSelected(index)) {
 109                 System.out.println("Index " + index + " is not selected, but it is expected to be");
 110                 return false;
 111             }
 112         }
 113         return true;
 114     }
 115     
 116     // Returns true if ALL indices are NOT selected
 117     private boolean isNotSelected(int... indices) {
 118         for (int index : indices) {
 119             if (sm.isSelected(index)) {
 120                 System.out.println("Index " + index + " is selected, but it is not expected to be");
 121                 return false;
 122             }
 123         }
 124         return true;
 125     }
 126     
 127     private int getAnchor() {
 128         return ListViewAnchorRetriever.getAnchor(listView);
 129     }
 130     
 131     private boolean isAnchor(int index) {
 132         return getAnchor() == index;
 133     }
 134     
 135     
 136     /***************************************************************************
 137      * General tests
 138      **************************************************************************/    
 139     
 140     @Test public void testInitialState() {
 141         assertTrue(sm.getSelectedIndices().isEmpty());
 142         assertTrue(sm.getSelectedItems().isEmpty());
 143     }
 144     
 145     /***************************************************************************
 146      * Tests for row-based single selection
 147      **************************************************************************/
 148     
 149     @Test public void testDownArrowChangesSelection() {
 150         sm.clearAndSelect(0);
 151         keyboard.doDownArrowPress();
 152         assertFalse(sm.isSelected(0));
 153         assertTrue(sm.isSelected(1));
 154     }
 155     
 156     @Test public void testDownArrowDoesNotChangeSelectionWhenAtLastIndex() {
 157         int endIndex = listView.getItems().size() - 1;
 158         sm.clearAndSelect(endIndex);
 159         assertTrue(sm.isSelected(endIndex));
 160         keyboard.doDownArrowPress();
 161         assertTrue(sm.isSelected(endIndex));
 162     }
 163     
 164     @Test public void testUpArrowDoesNotChangeSelectionWhenAt0Index() {
 165         sm.clearAndSelect(0);
 166         keyboard.doUpArrowPress();
 167         assertTrue(sm.isSelected(0));
 168         assertEquals(1, sm.getSelectedIndices().size());
 169         assertEquals(1, sm.getSelectedItems().size());
 170     }
 171     
 172     @Test public void testUpArrowChangesSelection() {
 173         sm.clearAndSelect(1);
 174         keyboard.doUpArrowPress();
 175         assertFalse(sm.isSelected(1));
 176         assertTrue(sm.isSelected(0));
 177     }
 178     
 179     @Test public void testLeftArrowDoesNotChangeState() {
 180         keyboard.doLeftArrowPress();
 181         testInitialState();
 182     }
 183     
 184     @Test public void testRightArrowDoesNotChangeState() {
 185         keyboard.doRightArrowPress();
 186         testInitialState();
 187     }
 188     
 189     // test 19
 190     @Test public void testCtrlDownMovesFocusButLeavesSelectionAlone() {
 191         sm.clearAndSelect(0);
 192         assertTrue(fm.isFocused(0));
 193         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 194         assertTrue(fm.isFocused(1));
 195         assertTrue(sm.isSelected(0));
 196         assertFalse(sm.isSelected(1));
 197     }
 198     
 199     // test 20
 200     @Test public void testCtrlUpDoesNotMoveFocus() {
 201         sm.clearAndSelect(0);
 202         assertTrue(fm.isFocused(0));
 203         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 204         assertTrue(fm.isFocused(0));
 205         assertTrue(sm.isSelected(0));
 206     }
 207     
 208     // test 21
 209     @Test public void testCtrlLeftDoesNotMoveFocus() {
 210         sm.clearAndSelect(0);
 211         assertTrue(fm.isFocused(0));
 212         keyboard.doLeftArrowPress(KeyModifier.getShortcutKey());
 213         assertTrue(fm.isFocused(0));
 214         assertTrue(sm.isSelected(0));
 215     }
 216     
 217     // test 22
 218     @Test public void testCtrlRightDoesNotMoveFocus() {
 219         sm.clearAndSelect(0);
 220         assertTrue(fm.isFocused(0));
 221         keyboard.doRightArrowPress(KeyModifier.getShortcutKey());
 222         assertTrue(fm.isFocused(0));
 223         assertTrue(sm.isSelected(0));
 224     }
 225     
 226     // test 23
 227     @Test public void testCtrlUpMovesFocus() {
 228         sm.clearAndSelect(1);
 229         assertTrue(fm.isFocused(1));
 230         assertTrue(sm.isSelected(1));
 231         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 232         assertTrue(fm.isFocused(0));
 233 
 234     } 
 235     
 236     // test 24
 237     @Test public void testCtrlDownDoesNotMoveFocusWhenAtLastIndex() {
 238         int endIndex = listView.getItems().size() - 1;
 239         sm.clearAndSelect(endIndex);
 240         assertTrue(fm.isFocused(endIndex));
 241         assertTrue(sm.isSelected(endIndex));
 242         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 243         assertTrue(fm.isFocused(endIndex));
 244         assertTrue(sm.isSelected(endIndex));
 245     }
 246     
 247     // test 25
 248     @Test public void testCtrlDownArrowWithSpaceChangesAnchor() {
 249         sm.clearAndSelect(0);
 250         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 251         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 252         keyboard.doKeyPress(KeyCode.SPACE, 
 253                 KeyModifier.getShortcutKey(),
 254                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 2
 255         
 256         assertTrue(isSelected(0, 2));
 257         assertTrue(isNotSelected(1));
 258         assertTrue(isAnchor(2));
 259     } 
 260     
 261     // test 26
 262     @Test public void testCtrlUpArrowWithSpaceChangesAnchor() {
 263         sm.clearAndSelect(2);
 264         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 265         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 266         keyboard.doKeyPress(KeyCode.SPACE, 
 267                 KeyModifier.getShortcutKey(),
 268                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 0
 269         
 270         assertTrue(isSelected(0, 2));
 271         assertTrue(isNotSelected(1));
 272         assertTrue(isAnchor(0));
 273     } 
 274     
 275     // test 44
 276     @Test public void testHomeKey() {
 277         sm.clearAndSelect(3);
 278         keyboard.doKeyPress(KeyCode.HOME);
 279         assertTrue(debug(), isSelected(0));
 280         assertTrue(isNotSelected(1,2,3));
 281     }
 282     
 283     // test 45
 284     @Test public void testEndKey() {
 285         sm.clearAndSelect(3);
 286         keyboard.doKeyPress(KeyCode.END);
 287         assertTrue(isSelected(listView.getItems().size() - 1));
 288         assertTrue(isNotSelected(1,2,3));
 289     }
 290     
 291     // test 53
 292     @Test public void testCtrlHome() {
 293         sm.clearAndSelect(5);
 294         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey());
 295         assertTrue(isSelected(5));
 296         assertTrue(fm.isFocused(0));
 297     } 
 298     
 299     // test 54
 300     @Test public void testCtrlEnd() {
 301         sm.clearAndSelect(5);
 302         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey());
 303         assertTrue(isSelected(5));
 304         assertTrue(fm.isFocused(listView.getItems().size() - 1));
 305     } 
 306     
 307     // test 68
 308     @Test public void testCtrlSpaceToClearSelection() {
 309         sm.clearAndSelect(5);
 310         assertTrue(isSelected(5));
 311         assertTrue(fm.isFocused(5));
 312            
 313         keyboard.doKeyPress(KeyCode.SPACE, 
 314                 KeyModifier.getShortcutKey(),
 315                 (Utils.isMac() ? KeyModifier.CTRL : null));
 316         
 317         assertTrue(isNotSelected(5));
 318         assertTrue(debug(), fm.isFocused(5));
 319         assertTrue(isAnchor(5));
 320     }
 321     
 322     
 323     
 324     /***************************************************************************
 325      * Tests for row-based multiple selection
 326      **************************************************************************/
 327     
 328     @Test public void testShiftDownArrowIncreasesSelection() {
 329         sm.clearAndSelect(0);
 330         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 331         assertTrue(sm.isSelected(0));
 332         assertTrue(sm.isSelected(1));
 333     }
 334     
 335     @Test public void testShiftDownArrowDoesNotChangeSelectionWhenAtLastIndex() {
 336         int endIndex = listView.getItems().size() - 1;
 337         sm.clearAndSelect(endIndex);
 338         assertTrue(sm.isSelected(endIndex));
 339         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 340         assertTrue(sm.isSelected(endIndex));
 341     }
 342     
 343     @Test public void testShiftUpArrowIncreasesSelection() {
 344         sm.clearAndSelect(1);
 345         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 346         assertTrue(sm.isSelected(0));
 347         assertTrue(sm.isSelected(1));
 348     }
 349     
 350     @Test public void testShiftUpArrowWhenAt0Index() {
 351         sm.clearAndSelect(0);
 352         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 353         assertTrue(sm.isSelected(0));
 354     }
 355     
 356     @Test public void testShiftLeftArrowWhenAt0Index() {
 357         sm.clearAndSelect(0);
 358         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 359         assertTrue(sm.isSelected(0));
 360         assertFalse(sm.isSelected(1));
 361     }
 362     
 363     @Test public void testShiftRightArrowWhenAt0Index() {
 364         sm.clearAndSelect(0);
 365         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 366         assertTrue(sm.isSelected(0));
 367         assertFalse(sm.isSelected(1));
 368     }
 369     
 370     @Test public void testShiftDownTwiceThenShiftUp() {
 371         sm.clearAndSelect(0);
 372         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 373         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 374         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 375         assertTrue(debug(), sm.isSelected(0));
 376         assertTrue(sm.isSelected(1));
 377         assertFalse(sm.isSelected(2));
 378     }
 379     
 380     @Test public void testShiftUpTwiceThenShiftDownFrom0Index() {
 381         sm.clearAndSelect(0);
 382         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 383         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 384         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 385         assertTrue(sm.isSelected(0));
 386         assertTrue(sm.isSelected(1));
 387         assertFalse(sm.isSelected(2));
 388     }
 389     
 390     @Test public void testShiftLeftTwiceThenShiftRight() {
 391         sm.clearAndSelect(0);
 392         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 393         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 394         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 395         assertTrue(sm.isSelected(0));
 396         assertFalse(sm.isSelected(1));
 397         assertFalse(sm.isSelected(2));
 398     }
 399     
 400     @Test public void testShiftRightTwiceThenShiftLeft() {
 401         sm.clearAndSelect(0);
 402         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 403         keyboard.doRightArrowPress(KeyModifier.SHIFT);
 404         keyboard.doLeftArrowPress(KeyModifier.SHIFT);
 405         assertTrue(sm.isSelected(0));
 406         assertFalse(sm.isSelected(1));
 407         assertFalse(sm.isSelected(2));
 408     }
 409     
 410     @Test public void testShiftUpTwiceThenShiftDown() {
 411         sm.clearAndSelect(2);
 412         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 413         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 414         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 415         assertFalse(sm.isSelected(0));
 416         assertTrue(sm.isSelected(1));
 417         assertTrue(sm.isSelected(2));
 418         assertFalse(sm.isSelected(3));
 419     }
 420     
 421     // test 18 from Jindra's testcases.rtf file
 422     @Test public void testShiftDownTwiceThenShiftUpWhenAtLastIndex() {
 423         int endIndex = listView.getItems().size() - 1;
 424         sm.clearAndSelect(endIndex);
 425         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 426         keyboard.doDownArrowPress(KeyModifier.SHIFT);
 427         keyboard.doUpArrowPress(KeyModifier.SHIFT);
 428         assertTrue(sm.isSelected(endIndex));
 429         assertTrue(sm.isSelected(endIndex - 1));
 430         assertFalse(sm.isSelected(endIndex - 2));
 431     }
 432     
 433     // test 27
 434     @Test public void testCtrlDownArrowWithSpaceChangesAnchor_extended() {
 435         sm.clearAndSelect(0);
 436         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 437         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 438         keyboard.doKeyPress(KeyCode.SPACE, 
 439                 KeyModifier.getShortcutKey(),
 440                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 2
 441         
 442         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 443         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 444         keyboard.doKeyPress(KeyCode.SPACE, 
 445                 KeyModifier.getShortcutKey(),
 446                 (Utils.isMac() ? KeyModifier.CTRL : null));  // deselect 0
 447         assertTrue(isSelected(2));
 448         assertTrue(isNotSelected(0, 1));
 449         assertTrue(isAnchor(0));
 450     } 
 451     
 452     // test 28
 453     @Test public void testCtrlUpArrowWithSpaceChangesAnchor_extended() {
 454         sm.clearAndSelect(2);
 455         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 456         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 457         keyboard.doKeyPress(KeyCode.SPACE, 
 458                 KeyModifier.getShortcutKey(),
 459                 Utils.isMac() ? KeyModifier.CTRL : null);  // select 0
 460         
 461         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 462         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 463         keyboard.doKeyPress(KeyCode.SPACE, 
 464                 KeyModifier.getShortcutKey(),
 465                 Utils.isMac() ? KeyModifier.CTRL : null);  // deselect 2
 466         assertTrue(isSelected(0));
 467         assertTrue(isNotSelected(1, 2));
 468         assertTrue(isAnchor(2));
 469     } 
 470     
 471     // test 29
 472     @Test public void testCtrlDownArrowWithSpaceChangesAnchor_extended2() {
 473         sm.clearAndSelect(0);
 474         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 475         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 476         keyboard.doKeyPress(KeyCode.SPACE, 
 477                 KeyModifier.getShortcutKey(),
 478                 Utils.isMac() ? KeyModifier.CTRL : null);  // select 2
 479         
 480         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 481         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 482         keyboard.doKeyPress(KeyCode.SPACE, 
 483                 KeyModifier.getShortcutKey(),
 484                 Utils.isMac() ? KeyModifier.CTRL : null);  // select 4
 485         assertTrue(isSelected(0, 2, 4));
 486         assertTrue(isNotSelected(1, 3, 5));
 487         assertTrue(isAnchor(4));
 488     } 
 489     
 490     // test 30
 491     @Test public void testCtrlUpArrowWithSpaceChangesAnchor_extended2() {
 492         sm.clearAndSelect(4);
 493         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 494         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 495         keyboard.doKeyPress(KeyCode.SPACE, 
 496                 KeyModifier.getShortcutKey(),
 497                 Utils.isMac() ? KeyModifier.CTRL : null);  // select 2
 498         
 499         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 500         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 501         keyboard.doKeyPress(KeyCode.SPACE, 
 502                 KeyModifier.getShortcutKey(),
 503                 Utils.isMac() ? KeyModifier.CTRL : null);  // select 0
 504         assertTrue(isSelected(0, 2, 4));
 505         assertTrue(isNotSelected(1, 3));
 506         assertTrue(isAnchor(0));
 507     } 
 508     
 509     // test 31
 510     @Test public void testCtrlDownArrowThenShiftSpaceToSelectRange() {
 511         sm.clearAndSelect(0);
 512         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 513         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 514         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 0,1,2
 515         assertTrue(isSelected(0, 1, 2));
 516         assertTrue(isNotSelected(3));
 517         assertTrue(isAnchor(0));
 518     } 
 519     
 520     // test 32
 521     @Test public void testCtrlUpArrowThenShiftSpaceToSelectRange() {
 522         sm.clearAndSelect(2);
 523         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 524         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 525         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 0,1,2
 526         assertTrue(isSelected(0, 1, 2));
 527         assertTrue(isNotSelected(3));
 528         assertTrue(debug(), isAnchor(2));
 529     } 
 530     
 531     // test 33
 532     @Test public void testCtrlDownArrowThenSpaceToChangeSelection() {
 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, 
 537                 KeyModifier.getShortcutKey(),
 538                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 2, keeping 0 selected
 539         assertTrue(isSelected(0, 2));
 540         assertTrue(isNotSelected(1, 3));
 541         assertTrue(isAnchor(2));
 542         
 543         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 544         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 545         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 2,3,4
 546         assertTrue(isSelected(2, 3, 4));
 547         assertTrue(isNotSelected(0, 1));
 548         assertTrue(isAnchor(2));
 549     } 
 550     
 551     // test 34
 552     @Test public void testCtrlUpArrowThenSpaceToChangeSelection() {
 553         sm.clearAndSelect(4);
 554         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 555         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 556         keyboard.doKeyPress(KeyCode.SPACE, 
 557                 KeyModifier.getShortcutKey(),
 558                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 2, keeping 4 selected
 559         assertTrue(isSelected(2, 4));
 560         assertTrue(isNotSelected(0, 1, 3));
 561         assertTrue(isAnchor(2));
 562         
 563         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 564         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 565         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.SHIFT);  // select 0,1,2
 566         assertTrue(isSelected(0, 1, 2));
 567         assertTrue(isNotSelected(3, 4));
 568         assertTrue(debug(), isAnchor(2));
 569     } 
 570     
 571     // test 35
 572     @Test public void testCtrlDownTwiceThenShiftDown() {
 573         sm.clearAndSelect(0);
 574         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 575         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 576         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);  // select 0,1,2,3
 577         assertTrue(isSelected(0, 1, 2, 3));
 578     } 
 579     
 580     // test 36
 581     @Test public void testCtrlUpThriceThenShiftDown() {
 582         sm.clearAndSelect(3);
 583         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 584         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 585         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 586         keyboard.doDownArrowPress(KeyModifier.SHIFT);  // select 1,2,3
 587         assertTrue(debug(), isSelected(1, 2, 3));
 588         assertTrue(isNotSelected(0));
 589     } 
 590     
 591     // test 37
 592     @Test public void testCtrlDownThriceThenShiftUp() {
 593         sm.clearAndSelect(0);
 594         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 595         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 596         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 597         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);  // select 0,1,2
 598         assertTrue(isSelected(0, 1, 2));
 599         assertTrue(isNotSelected(3, 4));
 600     } 
 601     
 602     // test 38
 603     @Test public void testCtrlUpTwiceThenShiftUp() {
 604         sm.clearAndSelect(3);
 605         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 606         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 607         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);  // select 0,1,2,3
 608         assertTrue(isSelected(0, 1, 2, 3));
 609         assertTrue(isNotSelected(4));
 610     } 
 611     
 612     // test 39
 613     @Test public void testCtrlDownTwiceThenSpace_extended() {
 614         sm.clearAndSelect(0);
 615         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 616         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 617         keyboard.doKeyPress(KeyCode.SPACE, 
 618                 KeyModifier.getShortcutKey(),
 619                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 0,2
 620         assertTrue(isSelected(0, 2));
 621         assertTrue(isNotSelected(1, 3));
 622         assertTrue(isAnchor(2));
 623         
 624         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 625         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 626         keyboard.doDownArrowPress(KeyModifier.SHIFT);   // select 2,3,4,5
 627         assertTrue(isSelected(2, 3, 4, 5));
 628         assertTrue(isNotSelected(0, 1));
 629         assertTrue(isAnchor(2));
 630     } 
 631     
 632     // test 40
 633     @Test public void testCtrlUpTwiceThenSpace_extended() {
 634         sm.clearAndSelect(5);
 635         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 636         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 637         keyboard.doKeyPress(KeyCode.SPACE, 
 638                 KeyModifier.getShortcutKey(),
 639                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 3,5
 640         assertTrue(isSelected(3,5));
 641         assertTrue(isNotSelected(0,1,2,4));
 642         assertTrue(isAnchor(3));
 643         
 644         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 645         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 646         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 0
 647         keyboard.doDownArrowPress(KeyModifier.SHIFT);   // select 1,2,3
 648         assertTrue(isSelected(1,2,3));
 649         assertTrue(isNotSelected(0,4,5));
 650         assertTrue(isAnchor(3));
 651     } 
 652     
 653     // test 41
 654     @Test public void testCtrlDownTwiceThenSpace_extended2() {
 655         sm.clearAndSelect(0);
 656         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 657         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 658         keyboard.doKeyPress(KeyCode.SPACE, 
 659                 KeyModifier.getShortcutKey(),
 660                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 0,2
 661         assertTrue(isSelected(0,2));
 662         assertTrue(isNotSelected(1,3,4));
 663         assertTrue(isAnchor(2));
 664         
 665         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 666         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 667         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 5
 668         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // select 2,3,4
 669         assertTrue(isSelected(2,3,4));
 670         assertTrue(isNotSelected(0,1,5));
 671         assertTrue(isAnchor(2));
 672     } 
 673     
 674     // test 50
 675     @Test public void testCtrlDownThenShiftHome() {
 676         sm.clearAndSelect(0);
 677         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 678         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 679         keyboard.doKeyPress(KeyCode.SPACE, 
 680                 KeyModifier.getShortcutKey(),
 681                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 0,2
 682         assertTrue(isSelected(0,2));
 683         assertTrue(isNotSelected(1,3,4));
 684         assertTrue(isAnchor(2));
 685         
 686         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 687         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 688         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
 689         assertTrue(isSelected(0,1,2));
 690         assertTrue(isNotSelected(3,4));
 691         assertTrue(debug(),isAnchor(2));
 692     } 
 693     
 694     // test 51
 695     @Test public void testCtrlUpThenShiftEnd() {
 696         sm.clearAndSelect(5);
 697         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 698         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 699         keyboard.doKeyPress(KeyCode.SPACE, 
 700                 KeyModifier.getShortcutKey(),
 701                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 3,5
 702         assertTrue(isSelected(3,5));
 703         assertTrue(isNotSelected(1,2,4));
 704         assertTrue(isAnchor(3));
 705         
 706         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 707         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 708         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
 709         assertTrue(isSelected(3,4,5,6,7,8,9));
 710         assertTrue(isNotSelected(0,1,2));
 711         assertTrue(debug(),isAnchor(3));
 712     } 
 713     
 714     // test 42
 715     @Test public void testCtrlUpTwiceThenSpace_extended2() {
 716         sm.clearAndSelect(5);
 717         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 4
 718         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 3
 719         keyboard.doKeyPress(KeyCode.SPACE, 
 720                 KeyModifier.getShortcutKey(),
 721                 (Utils.isMac() ? KeyModifier.CTRL : null));  // select 3,5
 722         assertTrue(isSelected(3,5));
 723         assertTrue(isNotSelected(0,1,2,4));
 724         assertTrue(isAnchor(3));
 725         
 726         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 2
 727         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());    // move focus to 1
 728         keyboard.doUpArrowPress(KeyModifier.SHIFT);     // select 0,1,2,3
 729         assertTrue(isSelected(0,1,2,3));
 730         assertTrue(isNotSelected(4,5));
 731         assertTrue(isAnchor(3));
 732     } 
 733     
 734     // test 46
 735     @Test public void testHomeKey_withSelectedItems() {
 736         sm.clearSelection();
 737         sm.selectRange(4, 11);
 738         keyboard.doKeyPress(KeyCode.HOME);
 739         assertTrue(isSelected(0));
 740         assertTrue(isNotSelected(1,2,3,4,5,6,7,8,9,10,11));
 741     }
 742     
 743     // test 47
 744     @Test public void testEndKey_withSelectedItems() {
 745         sm.clearSelection();
 746         sm.selectRange(4, 11);
 747         keyboard.doKeyPress(KeyCode.END);
 748         assertTrue(isSelected(listView.getItems().size() - 1));
 749         assertTrue(isNotSelected(1,2,3,4,5,6,7,8));
 750     }
 751     
 752     // test 48
 753     @Test public void testShiftHome() {
 754         sm.clearAndSelect(3);
 755         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
 756         assertTrue(isSelected(0,1,2,3));
 757         assertTrue(isNotSelected(4,5));
 758         assertTrue(debug(), isAnchor(3));
 759     }
 760     
 761     // test 49
 762     @Test public void testShiftEnd() {
 763         sm.clearAndSelect(3);
 764         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
 765         assertTrue(isSelected(3,4,5,6,7,8,9));
 766         assertTrue(isNotSelected(0,1,2));
 767         assertTrue(isAnchor(3));
 768     }
 769     
 770     // test 52
 771     @Test public void testShiftHomeThenShiftEnd() {
 772         sm.clearAndSelect(5);
 773         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
 774         assertTrue(isSelected(0,1,2,3,4,5));
 775         assertTrue(isAnchor(5));
 776         
 777         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
 778         assertTrue(isSelected(5,6,7,8,9));
 779         assertTrue(isAnchor(5));
 780     }
 781     
 782     // test 65
 783     @Test public void testShiftPageUp() {
 784         sm.clearAndSelect(0);
 785         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 786         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 787         keyboard.doKeyPress(KeyCode.SPACE, 
 788                 KeyModifier.getShortcutKey(),
 789                 (Utils.isMac() ? KeyModifier.CTRL : null));
 790         assertTrue(isSelected(0,2));
 791         assertTrue(isAnchor(2));
 792         
 793         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 794         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 795         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
 796         assertTrue(isSelected(0,1,2));
 797         assertTrue(isAnchor(2));
 798     } 
 799     
 800     // test 67
 801     @Test public void testCtrlAToSelectAll() {
 802         sm.clearAndSelect(5);
 803         keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey());
 804         assertTrue(isSelected(0,1,2,3,4,5,6,7,8,9));
 805     } 
 806     
 807     
 808     
 809     /***************************************************************************
 810      * Tests for discontinuous multiple selection (RT-18953)
 811      **************************************************************************/  
 812     
 813     // Test 1
 814     @Test public void test_rt18593_1() {
 815         sm.clearAndSelect(0);
 816         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 817         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 818         keyboard.doKeyPress(KeyCode.SPACE, 
 819                 KeyModifier.getShortcutKey(),
 820                 (Utils.isMac() ? KeyModifier.CTRL : null));
 821         assertTrue(isSelected(0,2));
 822         assertTrue(isAnchor(2));
 823         
 824         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 825         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 826         assertTrue(debug(),isSelected(0,2,3,4));
 827         assertTrue(isAnchor(2));
 828     }
 829     
 830     // Test 2
 831     @Test public void test_rt18593_2() {
 832         sm.clearAndSelect(5);
 833         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 834         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 835         keyboard.doKeyPress(KeyCode.SPACE, 
 836                 KeyModifier.getShortcutKey(),
 837                 (Utils.isMac() ? KeyModifier.CTRL : null));
 838         assertTrue(isSelected(3,5));
 839         assertTrue(isAnchor(3));
 840         
 841         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 842         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 843         assertTrue(isSelected(1,2,3,5));
 844         assertTrue(isAnchor(3));
 845     }
 846     
 847     // Test 3
 848     @Test public void test_rt18593_3() {
 849         sm.clearAndSelect(0);
 850         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 851         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 852         keyboard.doKeyPress(KeyCode.SPACE, 
 853                 KeyModifier.getShortcutKey(),
 854                 (Utils.isMac() ? KeyModifier.CTRL : null));
 855         assertTrue(isSelected(0,2));
 856         assertTrue(isAnchor(2));
 857         
 858         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 859         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 860         assertTrue(isSelected(0,2,3,4));
 861         assertTrue(isAnchor(2));
 862         
 863         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 864         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 865         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 866         assertTrue(isSelected(0,1,2,3,4));
 867         assertTrue(isAnchor(2));
 868     }
 869     
 870     // Test 4
 871     @Test public void test_rt18593_4() {
 872         sm.clearAndSelect(5);
 873         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 874         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 875         keyboard.doKeyPress(KeyCode.SPACE, 
 876                 KeyModifier.getShortcutKey(),
 877                 (Utils.isMac() ? KeyModifier.CTRL : null));
 878         assertTrue(isSelected(3,5));
 879         assertTrue(isAnchor(3));
 880         
 881         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 882         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 883         assertTrue(isSelected(1,2,3,5));
 884         assertTrue(isAnchor(3));
 885         
 886         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 887         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 888         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 889         assertTrue(isSelected(1,2,3,4,5));
 890         assertTrue(isAnchor(3));
 891     }
 892     
 893     // TODO skipped some tests here (5-8)
 894     
 895     // Test 9
 896     @Test public void test_rt18593_9() {
 897         sm.clearAndSelect(0);
 898         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 899         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 900         keyboard.doKeyPress(KeyCode.SPACE, 
 901                 KeyModifier.getShortcutKey(),
 902                 (Utils.isMac() ? KeyModifier.CTRL : null));
 903         assertTrue(isSelected(0,2));
 904         assertTrue(isAnchor(2));
 905         
 906         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 907         assertTrue(isSelected(0,2,3,4,5,6,7,8,9));
 908         assertTrue(isAnchor(2));
 909     }
 910     
 911     // Test 10
 912     @Test public void test_rt18593_10() {
 913         sm.clearAndSelect(9);
 914         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 915         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 916         keyboard.doKeyPress(KeyCode.SPACE, 
 917                 KeyModifier.getShortcutKey(),
 918                 (Utils.isMac() ? KeyModifier.CTRL : null));
 919         assertTrue(isSelected(7,9));
 920         assertTrue(isAnchor(7));
 921         
 922         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 923         assertTrue(isSelected(0,1,2,3,4,5,6,7,9));
 924         assertTrue(isAnchor(7));
 925     }
 926     
 927     // Test 11
 928     @Test public void test_rt18593_11() {
 929         sm.clearAndSelect(5);
 930         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 931         assertTrue(isSelected(0,1,2,3,4,5));
 932         assertTrue(isAnchor(5));
 933         
 934         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 935         assertTrue(isSelected(0,1,2,3,4,5,6,7,8,9));
 936         assertTrue(isAnchor(5));
 937     }
 938     
 939     // Test 12
 940     @Test public void test_rt18593_12() {
 941         sm.clearAndSelect(0);
 942         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 943         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
 944         keyboard.doKeyPress(KeyCode.SPACE, 
 945                 KeyModifier.getShortcutKey(),
 946                 (Utils.isMac() ? KeyModifier.CTRL : null));
 947         assertTrue(isSelected(0,2));
 948         assertTrue(isAnchor(2));
 949         
 950         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 951         keyboard.doDownArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 952         assertTrue(isSelected(0,2,3,4));
 953         assertTrue(isAnchor(2));
 954         
 955         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 956         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 957         keyboard.doUpArrowPress(KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
 958         assertTrue(isSelected(0,1,2,3,4));
 959         assertTrue(isAnchor(2));
 960 
 961         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
 962         keyboard.doKeyPress(KeyCode.SPACE,
 963                 KeyModifier.getShortcutKey(),
 964                 (Utils.isMac() ? KeyModifier.CTRL : null));
 965         assertTrue(isSelected(1,2,3,4));
 966         assertTrue(fm.isFocused(0));
 967         assertTrue(isAnchor(0));
 968     }
 969     
 970     
 971     /***************************************************************************
 972      * Tests for editing
 973      **************************************************************************/
 974     
 975     // test 43 (part 1)
 976     @Test public void testF2EntersEditModeAndEscapeCancelsEdit_part1() {
 977         listView.setEditable(true);
 978         
 979         sm.clearAndSelect(0);
 980         assertEquals(-1, listView.getEditingIndex());
 981         keyboard.doKeyPress(KeyCode.F2);
 982         assertEquals(0, listView.getEditingIndex());
 983         
 984         keyboard.doKeyPress(KeyCode.ESCAPE);
 985         assertEquals(-1, listView.getEditingIndex());
 986     }
 987     
 988 //    // test 43 (part 2)
 989 //    @Test public void testF2EntersEditModeAndEscapeCancelsEdit_part2() {
 990 //        listView.setEditable(true);
 991 //        
 992 //        sm.clearAndSelect(0);
 993 //        keyboard.doKeyPress(KeyCode.F2);
 994 //        
 995 //        
 996 //    }
 997     
 998     /***************************************************************************
 999      * Tests for specific bug reports
1000      **************************************************************************/
1001     
1002     @Test public void test_rt18642() {
1003         sm.clearAndSelect(1);                          // select 1
1004         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 2
1005         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 3
1006         keyboard.doKeyPress(KeyCode.SPACE, 
1007                 KeyModifier.getShortcutKey(),
1008                 (Utils.isMac() ? KeyModifier.CTRL : null)); // set anchor, and also select, 3
1009         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 4
1010         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());   // shift focus to 5
1011         keyboard.doKeyPress(KeyCode.SPACE, 
1012                 KeyModifier.getShortcutKey(),
1013                 (Utils.isMac() ? KeyModifier.CTRL : null)); // set anchor, and also select, 5
1014         
1015         assertTrue(isSelected(1, 3, 5));
1016         assertTrue(isNotSelected(0, 2, 4));
1017         
1018         // anchor is at 5, so shift+UP should select rows 4 and 5 only
1019         keyboard.doUpArrowPress(KeyModifier.SHIFT);   
1020         assertTrue(isSelected(4, 5));
1021         assertTrue(isNotSelected(0, 1, 2, 3));
1022     }
1023     
1024     @Test public void test_rt14451_1() {
1025         sm.clearAndSelect(5);                          
1026 
1027         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
1028         assertTrue(isSelected(0,1,2,3,4,5));
1029         assertTrue(isNotSelected(6,7,8,9));
1030         
1031         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
1032         assertTrue(isNotSelected(0,1,2,3,4));
1033         assertTrue(isSelected(5,6,7,8,9));
1034         
1035         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
1036         assertTrue(isSelected(0,1,2,3,4,5));
1037         assertTrue(debug(), isNotSelected(6,7,8,9));
1038     } 
1039     
1040     @Test public void test_rt14451_2() {
1041         sm.clearAndSelect(5);                          
1042 
1043         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
1044         assertTrue(isNotSelected(0,1,2,3,4));
1045         assertTrue(isSelected(5,6,7,8,9));
1046         
1047         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
1048         assertTrue(isSelected(0,1,2,3,4,5));
1049         assertTrue(debug(), isNotSelected(6,7,8,9));
1050         
1051         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
1052         assertTrue(isNotSelected(0,1,2,3,4));
1053         assertTrue(isSelected(5,6,7,8,9));
1054     } 
1055     
1056     @Test public void test_rt26835_1() {
1057         sm.clearAndSelect(5);                          
1058         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.getShortcutKey()); 
1059         assertTrue(fm.isFocused(0));
1060     } 
1061     
1062     @Test public void test_rt26835_2() {
1063         sm.clearAndSelect(5);                          
1064         keyboard.doKeyPress(KeyCode.END, KeyModifier.getShortcutKey()); 
1065         assertTrue(debug(), fm.isFocused(listView.getItems().size() - 1));
1066     } 
1067     
1068     @Test public void test_rt27175() {
1069         sm.clearAndSelect(5);                          
1070         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey()); 
1071         assertTrue(debug(), fm.isFocused(0));
1072         assertTrue(isSelected(0,1,2,3,4,5));
1073     }
1074     
1075     @Test public void test_rt28065() {
1076         sm.setSelectionMode(SelectionMode.MULTIPLE);
1077         listView.getItems().setAll("Apple", "Orange", "Banana");
1078         
1079         listView.getSelectionModel().select(0);
1080         assertEquals(0, listView.getSelectionModel().getSelectedIndex());
1081         assertEquals("Apple", listView.getSelectionModel().getSelectedItem());
1082         assertEquals(0, listView.getFocusModel().getFocusedIndex());
1083         assertEquals("Apple", listView.getFocusModel().getFocusedItem());
1084         
1085         keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey());
1086         assertEquals(0, listView.getSelectionModel().getSelectedIndex());
1087         assertEquals("Apple", listView.getSelectionModel().getSelectedItem());
1088         assertEquals(0, listView.getFocusModel().getFocusedIndex());
1089         assertEquals("Apple", listView.getFocusModel().getFocusedItem());
1090     }
1091     
1092     @Test public void test_rt29930() {
1093         sm.setSelectionMode(SelectionMode.MULTIPLE);
1094         
1095         sm.clearAndSelect(0);
1096         
1097         keyboard.doDownArrowPress(KeyModifier.SHIFT); // select rows [0,1]
1098         keyboard.doDownArrowPress(KeyModifier.SHIFT); // select rows [0,1,2]
1099         assertTrue(isSelected(0,1,2));
1100         assertEquals(2, fm.getFocusedIndex());
1101         assertEquals(0, getAnchor());
1102         
1103         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null); // set new anchor point
1104         assertTrue(isSelected(0,1));
1105         assertEquals(2, fm.getFocusedIndex());
1106         assertEquals(2, getAnchor());
1107         
1108         keyboard.doDownArrowPress(KeyModifier.SHIFT); // select rows [2,3]
1109         assertTrue(isSelected(2,3));
1110         assertTrue(isNotSelected(0,1));
1111         assertEquals(3, fm.getFocusedIndex());
1112         assertEquals(2, getAnchor());
1113     }
1114 
1115     private int rt29849_start_count = 0;
1116     private int rt29849_cancel_count = 0;
1117     @Test public void test_rt29849() {
1118         listView.setEditable(true);
1119 
1120         listView.setOnEditStart(t -> {
1121             rt29849_start_count++;
1122         });
1123         listView.setOnEditCancel(t -> {
1124             rt29849_cancel_count++;
1125         });
1126 
1127         // initially the counts should be zero
1128         assertEquals(0, rt29849_start_count);
1129         assertEquals(0, rt29849_cancel_count);
1130 
1131         IndexedCell cell = VirtualFlowTestUtils.getCell(listView, 0);
1132         assertTrue(cell.isEditable());
1133         assertFalse(cell.isEditing());
1134         assertEquals(0, cell.getIndex());
1135 
1136         // do an edit, start count should be one, cancel still zero
1137         listView.edit(0);
1138         assertTrue(cell.isEditing());
1139         assertEquals(1, rt29849_start_count);
1140         assertEquals(0, rt29849_cancel_count);
1141 
1142         // cancel edit, now both counts should be 1
1143         keyboard.doKeyPress(KeyCode.ESCAPE);
1144         assertFalse(cell.isEditing());
1145         assertEquals(1, rt29849_start_count);
1146         assertEquals(1, rt29849_cancel_count);
1147     }
1148 
1149     private int rt31577_count = 0;
1150     @Test public void test_rt31577() {
1151         final MultipleSelectionModel sm = listView.getSelectionModel();
1152         sm.setSelectionMode(SelectionMode.SINGLE);
1153         sm.clearSelection();
1154 
1155         // the actual bug is that the selectedItem property does not fire an
1156         // event when the selected items list changes (due to deselection).
1157         // It actually does always contain the right value - it just doesn't
1158         // let anyone know it!
1159         sm.selectedItemProperty().addListener(observable -> {
1160             rt31577_count++;
1161         });
1162 
1163         assertTrue(sm.getSelectedItems().isEmpty());
1164         assertFalse(sm.isSelected(1));
1165         assertEquals(0, rt31577_count);
1166 
1167         // select the first row
1168         keyboard.doKeyPress(KeyCode.KP_DOWN);
1169         assertEquals(1, sm.getSelectedItems().size());
1170         assertTrue(sm.isSelected(0));
1171         assertTrue(sm.getSelectedItems().contains("1"));
1172         assertEquals("1", sm.getSelectedItem());
1173         assertEquals(1, rt31577_count);
1174 
1175         // deselect the row
1176         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.CTRL,
1177                 Utils.isMac() ? KeyModifier.getShortcutKey() : null);
1178         assertTrue(sm.getSelectedItems().isEmpty());
1179         assertFalse(sm.isSelected(1));
1180         assertNull(sm.getSelectedItem());
1181         assertEquals(2, rt31577_count);
1182     }
1183 
1184     @Test public void test_rt32383_pageDown() {
1185         // this test requires a lot of data
1186         listView.getItems().clear();
1187         for (int i = 0; i < 100; i++) {
1188             listView.getItems().add("Row " + i);
1189         }
1190 
1191         final MultipleSelectionModel sm = listView.getSelectionModel();
1192         sm.setSelectionMode(SelectionMode.SINGLE);
1193         sm.clearAndSelect(0);
1194 
1195         final String initialFocusOwner = fm.getFocusedItem();
1196 
1197         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.getShortcutKey());
1198         Toolkit.getToolkit().firePulse();
1199         final String newFocusOwner = fm.getFocusedItem();
1200         assertNotSame(initialFocusOwner, newFocusOwner);
1201 
1202         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.getShortcutKey());
1203         Toolkit.getToolkit().firePulse();
1204         final String nextFocusOwner = fm.getFocusedItem();
1205         assertNotSame(initialFocusOwner, nextFocusOwner);
1206         assertNotSame(newFocusOwner, nextFocusOwner);
1207     }
1208 
1209     @Test public void test_rt32383_pageUp() {
1210         // this test requires a lot of data
1211         listView.getItems().clear();
1212         for (int i = 0; i < 100; i++) {
1213             listView.getItems().add("Row " + i);
1214         }
1215 
1216         final int lastIndex = 99;
1217 
1218         final MultipleSelectionModel sm = listView.getSelectionModel();
1219         sm.setSelectionMode(SelectionMode.SINGLE);
1220         sm.clearAndSelect(lastIndex);
1221 
1222         // need to make sure we scroll down to the bottom!
1223         listView.scrollTo(lastIndex);
1224         Toolkit.getToolkit().firePulse();
1225 
1226         assertEquals(lastIndex, sm.getSelectedIndex());
1227         assertEquals(lastIndex, fm.getFocusedIndex());
1228 
1229         final String initialFocusOwner = fm.getFocusedItem();
1230 
1231         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey());
1232         Toolkit.getToolkit().firePulse();
1233         final String newFocusOwner = fm.getFocusedItem();
1234         assertNotSame(initialFocusOwner, newFocusOwner);
1235 
1236         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey());
1237         Toolkit.getToolkit().firePulse();
1238         final String nextFocusOwner = fm.getFocusedItem();
1239         assertNotSame(initialFocusOwner, nextFocusOwner);
1240         assertNotSame(newFocusOwner, nextFocusOwner);
1241     }
1242 
1243     @Test public void test_rt19053_pageUp() {
1244         final int items = 8;
1245         listView.getItems().clear();
1246         for (int i = 0; i < items; i++) {
1247             listView.getItems().add("Row " + i);
1248         }
1249 
1250         final int middleIndex = items / 2;
1251 
1252         final MultipleSelectionModel sm = listView.getSelectionModel();
1253         sm.setSelectionMode(SelectionMode.SINGLE);
1254         sm.clearAndSelect(middleIndex);
1255 
1256         assertEquals(middleIndex, sm.getSelectedIndex());
1257 
1258         final Object initialSelectionOwner = sm.getSelectedItem();
1259 
1260         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1261         Toolkit.getToolkit().firePulse();
1262         final Object newSelectionOwner = sm.getSelectedItem();
1263         assertNotSame(initialSelectionOwner, newSelectionOwner);
1264 
1265         // selection should go all the way to the top, but this bug
1266         // shows that instead it seems to stop midway - where the anchor is
1267         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1268         Toolkit.getToolkit().firePulse();
1269         assertEquals(0, fm.getFocusedIndex());
1270         assertEquals(0, sm.getSelectedIndex());
1271         final Object nextSelectionOwner =  sm.getSelectedItem();
1272         assertNotSame(initialSelectionOwner, nextSelectionOwner);
1273         assertNotSame(newSelectionOwner, nextSelectionOwner);
1274     }
1275 
1276     @Test public void test_rt19053_pageDown() {
1277         final int items = 8;
1278         listView.getItems().clear();
1279         for (int i = 0; i < items; i++) {
1280             listView.getItems().add("Row " + i);
1281         }
1282 
1283         final int middleIndex = items / 2;
1284 
1285         final MultipleSelectionModel sm = listView.getSelectionModel();
1286         sm.setSelectionMode(SelectionMode.SINGLE);
1287         sm.clearAndSelect(middleIndex);
1288 
1289         assertEquals(middleIndex, sm.getSelectedIndex());
1290 
1291         final Object initialSelectionOwner = sm.getSelectedItem();
1292 
1293         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1294         Toolkit.getToolkit().firePulse();
1295         final Object newSelectionOwner = sm.getSelectedItem();
1296         assertNotSame(initialSelectionOwner, newSelectionOwner);
1297 
1298         // selection should go all the way to the bottom, but this bug
1299         // shows that instead it seems to stop midway - where the anchor is
1300         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1301         Toolkit.getToolkit().firePulse();
1302         assertEquals(items - 1, fm.getFocusedIndex());
1303         assertEquals(items - 1, sm.getSelectedIndex());
1304         final Object nextSelectionOwner =  sm.getSelectedItem();
1305         assertNotSame(initialSelectionOwner, nextSelectionOwner);
1306         assertNotSame(newSelectionOwner, nextSelectionOwner);
1307     }
1308 
1309     @Ignore("Fix not yet implemented")
1310     @Test public void test_rt20641_pageUp() {
1311         final int items = 20;
1312         listView.getItems().clear();
1313         for (int i = 0; i < items; i++) {
1314             listView.getItems().add("Row " + i);
1315         }
1316 
1317         final MultipleSelectionModel sm = listView.getSelectionModel();
1318         sm.setSelectionMode(SelectionMode.MULTIPLE);
1319         sm.clearAndSelect(0);
1320         assertEquals(0, sm.getSelectedIndex());
1321 
1322         final int selectedIndex0 = sm.getSelectedIndex();
1323 
1324         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1325         Toolkit.getToolkit().firePulse();
1326         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1327         Toolkit.getToolkit().firePulse();
1328         final int selectedIndex1 = sm.getSelectedIndex();
1329         assertNotSame(selectedIndex0, selectedIndex1);
1330         assertTrue(selectedIndex0 < selectedIndex1);
1331 
1332         // selection should go up one page, but bug shows it goes right back
1333         // to start
1334         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1335         Toolkit.getToolkit().firePulse();
1336         final int selectedIndex2 = sm.getSelectedIndex();
1337         assertNotSame(selectedIndex0, selectedIndex1);
1338         assertNotSame(selectedIndex0, selectedIndex2);
1339         assertTrue(selectedIndex2 < selectedIndex1);
1340         assertTrue(selectedIndex0 < selectedIndex2);
1341     }
1342 
1343     @Ignore("Fix not yet implemented")
1344     @Test public void test_rt20641_pageDown() {
1345         final int items = 100;
1346         listView.getItems().clear();
1347         for (int i = 0; i < items; i++) {
1348             listView.getItems().add("Row " + i);
1349         }
1350 
1351         final MultipleSelectionModel sm = listView.getSelectionModel();
1352         sm.setSelectionMode(SelectionMode.MULTIPLE);
1353         sm.clearAndSelect(items - 1);
1354         fm.setFocusedIndex(items - 1);
1355         assertEquals(items - 1, sm.getSelectedIndex());
1356         assertEquals(items - 1, fm.getFocusedIndex());
1357 
1358         final int selectedIndex0 = sm.getSelectedIndex();
1359 
1360         // need to make sure we scroll down to the bottom!
1361         listView.scrollTo(items - 1);
1362         Toolkit.getToolkit().firePulse();
1363 
1364         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1365         Toolkit.getToolkit().firePulse();
1366         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1367         Toolkit.getToolkit().firePulse();
1368         final int selectedIndex1 = sm.getSelectedIndex();
1369         assertNotSame(selectedIndex0, selectedIndex1);
1370         assertTrue(selectedIndex0 > selectedIndex1);
1371 
1372         // selection should go up down page, but bug shows it goes right back
1373         // to end (where selection started)
1374         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1375         Toolkit.getToolkit().firePulse();
1376         final int selectedIndex2 = sm.getSelectedIndex();
1377         assertNotSame(selectedIndex0, selectedIndex1);
1378         assertNotSame(selectedIndex0, selectedIndex2);
1379         assertTrue(selectedIndex2 > selectedIndex1);
1380         assertTrue(selectedIndex0 > selectedIndex2);
1381     }
1382 
1383     @Test public void test_rt21375_scenario_1a_down() {
1384         final int items = 8;
1385         listView.getItems().clear();
1386         for (int i = 1; i <= items; i++) {
1387             listView.getItems().add("Row " + i);
1388         }
1389 
1390         final MultipleSelectionModel sm = listView.getSelectionModel();
1391         sm.setSelectionMode(SelectionMode.MULTIPLE);
1392         sm.clearAndSelect(0);
1393 
1394         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1395         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1396         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT);
1397         Toolkit.getToolkit().firePulse();
1398         assertTrue(isSelected(0,1,2,3));
1399         assertEquals(4, sm.getSelectedItems().size());
1400     }
1401 
1402     @Test public void test_rt21375_scenario_1b_down() {
1403         final int items = 8;
1404         listView.getItems().clear();
1405         for (int i = 1; i <= items; i++) {
1406             listView.getItems().add("Row " + i);
1407         }
1408 
1409         final MultipleSelectionModel sm = listView.getSelectionModel();
1410         sm.setSelectionMode(SelectionMode.MULTIPLE);
1411         sm.clearAndSelect(0);
1412 
1413         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1414         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1415         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1416         Toolkit.getToolkit().firePulse();
1417         assertTrue(isSelected(0,1,2,3));
1418         assertEquals(4, sm.getSelectedItems().size());
1419     }
1420 
1421     @Test public void test_rt21375_scenario_2_down() {
1422         final int items = 8;
1423         listView.getItems().clear();
1424         for (int i = 1; i <= items; i++) {
1425             listView.getItems().add("Row " + i);
1426         }
1427 
1428         final MultipleSelectionModel sm = listView.getSelectionModel();
1429         sm.setSelectionMode(SelectionMode.MULTIPLE);
1430         sm.clearAndSelect(0);
1431 
1432         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
1433         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
1434         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
1435         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
1436         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.SHIFT);
1437         Toolkit.getToolkit().firePulse();
1438         assertTrue(isSelected(2,3,4));
1439         assertEquals(3, sm.getSelectedItems().size());
1440     }
1441 
1442     @Test public void test_rt21375_scenario_3_down() {
1443         final int items = 8;
1444         listView.getItems().clear();
1445         for (int i = 1; i <= items; i++) {
1446             listView.getItems().add("Row " + i);
1447         }
1448 
1449         final MultipleSelectionModel sm = listView.getSelectionModel();
1450         sm.setSelectionMode(SelectionMode.MULTIPLE);
1451         sm.clearAndSelect(0);
1452 
1453         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
1454         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
1455         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
1456         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey());
1457         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1458         Toolkit.getToolkit().firePulse();
1459         assertTrue(isSelected(0,2,3,4));
1460         assertEquals(4, sm.getSelectedItems().size());
1461     }
1462 
1463     @Test public void test_rt21375_scenario_1a_up() {
1464         final int items = 8;
1465         listView.getItems().clear();
1466         for (int i = 1; i <= items; i++) {
1467             listView.getItems().add("Row " + i);
1468         }
1469 
1470         final MultipleSelectionModel sm = listView.getSelectionModel();
1471         sm.setSelectionMode(SelectionMode.MULTIPLE);
1472         sm.clearAndSelect(7);
1473 
1474         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
1475         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
1476         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
1477         Toolkit.getToolkit().firePulse();
1478         assertTrue(isSelected(7,6,5,4));
1479         assertEquals(4, sm.getSelectedItems().size());
1480     }
1481 
1482     @Test public void test_rt21375_scenario_1b_up() {
1483         final int items = 8;
1484         listView.getItems().clear();
1485         for (int i = 1; i <= items; i++) {
1486             listView.getItems().add("Row " + i);
1487         }
1488 
1489         final MultipleSelectionModel sm = listView.getSelectionModel();
1490         sm.setSelectionMode(SelectionMode.MULTIPLE);
1491         sm.clearAndSelect(7);
1492 
1493         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
1494         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
1495         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1496         Toolkit.getToolkit().firePulse();
1497         assertTrue(isSelected(7,6,5,4));
1498         assertEquals(4, sm.getSelectedItems().size());
1499     }
1500 
1501     @Test public void test_rt21375_scenario_2_up() {
1502         final int items = 8;
1503         listView.getItems().clear();
1504         for (int i = 1; i <= items; i++) {
1505             listView.getItems().add("Row " + i);
1506         }
1507 
1508         final MultipleSelectionModel sm = listView.getSelectionModel();
1509         sm.setSelectionMode(SelectionMode.MULTIPLE);
1510         sm.clearAndSelect(7);
1511 
1512         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
1513         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
1514         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
1515         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
1516         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.SHIFT);
1517         Toolkit.getToolkit().firePulse();
1518         assertTrue(isSelected(5,4,3));
1519         assertEquals(3, sm.getSelectedItems().size());
1520     }
1521 
1522     @Test public void test_rt21375_scenario_3_up() {
1523         final int items = 8;
1524         listView.getItems().clear();
1525         for (int i = 1; i <= items; i++) {
1526             listView.getItems().add("Row " + i);
1527         }
1528 
1529         final MultipleSelectionModel sm = listView.getSelectionModel();
1530         sm.setSelectionMode(SelectionMode.MULTIPLE);
1531         sm.clearAndSelect(7);
1532 
1533         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
1534         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
1535         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
1536         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
1537         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1538         Toolkit.getToolkit().firePulse();
1539         assertTrue(isSelected(7,5,4,3));
1540         assertEquals(4, sm.getSelectedItems().size());
1541     }
1542 
1543     @Test public void test_rt33301_multipleSelection_down() {
1544         final int items = 5;
1545         listView.getItems().clear();
1546         for (int i = 0; i < items; i++) {
1547             listView.getItems().add("Row " + i);
1548         }
1549 
1550         final FocusModel fm = listView.getFocusModel();
1551         final MultipleSelectionModel sm = listView.getSelectionModel();
1552         sm.setSelectionMode(SelectionMode.MULTIPLE);
1553         sm.clearAndSelect(2);
1554 
1555         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
1556         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
1557         Toolkit.getToolkit().firePulse();
1558         assertTrue(isNotSelected(0,1));
1559         assertTrue(isSelected(2,3,4));
1560         assertEquals(3, sm.getSelectedItems().size());
1561         assertTrue(fm.isFocused(4));
1562 
1563         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
1564         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
1565         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
1566         Toolkit.getToolkit().firePulse();
1567         assertTrue(isNotSelected(0,1));
1568         assertTrue(isSelected(2,3,4));
1569         assertEquals(3, sm.getSelectedItems().size());
1570         assertTrue("Focus index incorrectly at: " + fm.getFocusedIndex(), fm.isFocused(4));
1571     }
1572 
1573     @Test public void test_rt33301_multipleSelection_up() {
1574         final int items = 5;
1575         listView.getItems().clear();
1576         for (int i = 0; i < items; i++) {
1577             listView.getItems().add("Row " + i);
1578         }
1579 
1580         final FocusModel fm = listView.getFocusModel();
1581         final MultipleSelectionModel sm = listView.getSelectionModel();
1582         sm.setSelectionMode(SelectionMode.MULTIPLE);
1583         sm.clearAndSelect(2);
1584 
1585         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
1586         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
1587         Toolkit.getToolkit().firePulse();
1588         assertTrue(isNotSelected(3,4));
1589         assertTrue(isSelected(0,1,2));
1590         assertEquals(3, sm.getSelectedItems().size());
1591         assertTrue(fm.isFocused(0));
1592 
1593         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
1594         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
1595         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
1596         Toolkit.getToolkit().firePulse();
1597         assertTrue(isNotSelected(3,4));
1598         assertTrue(isSelected(0,1,2));
1599         assertEquals(3, sm.getSelectedItems().size());
1600         assertTrue(fm.isFocused(0));
1601     }
1602 
1603     @Test public void test_rt33301_singleSelection_down() {
1604         final int items = 5;
1605         listView.getItems().clear();
1606         for (int i = 0; i < items; i++) {
1607             listView.getItems().add("Row " + i);
1608         }
1609 
1610         final FocusModel fm = listView.getFocusModel();
1611         final MultipleSelectionModel sm = listView.getSelectionModel();
1612         sm.setSelectionMode(SelectionMode.SINGLE);
1613         sm.clearAndSelect(2);
1614 
1615         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
1616         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
1617         Toolkit.getToolkit().firePulse();
1618         assertTrue(isNotSelected(0,1,2,3));
1619         assertTrue(isSelected(4));
1620         assertEquals(1, sm.getSelectedItems().size());
1621         assertTrue(fm.isFocused(4));
1622 
1623         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
1624         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
1625         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
1626         Toolkit.getToolkit().firePulse();
1627         assertTrue(isNotSelected(0,1,2,3));
1628         assertTrue(isSelected(4));
1629         assertEquals(1, sm.getSelectedItems().size());
1630         assertTrue(fm.isFocused(4));
1631     }
1632 
1633     @Test public void test_rt33301_singleSelection_up() {
1634         final int items = 5;
1635         listView.getItems().clear();
1636         for (int i = 0; i < items; i++) {
1637             listView.getItems().add("Row " + i);
1638         }
1639 
1640         final FocusModel fm = listView.getFocusModel();
1641         final MultipleSelectionModel sm = listView.getSelectionModel();
1642         sm.setSelectionMode(SelectionMode.SINGLE);
1643         sm.clearAndSelect(2);
1644 
1645         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
1646         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
1647         Toolkit.getToolkit().firePulse();
1648         assertTrue(isNotSelected(1,2,3,4));
1649         assertTrue(isSelected(0));
1650         assertEquals(1, sm.getSelectedItems().size());
1651         assertTrue(fm.isFocused(0));
1652 
1653         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
1654         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
1655         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
1656         Toolkit.getToolkit().firePulse();
1657         assertTrue(isNotSelected(1,2,3,4));
1658         assertTrue(isSelected(0));
1659         assertEquals(1, sm.getSelectedItems().size());
1660         assertTrue(fm.isFocused(0));
1661     }
1662 
1663     @Test public void test_rt20915() {
1664         final FocusModel fm = listView.getFocusModel();
1665         final MultipleSelectionModel sm = listView.getSelectionModel();
1666 
1667         sm.clearAndSelect(0);
1668         assertEquals(0, getAnchor());
1669 
1670         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1671         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1672         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1673         Toolkit.getToolkit().firePulse();
1674         assertTrue(isNotSelected(1,2,3));
1675         assertTrue(isSelected(0));
1676         assertEquals(1, sm.getSelectedItems().size());
1677         assertTrue(fm.isFocused(3));
1678 
1679         keyboard.doKeyPress(KeyCode.SPACE,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1680         Toolkit.getToolkit().firePulse();
1681         assertTrue(isSelected(0,1,2,3));
1682         assertEquals(4, sm.getSelectedItems().size());
1683         assertTrue(fm.isFocused(3));
1684     }
1685 
1686     @Test public void test_rt34200() {
1687         final int items = 100;
1688         listView.getItems().clear();
1689         for (int i = 0; i < items; i++) {
1690             listView.getItems().add("Row " + i);
1691         }
1692 
1693         sm.clearAndSelect(99);
1694         listView.scrollTo(99);
1695         assertEquals(99, getAnchor());
1696         assertEquals(99, fm.getFocusedIndex());
1697 
1698         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1699         Toolkit.getToolkit().firePulse();
1700         assertEquals(99, getAnchor());
1701         assertTrue(fm.getFocusedIndex() < 99);
1702     }
1703 
1704     @Test public void test_rt34369() {
1705         final int items = 100;
1706         listView.getItems().clear();
1707         for (int i = 0; i < items; i++) {
1708             listView.getItems().add("Row " + i);
1709         }
1710 
1711         sm.clearAndSelect(99);
1712         listView.scrollTo(99);
1713         assertEquals(99, getAnchor());
1714         assertEquals(99, fm.getFocusedIndex());
1715 
1716         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1717         Toolkit.getToolkit().firePulse();
1718         assertEquals(99, getAnchor());
1719         assertTrue(fm.getFocusedIndex() < 99);
1720     }
1721 
1722     @Test public void test_rt33894() {
1723         final int items = 5;
1724         listView.getItems().clear();
1725         for (int i = 0; i < items; i++) {
1726             listView.getItems().add("Row " + i);
1727         }
1728 
1729         sm.clearAndSelect(1);
1730         assertEquals(1, getAnchor());
1731         assertEquals(1, fm.getFocusedIndex());
1732         assertEquals(1, sm.getSelectedIndex());
1733 
1734         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1735         Toolkit.getToolkit().firePulse();
1736         assertEquals(1, getAnchor());
1737         assertEquals(2, fm.getFocusedIndex());
1738         assertEquals(1, sm.getSelectedIndex());
1739 
1740         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1741         Toolkit.getToolkit().firePulse();
1742         assertEquals(2, getAnchor());
1743         assertEquals(2, fm.getFocusedIndex());
1744         assertEquals(2, sm.getSelectedIndex());
1745         assertTrue(isSelected(1, 2));
1746 
1747         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
1748         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
1749         Toolkit.getToolkit().firePulse();
1750         assertEquals(2, getAnchor());
1751         assertEquals(0, fm.getFocusedIndex());
1752         assertEquals(2, sm.getSelectedIndex());
1753         assertTrue(isSelected(1, 2));
1754 
1755         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
1756         Toolkit.getToolkit().firePulse();
1757         assertEquals(0, getAnchor());
1758         assertEquals(0, fm.getFocusedIndex());
1759         assertEquals(0, sm.getSelectedIndex());
1760         assertTrue(isSelected(0, 1, 2));
1761     }
1762 
1763     @Test public void test_rt34425() {
1764         final int items = 5;
1765         listView.getItems().clear();
1766         for (int i = 0; i < items; i++) {
1767             listView.getItems().add("Row " + i);
1768         }
1769 
1770         sm.clearAndSelect(1);
1771         assertEquals(1, getAnchor());
1772         assertEquals(1, fm.getFocusedIndex());
1773         assertEquals(1, sm.getSelectedIndex());
1774 
1775         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
1776         Toolkit.getToolkit().firePulse();
1777         assertEquals(1, getAnchor());
1778         assertEquals(2, fm.getFocusedIndex());
1779         assertEquals(1, sm.getSelectedIndex());
1780 
1781         keyboard.doKeyPress(KeyCode.SPACE);
1782         Toolkit.getToolkit().firePulse();
1783         assertEquals(2, getAnchor());
1784         assertEquals(2, fm.getFocusedIndex());
1785         assertEquals(2, sm.getSelectedIndex());
1786         assertTrue(isSelected(1, 2));
1787     }
1788 
1789     @Test public void test_rt34407_down_down_up() {
1790         final int items = 100;
1791         listView.getItems().clear();
1792         for (int i = 0; i < items; i++) {
1793             listView.getItems().add("Row " + i);
1794         }
1795         listView.setPrefHeight(130); // roughly room for four rows
1796 
1797         // this stageLoader is needed....although right now I'm not sure why
1798         StageLoader sl = new StageLoader(listView);
1799         final FocusModel fm = listView.getFocusModel();
1800         final MultipleSelectionModel sm = listView.getSelectionModel();
1801         sm.setSelectionMode(SelectionMode.MULTIPLE);
1802 
1803         sm.clearAndSelect(0);
1804         fm.focus(0);
1805         assertEquals(0, getAnchor());
1806         assertTrue(fm.isFocused(0));
1807         assertTrue(sm.isSelected(0));
1808         assertFalse(sm.isSelected(1));
1809 
1810         // we expect the final Page-up to return us back to this selected index and with the same number of selected indices
1811         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1812         final int leadSelectedIndex = sm.getSelectedIndex();
1813         final int selectedIndicesCount = sm.getSelectedIndices().size();
1814         assertEquals(6, leadSelectedIndex);
1815         assertEquals(6, fm.getFocusedIndex());
1816         assertEquals(7, selectedIndicesCount);
1817 
1818         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1819         assertEquals(leadSelectedIndex * 2, sm.getSelectedIndex());
1820         assertEquals(leadSelectedIndex * 2, fm.getFocusedIndex());
1821         assertEquals(selectedIndicesCount * 2 - 1, sm.getSelectedIndices().size());
1822 
1823         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1824         assertEquals(leadSelectedIndex, sm.getSelectedIndex());
1825         assertEquals(leadSelectedIndex, fm.getFocusedIndex());
1826         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
1827 
1828         sl.dispose();
1829     }
1830 
1831     @Test public void test_rt34407_up_up_down() {
1832         final int items = 100;
1833         listView.getItems().clear();
1834         for (int i = 0; i < items; i++) {
1835             listView.getItems().add("Row " + i);
1836         }
1837         listView.setPrefHeight(130); // roughly room for four rows
1838 
1839         sm.setSelectionMode(SelectionMode.MULTIPLE);
1840 
1841         sm.clearAndSelect(99);
1842         fm.focus(99);
1843         listView.scrollTo(99);
1844         Toolkit.getToolkit().firePulse();
1845 
1846         assertEquals(99, getAnchor());
1847         assertTrue(fm.isFocused(99));
1848         assertTrue(sm.isSelected(99));
1849         assertFalse(sm.isSelected(98));
1850 
1851         // we expect the final Page-down to return us back to this selected index and with the same number of selected indices
1852         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1853         final int leadSelectedIndex = sm.getSelectedIndex();
1854         final int selectedIndicesCount = sm.getSelectedIndices().size();
1855         final int diff = 99 - leadSelectedIndex;
1856         assertEquals(99 - diff, leadSelectedIndex);
1857         assertEquals(99 - diff, fm.getFocusedIndex());
1858         assertEquals(7, selectedIndicesCount);
1859 
1860         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
1861         assertEquals(99 - diff * 2, sm.getSelectedIndex());
1862         assertEquals(selectedIndicesCount * 2 - 1, sm.getSelectedIndices().size());
1863 
1864         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
1865         assertEquals(leadSelectedIndex, sm.getSelectedIndex());
1866         assertEquals(selectedIndicesCount, sm.getSelectedIndices().size());
1867     }
1868 
1869     @Test public void test_rt34768() {
1870         listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
1871         listView.getItems().clear();
1872 
1873         // no need for an assert here - we're testing for an AIOOBE
1874         keyboard.doKeyPress(KeyCode.A, KeyModifier.getShortcutKey());
1875     }
1876 
1877     @Test public void test_rt35853_multipleSelection_shiftDown() {
1878         final int items = 10;
1879         listView.getItems().clear();
1880         for (int i = 0; i < items; i++) {
1881             listView.getItems().add("Row " + i);
1882         }
1883 
1884         sm.setSelectionMode(SelectionMode.MULTIPLE);
1885 
1886         sm.clearAndSelect(5);
1887         assertEquals(5, getAnchor());
1888         assertTrue(fm.isFocused(5));
1889         assertTrue(sm.isSelected(5));
1890 
1891         sm.selectedIndexProperty().addListener(observable -> {
1892             // we expect only one selected index change event, from 5 to 4
1893             assertEquals(4, sm.getSelectedIndex());
1894         });
1895 
1896         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
1897         assertEquals(5, getAnchor());
1898         assertTrue(fm.isFocused(4));
1899         assertTrue(sm.isSelected(4));
1900         assertTrue(sm.isSelected(5));
1901     }
1902 
1903     @Test public void test_rt35853_multipleSelection_noShiftDown() {
1904         final int items = 10;
1905         listView.getItems().clear();
1906         for (int i = 0; i < items; i++) {
1907             listView.getItems().add("Row " + i);
1908         }
1909 
1910         sm.setSelectionMode(SelectionMode.MULTIPLE);
1911 
1912         sm.clearAndSelect(5);
1913         assertEquals(5, getAnchor());
1914         assertTrue(fm.isFocused(5));
1915         assertTrue(sm.isSelected(5));
1916 
1917         sm.selectedIndexProperty().addListener(observable -> {
1918             // we expect only one selected index change event, from 5 to 4
1919             assertEquals(4, sm.getSelectedIndex());
1920         });
1921 
1922         keyboard.doKeyPress(KeyCode.UP);
1923         assertEquals(4, getAnchor());
1924         assertTrue(fm.isFocused(4));
1925         assertTrue(sm.isSelected(4));
1926         assertFalse(sm.isSelected(5));
1927     }
1928 
1929     @Test public void test_rt35853_singleSelection_shiftDown() {
1930         final int items = 10;
1931         listView.getItems().clear();
1932         for (int i = 0; i < items; i++) {
1933             listView.getItems().add("Row " + i);
1934         }
1935 
1936         sm.setSelectionMode(SelectionMode.SINGLE);
1937 
1938         sm.clearAndSelect(5);
1939         assertEquals(5, getAnchor());
1940         assertTrue(fm.isFocused(5));
1941         assertTrue(sm.isSelected(5));
1942 
1943         sm.selectedIndexProperty().addListener(observable -> {
1944             // we expect only one selected index change event, from 5 to 4
1945             assertEquals(4, sm.getSelectedIndex());
1946         });
1947 
1948         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
1949         assertEquals(4, getAnchor());
1950         assertTrue(fm.isFocused(4));
1951         assertTrue(sm.isSelected(4));
1952         assertFalse(sm.isSelected(5));
1953     }
1954 
1955     @Test public void test_rt35853_singleSelection_noShiftDown() {
1956         final int items = 10;
1957         listView.getItems().clear();
1958         for (int i = 0; i < items; i++) {
1959             listView.getItems().add("Row " + i);
1960         }
1961 
1962         sm.setSelectionMode(SelectionMode.SINGLE);
1963 
1964         sm.clearAndSelect(5);
1965         assertEquals(5, getAnchor());
1966         assertTrue(fm.isFocused(5));
1967         assertTrue(sm.isSelected(5));
1968 
1969         sm.selectedIndexProperty().addListener(observable -> {
1970             // we expect only one selected index change event, from 5 to 4
1971             assertEquals(4, sm.getSelectedIndex());
1972         });
1973 
1974         keyboard.doKeyPress(KeyCode.UP);
1975         assertEquals(4, getAnchor());
1976         assertTrue(fm.isFocused(4));
1977         assertTrue(sm.isSelected(4));
1978         assertFalse(sm.isSelected(5));
1979     }
1980 
1981     @Test public void test_rt36800() {
1982         // get the current exception handler before replacing with our own,
1983         // as ListListenerHelp intercepts the exception otherwise
1984         final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
1985         Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
1986 
1987         final int items = 10;
1988         listView.getItems().clear();
1989         for (int i = 0; i < items; i++) {
1990             listView.getItems().add("Row " + i);
1991         }
1992 
1993         sm.setSelectionMode(SelectionMode.SINGLE);
1994 
1995         sm.clearAndSelect(5);
1996         assertEquals(5, getAnchor());
1997         assertTrue(fm.isFocused(5));
1998         assertTrue(sm.isSelected(5));
1999 
2000         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 4
2001         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 3
2002         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 2
2003         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 1
2004         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 0
2005         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // bug time?
2006 
2007         assertEquals(0, getAnchor());
2008         assertTrue(fm.isFocused(0));
2009         assertTrue(sm.isSelected(0));
2010         assertFalse(sm.isSelected(1));
2011         assertFalse(sm.isSelected(2));
2012         assertFalse(sm.isSelected(3));
2013         assertFalse(sm.isSelected(4));
2014         assertFalse(sm.isSelected(5));
2015 
2016         // reset the exception handler
2017         Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
2018     }
2019 
2020     @Test public void test_rt_36942() {
2021         // get the current exception handler before replacing with our own,
2022         // as ListListenerHelp intercepts the exception otherwise
2023         final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
2024         Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
2025 
2026         final int items = 3;
2027         listView.getItems().clear();
2028         for (int i = 0; i < items; i++) {
2029             listView.getItems().add("Row " + i);
2030         }
2031 
2032         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2033         sm.setSelectionMode(SelectionMode.MULTIPLE);
2034         ObservableList<String> selectedItems = sm.getSelectedItems();
2035 
2036         ListView<String> selectedItemsListView = new ListView<>(selectedItems);
2037 
2038         HBox root = new HBox(5, listView, selectedItemsListView);
2039 
2040         StageLoader sl = new StageLoader(root);
2041 
2042         sm.select(0);
2043         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // 0,1
2044         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // 0,1,2
2045         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.SHIFT); // 0,1,2,Exception?
2046 
2047         sl.dispose();
2048 
2049         // reset the exception handler
2050         Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
2051     }
2052 
2053     @Test public void test_rt_37130_pageUpAtTop() {
2054         final int items = 100;
2055         listView.getItems().clear();
2056         for (int i = 0; i < items; i++) {
2057             listView.getItems().add("Row " + i);
2058         }
2059 
2060         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2061         sm.setSelectionMode(SelectionMode.MULTIPLE);
2062 
2063         StageLoader sl = new StageLoader(listView);
2064 
2065         sm.select(5);
2066         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2067         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2068 
2069         sl.dispose();
2070     }
2071 
2072     @Test public void test_rt_37130_pageUpAtBottom() {
2073         final int items = 100;
2074         listView.getItems().clear();
2075         for (int i = 0; i < items; i++) {
2076             listView.getItems().add("Row " + i);
2077         }
2078 
2079         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2080         sm.setSelectionMode(SelectionMode.MULTIPLE);
2081 
2082         StageLoader sl = new StageLoader(listView);
2083 
2084         sm.select(95);
2085         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2086         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.SHIFT);
2087 
2088         sl.dispose();
2089     }
2090 
2091     @Test public void test_rt_37130_pageDownAtTop() {
2092         final int items = 100;
2093         listView.getItems().clear();
2094         for (int i = 0; i < items; i++) {
2095             listView.getItems().add("Row " + i);
2096         }
2097 
2098         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2099         sm.setSelectionMode(SelectionMode.MULTIPLE);
2100 
2101         StageLoader sl = new StageLoader(listView);
2102 
2103         sm.select(5);
2104         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2105         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2106 
2107         sl.dispose();
2108     }
2109 
2110     @Test public void test_rt_37130_pageDownAtBottom() {
2111         final int items = 100;
2112         listView.getItems().clear();
2113         for (int i = 0; i < items; i++) {
2114             listView.getItems().add("Row " + i);
2115         }
2116 
2117         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2118         sm.setSelectionMode(SelectionMode.MULTIPLE);
2119 
2120         StageLoader sl = new StageLoader(listView);
2121 
2122         sm.select(95);
2123         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2124         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.SHIFT);
2125 
2126         sl.dispose();
2127     }
2128 
2129     private int rt_39088_indices_event_count = 0;
2130     private int rt_39088_items_event_count = 0;
2131     @Test public void test_rt_39088() {
2132         listView.getItems().clear();
2133         for (int i = 0; i < 4; i++) {
2134             listView.getItems().add("Row " + i);
2135         }
2136 
2137         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2138         sm.setSelectionMode(SelectionMode.MULTIPLE);
2139 
2140         ObservableList<Integer> indices = sm.getSelectedIndices();
2141         ObservableList<String> items = sm.getSelectedItems();
2142 
2143         indices.addListener((ListChangeListener<Integer>) change -> rt_39088_indices_event_count++);
2144         items.addListener((ListChangeListener<String>) change -> rt_39088_items_event_count++);
2145 
2146         StageLoader sl = new StageLoader(listView);
2147 
2148         assertEquals(0, rt_39088_indices_event_count);
2149         assertEquals(0, rt_39088_items_event_count);
2150         assertEquals(0, indices.size());
2151         assertEquals(0, items.size());
2152 
2153         sm.select(3);
2154         assertEquals(1, rt_39088_indices_event_count);
2155         assertEquals(1, rt_39088_items_event_count);
2156         assertEquals(1, indices.size());
2157         assertEquals(1, items.size());
2158 
2159         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
2160         assertEquals(2, rt_39088_indices_event_count);
2161         assertEquals(2, rt_39088_items_event_count);
2162         assertEquals(2, indices.size());
2163         assertEquals(2, items.size());
2164 
2165         // this is where the test fails...
2166         keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
2167         assertEquals(3, rt_39088_indices_event_count);
2168         assertEquals(3, rt_39088_items_event_count);
2169         assertEquals(3, indices.size());
2170         assertEquals(3, items.size());
2171 
2172         sl.dispose();
2173     }
2174 
2175     @Test public void test_rt_27709_singleSelection_rowSelection() {
2176         test_rt_27709(SelectionMode.SINGLE, false);
2177     }
2178 
2179     @Test public void test_rt_27709_multipleSelection_rowSelection() {
2180         test_rt_27709(SelectionMode.MULTIPLE, false);
2181     }
2182 
2183     @Test public void test_rt_27709_singleSelection_rowSelection_resetSelection() {
2184         test_rt_27709(SelectionMode.SINGLE, true);
2185     }
2186 
2187     @Test public void test_rt_27709_multipleSelection_rowSelection_resetSelection() {
2188         test_rt_27709(SelectionMode.MULTIPLE, true);
2189     }
2190 
2191     private void test_rt_27709(SelectionMode mode, boolean resetSelection) {
2192         ObservableList<String> itemsList = FXCollections.observableArrayList();
2193         for (int i = 0; i < 10; i++) {
2194             itemsList.add("Row " + i);
2195         }
2196 
2197         listView.setItems(itemsList);
2198 
2199         MultipleSelectionModel<String> sm = listView.getSelectionModel();
2200         sm.setSelectionMode(mode);
2201 
2202         ObservableList<Integer> indices = sm.getSelectedIndices();
2203 
2204         int expectedSize = mode == SelectionMode.SINGLE ? 1 : 10;
2205         int lookupIndex = mode == SelectionMode.SINGLE ? 0 : 9;
2206 
2207         sm.select(0);
2208         assertEquals(1, indices.size());
2209 
2210         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
2211         assertEquals(expectedSize, indices.size());
2212         assertEquals(9, (int) indices.get(lookupIndex));
2213 
2214         if (resetSelection) {
2215             sm.clearAndSelect(9);
2216             int anchor = ListCellBehavior.getAnchor(listView, null);
2217             assertEquals(9, anchor);
2218         } else {
2219             expectedSize = 1;
2220         }
2221 
2222         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT);
2223         assertEquals(expectedSize, indices.size());
2224         assertTrue(debug(),sm.isSelected(0));
2225 
2226         if (resetSelection) {
2227             sm.clearAndSelect(0);
2228 
2229             int anchor = ListCellBehavior.getAnchor(listView, null);
2230             assertEquals(0, anchor);
2231         } else {
2232             expectedSize = mode == SelectionMode.SINGLE ? 1 : 10;
2233         }
2234 
2235         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT);
2236         assertEquals(expectedSize, indices.size());
2237         assertTrue(sm.isSelected(9));
2238     }
2239 
2240     @Test public void test_rt_24865_moveDownwards() {
2241         listView.getItems().clear();
2242         for (int i = 0; i < 100; i++) {
2243             listView.getItems().add("Row " + i);
2244         }
2245 
2246         Toolkit.getToolkit().firePulse();
2247 
2248         ObservableList<Integer> indices = sm.getSelectedIndices();
2249 
2250         sm.select(0);
2251         assertTrue(isSelected(0));
2252         assertTrue(fm.isFocused(0));
2253         assertEquals(1, indices.size());
2254         assertEquals(0, (int) ListCellBehavior.getAnchor(listView, -1));
2255 
2256         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2257         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2258         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2259         assertTrue(isSelected(0, 1, 2, 3));
2260         assertTrue(fm.isFocused(3));
2261         assertEquals(4, indices.size());
2262         assertEquals(0, (int) ListCellBehavior.getAnchor(listView, -1));
2263 
2264         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
2265         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
2266         keyboard.doDownArrowPress(KeyModifier.getShortcutKey());
2267         assertTrue(isSelected(0, 1, 2, 3));
2268         assertTrue(isNotSelected(4, 5, 6, 7, 8, 9));
2269         assertTrue(fm.isFocused(6));
2270         assertEquals(4, indices.size());
2271         assertEquals(0, (int) ListCellBehavior.getAnchor(listView, -1));
2272 
2273         // main point of test: selection between the last index (3) and the focus
2274         // index (6) should now be true
2275         keyboard.doKeyPress(KeyCode.PAGE_DOWN, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2276         final int selectedRowCount = indices.size();
2277         for (int i = 0; i < selectedRowCount; i++) {
2278             assertTrue(isSelected(i));
2279         }
2280         assertTrue(fm.isFocused(selectedRowCount - 1));
2281         assertEquals(0, (int) ListCellBehavior.getAnchor(listView, -1));
2282 
2283         keyboard.doDownArrowPress(KeyModifier.SHIFT);
2284         int newSelectedRowCount = selectedRowCount + 1;
2285         for (int i = 0; i < newSelectedRowCount; i++) {
2286             assertTrue(isSelected(i));
2287         }
2288         assertTrue(fm.isFocused(newSelectedRowCount - 1));
2289         assertEquals(0, (int) ListCellBehavior.getAnchor(listView, -1));
2290     }
2291 
2292     @Test public void test_rt_24865_moveUpwards() {
2293         listView.getItems().clear();
2294         for (int i = 0; i < 100; i++) {
2295             listView.getItems().add("Row " + i);
2296         }
2297 
2298         Toolkit.getToolkit().firePulse();
2299 
2300         ObservableList<Integer> indices = sm.getSelectedIndices();
2301 
2302         sm.select(50);
2303         listView.scrollTo(50);
2304 
2305         Toolkit.getToolkit().firePulse();
2306 
2307         assertTrue(isSelected(50));
2308         assertTrue(fm.isFocused(50));
2309         assertEquals(1, indices.size());
2310         assertEquals(50, (int) ListCellBehavior.getAnchor(listView, -1));
2311 
2312         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2313         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2314         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2315         assertTrue(isSelected(50, 49, 48, 47));
2316         assertTrue(fm.isFocused(47));
2317         assertEquals(4, indices.size());
2318         assertEquals(50, (int) ListCellBehavior.getAnchor(listView, -1));
2319 
2320         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
2321         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
2322         keyboard.doUpArrowPress(KeyModifier.getShortcutKey());
2323         assertTrue(isSelected(50, 49, 48, 47));
2324         assertTrue(isNotSelected(46, 45, 44, 43, 42, 41));
2325         assertTrue(fm.isFocused(44));
2326         assertEquals(4, indices.size());
2327         assertEquals(50, (int) ListCellBehavior.getAnchor(listView, -1));
2328 
2329         // main point of test: selection between the last index (47) and the focus
2330         // index (44) should now be true
2331         keyboard.doKeyPress(KeyCode.PAGE_UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
2332         final int selectedRowCount = indices.size();
2333         for (int i = 0; i < selectedRowCount; i++) {
2334             assertTrue(isSelected(50 - i));
2335         }
2336         assertTrue(fm.isFocused(50 - selectedRowCount + 1));
2337         assertEquals(50, (int) ListCellBehavior.getAnchor(listView, -1));
2338 
2339         keyboard.doUpArrowPress(KeyModifier.SHIFT);
2340         int newSelectedRowCount = selectedRowCount + 1;
2341         for (int i = 0; i < newSelectedRowCount; i++) {
2342             assertTrue(isSelected(50 - i));
2343         }
2344         assertTrue(fm.isFocused(50 - newSelectedRowCount + 1));
2345         assertEquals(50, (int) ListCellBehavior.getAnchor(listView, -1));
2346     }
2347 }