modules/controls/src/main/java/javafx/scene/control/skin/TreeTableRowSkin.java
Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization
@@ -21,12 +21,14 @@
* 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 com.sun.javafx.scene.control.behavior.BehaviorBase;
+import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.scene.control.Control;
import javafx.scene.control.TableColumnBase;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
@@ -43,35 +45,39 @@
import javafx.scene.AccessibleAttribute;
import javafx.scene.Node;
import javafx.css.StyleableDoubleProperty;
import javafx.css.CssMetaData;
-import com.sun.javafx.css.converters.SizeConverter;
-import com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler;
+import javafx.css.converter.SizeConverter;
import com.sun.javafx.scene.control.behavior.TreeTableRowBehavior;
import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.WritableValue;
import javafx.collections.ObservableList;
import javafx.css.Styleable;
import javafx.css.StyleableProperty;
-public class TreeTableRowSkin<T> extends TableRowSkinBase<TreeItem<T>, TreeTableRow<T>, TreeTableRowBehavior<T>, TreeTableCell<T,?>> {
+/**
+ * Default skin implementation for the {@link TreeTableRow} control.
+ *
+ * @see TreeTableRow
+ * @since 9
+ */
+public class TreeTableRowSkin<T> extends TableRowSkinBase<TreeItem<T>, TreeTableRow<T>, TreeTableCell<T,?>> {
/***************************************************************************
* *
* Private Fields *
* *
**************************************************************************/
// maps into the TreeTableViewSkin items property via
// TreeTableViewSkin.treeItemToListMap
- private SimpleObjectProperty<ObservableList<TreeItem<T>>> itemsProperty;
private TreeItem<?> treeItem;
private boolean disclosureNodeDirty = true;
private Node graphic;
+ private final BehaviorBase<TreeTableRow<T>> behavior;
private TreeTableViewSkin treeTableViewSkin;
private boolean childrenDirty = false;
@@ -81,40 +87,53 @@
* *
* Constructors *
* *
**************************************************************************/
+ /**
+ * Creates a new TreeTableRowSkin instance, installing the necessary child
+ * nodes into the Control {@link Control#getChildren() children} list, as
+ * well as the necessary input mappings for handling key, mouse, etc events.
+ *
+ * @param control The control that this skin should be installed onto.
+ */
public TreeTableRowSkin(TreeTableRow<T> control) {
- super(control, new TreeTableRowBehavior<T>(control));
+ super(control);
- super.init(control);
+ // install default input map for the TreeTableRow control
+ behavior = new TreeTableRowBehavior<>(control);
+// control.setInputMap(behavior.getInputMap());
updateTreeItem();
updateTableViewSkin();
- registerChangeListener(control.treeTableViewProperty(), "TREE_TABLE_VIEW");
- registerChangeListener(control.indexProperty(), "INDEX");
- registerChangeListener(control.treeItemProperty(), "TREE_ITEM");
- registerChangeListener(control.getTreeTableView().treeColumnProperty(), "TREE_COLUMN");
+ registerChangeListener(control.treeTableViewProperty(), e -> updateTableViewSkin());
+ registerChangeListener(control.indexProperty(), e -> updateCells = true);
+ registerChangeListener(control.treeItemProperty(), e -> {
+ updateTreeItem();
+ isDirty = true;
+ });
+ registerChangeListener(control.getTreeTableView().treeColumnProperty(), e -> {
+ // Fix for RT-27782: Need to set isDirty to true, rather than the
+ // cheaper updateCells, as otherwise the text indentation will not
+ // be recalculated in TreeTableCellSkin.leftLabelPadding()
+ isDirty = true;
+ getSkinnable().requestLayout();
+ });
}
-
/***************************************************************************
* *
* Listeners *
* *
**************************************************************************/
- private MultiplePropertyChangeListenerHandler treeItemListener = new MultiplePropertyChangeListenerHandler(p -> {
- if ("GRAPHIC".equals(p)) {
+ private final InvalidationListener graphicListener = o -> {
disclosureNodeDirty = true;
getSkinnable().requestLayout();
- }
- return null;
- });
-
+ };
/***************************************************************************
* *
* Properties *
@@ -149,33 +168,24 @@
/***************************************************************************
* *
- * Public Methods *
+ * Public API *
* *
**************************************************************************/
- @Override protected void handleControlPropertyChanged(String p) {
- super.handleControlPropertyChanged(p);
+ /** {@inheritDoc} */
+ @Override public void dispose() {
+ super.dispose();
- if ("TREE_ABLE_VIEW".equals(p)) {
- updateTableViewSkin();
- } else if ("INDEX".equals(p)) {
- updateCells = true;
- } else if ("TREE_ITEM".equals(p)) {
- updateTreeItem();
- isDirty = true;
- } else if ("TREE_COLUMN".equals(p)) {
- // Fix for RT-27782: Need to set isDirty to true, rather than the
- // cheaper updateCells, as otherwise the text indentation will not
- // be recalculated in TreeTableCellSkin.leftLabelPadding()
- isDirty = true;
- getSkinnable().requestLayout();
+ if (behavior != null) {
+ behavior.dispose();
}
}
+ /** {@inheritDoc} */
@Override protected void updateChildren() {
super.updateChildren();
updateDisclosureNodeAndGraphic();
@@ -190,10 +200,11 @@
getChildren().addAll(cells);
}
}
}
+ /** {@inheritDoc} */
@Override protected void layoutChildren(double x, double y, double w, double h) {
if (disclosureNodeDirty) {
updateDisclosureNodeAndGraphic();
disclosureNodeDirty = false;
}
@@ -204,105 +215,118 @@
}
super.layoutChildren(x, y, w, h);
}
- @Override protected TreeTableCell<T, ?> getCell(TableColumnBase tcb) {
+
+
+ /***************************************************************************
+ * *
+ * Private Implementation *
+ * *
+ **************************************************************************/
+
+ /** {@inheritDoc} */
+ @Override TreeTableCell<T, ?> getCell(TableColumnBase tcb) {
TreeTableColumn tableColumn = (TreeTableColumn<T,?>) tcb;
TreeTableCell cell = (TreeTableCell) tableColumn.getCellFactory().call(tableColumn);
cell.updateTreeTableColumn(tableColumn);
cell.updateTreeTableView(tableColumn.getTreeTableView());
return cell;
}
- @Override protected void updateCells(boolean resetChildren) {
+ /** {@inheritDoc} */
+ @Override void updateCells(boolean resetChildren) {
super.updateCells(resetChildren);
if (resetChildren) {
childrenDirty = true;
updateChildren();
}
}
- @Override protected boolean isIndentationRequired() {
+ /** {@inheritDoc} */
+ @Override boolean isIndentationRequired() {
return true;
}
- @Override protected TableColumnBase getTreeColumn() {
+ /** {@inheritDoc} */
+ @Override TableColumnBase getTreeColumn() {
return getSkinnable().getTreeTableView().getTreeColumn();
}
- @Override protected int getIndentationLevel(TreeTableRow<T> control) {
+ /** {@inheritDoc} */
+ @Override int getIndentationLevel(TreeTableRow<T> control) {
return control.getTreeTableView().getTreeItemLevel(control.getTreeItem());
}
- @Override protected double getIndentationPerLevel() {
+ /** {@inheritDoc} */
+ @Override double getIndentationPerLevel() {
return getIndent();
}
- @Override protected Node getDisclosureNode() {
+ /** {@inheritDoc} */
+ @Override Node getDisclosureNode() {
return getSkinnable().getDisclosureNode();
}
- @Override protected boolean isDisclosureNodeVisible() {
+ @Override boolean isDisclosureNodeVisible() {
return getDisclosureNode() != null && treeItem != null && ! treeItem.isLeaf();
}
- @Override protected boolean isShowRoot() {
+ @Override boolean isShowRoot() {
return getSkinnable().getTreeTableView().isShowRoot();
}
- @Override protected ObservableList<TreeTableColumn<T, ?>> getVisibleLeafColumns() {
+ /** {@inheritDoc} */
+ @Override ObservableList<TreeTableColumn<T, ?>> getVisibleLeafColumns() {
return getSkinnable().getTreeTableView().getVisibleLeafColumns();
}
- @Override protected void updateCell(TreeTableCell<T, ?> cell, TreeTableRow<T> row) {
+ /** {@inheritDoc} */
+ @Override void updateCell(TreeTableCell<T, ?> cell, TreeTableRow<T> row) {
cell.updateTreeTableRow(row);
}
- @Override protected boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc) {
+ /** {@inheritDoc} */
+ @Override boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc) {
return treeTableViewSkin == null ? false : treeTableViewSkin.isColumnPartiallyOrFullyVisible(tc);
}
- @Override protected TreeTableColumn<T, ?> getTableColumnBase(TreeTableCell cell) {
+ /** {@inheritDoc} */
+ @Override TreeTableColumn<T, ?> getTableColumnBase(TreeTableCell cell) {
return cell.getTableColumn();
}
- @Override protected ObjectProperty<Node> graphicProperty() {
+ /** {@inheritDoc} */
+ @Override ObjectProperty<Node> graphicProperty() {
TreeTableRow<T> treeTableRow = getSkinnable();
if (treeTableRow == null) return null;
if (treeItem == null) return null;
return treeItem.graphicProperty();
}
- @Override protected Control getVirtualFlowOwner() {
+ /** {@inheritDoc} */
+ @Override Control getVirtualFlowOwner() {
return getSkinnable().getTreeTableView();
}
- @Override protected DoubleProperty fixedCellSizeProperty() {
+ /** {@inheritDoc} */
+ @Override DoubleProperty fixedCellSizeProperty() {
return getSkinnable().getTreeTableView().fixedCellSizeProperty();
}
-
-
- /***************************************************************************
- * *
- * Private Implementation *
- * *
- **************************************************************************/
-
private void updateTreeItem() {
if (treeItem != null) {
- treeItemListener.unregisterChangeListener(treeItem.expandedProperty());
- treeItemListener.unregisterChangeListener(treeItem.graphicProperty());
+ treeItem.graphicProperty().removeListener(graphicListener);
}
treeItem = getSkinnable().getTreeItem();
if (treeItem != null) {
- treeItemListener.registerChangeListener(treeItem.graphicProperty(), "GRAPHIC");
+ treeItem.graphicProperty().addListener(graphicListener);
}
}
private void updateDisclosureNodeAndGraphic() {
if (getSkinnable().isEmpty()) return;
@@ -385,11 +409,11 @@
STYLEABLES = Collections.unmodifiableList(styleables);
}
}
/**
- * @return The CssMetaData associated with this class, which may include the
+ * Returns the CssMetaData associated with this class, which may include the
* CssMetaData of its super classes.
*/
public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
return StyleableProperties.STYLEABLES;
}
@@ -400,13 +424,12 @@
@Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return getClassCssMetaData();
}
-
- @Override
- protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
+ /** {@inheritDoc} */
+ @Override protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
final TreeTableView<T> treeTableView = getSkinnable().getTreeTableView();
switch (attribute) {
case SELECTED_ITEMS: {
// FIXME this could be optimised to iterate over cellsMap only
// (selectedCells could be big, cellsMap is much smaller)