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 com.sun.javafx.scene.control.skin;
  27 
  28 
  29 import java.util.ArrayList;
  30 import java.util.List;
  31 
  32 import javafx.beans.property.DoubleProperty;
  33 import javafx.scene.control.TableCell;
  34 import javafx.scene.control.TableColumn;
  35 import javafx.scene.control.TablePosition;
  36 import javafx.scene.control.TableRow;
  37 import javafx.scene.control.TableView;
  38 
  39 import com.sun.javafx.scene.control.behavior.CellBehaviorBase;
  40 import com.sun.javafx.scene.control.behavior.TableRowBehavior;
  41 
  42 import javafx.beans.property.ObjectProperty;
  43 import javafx.collections.FXCollections;
  44 import javafx.collections.ObservableList;
  45 import javafx.scene.AccessibleAttribute;
  46 import javafx.scene.Node;
  47 import javafx.scene.control.Control;
  48 import javafx.scene.control.TableColumnBase;
  49 import javafx.scene.control.TableView.TableViewFocusModel;
  50 
  51 /**
  52  */
  53 public class TableRowSkin<T> extends TableRowSkinBase<T, TableRow<T>, CellBehaviorBase<TableRow<T>>, TableCell<T,?>> {
  54 
  55     private TableView<T> tableView;
  56     private TableViewSkin<T> tableViewSkin;
  57     
  58     public TableRowSkin(TableRow<T> tableRow) {
  59         super(tableRow, new TableRowBehavior<T>(tableRow));
  60         
  61         this.tableView = tableRow.getTableView();
  62         updateTableViewSkin();
  63         
  64         super.init(tableRow);
  65 
  66         registerChangeListener(tableRow.tableViewProperty(), "TABLE_VIEW");
  67     }
  68 
  69     @Override protected void handleControlPropertyChanged(String p) {
  70         super.handleControlPropertyChanged(p);
  71         if ("TABLE_VIEW".equals(p)) {
  72             updateTableViewSkin();
  73             
  74             for (int i = 0, max = cells.size(); i < max; i++) {
  75                 Node n = cells.get(i);
  76                 if (n instanceof TableCell) {
  77                     ((TableCell)n).updateTableView(getSkinnable().getTableView());
  78                 }
  79             }
  80             
  81             this.tableView = getSkinnable().getTableView();
  82         }
  83     }
  84     
  85     @Override protected TableCell<T, ?> getCell(TableColumnBase tcb) {
  86         TableColumn tableColumn = (TableColumn<T,?>) tcb;
  87         TableCell cell = (TableCell) tableColumn.getCellFactory().call(tableColumn);
  88 
  89         // we set it's TableColumn, TableView and TableRow
  90         cell.updateTableColumn(tableColumn);
  91         cell.updateTableView(tableColumn.getTableView());
  92         cell.updateTableRow(getSkinnable());
  93         
  94         return cell;
  95     }
  96 
  97     @Override protected ObservableList<TableColumn<T, ?>> getVisibleLeafColumns() {
  98         return tableView.getVisibleLeafColumns();
  99     }
 100 
 101     @Override protected void updateCell(TableCell<T, ?> cell, TableRow<T> row) {
 102         cell.updateTableRow(row);
 103     }
 104 
 105     @Override protected DoubleProperty fixedCellSizeProperty() {
 106         return tableView.fixedCellSizeProperty();
 107     }
 108 
 109     @Override protected boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc) {
 110         return tableViewSkin == null ? false : tableViewSkin.isColumnPartiallyOrFullyVisible((TableColumn)tc);
 111     }
 112 
 113     @Override protected TableColumn<T, ?> getTableColumnBase(TableCell<T, ?> cell) {
 114         return cell.getTableColumn();
 115     }
 116 
 117     @Override protected ObjectProperty<Node> graphicProperty() {
 118         return null;
 119     }
 120 
 121     @Override protected Control getVirtualFlowOwner() {
 122         return getSkinnable().getTableView();
 123     }
 124     
 125     private void updateTableViewSkin() {
 126         TableView<T> tableView = getSkinnable().getTableView();
 127         if (tableView.getSkin() instanceof TableViewSkin) {
 128             tableViewSkin = (TableViewSkin)tableView.getSkin();
 129         }
 130     }
 131 
 132     @Override
 133     protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
 134         switch (attribute) {
 135             case SELECTED_ITEMS: {
 136                 // FIXME this could be optimised to iterate over cellsMap only
 137                 // (selectedCells could be big, cellsMap is much smaller)
 138                 List<Node> selection = new ArrayList<>();
 139                 int index = getSkinnable().getIndex();
 140                 for (TablePosition<T,?> pos : tableView.getSelectionModel().getSelectedCells()) {
 141                     if (pos.getRow() == index) {
 142                         TableColumn<T,?> column = pos.getTableColumn();
 143                         if (column == null) {
 144                             /* This is the row-based case */
 145                             column = tableView.getVisibleLeafColumn(0);
 146                         }
 147                         TableCell<T,?> cell = cellsMap.get(column).get();
 148                         if (cell != null) selection.add(cell);
 149                     }
 150                     return FXCollections.observableArrayList(selection);
 151                 }
 152             }
 153             case CELL_AT_ROW_COLUMN: {
 154                 int colIndex = (Integer)parameters[1];
 155                 TableColumn<T,?> column = tableView.getVisibleLeafColumn(colIndex);
 156                 if (cellsMap.containsKey(column)) {
 157                     return cellsMap.get(column).get();
 158                 }
 159                 return null;
 160             }
 161             case FOCUS_ITEM: {
 162                 TableViewFocusModel<T> fm = tableView.getFocusModel();
 163                 TablePosition<T,?> focusedCell = fm.getFocusedCell();
 164                 TableColumn<T,?> column = focusedCell.getTableColumn();
 165                 if (column == null) {
 166                     /* This is the row-based case */
 167                     column = tableView.getVisibleLeafColumn(0);
 168                 }
 169                 if (cellsMap.containsKey(column)) {
 170                     return cellsMap.get(column).get();
 171                 }
 172                 return null;
 173             }
 174             default: return super.queryAccessibleAttribute(attribute, parameters);
 175         }
 176     }
 177 
 178 }