--- old/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java 2015-09-03 14:48:02.838975300 -0700 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java 2015-09-03 14:48:02.263942400 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,6 @@ * 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; @@ -33,15 +32,14 @@ import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.collections.WeakListChangeListener; -import javafx.event.EventType; -import javafx.geometry.NodeOrientation; +import javafx.event.EventHandler; 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 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; @@ -49,180 +47,197 @@ 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 extends BehaviorBase> { + private final InputMap> listViewInputMap; - /************************************************************************** - * Setup KeyBindings * - *************************************************************************/ - protected static final List LIST_VIEW_BINDINGS = new ArrayList(); - - 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()); + /** + * 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 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(); } + }; - // 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 + /*************************************************************************** + * * + * Constructors * + * * + **************************************************************************/ - // 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"; - } - } - } - } + public ListViewBehavior(ListView 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> 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> 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> 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> 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. } - 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); + + /*************************************************************************** + * * + * Implementation of BehaviorBase API * + * * + **************************************************************************/ + + @Override public InputMap> getInputMap() { + return listViewInputMap; } + @Override public void dispose() { + ListView control = getNode(); + + ListCellBehavior.removeAnchor(control); + if (tlFocus != null) tlFocus.dispose(); + super.dispose(); + + control.removeEventHandler(KeyEvent.ANY, keyEventListener); + } + + + + + /************************************************************************** * State and Functions * *************************************************************************/ - + private boolean isShiftDown = false; private boolean isShortcutDown = false; - + private Callback onScrollPageUp; private Callback onScrollPageDown; private Runnable onFocusPreviousRow; @@ -240,20 +255,20 @@ public void setOnSelectNextRow(Runnable r) { onSelectNextRow = r; } public void setOnMoveToFirstCell(Runnable r) { onMoveToFirstCell = r; } public void setOnMoveToLastCell(Runnable r) { onMoveToLastCell = r; } - + private boolean selectionChanging = false; - + private final ListChangeListener selectedIndicesListener = c -> { while (c.next()) { if (c.wasReplaced()) { - if (ListCellBehavior.hasDefaultAnchor(getControl())) { - ListCellBehavior.removeAnchor(getControl()); + if (ListCellBehavior.hasDefaultAnchor(getNode())) { + ListCellBehavior.removeAnchor(getNode()); } } final int shift = c.wasPermutated() ? c.getTo() - c.getFrom() : 0; - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); // there are no selected items, so lets clear out the anchor if (! selectionChanging) { @@ -272,7 +287,7 @@ } } }; - + private final ListChangeListener itemsListListener = c -> { while (c.next()) { if (c.wasAdded() && c.getFrom() <= getAnchor()) { @@ -282,25 +297,25 @@ } } }; - + private final ChangeListener> itemsListener = new ChangeListener>() { @Override public void changed( ObservableValue> observable, ObservableList oldValue, ObservableList newValue) { if (oldValue != null) { - oldValue.removeListener(weakItemsListListener); - } if (newValue != null) { - newValue.addListener(weakItemsListListener); - } + oldValue.removeListener(weakItemsListListener); + } if (newValue != null) { + newValue.addListener(weakItemsListListener); + } } }; - + private final ChangeListener> selectionModelListener = new ChangeListener>() { @Override public void changed( - ObservableValue> observable, - MultipleSelectionModel oldValue, - MultipleSelectionModel newValue) { + ObservableValue> observable, + MultipleSelectionModel oldValue, + MultipleSelectionModel newValue) { if (oldValue != null) { oldValue.getSelectedIndices().removeListener(weakSelectedIndicesListener); } @@ -309,75 +324,47 @@ } } }; - - private final WeakChangeListener> weakItemsListener = + + private final WeakChangeListener> weakItemsListener = new WeakChangeListener>(itemsListener); - private final WeakListChangeListener weakSelectedIndicesListener = + private final WeakListChangeListener weakSelectedIndicesListener = new WeakListChangeListener(selectedIndicesListener); - private final WeakListChangeListener weakItemsListListener = + private final WeakListChangeListener weakItemsListListener = new WeakListChangeListener<>(itemsListListener); - private final WeakChangeListener> weakSelectionModelListener = + private final WeakChangeListener> weakSelectionModelListener = new WeakChangeListener>(selectionModelListener); - - private TwoLevelFocusListBehavior tlFocus; - - public ListViewBehavior(ListView 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 TwoLevelFocusListBehavior tlFocus; private void setAnchor(int anchor) { - ListCellBehavior.setAnchor(getControl(), anchor < 0 ? null : anchor, false); + ListCellBehavior.setAnchor(getNode(), anchor < 0 ? null : anchor, false); } - + private int getAnchor() { - return ListCellBehavior.getAnchor(getControl(), getControl().getFocusModel().getFocusedIndex()); + return ListCellBehavior.getAnchor(getNode(), getNode().getFocusModel().getFocusedIndex()); } - + private boolean hasAnchor() { - return ListCellBehavior.hasNonDefaultAnchor(getControl()); + return ListCellBehavior.hasNonDefaultAnchor(getNode()); } - @Override public void mousePressed(MouseEvent e) { - super.mousePressed(e); - + private void mousePressed(MouseEvent e) { if (! e.isShiftDown() && ! e.isSynthesized()) { - int index = getControl().getSelectionModel().getSelectedIndex(); + int index = getNode().getSelectionModel().getSelectedIndex(); setAnchor(index); } - - if (! getControl().isFocused() && getControl().isFocusTraversable()) { - getControl().requestFocus(); + + if (! getNode().isFocused() && getNode().isFocusTraversable()) { + getNode().requestFocus(); } } - + private int getRowCount() { - return getControl().getItems() == null ? 0 : getControl().getItems().size(); + return getNode().getItems() == null ? 0 : getNode().getItems().size(); } private void clearSelection() { - getControl().getSelectionModel().clearSelection(); + getNode().getSelectionModel().clearSelection(); } private void scrollPageUp() { @@ -386,8 +373,8 @@ newSelectedIndex = onScrollPageUp.call(false); } if (newSelectedIndex == -1) return; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; sm.clearAndSelect(newSelectedIndex); } @@ -398,89 +385,89 @@ newSelectedIndex = onScrollPageDown.call(false); } if (newSelectedIndex == -1) return; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; sm.clearAndSelect(newSelectedIndex); } - + private void focusFirstRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(0); - + if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } - + private void focusLastRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(getRowCount() - 1); - + if (onMoveToLastCell != null) onMoveToLastCell.run(); } private void focusPreviousRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - + fm.focusPrevious(); - + if (! isShortcutDown || getAnchor() == -1) { setAnchor(fm.getFocusedIndex()); } - + if (onFocusPreviousRow != null) onFocusPreviousRow.run(); } private void focusNextRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - + fm.focusNext(); - + if (! isShortcutDown || getAnchor() == -1) { setAnchor(fm.getFocusedIndex()); } - + if (onFocusNextRow != null) onFocusNextRow.run(); } - + private void focusPageUp() { int newFocusIndex = onScrollPageUp.call(true); - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(newFocusIndex); } - + private void focusPageDown() { int newFocusIndex = onScrollPageDown.call(true); - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; fm.focus(newFocusIndex); } private void alsoSelectPreviousRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - + if (isShiftDown && getAnchor() != -1) { int newRow = fm.getFocusedIndex() - 1; if (newRow < 0) return; int anchor = getAnchor(); - + if (! hasAnchor()) { setAnchor(fm.getFocusedIndex()); } @@ -497,24 +484,24 @@ } else { sm.selectPrevious(); } - + onSelectPreviousRow.run(); } private void alsoSelectNextRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - + if (isShiftDown && getAnchor() != -1) { int newRow = fm.getFocusedIndex() + 1; int anchor = getAnchor(); - + if (! hasAnchor()) { setAnchor(fm.getFocusedIndex()); - } + } if (sm.getSelectedIndices().size() > 1) { clearSelectionOutsideRange(anchor, newRow); @@ -528,19 +515,19 @@ } else { sm.selectNext(); } - + onSelectNextRow.run(); } - + private void clearSelectionOutsideRange(int start, int end) { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - + int min = Math.min(start, end); int max = Math.max(start, end); - + List indices = new ArrayList<>(sm.getSelectedIndices()); - + selectionChanging = true; for (int i = 0; i < indices.size(); i++) { int index = indices.get(i); @@ -552,7 +539,7 @@ } private void selectPreviousRow() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); @@ -561,23 +548,23 @@ } setAnchor(focusIndex - 1); - getControl().getSelectionModel().clearAndSelect(focusIndex - 1); + getNode().getSelectionModel().clearAndSelect(focusIndex - 1); onSelectPreviousRow.run(); } private void selectNextRow() { - ListView listView = getControl(); + ListView listView = getNode(); FocusModel fm = listView.getFocusModel(); if (fm == null) return; - + int focusIndex = fm.getFocusedIndex(); if (focusIndex == getRowCount() - 1) { return; } - + MultipleSelectionModel sm = listView.getSelectionModel(); if (sm == null) return; - + setAnchor(focusIndex + 1); sm.clearAndSelect(focusIndex + 1); if (onSelectNextRow != null) onSelectNextRow.run(); @@ -585,18 +572,18 @@ private void selectFirstRow() { if (getRowCount() > 0) { - getControl().getSelectionModel().clearAndSelect(0); + getNode().getSelectionModel().clearAndSelect(0); if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } } private void selectLastRow() { - getControl().getSelectionModel().clearAndSelect(getRowCount() - 1); + getNode().getSelectionModel().clearAndSelect(getRowCount() - 1); if (onMoveToLastCell != null) onMoveToLastCell.run(); } - + private void selectAllPageUp() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); @@ -604,15 +591,15 @@ leadIndex = getAnchor() == -1 ? leadIndex : getAnchor(); setAnchor(leadIndex); } - + int leadSelectedIndex = onScrollPageUp.call(false); // fix for RT-34407 int adjust = leadIndex < leadSelectedIndex ? 1 : -1; - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - + selectionChanging = true; if (sm.getSelectionMode() == SelectionMode.SINGLE) { sm.select(leadSelectedIndex); @@ -622,23 +609,23 @@ } selectionChanging = false; } - + private void selectAllPageDown() { - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - + int leadIndex = fm.getFocusedIndex(); if (isShiftDown) { leadIndex = getAnchor() == -1 ? leadIndex : getAnchor(); setAnchor(leadIndex); } - + int leadSelectedIndex = onScrollPageDown.call(false); // fix for RT-34407 int adjust = leadIndex < leadSelectedIndex ? 1 : -1; - - MultipleSelectionModel sm = getControl().getSelectionModel(); + + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; selectionChanging = true; @@ -652,14 +639,14 @@ } private void selectAllToFirstRow() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - + int leadIndex = fm.getFocusedIndex(); - + if (isShiftDown) { leadIndex = hasAnchor() ? getAnchor() : leadIndex; } @@ -673,26 +660,27 @@ if (isShiftDown) { setAnchor(leadIndex); } - + if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } private void selectAllToLastRow() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int leadIndex = fm.getFocusedIndex(); + System.out.println("isShiftDown: " + isShiftDown); if (isShiftDown) { leadIndex = hasAnchor() ? getAnchor() : leadIndex; } - + sm.clearSelection(); sm.selectRange(leadIndex, getRowCount()); - + if (isShiftDown) { setAnchor(leadIndex); } @@ -701,14 +689,14 @@ } private void selectAll() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; sm.selectAll(); } - + private void selectAllToFocus(boolean setAnchorToFocusIndex) { // Fix for RT-31241 - final ListView listView = getControl(); + final ListView listView = getNode(); if (listView.getEditingIndex() >= 0) return; MultipleSelectionModel sm = listView.getSelectionModel(); @@ -719,64 +707,64 @@ int focusIndex = fm.getFocusedIndex(); int anchor = getAnchor(); - + sm.clearSelection(); int startPos = anchor; int endPos = anchor > focusIndex ? focusIndex - 1 : focusIndex + 1; sm.selectRange(startPos, endPos); setAnchor(setAnchorToFocusIndex ? focusIndex : anchor); } - + private void cancelEdit() { - getControl().edit(-1); + getNode().edit(-1); } private void activate() { - int focusedIndex = getControl().getFocusModel().getFocusedIndex(); - getControl().getSelectionModel().select(focusedIndex); + int focusedIndex = getNode().getFocusModel().getFocusedIndex(); + getNode().getSelectionModel().select(focusedIndex); setAnchor(focusedIndex); // edit this row also if (focusedIndex >= 0) { - getControl().edit(focusedIndex); + getNode().edit(focusedIndex); } } - + private void toggleFocusOwnerSelection() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - FocusModel fm = getControl().getFocusModel(); + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int focusedIndex = fm.getFocusedIndex(); - + if (sm.isSelected(focusedIndex)) { sm.clearSelection(focusedIndex); fm.focus(focusedIndex); } else { sm.select(focusedIndex); } - + setAnchor(focusedIndex); } - + /************************************************************************** * Discontinuous Selection * *************************************************************************/ - + private void discontinuousSelectPreviousRow() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; if (sm.getSelectionMode() != SelectionMode.MULTIPLE) { selectPreviousRow(); return; } - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - + int focusIndex = fm.getFocusedIndex(); final int newFocusIndex = focusIndex - 1; if (newFocusIndex < 0) return; @@ -791,17 +779,17 @@ if (onFocusPreviousRow != null) onFocusPreviousRow.run(); } - + private void discontinuousSelectNextRow() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; if (sm.getSelectionMode() != SelectionMode.MULTIPLE) { selectNextRow(); return; } - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int focusIndex = fm.getFocusedIndex(); @@ -818,36 +806,36 @@ if (onFocusNextRow != null) onFocusNextRow.run(); } - + private void discontinuousSelectPageUp() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int anchor = getAnchor(); int leadSelectedIndex = onScrollPageUp.call(false); sm.selectRange(anchor, leadSelectedIndex - 1); } - + private void discontinuousSelectPageDown() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; - + int anchor = getAnchor(); int leadSelectedIndex = onScrollPageDown.call(false); sm.selectRange(anchor, leadSelectedIndex + 1); } - + private void discontinuousSelectAllToFirstRow() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int index = fm.getFocusedIndex(); @@ -856,12 +844,12 @@ if (onMoveToFirstCell != null) onMoveToFirstCell.run(); } - + private void discontinuousSelectAllToLastRow() { - MultipleSelectionModel sm = getControl().getSelectionModel(); + MultipleSelectionModel sm = getNode().getSelectionModel(); if (sm == null) return; - - FocusModel fm = getControl().getFocusModel(); + + FocusModel fm = getNode().getFocusModel(); if (fm == null) return; int index = fm.getFocusedIndex() + 1; @@ -869,20 +857,4 @@ 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 type, String action) { - super(code, type, action); - } - - @Override public boolean getVertical(Control control) { - return ((ListView)control).getOrientation() == Orientation.VERTICAL; - } - } - }