modules/controls/src/main/java/javafx/scene/control/skin/TableRowSkinBase.java
Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization
@@ -21,11 +21,11 @@
* 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.skin;
+package javafx.scene.control.skin;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.*;
@@ -45,17 +45,32 @@
import javafx.scene.control.Control;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.TableColumnBase;
import javafx.util.Duration;
-import com.sun.javafx.scene.control.behavior.CellBehaviorBase;
import com.sun.javafx.tk.Toolkit;
+/**
+ * TableRowSkinBase is the base skin class used by controls such as
+ * {@link javafx.scene.control.TableRow} and {@link javafx.scene.control.TreeTableRow}
+ * (the concrete classes are {@link TableRowSkin} and {@link TreeTableRowSkin},
+ * respectively).
+ *
+ * @param <T> The type of the cell (i.e. the generic type of the {@link IndexedCell} subclass).
+ * @param <C> The cell type (e.g. TableRow or TreeTableRow)
+ * @param <R> The type of cell that is contained within each row (e.g.
+ * {@link javafx.scene.control.TableCell or {@link javafx.scene.control.TreeTableCell}}).
+ *
+ * @since 9
+ * @see javafx.scene.control.TableRow
+ * @see javafx.scene.control.TreeTableRow
+ * @see TableRowSkin
+ * @see TreeTableRowSkin
+ */
public abstract class TableRowSkinBase<T,
C extends IndexedCell/*<T>*/,
- B extends CellBehaviorBase<C>,
- R extends IndexedCell> extends CellSkinBase<C,B> {
+ R extends IndexedCell> extends CellSkinBase<C> {
/***************************************************************************
* *
* Static Fields *
* *
@@ -107,19 +122,19 @@
* Note that this means that it is possible for this map to therefore be
* a memory leak if an application uses TableView and is creating and removing
* a large number of tableColumns. This is mitigated in the recreateCells()
* function below - refer to that to learn more.
*/
- protected WeakHashMap<TableColumnBase, Reference<R>> cellsMap;
+ WeakHashMap<TableColumnBase, Reference<R>> cellsMap;
// This observableArrayList contains the currently visible table cells for this row.
- protected final List<R> cells = new ArrayList<R>();
+ final List<R> cells = new ArrayList<>();
private int fullRefreshCounter = DEFAULT_FULL_REFRESH_COUNTER;
- protected boolean isDirty = false;
- protected boolean updateCells = false;
+ boolean isDirty = false;
+ boolean updateCells = false;
private double fixedCellSize;
private boolean fixedCellSizeEnabled;
@@ -128,21 +143,19 @@
* *
* Constructors *
* *
**************************************************************************/
- public TableRowSkinBase(C control, B behavior) {
- super(control, behavior);
-
- // init(control) should not be called here - it should be called by the
- // subclass after initialising itself. This is to prevent NPEs (for
- // example, getVisibleLeafColumns() throws a NPE as the control itself
- // is not yet set in subclasses).
- }
-
- // init isn't a constructor, but it is part of the initialisation routine
- protected void init(C control) {
+ /**
+ * Creates a new instance of TableRowSkinBase, although note that this
+ * instance does not handle any behavior / input mappings - this needs to be
+ * handled appropriately by subclasses.
+ *
+ * @param control The control that this skin should be installed onto.
+ */
+ public TableRowSkinBase(C control) {
+ super(control);
getSkinnable().setPickOnBounds(false);
recreateCells();
updateCells(true);
@@ -155,14 +168,25 @@
// use invalidation listener here to update even when item equality is true
// (e.g. see RT-22463)
control.itemProperty().addListener(o -> requestCellUpdate());
- registerChangeListener(control.indexProperty(), "INDEX");
+ registerChangeListener(control.indexProperty(), e -> {
+ // Fix for RT-36661, where empty table cells were showing content, as they
+ // had incorrect table cell indices (but the table row index was correct).
+ // Note that we only do the update on empty cells to avoid the issue
+ // noted below in requestCellUpdate().
+ if (getSkinnable().isEmpty()) {
+ requestCellUpdate();
+ }
+ });
if (fixedCellSizeProperty() != null) {
- registerChangeListener(fixedCellSizeProperty(), "FIXED_CELL_SIZE");
+ registerChangeListener(fixedCellSizeProperty(), e -> {
+ fixedCellSize = fixedCellSizeProperty().get();
+ fixedCellSizeEnabled = fixedCellSize > 0;
+ });
fixedCellSize = fixedCellSizeProperty().get();
fixedCellSizeEnabled = fixedCellSize > 0;
}
}
@@ -194,53 +218,37 @@
* Returns the graphic to draw on the inside of the disclosure node. Null
* is acceptable when no graphic should be shown. Commonly this is the
* graphic associated with a TreeItem (i.e. treeItem.getGraphic()), rather
* than a graphic associated with a cell.
*/
- protected abstract ObjectProperty<Node> graphicProperty();
+ abstract ObjectProperty<Node> graphicProperty();
// return TableView / TreeTableView / etc
- protected abstract Control getVirtualFlowOwner();
+ abstract Control getVirtualFlowOwner();
- protected abstract ObservableList<? extends TableColumnBase/*<T,?>*/> getVisibleLeafColumns();
+ abstract ObservableList<? extends TableColumnBase/*<T,?>*/> getVisibleLeafColumns();
// cell.updateTableRow(skinnable); (i.e cell.updateTableRow(row))
- protected abstract void updateCell(R cell, C row);
+ abstract void updateCell(R cell, C row);
- protected abstract DoubleProperty fixedCellSizeProperty();
+ abstract DoubleProperty fixedCellSizeProperty();
- protected abstract boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc);
+ abstract boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc);
- protected abstract R getCell(TableColumnBase tc);
+ abstract R getCell(TableColumnBase tc);
- protected abstract TableColumnBase<T,?> getTableColumnBase(R cell);
+ abstract TableColumnBase<T,?> getTableColumnBase(R cell);
/***************************************************************************
* *
* Public Methods *
* *
**************************************************************************/
- @Override protected void handleControlPropertyChanged(String p) {
- super.handleControlPropertyChanged(p);
-
- if ("INDEX".equals(p)) {
- // Fix for RT-36661, where empty table cells were showing content, as they
- // had incorrect table cell indices (but the table row index was correct).
- // Note that we only do the update on empty cells to avoid the issue
- // noted below in requestCellUpdate().
- if (getSkinnable().isEmpty()) {
- requestCellUpdate();
- }
- } else if ("FIXED_CELL_SIZE".equals(p)) {
- fixedCellSize = fixedCellSizeProperty().get();
- fixedCellSizeEnabled = fixedCellSize > 0;
- }
- }
-
+ /** {@inheritDoc} */
@Override protected void layoutChildren(double x, final double y, final double w, final double h) {
checkState();
if (cellsMap.isEmpty()) return;
ObservableList<? extends TableColumnBase> visibleLeafColumns = getVisibleLeafColumns();
@@ -440,58 +448,58 @@
x += width;
}
}
- protected int getIndentationLevel(C control) {
+ int getIndentationLevel(C control) {
return 0;
}
- protected double getIndentationPerLevel() {
+ double getIndentationPerLevel() {
return 0;
}
/**
* Used to represent whether the current virtual flow owner is wanting
* indentation to be used in this table row.
*/
- protected boolean isIndentationRequired() {
+ boolean isIndentationRequired() {
return false;
}
/**
* Returns the table column that should show the disclosure nodes and / or
* a graphic. By default this is the left-most column.
*/
- protected TableColumnBase getTreeColumn() {
+ TableColumnBase getTreeColumn() {
return null;
}
- protected Node getDisclosureNode() {
+ Node getDisclosureNode() {
return null;
}
/**
* Used to represent whether a disclosure node is visible for _this_
* table row. Not to be confused with isIndentationRequired(), which is the
* more general API.
*/
- protected boolean isDisclosureNodeVisible() {
+ boolean isDisclosureNodeVisible() {
return false;
}
- protected boolean isShowRoot() {
+ boolean isShowRoot() {
return true;
}
- protected TableColumnBase<T,?> getVisibleLeafColumn(int column) {
+ TableColumnBase<T,?> getVisibleLeafColumn(int column) {
final List<? extends TableColumnBase/*<T,?>*/> visibleLeafColumns = getVisibleLeafColumns();
if (column < 0 || column >= visibleLeafColumns.size()) return null;
return visibleLeafColumns.get(column);
}
- protected void updateCells(boolean resetChildren) {
+ void updateCells(boolean resetChildren) {
// To avoid a potential memory leak (when the TableColumns in the
// TableView are created/inserted/removed/deleted, we have a 'refresh
// counter' that when we reach 0 will delete all cells in this row
// and recreate all of them.
if (resetChildren) {
@@ -572,11 +580,11 @@
// Support for RT-18467: making it easier to specify a height for
// cells via CSS, where the desired height is less than the height
// of the TableCells. Essentially, -fx-cell-size is given higher
// precedence now
- if (getCellSize() < CellSkinBase.DEFAULT_CELL_SIZE) {
+ if (getCellSize() < DEFAULT_CELL_SIZE) {
return getCellSize();
}
// FIXME according to profiling, this method is slow and should
// be optimised
@@ -601,11 +609,11 @@
// Support for RT-18467: making it easier to specify a height for
// cells via CSS, where the desired height is less than the height
// of the TableCells. Essentially, -fx-cell-size is given higher
// precedence now
- if (getCellSize() < CellSkinBase.DEFAULT_CELL_SIZE) {
+ if (getCellSize() < DEFAULT_CELL_SIZE) {
return getCellSize();
}
// FIXME according to profiling, this method is slow and should
// be optimised
@@ -623,12 +631,11 @@
return fixedCellSize;
}
return super.computeMaxHeight(width, topInset, rightInset, bottomInset, leftInset);
}
- // protected to allow subclasses to ensure a consistent state during layout
- protected final void checkState() {
+ final void checkState() {
if (isDirty) {
updateCells(true);
isDirty = false;
} else if (updateCells) {
updateCells(false);