/*
 * Copyright (c) 2011, 2016, 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 javafx.scene.control.Control;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumnBase;
import javafx.scene.control.TableFocusModel;
import javafx.scene.control.TablePositionBase;
import javafx.scene.control.TableSelectionModel;
import javafx.scene.input.MouseButton;

public abstract class TableCellBehaviorBase<S, T, TC extends TableColumnBase<S, ?>, C extends IndexedCell<T>> extends CellBehaviorBase<C> {

    /***************************************************************************
     *                                                                         *
     * Private fields                                                          *
     *                                                                         *
     **************************************************************************/


    
* Constructors * *
/*************************************************************************** * * * Constructors * * * **************************************************************************/
public TableCellBehaviorBase(C control) { super(control); }
* Abstract API * *
/************************************************************************** * * * Abstract API * * * *************************************************************************/
protected abstract TableColumnBase<S, T> getTableColumn(); // getControl().getTableColumn() protected abstract int getItemCount(); protected abstract TableSelectionModel<S> getSelectionModel(); protected abstract TableFocusModel<S,TC> getFocusModel(); protected abstract TablePositionBase getFocusedCell(); protected abstract boolean isTableRowSelected(); // tableCell.getTreeTableRow().isSelected()
Returns the position of the given table column in the visible leaf columns list of the underlying control.
/** * Returns the position of the given table column in the visible leaf columns * list of the underlying control. */
protected abstract int getVisibleLeafIndex(TableColumnBase<S,T> tc); protected abstract void focus(int row, TableColumnBase<S,T> tc); //fm.focus(new TreeTablePosition(tableView, row, tableColumn)); /*************************************************************************** * * * Public API * * * **************************************************************************/
* Private implementation * *
/*************************************************************************** * * * Private implementation * * * **************************************************************************/
protected void doSelect(final double x, final double y, final MouseButton button, final int clickCount, final boolean shiftDown, final boolean shortcutDown) { // Note that table.select will reset selection // for out of bounds indexes. So, need to check final C tableCell = getNode(); // If the mouse event is not contained within this tableCell, then // we don't want to react to it. if (! tableCell.contains(x, y)) return; final Control tableView = getCellContainer(); if (tableView == null) return; int count = getItemCount(); if (tableCell.getIndex() >= count) return; TableSelectionModel<S> sm = getSelectionModel(); if (sm == null) return; final boolean selected = isSelected(); final int row = tableCell.getIndex(); final int column = getColumn(); final TableColumnBase<S,T> tableColumn = getTableColumn(); TableFocusModel fm = getFocusModel(); if (fm == null) return; TablePositionBase focusedCell = getFocusedCell(); // if the user has clicked on the disclosure node, we do nothing other // than expand/collapse the tree item (if applicable). We do not do editing! if (handleDisclosureNode(x, y)) { return; } // if shift is down, and we don't already have the initial focus index // recorded, we record the focus index now so that subsequent shift+clicks // result in the correct selection occuring (whilst the focus index moves // about). if (shiftDown) { if (! hasNonDefaultAnchor(tableView)) { setAnchor(tableView, focusedCell, false); } } else { removeAnchor(tableView); } // we must update the table appropriately, and this is determined by // what modifiers the user held down as they released the mouse. if (button == MouseButton.PRIMARY || (button == MouseButton.SECONDARY && !selected)) { if (sm.getSelectionMode() == SelectionMode.SINGLE) { simpleSelect(button, clickCount, shortcutDown); } else { if (shortcutDown) { if (selected) { // we remove this row/cell from the current selection sm.clearSelection(row, tableColumn); fm.focus(row, tableColumn); } else { // We add this cell/row to the current selection sm.select(row, tableColumn); } } else if (shiftDown) { // we add all cells/rows between the current selection focus and // this cell/row (inclusive) to the current selection. final TablePositionBase anchor = getAnchor(tableView, focusedCell); final int anchorRow = anchor.getRow(); final boolean asc = anchorRow < row; // clear selection, but maintain the anchor sm.clearSelection(); // and then determine all row and columns which must be selected int minRow = Math.min(anchorRow, row); int maxRow = Math.max(anchorRow, row); TableColumnBase<S,T> minColumn = anchor.getColumn() < column ? anchor.getTableColumn() : tableColumn; TableColumnBase<S,T> maxColumn = anchor.getColumn() >= column ? anchor.getTableColumn() : tableColumn; // and then perform the selection. // RT-21444: We need to put the range in the correct // order or else the last selected row will not be the // last item in the selectedItems list of the selection // model, if (asc) { sm.selectRange(minRow, minColumn, maxRow, maxColumn); } else { sm.selectRange(maxRow, minColumn, minRow, maxColumn); } // This line of code below was disabled as a fix for RT-30394. // Unit tests were written, so if by disabling this code I // have introduced regressions elsewhere, it is allowable to // re-enable this code as tests will fail if it is done so // without taking care of RT-30394 in an alternative manner. // return selection back to the focus owner // focus(anchor.getRow(), tableColumn); } else { simpleSelect(button, clickCount, shortcutDown); } } } } protected void simpleSelect(MouseButton button, int clickCount, boolean shortcutDown) { final TableSelectionModel<S> sm = getSelectionModel(); final int row = getNode().getIndex(); final TableColumnBase<S,T> column = getTableColumn(); boolean isAlreadySelected = sm.isSelected(row, column); if (isAlreadySelected && shortcutDown) { sm.clearSelection(row, column); getFocusModel().focus(row, (TC) column); isAlreadySelected = false; } else { // we check if cell selection is enabled to fix RT-33897 sm.clearAndSelect(row, column); } handleClicks(button, clickCount, isAlreadySelected); } private int getColumn() { if (getSelectionModel().isCellSelectionEnabled()) { TableColumnBase<S,T> tc = getTableColumn(); return getVisibleLeafIndex(tc); } return -1; } @Override protected boolean isSelected() { TableSelectionModel<S> sm = getSelectionModel(); if (sm == null) return false; if (sm.isCellSelectionEnabled()) { final C cell = getNode(); return cell.isSelected(); } else { return isTableRowSelected(); } } }