diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java index 20e06fae49e..c34524be811 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java @@ -25,28 +25,28 @@ package javafx.scene.control.skin; -import com.sun.javafx.scene.control.skin.Utils; -import javafx.beans.property.ObjectProperty; -import javafx.collections.WeakListChangeListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicBoolean; - import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; +import javafx.collections.WeakListChangeListener; import javafx.event.EventHandler; import javafx.geometry.NodeOrientation; import javafx.scene.Cursor; import javafx.scene.Node; -import javafx.scene.control.*; +import javafx.scene.control.ResizeFeaturesBase; +import javafx.scene.control.TableColumnBase; +import javafx.scene.control.TableView; +import javafx.scene.control.TreeTableView; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.util.Callback; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + /** *

This class is used to construct the header of a TableView. We take the approach * that every TableView header is nested - even if it isn't. This allows for us @@ -165,7 +165,11 @@ public NestedTableColumnHeader(final TableColumnBase tc) { if (me.getClickCount() == 2 && me.isPrimaryButtonDown()) { // the user wants to resize the column such that its // width is equal to the widest element in the column - TableSkinUtils.resizeColumnToFitContent(header.getTableSkin(), column, -1); + TableHeaderRow tableHeader = header.getTableHeaderRow(); + TableColumnHeader columnHeader = tableHeader.getColumnHeaderFor(column); + if (columnHeader != null) { + columnHeader.resizeColumnToFitContent(-1); + } } else { // rather than refer to the rect variable, we just grab // it from the source to prevent a small memory leak. diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java index daee836443e..c3eefee5b3f 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java @@ -28,6 +28,8 @@ import com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler; import com.sun.javafx.scene.control.Properties; import com.sun.javafx.scene.control.TableColumnBaseHelper; +import com.sun.javafx.scene.control.TreeTableViewBackingList; +import com.sun.javafx.scene.control.skin.Utils; import javafx.beans.property.DoubleProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -40,6 +42,7 @@ import javafx.css.Styleable; import javafx.css.StyleableDoubleProperty; import javafx.css.StyleableProperty; +import javafx.css.converter.SizeConverter; import javafx.event.EventHandler; import javafx.geometry.HPos; import javafx.geometry.Insets; @@ -50,22 +53,27 @@ import javafx.scene.Node; import javafx.scene.control.ContextMenu; import javafx.scene.control.Label; +import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumnBase; +import javafx.scene.control.TableView; +import javafx.scene.control.TreeTableCell; +import javafx.scene.control.TreeTableColumn; +import javafx.scene.control.TreeTableRow; +import javafx.scene.control.TreeTableView; import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.MouseEvent; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; +import javafx.util.Callback; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; -import javafx.css.converter.SizeConverter; - import static com.sun.javafx.scene.control.TableColumnSortTypeWrapper.getSortTypeName; import static com.sun.javafx.scene.control.TableColumnSortTypeWrapper.getSortTypeProperty; import static com.sun.javafx.scene.control.TableColumnSortTypeWrapper.isAscending; @@ -529,7 +537,7 @@ private void updateScene() { if (getTableColumn() == null || getTableColumn().getWidth() != DEFAULT_COLUMN_WIDTH || getScene() == null) { return; } - doColumnAutoSize(getTableColumn(), n); + doColumnAutoSize(n); autoSizeComplete = true; } } @@ -581,13 +589,190 @@ private void initUI() { } } - private void doColumnAutoSize(TableColumnBase column, int cellsToMeasure) { - double prefWidth = column.getPrefWidth(); + private void doColumnAutoSize(int cellsToMeasure) { + double prefWidth = getTableColumn().getPrefWidth(); // if the prefWidth has been set, we do _not_ autosize columns if (prefWidth == DEFAULT_COLUMN_WIDTH) { - TableSkinUtils.resizeColumnToFitContent(getTableSkin(), column, cellsToMeasure); -// getTableViewSkin().resizeColumnToFitContent(column, cellsToMeasure); + resizeColumnToFitContent(cellsToMeasure); + } + } + + /** + * Resizes this {@code TableColumnHeader}'s column to fit the width of its content. + * + * @implSpec The resulting column width for this implementation is the maximum of the preferred width of the header + * cell and the preferred width of the first {@code maxRow} cells. + *

+ * Subclasses can either use this method or override it (without the need to call {@code super()}) to provide their + * custom implementation (such as ones that exclude the header, exclude {@code null} content, compute the minimum + * width, etc.). + * + * @param maxRows the number of rows considered when resizing. If -1 is given, all rows are considered. + * @since 14 + */ + protected void resizeColumnToFitContent(int maxRows) { + TableColumnBase tc = getTableColumn(); + if (!tc.isResizable()) return; + + Object control = this.getTableSkin().getSkinnable(); + if (control instanceof TableView) { + resizeColumnToFitContent((TableView) control, (TableColumn) tc, this.getTableSkin(), maxRows); + } else if (control instanceof TreeTableView) { + resizeColumnToFitContent((TreeTableView) control, (TreeTableColumn) tc, this.getTableSkin(), maxRows); + } + } + + private void resizeColumnToFitContent(TableView tv, TableColumn tc, TableViewSkinBase tableSkin, int maxRows) { + List items = tv.getItems(); + if (items == null || items.isEmpty()) return; + + Callback/*, TableCell>*/ cellFactory = tc.getCellFactory(); + if (cellFactory == null) return; + + TableCell cell = (TableCell) 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(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) { + Region r = (Region) n; + padding = r.snappedLeftInset() + r.snappedRightInset(); + } + + 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(tv); + cell.updateIndex(row); + + if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null) { + tableSkin.getChildren().add(cell); + cell.applyCss(); + maxWidth = Math.max(maxWidth, cell.prefWidth(-1)); + tableSkin.getChildren().remove(cell); + } + } + + // dispose of the cell to prevent it retaining listeners (see RT-31015) + cell.updateIndex(-1); + + // RT-36855 - take into account the column header text / graphic widths. + // Magic 10 is to allow for sort arrow to appear without text truncation. + TableColumnHeader header = tableSkin.getTableHeaderRow().getColumnHeaderFor(tc); + double headerTextWidth = Utils.computeTextWidth(header.label.getFont(), tc.getText(), -1); + Node graphic = header.label.getGraphic(); + double headerGraphicWidth = graphic == null ? 0 : graphic.prefWidth(-1) + header.label.getGraphicTextGap(); + double headerWidth = headerTextWidth + headerGraphicWidth + 10 + header.snappedLeftInset() + header.snappedRightInset(); + maxWidth = Math.max(maxWidth, headerWidth); + + // RT-23486 + maxWidth += padding; + if (tv.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY && tv.getWidth() > 0) { + if (maxWidth > tc.getMaxWidth()) { + maxWidth = tc.getMaxWidth(); + } + + int size = tc.getColumns().size(); + if (size > 0) { + TableColumnHeader columnHeader = getTableHeaderRow().getColumnHeaderFor(tc.getColumns().get(size - 1)); + if (columnHeader != null) { + columnHeader.resizeColumnToFitContent(maxRows); + } + return; + } + + TableSkinUtils.resizeColumn(tableSkin, tc, Math.round(maxWidth - tc.getWidth())); + } else { + TableColumnBaseHelper.setWidth(tc, maxWidth); + } + } + + private void resizeColumnToFitContent(TreeTableView ttv, TreeTableColumn tc, TableViewSkinBase tableSkin, int maxRows) { + List items = new TreeTableViewBackingList(ttv); + if (items == null || items.isEmpty()) return; + + Callback cellFactory = tc.getCellFactory(); + if (cellFactory == null) return; + + TreeTableCell cell = (TreeTableCell) 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(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) { + Region r = (Region) n; + padding = r.snappedLeftInset() + r.snappedRightInset(); + } + + TreeTableRow treeTableRow = new TreeTableRow<>(); + treeTableRow.updateTreeTableView(ttv); + + int rows = maxRows == -1 ? items.size() : Math.min(items.size(), maxRows); + double maxWidth = 0; + for (int row = 0; row < rows; row++) { + treeTableRow.updateIndex(row); + treeTableRow.updateTreeItem(ttv.getTreeItem(row)); + + cell.updateTreeTableColumn(tc); + cell.updateTreeTableView(ttv); + cell.updateTreeTableRow(treeTableRow); + cell.updateIndex(row); + + if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null) { + tableSkin.getChildren().add(cell); + cell.applyCss(); + + double w = cell.prefWidth(-1); + + maxWidth = Math.max(maxWidth, w); + tableSkin.getChildren().remove(cell); + } + } + + // dispose of the cell to prevent it retaining listeners (see RT-31015) + cell.updateIndex(-1); + + // RT-36855 - take into account the column header text / graphic widths. + // Magic 10 is to allow for sort arrow to appear without text truncation. + TableColumnHeader header = tableSkin.getTableHeaderRow().getColumnHeaderFor(tc); + double headerTextWidth = Utils.computeTextWidth(header.label.getFont(), tc.getText(), -1); + Node graphic = header.label.getGraphic(); + double headerGraphicWidth = graphic == null ? 0 : graphic.prefWidth(-1) + header.label.getGraphicTextGap(); + double headerWidth = headerTextWidth + headerGraphicWidth + 10 + header.snappedLeftInset() + header.snappedRightInset(); + maxWidth = Math.max(maxWidth, headerWidth); + + // RT-23486 + maxWidth += padding; + if (ttv.getColumnResizePolicy() == TreeTableView.CONSTRAINED_RESIZE_POLICY && ttv.getWidth() > 0) { + + if (maxWidth > tc.getMaxWidth()) { + maxWidth = tc.getMaxWidth(); + } + + int size = tc.getColumns().size(); + if (size > 0) { + TableColumnHeader columnHeader = getTableHeaderRow().getColumnHeaderFor(tc.getColumns().get(size - 1)); + if (columnHeader != null) { + columnHeader.resizeColumnToFitContent(maxRows); + } + return; + } + + TableSkinUtils.resizeColumn(tableSkin, tc, Math.round(maxWidth - tc.getWidth())); + } else { + TableColumnBaseHelper.setWidth(tc, maxWidth); } } diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java index f1e0419346b..2914e7368f5 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java @@ -71,179 +71,6 @@ public static boolean resizeColumn(TableViewSkinBase tableSkin, Table return false; } - /* - * 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. - */ - /** {@inheritDoc} */ - public static void resizeColumnToFitContent(TableViewSkinBase tableSkin, TableColumnBase tc, int maxRows) { - if (!tc.isResizable()) return; - - Object control = tableSkin.getSkinnable(); - if (control instanceof TableView) { - resizeColumnToFitContent((TableView)control, (TableColumn)tc, tableSkin, maxRows); - } else if (control instanceof TreeTableView) { - resizeColumnToFitContent((TreeTableView)control, (TreeTableColumn)tc, tableSkin, maxRows); - } - } - - private static void resizeColumnToFitContent(TableView tv, TableColumn tc, TableViewSkinBase tableSkin, int maxRows) { - List items = tv.getItems(); - if (items == null || items.isEmpty()) return; - - Callback/*, TableCell>*/ cellFactory = tc.getCellFactory(); - if (cellFactory == null) return; - - TableCell cell = (TableCell) 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(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) { - Region r = (Region) n; - padding = r.snappedLeftInset() + r.snappedRightInset(); - } - - 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(tv); - cell.updateIndex(row); - - if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null) { - tableSkin.getChildren().add(cell); - cell.applyCss(); - maxWidth = Math.max(maxWidth, cell.prefWidth(-1)); - tableSkin.getChildren().remove(cell); - } - } - - // dispose of the cell to prevent it retaining listeners (see RT-31015) - cell.updateIndex(-1); - - // RT-36855 - take into account the column header text / graphic widths. - // Magic 10 is to allow for sort arrow to appear without text truncation. - TableColumnHeader header = tableSkin.getTableHeaderRow().getColumnHeaderFor(tc); - double headerTextWidth = Utils.computeTextWidth(header.label.getFont(), tc.getText(), -1); - Node graphic = header.label.getGraphic(); - double headerGraphicWidth = graphic == null ? 0 : graphic.prefWidth(-1) + header.label.getGraphicTextGap(); - double headerWidth = headerTextWidth + headerGraphicWidth + 10 + header.snappedLeftInset() + header.snappedRightInset(); - maxWidth = Math.max(maxWidth, headerWidth); - - // RT-23486 - maxWidth += padding; - if (tv.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY && tv.getWidth() > 0) { - - if (maxWidth > tc.getMaxWidth()) { - maxWidth = tc.getMaxWidth(); - } - - int size = tc.getColumns().size(); - if (size > 0) { - resizeColumnToFitContent(tableSkin, tc.getColumns().get(size - 1), maxRows); - return; - } - - resizeColumn(tableSkin, tc, Math.round(maxWidth - tc.getWidth())); - } else { - TableColumnBaseHelper.setWidth(tc, maxWidth); - } - } - - - /* - * 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. - */ - private static void resizeColumnToFitContent(TreeTableView ttv, TreeTableColumn tc, TableViewSkinBase tableSkin, int maxRows) { - List items = new TreeTableViewBackingList(ttv); - if (items == null || items.isEmpty()) return; - - Callback cellFactory = tc.getCellFactory(); - if (cellFactory == null) return; - - TreeTableCell cell = (TreeTableCell) 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(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) { - Region r = (Region) n; - padding = r.snappedLeftInset() + r.snappedRightInset(); - } - - TreeTableRow treeTableRow = new TreeTableRow<>(); - treeTableRow.updateTreeTableView(ttv); - - int rows = maxRows == -1 ? items.size() : Math.min(items.size(), maxRows); - double maxWidth = 0; - for (int row = 0; row < rows; row++) { - treeTableRow.updateIndex(row); - treeTableRow.updateTreeItem(ttv.getTreeItem(row)); - - cell.updateTreeTableColumn(tc); - cell.updateTreeTableView(ttv); - cell.updateTreeTableRow(treeTableRow); - cell.updateIndex(row); - - if ((cell.getText() != null && !cell.getText().isEmpty()) || cell.getGraphic() != null) { - tableSkin.getChildren().add(cell); - cell.applyCss(); - - double w = cell.prefWidth(-1); - - maxWidth = Math.max(maxWidth, w); - tableSkin.getChildren().remove(cell); - } - } - - // dispose of the cell to prevent it retaining listeners (see RT-31015) - cell.updateIndex(-1); - - // RT-36855 - take into account the column header text / graphic widths. - // Magic 10 is to allow for sort arrow to appear without text truncation. - TableColumnHeader header = tableSkin.getTableHeaderRow().getColumnHeaderFor(tc); - double headerTextWidth = Utils.computeTextWidth(header.label.getFont(), tc.getText(), -1); - Node graphic = header.label.getGraphic(); - double headerGraphicWidth = graphic == null ? 0 : graphic.prefWidth(-1) + header.label.getGraphicTextGap(); - double headerWidth = headerTextWidth + headerGraphicWidth + 10 + header.snappedLeftInset() + header.snappedRightInset(); - maxWidth = Math.max(maxWidth, headerWidth); - - // RT-23486 - maxWidth += padding; - if (ttv.getColumnResizePolicy() == TreeTableView.CONSTRAINED_RESIZE_POLICY && ttv.getWidth() > 0) { - - if (maxWidth > tc.getMaxWidth()) { - maxWidth = tc.getMaxWidth(); - } - - int size = tc.getColumns().size(); - if (size > 0) { - resizeColumnToFitContent(tableSkin, tc.getColumns().get(size - 1), maxRows); - return; - } - - resizeColumn(tableSkin, tc, Math.round(maxWidth - tc.getWidth())); - } else { - TableColumnBaseHelper.setWidth(tc, maxWidth); - } - } - public static ObjectProperty> columnResizePolicyProperty(TableViewSkinBase tableSkin) { Object control = tableSkin.getSkinnable(); if (control instanceof TableView) { diff --git a/modules/javafx.controls/src/shims/java/javafx/scene/control/skin/TableColumnHeaderShim.java b/modules/javafx.controls/src/shims/java/javafx/scene/control/skin/TableColumnHeaderShim.java index 2cc4351363b..c1ee3b57d64 100644 --- a/modules/javafx.controls/src/shims/java/javafx/scene/control/skin/TableColumnHeaderShim.java +++ b/modules/javafx.controls/src/shims/java/javafx/scene/control/skin/TableColumnHeaderShim.java @@ -56,4 +56,8 @@ public static void columnReordering(TableColumnHeader header, double sceneX, dou public static void columnReorderingComplete(TableColumnHeader header) { header.columnReorderingComplete(); } + + public static void resizeColumnToFitContent(TableColumnHeader header, int nbRows) { + header.resizeColumnToFitContent(nbRows); + } } diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/TableColumnHeaderTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/TableColumnHeaderTest.java new file mode 100644 index 00000000000..6c043ab4d55 --- /dev/null +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/TableColumnHeaderTest.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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 test.javafx.scene.control.skin; + +import com.sun.javafx.tk.Toolkit; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.control.skin.TableColumnHeader; +import org.junit.Before; +import org.junit.After; +import org.junit.Test; +import test.com.sun.javafx.scene.control.infrastructure.StageLoader; +import test.com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils; +import test.com.sun.javafx.scene.control.test.Person; +import javafx.scene.control.skin.TableColumnHeaderShim; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TableColumnHeaderTest { + + private TableColumnHeader firstColumnHeader; + private TableView tableView; + private StageLoader sl; + private static String NAME0 = "Humphrey McPhee"; + private static String NAME1 = "Justice Caldwell"; + private static String NAME2 = "Orrin Davies"; + private static String NAME3 = "Emma Wilson"; + + @Before + public void before() { + ObservableList model = FXCollections.observableArrayList( + new Person(NAME0, 76), + new Person(NAME1, 30), + new Person(NAME2, 30), + new Person(NAME3, 8) + ); + TableColumn column = new TableColumn<>("Col "); + column.setCellValueFactory(new PropertyValueFactory("firstName")); + + tableView = new TableView<>(model); + + tableView.getColumns().add(column); + + sl = new StageLoader(tableView); + Toolkit tk = Toolkit.getToolkit(); + + tk.firePulse(); + //Force the column to have default font, otherwise font Amble is applied and mess with header width size + column.setStyle("-fx-font: System;"); + firstColumnHeader = VirtualFlowTestUtils.getTableColumnHeader(tableView, column); + } + + @After + public void after() { + sl.dispose(); + } + + /** + * @test + * @bug 8207957 + * Resize the column header without modifications + */ + @Test + public void test_resizeColumnToFitContent() { + TableColumn column = tableView.getColumns().get(0); + double width = column.getWidth(); + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, -1); + + assertEquals("Width must be the same", + width, column.getWidth(), 0.001); + } + + /** + * @test + * @bug 8207957 + * Resize the column header with first column increase + */ + @Test + public void test_resizeColumnToFitContentIncrease() { + TableColumn column = tableView.getColumns().get(0); + double width = column.getWidth(); + + tableView.getItems().get(0).setFirstName("This is a big text inside that column"); + + assertEquals("Width must be the same", + width, column.getWidth(), 0.001); + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, -1); + assertTrue("Column width must be greater", + width < column.getWidth()); + + //Back to initial value + tableView.getItems().get(0).setFirstName(NAME0); + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, -1); + assertEquals("Width must be equal to initial value", + width, column.getWidth(), 0.001); + } + + /** + * @test + * @bug 8207957 + * Resize the column header with first column decrease + */ + @Test + public void test_resizeColumnToFitContentDecrease() { + TableColumn column = tableView.getColumns().get(0); + double width = column.getWidth(); + + tableView.getItems().get(0).setFirstName("small"); + tableView.getItems().get(1).setFirstName("small"); + tableView.getItems().get(2).setFirstName("small"); + tableView.getItems().get(3).setFirstName("small"); + + assertEquals("Width must be the same", + width, column.getWidth(), 0.001); + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, -1); + assertTrue("Column width must be smaller", + width > column.getWidth()); + + //Back to initial value + tableView.getItems().get(0).setFirstName(NAME0); + tableView.getItems().get(1).setFirstName(NAME1); + tableView.getItems().get(2).setFirstName(NAME2); + tableView.getItems().get(3).setFirstName(NAME3); + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, -1); + assertEquals("Width must be equal to initial value", + width, column.getWidth(), 0.001); + } + + /** + * @test + * @bug 8207957 + * Resize the column header itself + */ + @Test + public void test_resizeColumnToFitContentHeader() { + TableColumn column = tableView.getColumns().get(0); + double width = column.getWidth(); + + column.setText("This is a big text inside that column"); + + assertEquals("Width must be the same", + width, column.getWidth(), 0.001); + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, -1); + assertTrue("Column width must be greater", + width < column.getWidth()); + + //Back to initial value + column.setText("Col"); + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, 3); + assertEquals("Width must be equal to initial value", + width, column.getWidth(), 0.001); + } + + /** + * @test + * @bug 8207957 + * Resize the column header with only 3 first rows + */ + @Test + public void test_resizeColumnToFitContentMaxRow() { + TableColumn column = tableView.getColumns().get(0); + double width = column.getWidth(); + + tableView.getItems().get(3).setFirstName("This is a big text inside that column"); + + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, 3); + assertEquals("Width must be the same", + width, column.getWidth(), 0.001); + + + //Back to initial value + tableView.getItems().get(3).setFirstName(NAME3); + + + TableColumnHeaderShim.resizeColumnToFitContent(firstColumnHeader, 3); + assertEquals("Width must be equal to initial value", + width, column.getWidth(), 0.001); + } +}