modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization

*** 1,7 **** /* ! * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 20,223 **** * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.sun.javafx.scene.control.behavior; import com.sun.javafx.PlatformUtil; import com.sun.javafx.scene.control.skin.Utils; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.beans.value.WeakChangeListener; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.collections.WeakListChangeListener; ! import javafx.event.EventType; ! import javafx.geometry.NodeOrientation; import javafx.geometry.Orientation; - import javafx.scene.control.Control; import javafx.scene.control.FocusModel; import javafx.scene.control.ListView; import javafx.scene.control.MultipleSelectionModel; import javafx.scene.control.SelectionMode; ! import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseEvent; import javafx.util.Callback; import java.util.ArrayList; import java.util.List; import static javafx.scene.input.KeyCode.*; - /** - * - */ public class ListViewBehavior<T> extends BehaviorBase<ListView<T>> { ! /************************************************************************** ! * Setup KeyBindings * ! *************************************************************************/ ! protected static final List<KeyBinding> LIST_VIEW_BINDINGS = new ArrayList<KeyBinding>(); ! ! static { ! LIST_VIEW_BINDINGS.add(new KeyBinding(HOME, "SelectFirstRow")); ! LIST_VIEW_BINDINGS.add(new KeyBinding(END, "SelectLastRow")); ! LIST_VIEW_BINDINGS.add(new KeyBinding(HOME, "SelectAllToFirstRow").shift()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(END, "SelectAllToLastRow").shift()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "SelectAllPageUp").shift()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "SelectAllPageDown").shift()); ! ! LIST_VIEW_BINDINGS.add(new KeyBinding(SPACE, "SelectAllToFocus").shift()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(SPACE, "SelectAllToFocusAndSetAnchor").shortcut().shift()); ! ! LIST_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "ScrollUp")); ! LIST_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "ScrollDown")); ! ! LIST_VIEW_BINDINGS.add(new KeyBinding(ENTER, "Activate")); ! LIST_VIEW_BINDINGS.add(new KeyBinding(SPACE, "Activate")); ! LIST_VIEW_BINDINGS.add(new KeyBinding(F2, "Activate")); ! LIST_VIEW_BINDINGS.add(new KeyBinding(ESCAPE, "CancelEdit")); ! ! LIST_VIEW_BINDINGS.add(new KeyBinding(A, "SelectAll").shortcut()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(HOME, "FocusFirstRow").shortcut()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(END, "FocusLastRow").shortcut()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "FocusPageUp").shortcut()); ! LIST_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "FocusPageDown").shortcut()); ! if (PlatformUtil.isMac()) { ! LIST_VIEW_BINDINGS.add(new KeyBinding(SPACE, "toggleFocusOwnerSelection").ctrl().shortcut()); ! } else { ! LIST_VIEW_BINDINGS.add(new KeyBinding(SPACE, "toggleFocusOwnerSelection").ctrl()); } ! ! // if listView is vertical... ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(UP, "SelectPreviousRow").vertical()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_UP, "SelectPreviousRow").vertical()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(DOWN, "SelectNextRow").vertical()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_DOWN, "SelectNextRow").vertical()); ! ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(UP, "AlsoSelectPreviousRow").vertical().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_UP, "AlsoSelectPreviousRow").vertical().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(DOWN, "AlsoSelectNextRow").vertical().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_DOWN, "AlsoSelectNextRow").vertical().shift()); ! ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(UP, "FocusPreviousRow").vertical().shortcut()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(DOWN, "FocusNextRow").vertical().shortcut()); ! ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(UP, "DiscontinuousSelectPreviousRow").vertical().shortcut().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(DOWN, "DiscontinuousSelectNextRow").vertical().shortcut().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(PAGE_UP, "DiscontinuousSelectPageUp").vertical().shortcut().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(PAGE_DOWN, "DiscontinuousSelectPageDown").vertical().shortcut().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(HOME, "DiscontinuousSelectAllToFirstRow").vertical().shortcut().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(END, "DiscontinuousSelectAllToLastRow").vertical().shortcut().shift()); ! // --- end of vertical ! // if listView is horizontal... ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(LEFT, "SelectPreviousRow")); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_LEFT, "SelectPreviousRow")); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(RIGHT, "SelectNextRow")); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_RIGHT, "SelectNextRow")); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(LEFT, "AlsoSelectPreviousRow").shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_LEFT, "AlsoSelectPreviousRow").shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(RIGHT, "AlsoSelectNextRow").shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(KP_RIGHT, "AlsoSelectNextRow").shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(LEFT, "FocusPreviousRow").shortcut()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(RIGHT, "FocusNextRow").shortcut()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(LEFT, "DiscontinuousSelectPreviousRow").shortcut().shift()); ! LIST_VIEW_BINDINGS.add(new ListViewKeyBinding(RIGHT, "DiscontinuousSelectNextRow").shortcut().shift()); ! // --- end of horizontal ! LIST_VIEW_BINDINGS.add(new KeyBinding(BACK_SLASH, "ClearSelection").shortcut()); } ! protected /*final*/ String matchActionForEvent(KeyEvent e) { ! String action = super.matchActionForEvent(e); ! if (action != null) { ! if (e.getCode() == LEFT || e.getCode() == KP_LEFT) { ! if (getControl().getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) { ! if (e.isShiftDown()) { ! action = "AlsoSelectNextRow"; ! } else { ! if (e.isShortcutDown()) { ! action = "FocusNextRow"; ! } else { ! action = getControl().getOrientation() == Orientation.HORIZONTAL ? "SelectNextRow" : "TraverseRight"; ! } ! } ! } ! } else if (e.getCode() == RIGHT || e.getCode() == KP_RIGHT) { ! if (getControl().getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) { ! if (e.isShiftDown()) { ! action = "AlsoSelectPreviousRow"; ! } else { ! if (e.isShortcutDown()) { ! action = "FocusPreviousRow"; ! } else { ! action = getControl().getOrientation() == Orientation.HORIZONTAL ? "SelectPreviousRow" : "TraverseLeft"; ! } ! } ! } } } - return action; } ! @Override protected void callAction(String name) { ! if ("SelectPreviousRow".equals(name)) selectPreviousRow(); ! else if ("SelectNextRow".equals(name)) selectNextRow(); ! else if ("SelectFirstRow".equals(name)) selectFirstRow(); ! else if ("SelectLastRow".equals(name)) selectLastRow(); ! else if ("SelectAllToFirstRow".equals(name)) selectAllToFirstRow(); ! else if ("SelectAllToLastRow".equals(name)) selectAllToLastRow(); ! else if ("SelectAllPageUp".equals(name)) selectAllPageUp(); ! else if ("SelectAllPageDown".equals(name)) selectAllPageDown(); ! else if ("AlsoSelectNextRow".equals(name)) alsoSelectNextRow(); ! else if ("AlsoSelectPreviousRow".equals(name)) alsoSelectPreviousRow(); ! else if ("ClearSelection".equals(name)) clearSelection(); ! else if ("SelectAll".equals(name)) selectAll(); ! else if ("ScrollUp".equals(name)) scrollPageUp(); ! else if ("ScrollDown".equals(name)) scrollPageDown(); ! else if ("FocusPreviousRow".equals(name)) focusPreviousRow(); ! else if ("FocusNextRow".equals(name)) focusNextRow(); ! else if ("FocusPageUp".equals(name)) focusPageUp(); ! else if ("FocusPageDown".equals(name)) focusPageDown(); ! else if ("Activate".equals(name)) activate(); ! else if ("CancelEdit".equals(name)) cancelEdit(); ! else if ("FocusFirstRow".equals(name)) focusFirstRow(); ! else if ("FocusLastRow".equals(name)) focusLastRow(); ! else if ("toggleFocusOwnerSelection".equals(name)) toggleFocusOwnerSelection(); ! ! else if ("SelectAllToFocus".equals(name)) selectAllToFocus(false); ! else if ("SelectAllToFocusAndSetAnchor".equals(name)) selectAllToFocus(true); ! ! else if ("DiscontinuousSelectNextRow".equals(name)) discontinuousSelectNextRow(); ! else if ("DiscontinuousSelectPreviousRow".equals(name)) discontinuousSelectPreviousRow(); ! else if ("DiscontinuousSelectPageUp".equals(name)) discontinuousSelectPageUp(); ! else if ("DiscontinuousSelectPageDown".equals(name)) discontinuousSelectPageDown(); ! else if ("DiscontinuousSelectAllToLastRow".equals(name)) discontinuousSelectAllToLastRow(); ! else if ("DiscontinuousSelectAllToFirstRow".equals(name)) discontinuousSelectAllToFirstRow(); ! else super.callAction(name); } ! @Override protected void callActionForEvent(KeyEvent e) { ! // RT-12751: we want to keep an eye on the user holding down the shift key, ! // so that we know when they enter/leave multiple selection mode. This ! // changes what happens when certain key combinations are pressed. ! isShiftDown = e.getEventType() == KeyEvent.KEY_PRESSED && e.isShiftDown(); ! isShortcutDown = e.getEventType() == KeyEvent.KEY_PRESSED && e.isShortcutDown(); ! super.callActionForEvent(e); } /************************************************************************** * State and Functions * *************************************************************************/ private boolean isShiftDown = false; --- 20,238 ---- * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.javafx.scene.control.behavior; import com.sun.javafx.PlatformUtil; import com.sun.javafx.scene.control.skin.Utils; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.beans.value.WeakChangeListener; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.collections.WeakListChangeListener; ! import javafx.event.EventHandler; import javafx.geometry.Orientation; import javafx.scene.control.FocusModel; import javafx.scene.control.ListView; import javafx.scene.control.MultipleSelectionModel; import javafx.scene.control.SelectionMode; ! import com.sun.javafx.scene.control.inputmap.InputMap; ! import com.sun.javafx.scene.control.inputmap.KeyBinding; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseEvent; import javafx.util.Callback; import java.util.ArrayList; import java.util.List; + import static com.sun.javafx.scene.control.inputmap.InputMap.*; import static javafx.scene.input.KeyCode.*; public class ListViewBehavior<T> extends BehaviorBase<ListView<T>> { + private final InputMap<ListView<T>> listViewInputMap; ! /** ! * Indicates that a keyboard key has been pressed which represents the ! * event (this could be space bar for example). As long as keyDown is true, ! * we are also armed, and will ignore mouse events related to arming. ! * Note this is made package private solely for the sake of testing. ! */ ! private boolean keyDown; ! private final EventHandler<KeyEvent> keyEventListener = e -> { ! if (!e.isConsumed()) { ! // RT-12751: we want to keep an eye on the user holding down the shift key, ! // so that we know when they enter/leave multiple selection mode. This ! // changes what happens when certain key combinations are pressed. ! isShiftDown = e.getEventType() == KeyEvent.KEY_PRESSED && e.isShiftDown(); ! isShortcutDown = e.getEventType() == KeyEvent.KEY_PRESSED && e.isShortcutDown(); } ! }; ! /*************************************************************************** ! * * ! * Constructors * ! * * ! **************************************************************************/ ! public ListViewBehavior(ListView<T> control) { ! super(control); ! // create a map for listView-specific mappings ! listViewInputMap = createInputMap(); ! // add focus traversal mappings ! addDefaultMapping(listViewInputMap, FocusTraversalInputMap.getFocusTraversalMappings()); ! addDefaultMapping(listViewInputMap, ! new KeyMapping(HOME, e -> selectFirstRow()), ! new KeyMapping(END, e -> selectLastRow()), ! new KeyMapping(new KeyBinding(HOME).shift(), e -> selectAllToFirstRow()), ! new KeyMapping(new KeyBinding(END).shift(), e -> selectAllToLastRow()), ! new KeyMapping(new KeyBinding(PAGE_UP).shift(), e -> selectAllPageUp()), ! new KeyMapping(new KeyBinding(PAGE_DOWN).shift(), e -> selectAllPageDown()), ! ! new KeyMapping(new KeyBinding(SPACE).shift(), e -> selectAllToFocus(false)), ! new KeyMapping(new KeyBinding(SPACE).shortcut().shift(), e -> selectAllToFocus(true)), ! ! new KeyMapping(PAGE_UP, e -> scrollPageUp()), ! new KeyMapping(PAGE_DOWN, e -> scrollPageDown()), ! ! new KeyMapping(ENTER, e -> activate()), ! new KeyMapping(SPACE, e -> activate()), ! new KeyMapping(F2, e -> activate()), ! new KeyMapping(ESCAPE, e -> cancelEdit()), ! ! new KeyMapping(new KeyBinding(A).shortcut(), e -> selectAll()), ! new KeyMapping(new KeyBinding(HOME).shortcut(), e -> focusFirstRow()), ! new KeyMapping(new KeyBinding(END).shortcut(), e -> focusLastRow()), ! new KeyMapping(new KeyBinding(PAGE_UP).shortcut(), e -> focusPageUp()), ! new KeyMapping(new KeyBinding(PAGE_DOWN).shortcut(), e -> focusPageDown()), ! ! new KeyMapping(new KeyBinding(BACK_SLASH).shortcut(), e -> clearSelection()), ! ! new MouseMapping(MouseEvent.MOUSE_PRESSED, this::mousePressed) ! ); ! ! // create OS-specific child mappings ! // --- mac OS ! InputMap<ListView<T>> macInputMap = new InputMap<>(control); ! macInputMap.setInterceptor(event -> !PlatformUtil.isMac()); ! addDefaultMapping(macInputMap, new KeyMapping(new KeyBinding(SPACE).shortcut().ctrl(), e -> toggleFocusOwnerSelection())); ! addDefaultChildMap(listViewInputMap, macInputMap); ! ! // --- all other platforms ! InputMap<ListView<T>> otherOsInputMap = new InputMap<>(control); ! otherOsInputMap.setInterceptor(event -> PlatformUtil.isMac()); ! addDefaultMapping(otherOsInputMap, new KeyMapping(new KeyBinding(SPACE).ctrl(), e -> toggleFocusOwnerSelection())); ! addDefaultChildMap(listViewInputMap, otherOsInputMap); ! ! // create two more child maps, one for vertical listview and one for horizontal listview ! // --- vertical listview ! InputMap<ListView<T>> verticalListInputMap = new InputMap<>(control); ! verticalListInputMap.setInterceptor(event -> control.getOrientation() != Orientation.VERTICAL); ! ! addDefaultMapping(verticalListInputMap, ! new KeyMapping(UP, e -> selectPreviousRow()), ! new KeyMapping(KP_UP, e -> selectPreviousRow()), ! new KeyMapping(DOWN, e -> selectNextRow()), ! new KeyMapping(KP_DOWN, e -> selectNextRow()), ! ! new KeyMapping(new KeyBinding(UP).shift(), e -> alsoSelectPreviousRow()), ! new KeyMapping(new KeyBinding(KP_UP).shift(), e -> alsoSelectPreviousRow()), ! new KeyMapping(new KeyBinding(DOWN).shift(), e -> alsoSelectNextRow()), ! new KeyMapping(new KeyBinding(KP_DOWN).shift(), e -> alsoSelectNextRow()), ! ! new KeyMapping(new KeyBinding(UP).shortcut(), e -> focusPreviousRow()), ! new KeyMapping(new KeyBinding(DOWN).shortcut(), e -> focusNextRow()), ! ! new KeyMapping(new KeyBinding(UP).shortcut().shift(), e -> discontinuousSelectPreviousRow()), ! new KeyMapping(new KeyBinding(DOWN).shortcut().shift(), e -> discontinuousSelectNextRow()), ! new KeyMapping(new KeyBinding(PAGE_UP).shortcut().shift(), e -> discontinuousSelectPageUp()), ! new KeyMapping(new KeyBinding(PAGE_DOWN).shortcut().shift(), e -> discontinuousSelectPageDown()), ! new KeyMapping(new KeyBinding(HOME).shortcut().shift(), e -> discontinuousSelectAllToFirstRow()), ! new KeyMapping(new KeyBinding(END).shortcut().shift(), e -> discontinuousSelectAllToLastRow()) ! ); ! ! addDefaultChildMap(listViewInputMap, verticalListInputMap); ! ! // --- horizontal listview ! InputMap<ListView<T>> horizontalListInputMap = new InputMap<>(control); ! horizontalListInputMap.setInterceptor(event -> control.getOrientation() != Orientation.HORIZONTAL); ! ! addDefaultMapping(horizontalListInputMap, ! new KeyMapping(LEFT, e -> selectPreviousRow()), ! new KeyMapping(KP_LEFT, e -> selectPreviousRow()), ! new KeyMapping(RIGHT, e -> selectNextRow()), ! new KeyMapping(KP_RIGHT, e -> selectNextRow()), ! ! new KeyMapping(new KeyBinding(LEFT).shift(), e -> alsoSelectPreviousRow()), ! new KeyMapping(new KeyBinding(KP_LEFT).shift(), e -> alsoSelectPreviousRow()), ! new KeyMapping(new KeyBinding(RIGHT).shift(), e -> alsoSelectNextRow()), ! new KeyMapping(new KeyBinding(KP_RIGHT).shift(), e -> alsoSelectNextRow()), ! ! new KeyMapping(new KeyBinding(LEFT).shortcut(), e -> focusPreviousRow()), ! new KeyMapping(new KeyBinding(RIGHT).shortcut(), e -> focusNextRow()), ! ! new KeyMapping(new KeyBinding(LEFT).shortcut().shift(), e -> discontinuousSelectPreviousRow()), ! new KeyMapping(new KeyBinding(RIGHT).shortcut().shift(), e -> discontinuousSelectNextRow()) ! ); ! ! addDefaultChildMap(listViewInputMap, horizontalListInputMap); ! ! // set up other listeners ! // We make this an event _filter_ so that we can determine the state ! // of the shift key before the event handlers get a shot at the event. ! control.addEventFilter(KeyEvent.ANY, keyEventListener); ! control.itemsProperty().addListener(weakItemsListener); ! if (control.getItems() != null) { ! control.getItems().addListener(weakItemsListListener); } ! // Fix for RT-16565 ! control.selectionModelProperty().addListener(weakSelectionModelListener); ! if (control.getSelectionModel() != null) { ! control.getSelectionModel().getSelectedIndices().addListener(weakSelectedIndicesListener); } + + // Only add this if we're on an embedded platform that supports 5-button navigation + if (Utils.isTwoLevelFocus()) { + tlFocus = new TwoLevelFocusListBehavior(control); // needs to be last. } } ! ! ! /*************************************************************************** ! * * ! * Implementation of BehaviorBase API * ! * * ! **************************************************************************/ ! ! @Override public InputMap<ListView<T>> getInputMap() { ! return listViewInputMap; } ! @Override public void dispose() { ! ListView<T> control = getNode(); ! ListCellBehavior.removeAnchor(control); ! if (tlFocus != null) tlFocus.dispose(); ! super.dispose(); ! ! control.removeEventHandler(KeyEvent.ANY, keyEventListener); } + + + + /************************************************************************** * State and Functions * *************************************************************************/ private boolean isShiftDown = false;
*** 244,261 **** private boolean selectionChanging = false; private final ListChangeListener<Integer> selectedIndicesListener = c -> { while (c.next()) { if (c.wasReplaced()) { ! if (ListCellBehavior.hasDefaultAnchor(getControl())) { ! ListCellBehavior.removeAnchor(getControl()); } } final int shift = c.wasPermutated() ? c.getTo() - c.getFrom() : 0; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); // there are no selected items, so lets clear out the anchor if (! selectionChanging) { if (sm.isEmpty()) { setAnchor(-1); --- 259,276 ---- private boolean selectionChanging = false; private final ListChangeListener<Integer> selectedIndicesListener = c -> { while (c.next()) { if (c.wasReplaced()) { ! if (ListCellBehavior.hasDefaultAnchor(getNode())) { ! ListCellBehavior.removeAnchor(getNode()); } } final int shift = c.wasPermutated() ? c.getTo() - c.getFrom() : 0; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); // there are no selected items, so lets clear out the anchor if (! selectionChanging) { if (sm.isEmpty()) { setAnchor(-1);
*** 319,395 **** private final WeakChangeListener<MultipleSelectionModel<T>> weakSelectionModelListener = new WeakChangeListener<MultipleSelectionModel<T>>(selectionModelListener); private TwoLevelFocusListBehavior tlFocus; - public ListViewBehavior(ListView<T> control) { - super(control, LIST_VIEW_BINDINGS); - - control.itemsProperty().addListener(weakItemsListener); - if (control.getItems() != null) { - control.getItems().addListener(weakItemsListListener); - } - - // Fix for RT-16565 - getControl().selectionModelProperty().addListener(weakSelectionModelListener); - if (control.getSelectionModel() != null) { - control.getSelectionModel().getSelectedIndices().addListener(weakSelectedIndicesListener); - } - - // Only add this if we're on an embedded platform that supports 5-button navigation - if (Utils.isTwoLevelFocus()) { - tlFocus = new TwoLevelFocusListBehavior(control); // needs to be last. - } - } - - @Override public void dispose() { - ListCellBehavior.removeAnchor(getControl()); - if (tlFocus != null) tlFocus.dispose(); - super.dispose(); - } - private void setAnchor(int anchor) { ! ListCellBehavior.setAnchor(getControl(), anchor < 0 ? null : anchor, false); } private int getAnchor() { ! return ListCellBehavior.getAnchor(getControl(), getControl().getFocusModel().getFocusedIndex()); } private boolean hasAnchor() { ! return ListCellBehavior.hasNonDefaultAnchor(getControl()); } ! @Override public void mousePressed(MouseEvent e) { ! super.mousePressed(e); ! if (! e.isShiftDown() && ! e.isSynthesized()) { ! int index = getControl().getSelectionModel().getSelectedIndex(); setAnchor(index); } ! if (! getControl().isFocused() && getControl().isFocusTraversable()) { ! getControl().requestFocus(); } } private int getRowCount() { ! return getControl().getItems() == null ? 0 : getControl().getItems().size(); } private void clearSelection() { ! getControl().getSelectionModel().clearSelection(); } private void scrollPageUp() { int newSelectedIndex = -1; if (onScrollPageUp != null) { newSelectedIndex = onScrollPageUp.call(false); } if (newSelectedIndex == -1) return; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; sm.clearAndSelect(newSelectedIndex); } private void scrollPageDown() { --- 334,382 ---- private final WeakChangeListener<MultipleSelectionModel<T>> weakSelectionModelListener = new WeakChangeListener<MultipleSelectionModel<T>>(selectionModelListener); private TwoLevelFocusListBehavior tlFocus; private void setAnchor(int anchor) { ! ListCellBehavior.setAnchor(getNode(), anchor < 0 ? null : anchor, false); } private int getAnchor() { ! return ListCellBehavior.getAnchor(getNode(), getNode().getFocusModel().getFocusedIndex()); } private boolean hasAnchor() { ! return ListCellBehavior.hasNonDefaultAnchor(getNode()); } ! private void mousePressed(MouseEvent e) { if (! e.isShiftDown() && ! e.isSynthesized()) { ! int index = getNode().getSelectionModel().getSelectedIndex(); setAnchor(index); } ! if (! getNode().isFocused() && getNode().isFocusTraversable()) { ! getNode().requestFocus(); } } private int getRowCount() { ! return getNode().getItems() == null ? 0 : getNode().getItems().size(); } private void clearSelection() { ! getNode().getSelectionModel().clearSelection(); } private void scrollPageUp() { int newSelectedIndex = -1; if (onScrollPageUp != null) { newSelectedIndex = onScrollPageUp.call(false); } if (newSelectedIndex == -1) return; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; sm.clearAndSelect(newSelectedIndex); } private void scrollPageDown() {
*** 397,432 **** if (onScrollPageDown != null) { newSelectedIndex = onScrollPageDown.call(false); } if (newSelectedIndex == -1) return; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; sm.clearAndSelect(newSelectedIndex); } private void focusFirstRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; fm.focus(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void focusLastRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; fm.focus(getRowCount() - 1); if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void focusPreviousRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; fm.focusPrevious(); if (! isShortcutDown || getAnchor() == -1) { --- 384,419 ---- if (onScrollPageDown != null) { newSelectedIndex = onScrollPageDown.call(false); } if (newSelectedIndex == -1) return; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; sm.clearAndSelect(newSelectedIndex); } private void focusFirstRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void focusLastRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(getRowCount() - 1); if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void focusPreviousRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; fm.focusPrevious(); if (! isShortcutDown || getAnchor() == -1) {
*** 435,448 **** if (onFocusPreviousRow != null) onFocusPreviousRow.run(); } private void focusNextRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; fm.focusNext(); if (! isShortcutDown || getAnchor() == -1) { --- 422,435 ---- if (onFocusPreviousRow != null) onFocusPreviousRow.run(); } private void focusNextRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; fm.focusNext(); if (! isShortcutDown || getAnchor() == -1) {
*** 453,480 **** } private void focusPageUp() { int newFocusIndex = onScrollPageUp.call(true); ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; fm.focus(newFocusIndex); } private void focusPageDown() { int newFocusIndex = onScrollPageDown.call(true); ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; fm.focus(newFocusIndex); } private void alsoSelectPreviousRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; if (isShiftDown && getAnchor() != -1) { int newRow = fm.getFocusedIndex() - 1; if (newRow < 0) return; --- 440,467 ---- } private void focusPageUp() { int newFocusIndex = onScrollPageUp.call(true); ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(newFocusIndex); } private void focusPageDown() { int newFocusIndex = onScrollPageDown.call(true); ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(newFocusIndex); } private void alsoSelectPreviousRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; if (isShiftDown && getAnchor() != -1) { int newRow = fm.getFocusedIndex() - 1; if (newRow < 0) return;
*** 500,513 **** onSelectPreviousRow.run(); } private void alsoSelectNextRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; if (isShiftDown && getAnchor() != -1) { int newRow = fm.getFocusedIndex() + 1; int anchor = getAnchor(); --- 487,500 ---- onSelectPreviousRow.run(); } private void alsoSelectNextRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; if (isShiftDown && getAnchor() != -1) { int newRow = fm.getFocusedIndex() + 1; int anchor = getAnchor();
*** 531,541 **** onSelectNextRow.run(); } private void clearSelectionOutsideRange(int start, int end) { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; int min = Math.min(start, end); int max = Math.max(start, end); --- 518,528 ---- onSelectNextRow.run(); } private void clearSelectionOutsideRange(int start, int end) { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; int min = Math.min(start, end); int max = Math.max(start, end);
*** 550,574 **** } selectionChanging = false; } private void selectPreviousRow() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); if (focusIndex <= 0) { return; } setAnchor(focusIndex - 1); ! getControl().getSelectionModel().clearAndSelect(focusIndex - 1); onSelectPreviousRow.run(); } private void selectNextRow() { ! ListView<T> listView = getControl(); FocusModel<T> fm = listView.getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); if (focusIndex == getRowCount() - 1) { --- 537,561 ---- } selectionChanging = false; } private void selectPreviousRow() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); if (focusIndex <= 0) { return; } setAnchor(focusIndex - 1); ! getNode().getSelectionModel().clearAndSelect(focusIndex - 1); onSelectPreviousRow.run(); } private void selectNextRow() { ! ListView<T> listView = getNode(); FocusModel<T> fm = listView.getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); if (focusIndex == getRowCount() - 1) {
*** 583,604 **** if (onSelectNextRow != null) onSelectNextRow.run(); } private void selectFirstRow() { if (getRowCount() > 0) { ! getControl().getSelectionModel().clearAndSelect(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } } private void selectLastRow() { ! getControl().getSelectionModel().clearAndSelect(getRowCount() - 1); if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void selectAllPageUp() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { leadIndex = getAnchor() == -1 ? leadIndex : getAnchor(); --- 570,591 ---- if (onSelectNextRow != null) onSelectNextRow.run(); } private void selectFirstRow() { if (getRowCount() > 0) { ! getNode().getSelectionModel().clearAndSelect(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } } private void selectLastRow() { ! getNode().getSelectionModel().clearAndSelect(getRowCount() - 1); if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void selectAllPageUp() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { leadIndex = getAnchor() == -1 ? leadIndex : getAnchor();
*** 608,618 **** int leadSelectedIndex = onScrollPageUp.call(false); // fix for RT-34407 int adjust = leadIndex < leadSelectedIndex ? 1 : -1; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; selectionChanging = true; if (sm.getSelectionMode() == SelectionMode.SINGLE) { sm.select(leadSelectedIndex); --- 595,605 ---- int leadSelectedIndex = onScrollPageUp.call(false); // fix for RT-34407 int adjust = leadIndex < leadSelectedIndex ? 1 : -1; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; selectionChanging = true; if (sm.getSelectionMode() == SelectionMode.SINGLE) { sm.select(leadSelectedIndex);
*** 622,632 **** } selectionChanging = false; } private void selectAllPageDown() { ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { leadIndex = getAnchor() == -1 ? leadIndex : getAnchor(); --- 609,619 ---- } selectionChanging = false; } private void selectAllPageDown() { ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { leadIndex = getAnchor() == -1 ? leadIndex : getAnchor();
*** 636,646 **** int leadSelectedIndex = onScrollPageDown.call(false); // fix for RT-34407 int adjust = leadIndex < leadSelectedIndex ? 1 : -1; ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; selectionChanging = true; if (sm.getSelectionMode() == SelectionMode.SINGLE) { sm.select(leadSelectedIndex); --- 623,633 ---- int leadSelectedIndex = onScrollPageDown.call(false); // fix for RT-34407 int adjust = leadIndex < leadSelectedIndex ? 1 : -1; ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; selectionChanging = true; if (sm.getSelectionMode() == SelectionMode.SINGLE) { sm.select(leadSelectedIndex);
*** 650,663 **** } selectionChanging = false; } private void selectAllToFirstRow() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { --- 637,650 ---- } selectionChanging = false; } private void selectAllToFirstRow() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) {
*** 676,693 **** if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void selectAllToLastRow() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { leadIndex = hasAnchor() ? getAnchor() : leadIndex; } sm.clearSelection(); --- 663,681 ---- if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void selectAllToLastRow() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); + System.out.println("isShiftDown: " + isShiftDown); if (isShiftDown) { leadIndex = hasAnchor() ? getAnchor() : leadIndex; } sm.clearSelection();
*** 699,716 **** if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void selectAll() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; sm.selectAll(); } private void selectAllToFocus(boolean setAnchorToFocusIndex) { // Fix for RT-31241 ! final ListView<T> listView = getControl(); if (listView.getEditingIndex() >= 0) return; MultipleSelectionModel<T> sm = listView.getSelectionModel(); if (sm == null) return; --- 687,704 ---- if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void selectAll() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; sm.selectAll(); } private void selectAllToFocus(boolean setAnchorToFocusIndex) { // Fix for RT-31241 ! final ListView<T> listView = getNode(); if (listView.getEditingIndex() >= 0) return; MultipleSelectionModel<T> sm = listView.getSelectionModel(); if (sm == null) return;
*** 726,754 **** sm.selectRange(startPos, endPos); setAnchor(setAnchorToFocusIndex ? focusIndex : anchor); } private void cancelEdit() { ! getControl().edit(-1); } private void activate() { ! int focusedIndex = getControl().getFocusModel().getFocusedIndex(); ! getControl().getSelectionModel().select(focusedIndex); setAnchor(focusedIndex); // edit this row also if (focusedIndex >= 0) { ! getControl().edit(focusedIndex); } } private void toggleFocusOwnerSelection() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int focusedIndex = fm.getFocusedIndex(); if (sm.isSelected(focusedIndex)) { --- 714,742 ---- sm.selectRange(startPos, endPos); setAnchor(setAnchorToFocusIndex ? focusIndex : anchor); } private void cancelEdit() { ! getNode().edit(-1); } private void activate() { ! int focusedIndex = getNode().getFocusModel().getFocusedIndex(); ! getNode().getSelectionModel().select(focusedIndex); setAnchor(focusedIndex); // edit this row also if (focusedIndex >= 0) { ! getNode().edit(focusedIndex); } } private void toggleFocusOwnerSelection() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int focusedIndex = fm.getFocusedIndex(); if (sm.isSelected(focusedIndex)) {
*** 764,782 **** /************************************************************************** * Discontinuous Selection * *************************************************************************/ private void discontinuousSelectPreviousRow() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; if (sm.getSelectionMode() != SelectionMode.MULTIPLE) { selectPreviousRow(); return; } ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); final int newFocusIndex = focusIndex - 1; if (newFocusIndex < 0) return; --- 752,770 ---- /************************************************************************** * Discontinuous Selection * *************************************************************************/ private void discontinuousSelectPreviousRow() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; if (sm.getSelectionMode() != SelectionMode.MULTIPLE) { selectPreviousRow(); return; } ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); final int newFocusIndex = focusIndex - 1; if (newFocusIndex < 0) return;
*** 791,809 **** if (onFocusPreviousRow != null) onFocusPreviousRow.run(); } private void discontinuousSelectNextRow() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; if (sm.getSelectionMode() != SelectionMode.MULTIPLE) { selectNextRow(); return; } ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); final int newFocusIndex = focusIndex + 1; if (newFocusIndex >= getRowCount()) return; --- 779,797 ---- if (onFocusPreviousRow != null) onFocusPreviousRow.run(); } private void discontinuousSelectNextRow() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; if (sm.getSelectionMode() != SelectionMode.MULTIPLE) { selectNextRow(); return; } ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); final int newFocusIndex = focusIndex + 1; if (newFocusIndex >= getRowCount()) return;
*** 818,888 **** if (onFocusNextRow != null) onFocusNextRow.run(); } private void discontinuousSelectPageUp() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int anchor = getAnchor(); int leadSelectedIndex = onScrollPageUp.call(false); sm.selectRange(anchor, leadSelectedIndex - 1); } private void discontinuousSelectPageDown() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int anchor = getAnchor(); int leadSelectedIndex = onScrollPageDown.call(false); sm.selectRange(anchor, leadSelectedIndex + 1); } private void discontinuousSelectAllToFirstRow() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int index = fm.getFocusedIndex(); sm.selectRange(0, index); fm.focus(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void discontinuousSelectAllToLastRow() { ! MultipleSelectionModel<T> sm = getControl().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getControl().getFocusModel(); if (fm == null) return; int index = fm.getFocusedIndex() + 1; sm.selectRange(index, getRowCount()); if (onMoveToLastCell != null) onMoveToLastCell.run(); } - - private static class ListViewKeyBinding extends OrientedKeyBinding { - - public ListViewKeyBinding(KeyCode code, String action) { - super(code, action); - } - - public ListViewKeyBinding(KeyCode code, EventType<KeyEvent> type, String action) { - super(code, type, action); - } - - @Override public boolean getVertical(Control control) { - return ((ListView<?>)control).getOrientation() == Orientation.VERTICAL; - } - } - } --- 806,860 ---- if (onFocusNextRow != null) onFocusNextRow.run(); } private void discontinuousSelectPageUp() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int anchor = getAnchor(); int leadSelectedIndex = onScrollPageUp.call(false); sm.selectRange(anchor, leadSelectedIndex - 1); } private void discontinuousSelectPageDown() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int anchor = getAnchor(); int leadSelectedIndex = onScrollPageDown.call(false); sm.selectRange(anchor, leadSelectedIndex + 1); } private void discontinuousSelectAllToFirstRow() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int index = fm.getFocusedIndex(); sm.selectRange(0, index); fm.focus(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void discontinuousSelectAllToLastRow() { ! MultipleSelectionModel<T> sm = getNode().getSelectionModel(); if (sm == null) return; ! FocusModel<T> fm = getNode().getFocusModel(); if (fm == null) return; int index = fm.getFocusedIndex() + 1; sm.selectRange(index, getRowCount()); if (onMoveToLastCell != null) onMoveToLastCell.run(); } }