Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sun.javafx.scene.control.behavior.TableViewBehaviorBase Maven / Gradle / Ivy
/*
* Copyright (c) 2011, 2013, 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
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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 static javafx.scene.input.KeyCode.A;
import static javafx.scene.input.KeyCode.BACK_SLASH;
import static javafx.scene.input.KeyCode.DOWN;
import static javafx.scene.input.KeyCode.END;
import static javafx.scene.input.KeyCode.ENTER;
import static javafx.scene.input.KeyCode.ESCAPE;
import static javafx.scene.input.KeyCode.F2;
import static javafx.scene.input.KeyCode.HOME;
import static javafx.scene.input.KeyCode.KP_DOWN;
import static javafx.scene.input.KeyCode.KP_LEFT;
import static javafx.scene.input.KeyCode.KP_RIGHT;
import static javafx.scene.input.KeyCode.KP_UP;
import static javafx.scene.input.KeyCode.LEFT;
import static javafx.scene.input.KeyCode.PAGE_DOWN;
import static javafx.scene.input.KeyCode.PAGE_UP;
import static javafx.scene.input.KeyCode.RIGHT;
import static javafx.scene.input.KeyCode.SPACE;
import static javafx.scene.input.KeyCode.TAB;
import static javafx.scene.input.KeyCode.UP;
import java.util.ArrayList;
import java.util.List;
import javafx.collections.ObservableList;
import javafx.scene.control.SelectionMode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import com.sun.javafx.PlatformUtil;
import javafx.collections.ListChangeListener;
import javafx.collections.WeakListChangeListener;
import javafx.scene.control.Control;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.control.TableColumnBase;
import javafx.scene.control.TableFocusModel;
import javafx.scene.control.TablePositionBase;
import javafx.scene.control.TableSelectionModel;
import javafx.util.Callback;
public abstract class TableViewBehaviorBase> extends BehaviorBase {
/**************************************************************************
* *
* Setup key bindings *
* *
*************************************************************************/
protected static final List TABLE_VIEW_BINDINGS = new ArrayList();
static {
TABLE_VIEW_BINDINGS.add(new KeyBinding(TAB, "TraverseNext"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(TAB, "TraversePrevious").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(HOME, "SelectFirstRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(END, "SelectLastRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "ScrollUp"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "ScrollDown"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(LEFT, "SelectLeftCell"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_LEFT, "SelectLeftCell"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(RIGHT, "SelectRightCell"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_RIGHT, "SelectRightCell"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(UP, "SelectPreviousRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_UP, "SelectPreviousRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(DOWN, "SelectNextRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_DOWN, "SelectNextRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(LEFT, "TraverseLeft"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_LEFT, "TraverseLeft"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(RIGHT, "SelectNextRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_RIGHT, "SelectNextRow"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(UP, "TraverseUp"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_UP, "TraverseUp"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(DOWN, "TraverseDown"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_DOWN, "TraverseDown"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(HOME, "SelectAllToFirstRow").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(END, "SelectAllToLastRow").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "SelectAllPageUp").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "SelectAllPageDown").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(UP, "AlsoSelectPrevious").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_UP, "AlsoSelectPrevious").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(DOWN, "AlsoSelectNext").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_DOWN, "AlsoSelectNext").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(SPACE, "SelectAllToFocus").shift());
// TABLE_VIEW_BINDINGS.add(new KeyBinding(UP, "AlsoSelectPreviousCell").shift());
// TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_UP, "AlsoSelectPreviousCell").shift());
// TABLE_VIEW_BINDINGS.add(new KeyBinding(DOWN, "AlsoSelectNextCell").shift());
// TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_DOWN, "AlsoSelectNextCell").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(LEFT, "AlsoSelectLeftCell").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_LEFT, "AlsoSelectLeftCell").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(RIGHT, "AlsoSelectRightCell").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_RIGHT, "AlsoSelectRightCell").shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(UP, "FocusPreviousRow").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(DOWN, "FocusNextRow").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(RIGHT, "FocusRightCell").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_RIGHT, "FocusRightCell").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(LEFT, "FocusLeftCell").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(KP_LEFT, "FocusLeftCell").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(A, "SelectAll").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(HOME, "FocusFirstRow").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(END, "FocusLastRow").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "FocusPageUp").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "FocusPageDown").shortcut());
TABLE_VIEW_BINDINGS.add(new KeyBinding(UP, "DiscontinuousSelectPreviousRow").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(DOWN, "DiscontinuousSelectNextRow").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(LEFT, "DiscontinuousSelectPreviousColumn").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(RIGHT, "DiscontinuousSelectNextColumn").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_UP, "DiscontinuousSelectPageUp").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(PAGE_DOWN, "DiscontinuousSelectPageDown").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(HOME, "DiscontinuousSelectAllToFirstRow").shortcut().shift());
TABLE_VIEW_BINDINGS.add(new KeyBinding(END, "DiscontinuousSelectAllToLastRow").shortcut().shift());
if (PlatformUtil.isMac()) {
TABLE_VIEW_BINDINGS.add(new KeyBinding(SPACE, "toggleFocusOwnerSelection").ctrl().shortcut());
} else {
TABLE_VIEW_BINDINGS.add(new KeyBinding(SPACE, "toggleFocusOwnerSelection").ctrl());
}
TABLE_VIEW_BINDINGS.add(new KeyBinding(ENTER, "Activate"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(SPACE, "Activate"));
TABLE_VIEW_BINDINGS.add(new KeyBinding(F2, "Activate"));
// TABLE_VIEW_BINDINGS.add(new KeyBinding(SPACE, "Activate").ctrl());
TABLE_VIEW_BINDINGS.add(new KeyBinding(ESCAPE, "CancelEdit"));
}
@Override protected void callAction(String name) {
if ("SelectPreviousRow".equals(name)) selectPreviousRow();
else if ("SelectNextRow".equals(name)) selectNextRow();
else if ("SelectLeftCell".equals(name)) selectLeftCell();
else if ("SelectRightCell".equals(name)) selectRightCell();
else if ("SelectFirstRow".equals(name)) selectFirstRow();
else if ("SelectLastRow".equals(name)) selectLastRow();
else if ("SelectAll".equals(name)) selectAll();
else if ("SelectAllPageUp".equals(name)) selectAllPageUp();
else if ("SelectAllPageDown".equals(name)) selectAllPageDown();
else if ("SelectAllToFirstRow".equals(name)) selectAllToFirstRow();
else if ("SelectAllToLastRow".equals(name)) selectAllToLastRow();
else if ("AlsoSelectNext".equals(name)) alsoSelectNext();
else if ("AlsoSelectPrevious".equals(name)) alsoSelectPrevious();
else if ("AlsoSelectLeftCell".equals(name)) alsoSelectLeftCell();
else if ("AlsoSelectRightCell".equals(name)) alsoSelectRightCell();
else if ("ClearSelection".equals(name)) clearSelection();
else if ("ScrollUp".equals(name)) scrollUp();
else if ("ScrollDown".equals(name)) scrollDown();
else if ("FocusPreviousRow".equals(name)) focusPreviousRow();
else if ("FocusNextRow".equals(name)) focusNextRow();
else if ("FocusLeftCell".equals(name)) focusLeftCell();
else if ("FocusRightCell".equals(name)) focusRightCell();
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();
else if ("FocusPageUp".equals(name)) focusPageUp();
else if ("FocusPageDown".equals(name)) focusPageDown();
else if ("DiscontinuousSelectNextRow".equals(name)) discontinuousSelectNextRow();
else if ("DiscontinuousSelectPreviousRow".equals(name)) discontinuousSelectPreviousRow();
else if ("DiscontinuousSelectNextColumn".equals(name)) discontinuousSelectNextColumn();
else if ("DiscontinuousSelectPreviousColumn".equals(name)) discontinuousSelectPreviousColumn();
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 List createKeyBindings() {
return TABLE_VIEW_BINDINGS;
}
@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);
}
/**************************************************************************
* *
* Internal fields *
* *
*************************************************************************/
protected boolean isShortcutDown = false;
protected boolean isShiftDown = false;
protected boolean selectionPathDeviated = false;
protected boolean selectionChanging = false;
protected final ListChangeListener selectedCellsListener = new ListChangeListener() {
@Override public void onChanged(ListChangeListener.Change c) {
while (c.next()) {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TablePositionBase anchor = getAnchor();
boolean cellSelectionEnabled = sm.isCellSelectionEnabled();
int addedSize = c.getAddedSize();
List addedSubList = (List) c.getAddedSubList();
// newest selection
if (addedSize > 0 && ! hasAnchor()) {
TablePositionBase tp = addedSubList.get(addedSize - 1);
setAnchor(tp);
}
if (!hasAnchor() && cellSelectionEnabled && ! selectionPathDeviated) {
// check if the selection is on the same row or column,
// otherwise set selectionPathDeviated to true
for (int i = 0; i < addedSize; i++) {
TablePositionBase tp = addedSubList.get(i);
if (anchor.getRow() != -1 && tp.getRow() != anchor.getRow() && tp.getColumn() != anchor.getColumn()) {
selectionPathDeviated = true;
break;
}
}
}
}
}
};
protected final WeakListChangeListener weakSelectedCellsListener =
new WeakListChangeListener(selectedCellsListener);
/**************************************************************************
* *
* Constructors *
* *
*************************************************************************/
public TableViewBehaviorBase(C control) {
super(control);
}
/**************************************************************************
* *
* Abstract API *
* *
*************************************************************************/
/**
* Call to record the current anchor position
*/
protected void setAnchor(TablePositionBase tp) {
TableCellBehaviorBase.setAnchor(getControl(), tp);
selectionPathDeviated = false;
}
/**
* Will return the current anchor position.
*/
protected TablePositionBase getAnchor() {
return TableCellBehaviorBase.getAnchor(getControl(), getFocusedCell());
}
/**
* Returns true if there is an anchor set, and false if not anchor is set.
*/
protected boolean hasAnchor() {
return TableCellBehaviorBase.hasAnchor(getControl());
}
/**
* Returns the number of items in the underlying data model.
*/
protected abstract int getItemCount();
/**
* Returns the focus model for the underlying UI control (which must extend
* from TableFocusModel).
*/
protected abstract TableFocusModel getFocusModel();
/**
* Returns the selection model for the underlying UI control (which must extend
* from TableSelectionModel).
*/
protected abstract TableSelectionModel getSelectionModel();
/**
* Returns an observable list of all cells that are currently selected in
* the selection model of the underlying control.
*/
protected abstract ObservableList*/> getSelectedCells();
/**
* Returns the focused cell from the focus model of the underlying control.
*/
protected abstract TablePositionBase getFocusedCell();
/**
* Returns the position of the given table column in the visible leaf columns
* list of the underlying control.
*/
protected abstract int getVisibleLeafIndex(TableColumnBase tc);
/**
* Returns the column at the given index in the visible leaf columns list of
* the underlying control.
*/
protected abstract TableColumnBase getVisibleLeafColumn(int index);
/**
* Begins the edit process in the underlying control for the given row/column
* position.
*/
protected abstract void editCell(int row, TableColumnBase tc);
/**
* Returns an observable list of all visible leaf columns in the underlying
* control.
*/
protected abstract ObservableList getVisibleLeafColumns();
/**
* Creates a TablePositionBase instance using the underlying controls
* concrete implementation for the given row/column intersection.
*/
protected abstract TablePositionBase getTablePosition(int row, TableColumnBase tc);
/**************************************************************************
* *
* Public API *
* *
*************************************************************************/
/*
* Anchor is created upon
* - initial selection of an item (by mouse or keyboard)
*
* Anchor is changed when you
* - move the selection to an item by UP/DOWN/LEFT/RIGHT arrow keys
* - select an item by mouse click
* - add/remove an item to/from an existing selection by CTRL+SPACE shortcut
* - add/remove an items to/from an existing selection by CTRL+mouse click
*
* Note that if an item is removed from an existing selection by
* CTRL+SPACE/CTRL+mouse click, anchor still remains on this item even
* though it is not selected.
*
* Anchor is NOT changed when you
* - create linear multi-selection by SHIFT+UP/DOWN/LEFT/RIGHT arrow keys
* - create linear multi-selection by SHIFT+SPACE arrow keys
* - create linear multi-selection by SHIFT+mouse click
*
* In case there is a discontinuous selection in the list, creating linear
* multi-selection between anchor and focused item will cancel the
* discontinuous selection. It means that only items that are located between
* anchor and focused item will be selected.
*/
protected void setAnchor(int row, TableColumnBase col) {
setAnchor(row == -1 && col == null ? null : getTablePosition(row, col));
}
private Callback onScrollPageUp;
public void setOnScrollPageUp(Callback c) { onScrollPageUp = c; }
private Callback onScrollPageDown;
public void setOnScrollPageDown(Callback c) { onScrollPageDown = c; }
private Runnable onFocusPreviousRow;
public void setOnFocusPreviousRow(Runnable r) { onFocusPreviousRow = r; }
private Runnable onFocusNextRow;
public void setOnFocusNextRow(Runnable r) { onFocusNextRow = r; }
private Runnable onSelectPreviousRow;
public void setOnSelectPreviousRow(Runnable r) { onSelectPreviousRow = r; }
private Runnable onSelectNextRow;
public void setOnSelectNextRow(Runnable r) { onSelectNextRow = r; }
private Runnable onMoveToFirstCell;
public void setOnMoveToFirstCell(Runnable r) { onMoveToFirstCell = r; }
private Runnable onMoveToLastCell;
public void setOnMoveToLastCell(Runnable r) { onMoveToLastCell = r; }
private Runnable onSelectRightCell;
public void setOnSelectRightCell(Runnable r) { onSelectRightCell = r; }
private Runnable onSelectLeftCell;
public void setOnSelectLeftCell(Runnable r) { onSelectLeftCell = r; }
@Override public void mousePressed(MouseEvent e) {
super.mousePressed(e);
// // FIXME can't assume (yet) cells.get(0) is necessarily the lead cell
// ObservableList cells = getSelectedCells();
// setAnchor(cells.isEmpty() ? null : cells.get(0));
if (!getControl().isFocused() && getControl().isFocusTraversable()) {
getControl().requestFocus();
}
}
/**************************************************************************
* *
* Private implementation *
* *
*************************************************************************/
protected void scrollUp() {
TableSelectionModel sm = getSelectionModel();
if (sm == null || getSelectedCells().isEmpty()) return;
TablePositionBase selectedCell = getSelectedCells().get(0);
int newSelectedIndex = -1;
if (onScrollPageUp != null) {
newSelectedIndex = onScrollPageUp.call(null);
}
if (newSelectedIndex == -1) return;
sm.clearAndSelect(newSelectedIndex, selectedCell.getTableColumn());
}
protected void scrollDown() {
TableSelectionModel sm = getSelectionModel();
if (sm == null || getSelectedCells().isEmpty()) return;
TablePositionBase selectedCell = getSelectedCells().get(0);
int newSelectedIndex = -1;
if (onScrollPageDown != null) {
newSelectedIndex = onScrollPageDown.call(null);
}
if (newSelectedIndex == -1) return;
sm.clearAndSelect(newSelectedIndex, selectedCell.getTableColumn());
}
protected void focusFirstRow() {
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TableColumnBase tc = getFocusedCell() == null ? null : getFocusedCell().getTableColumn();
fm.focus(0, tc);
if (onMoveToFirstCell != null) onMoveToFirstCell.run();
}
protected void focusLastRow() {
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TableColumnBase tc = getFocusedCell() == null ? null : getFocusedCell().getTableColumn();
fm.focus(getItemCount() - 1, tc);
if (onMoveToLastCell != null) onMoveToLastCell.run();
}
protected void focusPreviousRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
if (sm.isCellSelectionEnabled()) {
fm.focusAboveCell();
} else {
fm.focusPrevious();
}
if (! isShortcutDown || getAnchor() == null) {
setAnchor(fm.getFocusedIndex(), null);
}
if (onFocusPreviousRow != null) onFocusPreviousRow.run();
}
protected void focusNextRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
if (sm.isCellSelectionEnabled()) {
fm.focusBelowCell();
} else {
fm.focusNext();
}
if (! isShortcutDown || getAnchor() == null) {
setAnchor(fm.getFocusedIndex(), null);
}
if (onFocusNextRow != null) onFocusNextRow.run();
}
protected void focusLeftCell() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
fm.focusLeftCell();
if (onFocusPreviousRow != null) onFocusPreviousRow.run();
}
protected void focusRightCell() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
fm.focusRightCell();
if (onFocusNextRow != null) onFocusNextRow.run();
}
protected void focusPageUp() {
int newFocusIndex = onScrollPageUp.call(null);
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TableColumnBase tc = getFocusedCell() == null ? null : getFocusedCell().getTableColumn();
fm.focus(newFocusIndex, tc);
}
protected void focusPageDown() {
int newFocusIndex = onScrollPageDown.call(null);
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TableColumnBase tc = getFocusedCell() == null ? null : getFocusedCell().getTableColumn();
fm.focus(newFocusIndex, tc);
}
protected void clearSelection() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
sm.clearSelection();
}
protected void clearSelectionOutsideRange(int start, int end) {
TableSelectionModel sm = 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);
if (index < min || index >= max) {
sm.clearSelection(index);
}
}
selectionChanging = false;
}
protected void alsoSelectPrevious() {
TableSelectionModel sm = getSelectionModel();
if (sm == null || sm.getSelectionMode() == SelectionMode.SINGLE) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
if (sm.isCellSelectionEnabled()) {
updateCellVerticalSelection(-1, new Runnable() {
@Override public void run() {
getSelectionModel().selectAboveCell();
}
});
} else {
if (isShiftDown && hasAnchor()) {
updateRowSelection(-1);
} else {
sm.selectPrevious();
}
}
onSelectPreviousRow.run();
}
protected void alsoSelectNext() {
TableSelectionModel sm = getSelectionModel();
if (sm == null || sm.getSelectionMode() == SelectionMode.SINGLE) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
if (sm.isCellSelectionEnabled()) {
updateCellVerticalSelection(1, new Runnable() {
@Override public void run() {
getSelectionModel().selectBelowCell();
}
});
} else {
if (isShiftDown && hasAnchor()) {
updateRowSelection(1);
} else {
sm.selectNext();
}
}
onSelectNextRow.run();
}
protected void alsoSelectLeftCell() {
updateCellHorizontalSelection(-1, new Runnable() {
@Override public void run() {
getSelectionModel().selectLeftCell();
}
});
}
protected void alsoSelectRightCell() {
updateCellHorizontalSelection(1, new Runnable() {
@Override public void run() {
getSelectionModel().selectRightCell();
}
});
}
protected void updateRowSelection(int delta) {
TableSelectionModel sm = getSelectionModel();
if (sm == null || sm.getSelectionMode() == SelectionMode.SINGLE) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int newRow = fm.getFocusedIndex() + delta;
TablePositionBase anchor = getAnchor();
if (! hasAnchor()) {
setAnchor(getFocusedCell());
}
clearSelectionOutsideRange(anchor.getRow(), newRow);
if (anchor.getRow() > newRow) {
sm.selectRange(anchor.getRow(), newRow - 1);
} else {
sm.selectRange(anchor.getRow(), newRow + 1);
}
}
protected void updateCellVerticalSelection(int delta, Runnable defaultAction) {
TableSelectionModel sm = getSelectionModel();
if (sm == null || sm.getSelectionMode() == SelectionMode.SINGLE) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
if (isShiftDown && sm.isSelected(focusedCell.getRow() + delta, focusedCell.getTableColumn())) {
int newFocusOwner = focusedCell.getRow() + delta;
sm.clearSelection(selectionPathDeviated ? newFocusOwner : focusedCell.getRow(), focusedCell.getTableColumn());
fm.focus(newFocusOwner, focusedCell.getTableColumn());
} else if (isShiftDown && getAnchor() != null && ! selectionPathDeviated) {
int newRow = fm.getFocusedIndex() + delta;
// we don't let the newRow go outside the bounds of the data
newRow = Math.max(Math.min(getItemCount() - 1, newRow), 0);
int start = Math.min(getAnchor().getRow(), newRow);
int end = Math.max(getAnchor().getRow(), newRow);
for (int _row = start; _row <= end; _row++) {
sm.select(_row, focusedCell.getTableColumn());
}
fm.focus(newRow, focusedCell.getTableColumn());
} else {
final int focusIndex = fm.getFocusedIndex();
if (! sm.isSelected(focusIndex, focusedCell.getTableColumn())) {
sm.select(focusIndex, focusedCell.getTableColumn());
}
defaultAction.run();
}
}
protected void updateCellHorizontalSelection(int delta, Runnable defaultAction) {
TableSelectionModel sm = getSelectionModel();
if (sm == null || sm.getSelectionMode() == SelectionMode.SINGLE) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
if (focusedCell == null || focusedCell.getTableColumn() == null) return;
TableColumnBase adjacentColumn = getColumn(focusedCell.getTableColumn(), delta);
if (adjacentColumn == null) return;
if (isShiftDown && getAnchor() != null &&
sm.isSelected(focusedCell.getRow(), adjacentColumn) &&
! (focusedCell.getRow() == getAnchor().getRow() && focusedCell.getTableColumn().equals(adjacentColumn))) {
sm.clearSelection(focusedCell.getRow(),selectionPathDeviated ? adjacentColumn : focusedCell.getTableColumn());
fm.focus(focusedCell.getRow(), adjacentColumn);
} else if (isShiftDown && getAnchor() != null && ! selectionPathDeviated) {
final int columnPos = getVisibleLeafIndex(focusedCell.getTableColumn());
final int newColumn = columnPos + delta;
int start = Math.min(columnPos, newColumn);
int end = Math.max(columnPos, newColumn);
for (int _col = start; _col <= end; _col++) {
sm.select(focusedCell.getRow(), getColumn(_col));
}
fm.focus(focusedCell.getRow(), getColumn(newColumn));
} else {
defaultAction.run();
}
}
protected TableColumnBase getColumn(int index) {
return getVisibleLeafColumn(index);
}
protected TableColumnBase getColumn(TableColumnBase tc, int delta) {
return getVisibleLeafColumn(getVisibleLeafIndex(tc) + delta);
}
protected void selectFirstRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
ObservableList selection = getSelectedCells();
TableColumnBase selectedColumn = selection.size() == 0 ? null : selection.get(0).getTableColumn();
sm.clearAndSelect(0, selectedColumn);
if (onMoveToFirstCell != null) onMoveToFirstCell.run();
}
protected void selectLastRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
ObservableList selection = getSelectedCells();
TableColumnBase selectedColumn = selection.size() == 0 ? null : selection.get(0).getTableColumn();
sm.clearAndSelect(getItemCount() - 1, selectedColumn);
if (onMoveToLastCell != null) onMoveToLastCell.run();
}
protected void selectPreviousRow() {
selectCell(-1, 0);
if (onSelectPreviousRow != null) onSelectPreviousRow.run();
}
protected void selectNextRow() {
selectCell(1, 0);
if (onSelectNextRow != null) onSelectNextRow.run();
}
protected void selectLeftCell() {
selectCell(0, -1);
if (onSelectLeftCell != null) onSelectLeftCell.run();
}
protected void selectRightCell() {
selectCell(0, 1);
if (onSelectRightCell != null) onSelectRightCell.run();
}
protected void selectCell(int rowDiff, int columnDiff) {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
int currentRow = focusedCell.getRow();
int currentColumn = getVisibleLeafIndex(focusedCell.getTableColumn());
if (rowDiff < 0 && currentRow == 0) return;
else if (rowDiff > 0 && currentRow == getItemCount() - 1) return;
else if (columnDiff < 0 && currentColumn == 0) return;
else if (columnDiff > 0 && currentColumn == getVisibleLeafColumns().size() - 1) return;
TableColumnBase tc = focusedCell.getTableColumn();
tc = getColumn(tc, columnDiff);
int row = focusedCell.getRow() + rowDiff;
sm.clearAndSelect(row, tc);
setAnchor(row, tc);
}
protected void cancelEdit() {
editCell(-1, null);
}
protected void activate() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase cell = getFocusedCell();
sm.select(cell.getRow(), cell.getTableColumn());
// edit this row also
editCell(cell.getRow(), cell.getTableColumn());
}
protected void selectAllToFocus() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
int focusRow = focusedCell.getRow();
TablePositionBase anchor = getAnchor();
int anchorRow = anchor.getRow();
sm.clearSelection();
if (! sm.isCellSelectionEnabled()) {
int startPos = anchorRow;
int endPos = anchorRow > focusRow ? focusRow - 1 : focusRow + 1;
sm.selectRange(startPos, endPos);
} else {
// we add all cells/rows between the current selection focus and
// the acnhor (inclusive) to the current selection.
// and then determine all row and columns which must be selected
int minRow = Math.min(focusedCell.getRow(), anchorRow);
int maxRow = Math.max(focusedCell.getRow(), anchorRow);
final int focusedCellColumnPos = getVisibleLeafIndex(focusedCell.getTableColumn());
final int anchorColumnPos = getVisibleLeafIndex(anchor.getTableColumn());
int minColumn = Math.min(focusedCellColumnPos, anchorColumnPos);
int maxColumn = Math.max(focusedCellColumnPos, anchorColumnPos);
// clear selection
sm.clearSelection();
// and then perform the selection
for (int _row = minRow; _row <= maxRow; _row++) {
for (int _col = minColumn; _col <= maxColumn; _col++) {
sm.select(_row, getVisibleLeafColumn(_col));
}
}
}
setAnchor(anchor);
}
protected void selectAll() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
sm.selectAll();
}
protected void selectAllToFirstRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
int leadIndex = focusedCell.getRow();
if (isShiftDown) {
leadIndex = getAnchor() == null ? leadIndex : getAnchor().getRow();
}
sm.clearSelection();
if (! sm.isCellSelectionEnabled()) {
// we are going from 0 to one before the focused cell as that is
// the requirement of selectRange, so we call focus on the 0th row
sm.selectRange(0, leadIndex + 1);
getFocusModel().focus(0);
// setAnchor(leadIndex, null);
} else {
// TODO
// setAnchor(leadIndex, );
}
if (isShiftDown) {
setAnchor(leadIndex, null);
}
if (onMoveToFirstCell != null) onMoveToFirstCell.run();
}
protected void selectAllToLastRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
int leadIndex = focusedCell.getRow();
if (isShiftDown) {
leadIndex = getAnchor() == null ? leadIndex : getAnchor().getRow();
}
sm.clearSelection();
if (! sm.isCellSelectionEnabled()) {
sm.selectRange(leadIndex, getItemCount());
} else {
// TODO
}
if (isShiftDown) {
setAnchor(leadIndex, null);
}
if (onMoveToLastCell != null) onMoveToLastCell.run();
}
protected void selectAllPageUp() {
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int leadIndex = fm.getFocusedIndex();
if (isShiftDown) {
leadIndex = getAnchor() == null ? leadIndex : getAnchor().getRow();
setAnchor(leadIndex, null);
}
int leadSelectedIndex = onScrollPageUp.call(null);
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
selectionChanging = true;
sm.clearSelection();
sm.selectRange(leadSelectedIndex, leadIndex + 1);
selectionChanging = false;
}
protected void selectAllPageDown() {
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int leadIndex = fm.getFocusedIndex();
if (isShiftDown) {
leadIndex = getAnchor() == null ? leadIndex : getAnchor().getRow();
setAnchor(leadIndex, null);
}
int leadSelectedIndex = onScrollPageDown.call(null);
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
selectionChanging = true;
sm.clearSelection();
sm.selectRange(leadIndex, leadSelectedIndex + 1);
selectionChanging = false;
}
protected void toggleFocusOwnerSelection() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePositionBase focusedCell = getFocusedCell();
if (sm.isSelected(focusedCell.getRow(), focusedCell.getTableColumn())) {
sm.clearSelection(focusedCell.getRow(), focusedCell.getTableColumn());
fm.focus(focusedCell.getRow(), focusedCell.getTableColumn());
} else {
sm.select(focusedCell.getRow(), focusedCell.getTableColumn());
}
setAnchor(focusedCell.getRow(), focusedCell.getTableColumn());
}
// This functionality was added, but then removed when it was realised by
// UX that TableView should not include 'spreadsheet-like' functionality.
// When / if we ever introduce this kind of control, this functionality can
// be re-enabled then.
/*
protected void moveToLeftMostColumn() {
// Functionality as described in RT-12752
if (onMoveToLeftMostColumn != null) onMoveToLeftMostColumn.run();
TableSelectionModel sm = getSelectionModel();
if (sm == null || ! sm.isCellSelectionEnabled()) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePosition focusedCell = fm.getFocusedCell();
TableColumn endColumn = getControl().getVisibleLeafColumn(0);
sm.clearAndSelect(focusedCell.getRow(), endColumn);
}
protected void moveToRightMostColumn() {
// Functionality as described in RT-12752
if (onMoveToRightMostColumn != null) onMoveToRightMostColumn.run();
TableSelectionModel sm = getSelectionModel();
if (sm == null || ! sm.isCellSelectionEnabled()) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TablePosition focusedCell = fm.getFocusedCell();
TableColumn endColumn = getControl().getVisibleLeafColumn(getControl().getVisibleLeafColumns().size() - 1);
sm.clearAndSelect(focusedCell.getRow(), endColumn);
}
*/
/**************************************************************************
* Discontinuous Selection *
*************************************************************************/
protected void discontinuousSelectPreviousRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int index = fm.getFocusedIndex() - 1;
if (index < 0) return;
if (! sm.isCellSelectionEnabled()) {
sm.select(index);
} else {
sm.select(index, getFocusedCell().getTableColumn());
}
}
protected void discontinuousSelectNextRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int index = fm.getFocusedIndex() + 1;
if (! sm.isCellSelectionEnabled()) {
sm.select(index);
} else {
sm.select(index, getFocusedCell().getTableColumn());
}
}
protected void discontinuousSelectPreviousColumn() {
TableSelectionModel sm = getSelectionModel();
if (sm == null || ! sm.isCellSelectionEnabled()) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TableColumnBase tc = getColumn(getFocusedCell().getTableColumn(), -1);
sm.select(fm.getFocusedIndex(), tc);
}
protected void discontinuousSelectNextColumn() {
TableSelectionModel sm = getSelectionModel();
if (sm == null || ! sm.isCellSelectionEnabled()) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
TableColumnBase tc = getColumn(getFocusedCell().getTableColumn(), 1);
sm.select(fm.getFocusedIndex(), tc);
}
protected void discontinuousSelectPageUp() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int leadIndex = fm.getFocusedIndex();
int leadSelectedIndex = onScrollPageUp.call(null);
if (! sm.isCellSelectionEnabled()) {
sm.selectRange(leadSelectedIndex, leadIndex + 1);
}
}
protected void discontinuousSelectPageDown() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int leadIndex = fm.getFocusedIndex();
int leadSelectedIndex = onScrollPageDown.call(null);
if (! sm.isCellSelectionEnabled()) {
sm.selectRange(leadIndex, leadSelectedIndex + 1);
}
}
protected void discontinuousSelectAllToFirstRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int index = fm.getFocusedIndex();
if (! sm.isCellSelectionEnabled()) {
sm.selectRange(0, index);
fm.focus(0);
} else {
for (int i = 0; i < index; i++) {
sm.select(i, getFocusedCell().getTableColumn());
}
fm.focus(0, getFocusedCell().getTableColumn());
}
if (onMoveToFirstCell != null) onMoveToFirstCell.run();
}
protected void discontinuousSelectAllToLastRow() {
TableSelectionModel sm = getSelectionModel();
if (sm == null) return;
TableFocusModel fm = getFocusModel();
if (fm == null) return;
int index = fm.getFocusedIndex() + 1;
if (! sm.isCellSelectionEnabled()) {
sm.selectRange(index, getItemCount());
} else {
for (int i = index; i < getItemCount(); i++) {
sm.select(i, getFocusedCell().getTableColumn());
}
}
if (onMoveToLastCell != null) onMoveToLastCell.run();
}
}