modules/controls/src/main/java/javafx/scene/control/skin/TableViewSkin.java
Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization
@@ -21,23 +21,28 @@
* 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.util.ArrayList;
import java.util.List;
+import com.sun.javafx.scene.control.Properties;
+import com.sun.javafx.scene.control.behavior.BehaviorBase;
+import com.sun.javafx.scene.control.skin.Utils;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.AccessibleAction;
import javafx.scene.AccessibleAttribute;
import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Control;
import javafx.scene.control.ResizeFeaturesBase;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableRow;
@@ -49,168 +54,267 @@
import javafx.scene.layout.Region;
import javafx.util.Callback;
import com.sun.javafx.scene.control.behavior.TableViewBehavior;
-public class TableViewSkin<T> extends TableViewSkinBase<T, T, TableView<T>, TableViewBehavior<T>, TableRow<T>, TableColumn<T, ?>> {
+/**
+ * Default skin implementation for the {@link TableView} control.
+ *
+ * @see TableView
+ * @since 9
+ */
+public class TableViewSkin<T> extends TableViewSkinBase<T, T, TableView<T>, TableRow<T>, TableColumn<T, ?>> {
+
+ /***************************************************************************
+ * *
+ * Private Fields *
+ * *
+ **************************************************************************/
- private final TableView<T> tableView;
+ private final TableViewBehavior<T> behavior;
- public TableViewSkin(final TableView<T> tableView) {
- super(tableView, new TableViewBehavior<T>(tableView));
- this.tableView = tableView;
- flow.setFixedCellSize(tableView.getFixedCellSize());
- super.init(tableView);
+ /***************************************************************************
+ * *
+ * Constructors *
+ * *
+ **************************************************************************/
+
+ /**
+ * Creates a new TableViewSkin 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 TableViewSkin(final TableView<T> control) {
+ super(control);
+
+ // install default input map for the TableView control
+ behavior = new TableViewBehavior<>(control);
+// control.setInputMap(behavior.getInputMap());
+
+ flow.setFixedCellSize(control.getFixedCellSize());
+ flow.setCellFactory(flow -> createCell());
EventHandler<MouseEvent> ml = event -> {
// RT-15127: cancel editing on scroll. This is a bit extreme
// (we are cancelling editing on touching the scrollbars).
// This can be improved at a later date.
- if (tableView.getEditingCell() != null) {
- tableView.edit(-1, null);
+ if (control.getEditingCell() != null) {
+ control.edit(-1, null);
}
// This ensures that the table maintains the focus, even when the vbar
// and hbar controls inside the flow are clicked. Without this, the
// focus border will not be shown when the user interacts with the
// scrollbars, and more importantly, keyboard navigation won't be
// available to the user.
- if (tableView.isFocusTraversable()) {
- tableView.requestFocus();
+ if (control.isFocusTraversable()) {
+ control.requestFocus();
}
};
flow.getVbar().addEventFilter(MouseEvent.MOUSE_PRESSED, ml);
flow.getHbar().addEventFilter(MouseEvent.MOUSE_PRESSED, ml);
// init the behavior 'closures'
- TableViewBehavior<T> behavior = getBehavior();
- behavior.setOnFocusPreviousRow(() -> { onFocusPreviousCell(); });
- behavior.setOnFocusNextRow(() -> { onFocusNextCell(); });
- behavior.setOnMoveToFirstCell(() -> { onMoveToFirstCell(); });
- behavior.setOnMoveToLastCell(() -> { onMoveToLastCell(); });
+ behavior.setOnFocusPreviousRow(() -> onFocusPreviousCell());
+ behavior.setOnFocusNextRow(() -> onFocusNextCell());
+ behavior.setOnMoveToFirstCell(() -> onMoveToFirstCell());
+ behavior.setOnMoveToLastCell(() -> onMoveToLastCell());
behavior.setOnScrollPageDown(isFocusDriven -> onScrollPageDown(isFocusDriven));
behavior.setOnScrollPageUp(isFocusDriven -> onScrollPageUp(isFocusDriven));
- behavior.setOnSelectPreviousRow(() -> { onSelectPreviousCell(); });
- behavior.setOnSelectNextRow(() -> { onSelectNextCell(); });
- behavior.setOnSelectLeftCell(() -> { onSelectLeftCell(); });
- behavior.setOnSelectRightCell(() -> { onSelectRightCell(); });
+ behavior.setOnSelectPreviousRow(() -> onSelectPreviousCell());
+ behavior.setOnSelectNextRow(() -> onSelectNextCell());
+ behavior.setOnSelectLeftCell(() -> onSelectLeftCell());
+ behavior.setOnSelectRightCell(() -> onSelectRightCell());
- registerChangeListener(tableView.fixedCellSizeProperty(), "FIXED_CELL_SIZE");
+ registerChangeListener(control.fixedCellSizeProperty(), e -> flow.setFixedCellSize(getSkinnable().getFixedCellSize()));
}
- @Override protected void handleControlPropertyChanged(String p) {
- super.handleControlPropertyChanged(p);
- if ("FIXED_CELL_SIZE".equals(p)) {
- flow.setFixedCellSize(getSkinnable().getFixedCellSize());
- }
- }
/***************************************************************************
* *
- * Listeners *
+ * Public API *
* *
**************************************************************************/
+ /** {@inheritDoc} */
+ @Override public void dispose() {
+ super.dispose();
+ if (behavior != null) {
+ behavior.dispose();
+ }
+ }
- /***************************************************************************
- * *
- * Internal Fields *
- * *
- **************************************************************************/
+ /** {@inheritDoc} */
+ @Override public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
+ switch (attribute) {
+ case SELECTED_ITEMS: {
+ List<Node> selection = new ArrayList<>();
+ TableViewSelectionModel<T> sm = getSkinnable().getSelectionModel();
+ for (TablePosition<T,?> pos : sm.getSelectedCells()) {
+ TableRow<T> row = flow.getPrivateCell(pos.getRow());
+ if (row != null) selection.add(row);
+ }
+ return FXCollections.observableArrayList(selection);
+ }
+ default: return super.queryAccessibleAttribute(attribute, parameters);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void executeAccessibleAction(AccessibleAction action, Object... parameters) {
+ switch (action) {
+ case SHOW_ITEM: {
+ Node item = (Node)parameters[0];
+ if (item instanceof TableCell) {
+ @SuppressWarnings("unchecked")
+ TableCell<T, ?> cell = (TableCell<T, ?>)item;
+ flow.scrollTo(cell.getIndex());
+ }
+ break;
+ }
+ case SET_SELECTED_ITEMS: {
+ @SuppressWarnings("unchecked")
+ ObservableList<Node> items = (ObservableList<Node>)parameters[0];
+ if (items != null) {
+ TableSelectionModel<T> sm = getSkinnable().getSelectionModel();
+ if (sm != null) {
+ sm.clearSelection();
+ for (Node item : items) {
+ if (item instanceof TableCell) {
+ @SuppressWarnings("unchecked")
+ TableCell<T, ?> cell = (TableCell<T, ?>)item;
+ sm.select(cell.getIndex(), cell.getTableColumn());
+ }
+ }
+ }
+ }
+ break;
+ }
+ default: super.executeAccessibleAction(action, parameters);
+ }
+ }
/***************************************************************************
* *
- * Public API *
+ * Private methods *
* *
**************************************************************************/
/** {@inheritDoc} */
- @Override protected ObservableList<TableColumn<T, ?>> getVisibleLeafColumns() {
- return tableView.getVisibleLeafColumns();
+ private TableRow<T> createCell() {
+ TableRow<T> cell;
+
+ TableView<T> tableView = getSkinnable();
+ if (tableView.getRowFactory() != null) {
+ cell = tableView.getRowFactory().call(tableView);
+ } else {
+ cell = new TableRow<T>();
}
- @Override protected int getVisibleLeafIndex(TableColumn<T, ?> tc) {
- return tableView.getVisibleLeafIndex(tc);
+ cell.updateTableView(tableView);
+ return cell;
}
- @Override protected TableColumn<T, ?> getVisibleLeafColumn(int col) {
- return tableView.getVisibleLeafColumn(col);
+ /** {@inheritDoc} */
+ @Override int getItemCount() {
+ TableView<T> tableView = getSkinnable();
+ return tableView.getItems() == null ? 0 : tableView.getItems().size();
}
/** {@inheritDoc} */
- @Override protected TableViewFocusModel<T> getFocusModel() {
- return tableView.getFocusModel();
+ @Override void horizontalScroll() {
+ super.horizontalScroll();
+ if (getSkinnable().getFixedCellSize() > 0) {
+ flow.requestCellLayout();
+ }
}
/** {@inheritDoc} */
- @Override protected TablePosition<T, ?> getFocusedCell() {
- return tableView.getFocusModel().getFocusedCell();
+ @Override ObservableList<TableColumn<T, ?>> getVisibleLeafColumns() {
+ return getSkinnable().getVisibleLeafColumns();
+ }
+
+ @Override int getVisibleLeafIndex(TableColumn<T, ?> tc) {
+ return getSkinnable().getVisibleLeafIndex(tc);
+ }
+
+ @Override TableColumn<T, ?> getVisibleLeafColumn(int col) {
+ return getSkinnable().getVisibleLeafColumn(col);
}
/** {@inheritDoc} */
- @Override protected TableSelectionModel<T> getSelectionModel() {
- return tableView.getSelectionModel();
+ @Override TableViewFocusModel<T> getFocusModel() {
+ return getSkinnable().getFocusModel();
}
/** {@inheritDoc} */
- @Override protected ObjectProperty<Callback<TableView<T>, TableRow<T>>> rowFactoryProperty() {
- return tableView.rowFactoryProperty();
+ @Override TablePosition<T, ?> getFocusedCell() {
+ return getSkinnable().getFocusModel().getFocusedCell();
}
/** {@inheritDoc} */
- @Override protected ObjectProperty<Node> placeholderProperty() {
- return tableView.placeholderProperty();
+ @Override TableSelectionModel<T> getSelectionModel() {
+ return getSkinnable().getSelectionModel();
}
/** {@inheritDoc} */
- @Override protected ObjectProperty<ObservableList<T>> itemsProperty() {
- return tableView.itemsProperty();
+ @Override ObjectProperty<Callback<TableView<T>, TableRow<T>>> rowFactoryProperty() {
+ return getSkinnable().rowFactoryProperty();
}
/** {@inheritDoc} */
- @Override protected ObservableList<TableColumn<T, ?>> getColumns() {
- return tableView.getColumns();
+ @Override ObjectProperty<Node> placeholderProperty() {
+ return getSkinnable().placeholderProperty();
}
/** {@inheritDoc} */
- @Override protected BooleanProperty tableMenuButtonVisibleProperty() {
- return tableView.tableMenuButtonVisibleProperty();
+ @Override ObjectProperty<ObservableList<T>> itemsProperty() {
+ return getSkinnable().itemsProperty();
}
/** {@inheritDoc} */
- @Override protected ObjectProperty<Callback<ResizeFeaturesBase, Boolean>> columnResizePolicyProperty() {
- // TODO Ugly!
- return (ObjectProperty<Callback<ResizeFeaturesBase, Boolean>>) (Object) tableView.columnResizePolicyProperty();
+ @Override ObservableList<TableColumn<T, ?>> getColumns() {
+ return getSkinnable().getColumns();
}
/** {@inheritDoc} */
- @Override protected ObservableList<TableColumn<T,?>> getSortOrder() {
- return tableView.getSortOrder();
+ @Override BooleanProperty tableMenuButtonVisibleProperty() {
+ return getSkinnable().tableMenuButtonVisibleProperty();
}
- @Override protected boolean resizeColumn(TableColumn<T, ?> tc, double delta) {
- return tableView.resizeColumn(tc, delta);
+ /** {@inheritDoc} */
+ @Override ObjectProperty<Callback<ResizeFeaturesBase, Boolean>> columnResizePolicyProperty() {
+ return (ObjectProperty<Callback<ResizeFeaturesBase, Boolean>>) (Object) getSkinnable().columnResizePolicyProperty();
+ }
+
+ /** {@inheritDoc} */
+ @Override ObservableList<TableColumn<T,?>> getSortOrder() {
+ return getSkinnable().getSortOrder();
}
- @Override protected void edit(int index, TableColumn<T, ?> column) {
- tableView.edit(index, (TableColumn<T,?>)column);
+ /** {@inheritDoc} */
+ @Override boolean resizeColumn(TableColumn<T, ?> tc, double delta) {
+ return getSkinnable().resizeColumn(tc, delta);
}
/*
* FIXME: Naive implementation ahead
* Attempts to resize column based on the pref width of all items contained
* in this column. This can be potentially very expensive if the number of
* rows is large.
*/
- @Override protected void resizeColumnToFitContent(TableColumn<T, ?> tc, int maxRows) {
+ /** {@inheritDoc} */
+ @Override void resizeColumnToFitContent(TableColumn<T, ?> tc, int maxRows) {
if (!tc.isResizable()) return;
// final TableColumn<T, ?> col = tc;
List<?> items = itemsProperty().get();
if (items == null || items.isEmpty()) return;
@@ -221,11 +325,11 @@
TableCell<T,?> cell = (TableCell<T, ?>) cellFactory.call(tc);
if (cell == null) return;
// set this property to tell the TableCell we want to know its actual
// preferred width, not the width of the associated TableColumnBase
- cell.getProperties().put(TableCellSkin.DEFER_TO_PARENT_PREF_WIDTH, Boolean.TRUE);
+ cell.getProperties().put(Properties.DEFER_TO_PARENT_PREF_WIDTH, Boolean.TRUE);
// determine cell padding
double padding = 10;
Node n = cell.getSkin() == null ? null : cell.getSkin().getNode();
if (n instanceof Region) {
@@ -235,11 +339,11 @@
int rows = maxRows == -1 ? items.size() : Math.min(items.size(), maxRows);
double maxWidth = 0;
for (int row = 0; row < rows; row++) {
cell.updateTableColumn(tc);
- cell.updateTableView(tableView);
+ cell.updateTableView(getSkinnable());
cell.updateIndex(row);
if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null) {
getChildren().add(cell);
cell.applyCss();
@@ -260,103 +364,12 @@
double headerWidth = headerTextWidth + headerGraphicWidth + 10 + header.snappedLeftInset() + header.snappedRightInset();
maxWidth = Math.max(maxWidth, headerWidth);
// RT-23486
maxWidth += padding;
- if(tableView.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY) {
+ if(getSkinnable().getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY) {
maxWidth = Math.max(maxWidth, tc.getWidth());
}
tc.impl_setWidth(maxWidth);
}
-
- /** {@inheritDoc} */
- @Override public int getItemCount() {
- return tableView.getItems() == null ? 0 : tableView.getItems().size();
- }
-
- /** {@inheritDoc} */
- @Override public TableRow<T> createCell() {
- TableRow<T> cell;
-
- if (tableView.getRowFactory() != null) {
- cell = tableView.getRowFactory().call(tableView);
- } else {
- cell = new TableRow<T>();
- }
-
- cell.updateTableView(tableView);
- return cell;
- }
-
- @Override protected void horizontalScroll() {
- super.horizontalScroll();
- if (getSkinnable().getFixedCellSize() > 0) {
- flow.requestCellLayout();
- }
- }
-
- @Override
- public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
- switch (attribute) {
- case SELECTED_ITEMS: {
- List<Node> selection = new ArrayList<>();
- TableViewSelectionModel<T> sm = getSkinnable().getSelectionModel();
- for (TablePosition<T,?> pos : sm.getSelectedCells()) {
- TableRow<T> row = flow.getPrivateCell(pos.getRow());
- if (row != null) selection.add(row);
- }
- return FXCollections.observableArrayList(selection);
- }
- default: return super.queryAccessibleAttribute(attribute, parameters);
- }
- }
-
- @Override
- protected void executeAccessibleAction(AccessibleAction action, Object... parameters) {
- switch (action) {
- case SHOW_ITEM: {
- Node item = (Node)parameters[0];
- if (item instanceof TableCell) {
- @SuppressWarnings("unchecked")
- TableCell<T, ?> cell = (TableCell<T, ?>)item;
- flow.show(cell.getIndex());
- }
- break;
- }
- case SET_SELECTED_ITEMS: {
- @SuppressWarnings("unchecked")
- ObservableList<Node> items = (ObservableList<Node>)parameters[0];
- if (items != null) {
- TableSelectionModel<T> sm = getSkinnable().getSelectionModel();
- if (sm != null) {
- sm.clearSelection();
- for (Node item : items) {
- if (item instanceof TableCell) {
- @SuppressWarnings("unchecked")
- TableCell<T, ?> cell = (TableCell<T, ?>)item;
- sm.select(cell.getIndex(), cell.getTableColumn());
- }
- }
- }
- }
- break;
- }
- default: super.executeAccessibleAction(action, parameters);
- }
- }
-
- /***************************************************************************
- * *
- * Layout *
- * *
- **************************************************************************/
-
-
-
- /***************************************************************************
- * *
- * Private methods *
- * *
- **************************************************************************/
-
}