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