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 }