1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.control.skin;
  27 
  28 
  29 import java.util.ArrayList;
  30 import java.util.List;
  31 
  32 import com.sun.javafx.scene.control.behavior.BehaviorBase;
  33 import javafx.beans.property.DoubleProperty;
  34 import javafx.scene.control.Accordion;
  35 import javafx.scene.control.Button;
  36 import javafx.scene.control.TableCell;
  37 import javafx.scene.control.TableColumn;
  38 import javafx.scene.control.TablePosition;
  39 import javafx.scene.control.TableRow;
  40 import javafx.scene.control.TableView;
  41 
  42 import com.sun.javafx.scene.control.behavior.TableRowBehavior;
  43 
  44 import javafx.beans.property.ObjectProperty;
  45 import javafx.collections.FXCollections;
  46 import javafx.collections.ObservableList;
  47 import javafx.scene.AccessibleAttribute;
  48 import javafx.scene.Node;
  49 import javafx.scene.control.Control;
  50 import javafx.scene.control.TableColumnBase;
  51 import javafx.scene.control.TableView.TableViewFocusModel;
  52 
  53 /**
  54  * Default skin implementation for the {@link TableRow} control.
  55  *
  56  * @see TableRow
  57  * @since 9
  58  */
  59 public class TableRowSkin<T> extends TableRowSkinBase<T, TableRow<T>, TableCell<T,?>> {
  60 
  61     /***************************************************************************
  62      *                                                                         *
  63      * Private fields                                                          *
  64      *                                                                         *
  65      **************************************************************************/
  66 
  67     private TableViewSkin<T> tableViewSkin;
  68     private final BehaviorBase<TableRow<T>> behavior;
  69 
  70 
  71 
  72     /***************************************************************************
  73      *                                                                         *
  74      * Constructors                                                            *
  75      *                                                                         *
  76      **************************************************************************/
  77 
  78     /**
  79      * Creates a new TableRowSkin instance, installing the necessary child
  80      * nodes into the Control {@link Control#getChildren() children} list, as
  81      * well as the necessary input mappings for handling key, mouse, etc events.
  82      *
  83      * @param control The control that this skin should be installed onto.
  84      */
  85     public TableRowSkin(TableRow<T> control) {
  86         super(control);
  87 
  88         // install default input map for the TableRow control
  89         behavior = new TableRowBehavior<>(control);
  90 //        control.setInputMap(behavior.getInputMap());
  91         
  92         updateTableViewSkin();
  93 
  94         registerChangeListener(control.tableViewProperty(), e -> {
  95             updateTableViewSkin();
  96 
  97             for (int i = 0, max = cells.size(); i < max; i++) {
  98                 Node n = cells.get(i);
  99                 if (n instanceof TableCell) {
 100                     ((TableCell)n).updateTableView(getSkinnable().getTableView());
 101                 }
 102             }
 103         });
 104     }
 105 
 106 
 107 
 108     /***************************************************************************
 109      *                                                                         *
 110      * Public API                                                              *
 111      *                                                                         *
 112      **************************************************************************/
 113 
 114     /** {@inheritDoc} */
 115     @Override public void dispose() {
 116         super.dispose();
 117 
 118         if (behavior != null) {
 119             behavior.dispose();
 120         }
 121     }
 122 
 123     /** {@inheritDoc} */
 124     @Override protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
 125         switch (attribute) {
 126             case SELECTED_ITEMS: {
 127                 // FIXME this could be optimised to iterate over cellsMap only
 128                 // (selectedCells could be big, cellsMap is much smaller)
 129                 List<Node> selection = new ArrayList<>();
 130                 int index = getSkinnable().getIndex();
 131                 for (TablePosition<T,?> pos : getVirtualFlowOwner().getSelectionModel().getSelectedCells()) {
 132                     if (pos.getRow() == index) {
 133                         TableColumn<T,?> column = pos.getTableColumn();
 134                         if (column == null) {
 135                             /* This is the row-based case */
 136                             column = getVirtualFlowOwner().getVisibleLeafColumn(0);
 137                         }
 138                         TableCell<T,?> cell = cellsMap.get(column).get();
 139                         if (cell != null) selection.add(cell);
 140                     }
 141                     return FXCollections.observableArrayList(selection);
 142                 }
 143             }
 144             case CELL_AT_ROW_COLUMN: {
 145                 int colIndex = (Integer)parameters[1];
 146                 TableColumn<T,?> column = getVirtualFlowOwner().getVisibleLeafColumn(colIndex);
 147                 if (cellsMap.containsKey(column)) {
 148                     return cellsMap.get(column).get();
 149                 }
 150                 return null;
 151             }
 152             case FOCUS_ITEM: {
 153                 TableViewFocusModel<T> fm = getVirtualFlowOwner().getFocusModel();
 154                 TablePosition<T,?> focusedCell = fm.getFocusedCell();
 155                 TableColumn<T,?> column = focusedCell.getTableColumn();
 156                 if (column == null) {
 157                     /* This is the row-based case */
 158                     column = getVirtualFlowOwner().getVisibleLeafColumn(0);
 159                 }
 160                 if (cellsMap.containsKey(column)) {
 161                     return cellsMap.get(column).get();
 162                 }
 163                 return null;
 164             }
 165             default: return super.queryAccessibleAttribute(attribute, parameters);
 166         }
 167     }
 168 
 169 
 170 
 171     /***************************************************************************
 172      *                                                                         *
 173      * Private implementation                                                  *
 174      *                                                                         *
 175      **************************************************************************/
 176 
 177     /** {@inheritDoc} */
 178     @Override TableCell<T, ?> getCell(TableColumnBase tcb) {
 179         TableColumn tableColumn = (TableColumn<T,?>) tcb;
 180         TableCell cell = (TableCell) tableColumn.getCellFactory().call(tableColumn);
 181 
 182         // we set it's TableColumn, TableView and TableRow
 183         cell.updateTableColumn(tableColumn);
 184         cell.updateTableView(tableColumn.getTableView());
 185         cell.updateTableRow(getSkinnable());
 186         
 187         return cell;
 188     }
 189 
 190     /** {@inheritDoc} */
 191     @Override ObservableList<TableColumn<T, ?>> getVisibleLeafColumns() {
 192         return getVirtualFlowOwner().getVisibleLeafColumns();
 193     }
 194 
 195     /** {@inheritDoc} */
 196     @Override void updateCell(TableCell<T, ?> cell, TableRow<T> row) {
 197         cell.updateTableRow(row);
 198     }
 199 
 200     /** {@inheritDoc} */
 201     @Override DoubleProperty fixedCellSizeProperty() {
 202         return getVirtualFlowOwner().fixedCellSizeProperty();
 203     }
 204 
 205     /** {@inheritDoc} */
 206     @Override boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc) {
 207         return tableViewSkin == null ? false : tableViewSkin.isColumnPartiallyOrFullyVisible((TableColumn)tc);
 208     }
 209 
 210     /** {@inheritDoc} */
 211     @Override TableColumn<T, ?> getTableColumnBase(TableCell<T, ?> cell) {
 212         return cell.getTableColumn();
 213     }
 214 
 215     /** {@inheritDoc} */
 216     @Override ObjectProperty<Node> graphicProperty() {
 217         return null;
 218     }
 219 
 220     /** {@inheritDoc} */
 221     @Override TableView<T> getVirtualFlowOwner() {
 222         return getSkinnable().getTableView();
 223     }
 224 
 225     private void updateTableViewSkin() {
 226         TableView<T> tableView = getSkinnable().getTableView();
 227         if (tableView.getSkin() instanceof TableViewSkin) {
 228             tableViewSkin = (TableViewSkin)tableView.getSkin();
 229         }
 230     }
 231 }