--- old/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkin.java 2018-04-12 15:20:29.265330700 +0530 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkin.java 2018-04-12 15:20:27.975572800 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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 @@ -262,11 +262,22 @@ // RT-23486 maxWidth += padding; - if(tableView.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY) { - maxWidth = Math.max(maxWidth, tc.getWidth()); - } + if (tableView.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY && tableView.getWidth() > 0) { + + if (maxWidth > tc.getMaxWidth()) { + maxWidth = tc.getMaxWidth(); + } - tc.impl_setWidth(maxWidth); + int size = tc.getColumns().size(); + if (size > 0) { + resizeColumnToFitContent(tc.getColumns().get(size - 1), maxRows); + return; + } + + resizeColumn(tc, Math.round(maxWidth - tc.getWidth())); + } else { + tc.impl_setWidth(maxWidth); + } } /** {@inheritDoc} */ --- old/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeTableViewSkin.java 2018-04-12 15:20:37.607998900 +0530 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeTableViewSkin.java 2018-04-12 15:20:36.293736100 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018, 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 @@ -351,11 +351,22 @@ // RT-23486 maxWidth += padding; - if(treeTableView.getColumnResizePolicy() == TreeTableView.CONSTRAINED_RESIZE_POLICY) { - maxWidth = Math.max(maxWidth, col.getWidth()); - } + if (treeTableView.getColumnResizePolicy() == TreeTableView.CONSTRAINED_RESIZE_POLICY && treeTableView.getWidth() > 0) { + + if (maxWidth > tc.getMaxWidth()) { + maxWidth = tc.getMaxWidth(); + } - col.impl_setWidth(maxWidth); + int size = tc.getColumns().size(); + if (size > 0) { + resizeColumnToFitContent(tc.getColumns().get(size - 1), maxRows); + return; + } + + resizeColumn(tc, Math.round(maxWidth - tc.getWidth())); + } else { + col.impl_setWidth(maxWidth); + } } /** {@inheritDoc} */ --- /dev/null 2018-04-12 15:20:46.000000000 +0530 +++ new/tests/system/src/test/java/test/robot/javafx/scene/tableview/TableViewResizeColumnToFitContentTest.java 2018-04-12 15:20:44.750927200 +0530 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018, 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.robot.javafx.scene.tableview; + +import com.sun.glass.ui.Robot; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.Scene; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.stage.WindowEvent; + +import javafx.beans.property.SimpleObjectProperty; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.fail; + +/* + * Test to verify TableView resizeColumnToFitContent with + * column resize policy set to CONSTRAINED_RESIZE_POLICY. + */ +public class TableViewResizeColumnToFitContentTest { + + static Robot robot; + static TableView table; + static volatile Stage stage; + static volatile Scene scene; + static final int SCENE_WIDTH = 450; + static final int SCENE_HEIGHT = 100; + static CountDownLatch startupLatch; + + public static void main(String[] args) { + TableViewResizeColumnToFitContentTest test = + new TableViewResizeColumnToFitContentTest(); + test.resizeColumnToFitContentTest(); + } + + @Test + public void resizeColumnToFitContentTest() { + double colOneWidth = table.getColumns().get(0).getWidth(); + double colTwoWidth = table.getColumns().get(1).getWidth(); + double colThreeWidth = table.getColumns().get(2).getWidth(); + double colsWidthBeforeResize = colOneWidth + colTwoWidth + colThreeWidth; + double colHeaderHeight = 25; + double posX = scene.getWindow().getX() + table.getLayoutX() + + colOneWidth + colTwoWidth; + double posY = scene.getWindow().getY() + table.getLayoutY() + + colHeaderHeight / 2; + + CountDownLatch latch = new CountDownLatch(1); + Platform.runLater(() -> { + robot.mouseMove((int) posX, (int) posY); + robot.mousePress(Robot.MOUSE_LEFT_BTN); + robot.mouseRelease(Robot.MOUSE_LEFT_BTN); + robot.mousePress(Robot.MOUSE_LEFT_BTN); + robot.mouseRelease(Robot.MOUSE_LEFT_BTN); + latch.countDown(); + }); + waitForLatch(latch, 5, "Timeout while waiting for mouse double click"); + try { + Thread.sleep(1000); // Delay for table resizing of table columns. + } catch (Exception e) { + fail("Thread was interrupted." + e); + } + Assert.assertTrue("resizeColumnToFitContent failed", + (colTwoWidth != table.getColumns().get(1).getWidth())); + colTwoWidth = table.getColumns().get(1).getWidth(); + colThreeWidth = table.getColumns().get(2).getWidth(); + double colsWidthAfterResize = colOneWidth + colTwoWidth + colThreeWidth; + Assert.assertEquals("TableView.CONSTRAINED_RESIZE_POLICY ignored.", + colsWidthBeforeResize, colsWidthAfterResize, 0); + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch( + TableViewResizeColumnToFitContentTest.TestApp.class, + (String[]) null)).start(); + waitForLatch(startupLatch, 10, "Timeout waiting for FX runtime to start"); + } + + @AfterClass + public static void exit() { + Platform.runLater(() -> { + stage.hide(); + }); + Platform.exit(); + } + + public static void waitForLatch(CountDownLatch latch, + int seconds, String msg) { + try { + if (!latch.await(seconds, TimeUnit.SECONDS)) { + fail(msg); + } + } catch (Exception ex) { + fail("Unexpected exception: " + ex); + } + } + + public static class TestApp extends Application { + + @Override + public void start(Stage primaryStage) { + robot = com.sun.glass.ui.Application.GetApplication().createRobot(); + stage = primaryStage; + + table = new TableView<>(); + TableColumn column; + column = new TableColumn<>("First Name"); + column.setCellValueFactory((d) -> d.getValue().firstNameProperty); + table.getColumns().add(column); + + column = new TableColumn<>("Description"); + column.setCellValueFactory((d) -> d.getValue().descriptionProperty); + table.getColumns().add(column); + + column = new TableColumn<>("Last Name"); + column.setCellValueFactory((d) -> d.getValue().lastNameProperty); + table.getColumns().add(column); + table.getItems().add( + new TableObject("John", "Doe", + "Currently wearing brown pants")); + table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + + scene = new Scene(table, SCENE_WIDTH, SCENE_HEIGHT); + stage.setScene(scene); + stage.initStyle(StageStyle.UNDECORATED); + stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e + -> Platform.runLater(startupLatch::countDown)); + stage.setAlwaysOnTop(true); + stage.show(); + } + } + + private static final class TableObject { + + private final SimpleObjectProperty firstNameProperty; + private final SimpleObjectProperty lastNameProperty; + private final SimpleObjectProperty descriptionProperty; + + public TableObject(String firstName, String lastName, + String description) { + this.firstNameProperty = new SimpleObjectProperty<>(firstName); + this.lastNameProperty = new SimpleObjectProperty<>(lastName); + this.descriptionProperty = new SimpleObjectProperty<>(description); + } + } + +} --- /dev/null 2018-04-12 15:20:53.000000000 +0530 +++ new/tests/system/src/test/java/test/robot/javafx/scene/treetableview/TreeTableViewResizeColumnToFitContentTest.java 2018-04-12 15:20:51.554787700 +0530 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2018, 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.robot.scene.treetableview; + +import com.sun.glass.ui.Robot; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.scene.control.cell.TreeItemPropertyValueFactory; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeTableColumn; +import javafx.scene.control.TreeTableView; +import javafx.scene.Scene; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.stage.WindowEvent; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.fail; + +/* + * Test to verify treeTableView resizeColumnToFitContent with + * column resize policy set to CONSTRAINED_RESIZE_POLICY. + */ +public class TreeTableViewResizeColumnToFitContentTest { + + static Robot robot; + static TreeTableView treeTableView; + static volatile Stage stage; + static volatile Scene scene; + static final int SCENE_WIDTH = 450; + static final int SCENE_HEIGHT = 100; + static CountDownLatch startupLatch; + + public static void main(String[] args) { + TreeTableViewResizeColumnToFitContentTest test = + new TreeTableViewResizeColumnToFitContentTest(); + test.resizeColumnToFitContentTest(); + } + + @Test + public void resizeColumnToFitContentTest() { + double colOneWidth = treeTableView.getColumns().get(0).getWidth(); + double colTwoWidth = treeTableView.getColumns().get(1).getWidth(); + double colThreeWidth = treeTableView.getColumns().get(2).getWidth(); + double colsWidthBeforeResize = colOneWidth + colTwoWidth + colThreeWidth; + double colHeaderHeight = 25; + double posX = scene.getWindow().getX() + treeTableView.getLayoutX() + + colOneWidth + colTwoWidth; + double posY = scene.getWindow().getY() + treeTableView.getLayoutY() + + colHeaderHeight / 2; + CountDownLatch latch = new CountDownLatch(1); + Platform.runLater(() -> { + robot.mouseMove((int) posX, (int) posY); + robot.mousePress(Robot.MOUSE_LEFT_BTN); + robot.mouseRelease(Robot.MOUSE_LEFT_BTN); + robot.mousePress(Robot.MOUSE_LEFT_BTN); + robot.mouseRelease(Robot.MOUSE_LEFT_BTN); + latch.countDown(); + }); + waitForLatch(latch, 5, "Timeout while waiting for mouse double click"); + try { + Thread.sleep(1000); // Delay for table resizing of table columns. + } catch (Exception e) { + fail("Thread was interrupted." + e); + } + Assert.assertTrue("resizeColumnToFitContent failed", + (colTwoWidth != treeTableView.getColumns().get(1).getWidth())); + colTwoWidth = treeTableView.getColumns().get(1).getWidth(); + colThreeWidth = treeTableView.getColumns().get(2).getWidth(); + double colsWidthAfterResize = colOneWidth + colTwoWidth + colThreeWidth; + Assert.assertEquals("TreeTableView.CONSTRAINED_RESIZE_POLICY ignored.", + colsWidthBeforeResize, colsWidthAfterResize, 0); + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch( + TreeTableViewResizeColumnToFitContentTest.TestApp.class, + (String[]) null)).start(); + waitForLatch(startupLatch, 10, "Timeout waiting for FX runtime to start"); + } + + @AfterClass + public static void exit() { + Platform.runLater(() -> { + stage.hide(); + }); + Platform.exit(); + } + + public static void waitForLatch(CountDownLatch latch, + int seconds, String msg) { + try { + if (!latch.await(seconds, TimeUnit.SECONDS)) { + fail(msg); + } + } catch (Exception ex) { + fail("Unexpected exception: " + ex); + } + } + + public static class TestApp extends Application { + + @Override + public void start(Stage primaryStage) { + robot = com.sun.glass.ui.Application.GetApplication().createRobot(); + stage = primaryStage; + + treeTableView = new TreeTableView<>(); + TreeTableColumn firstNameCol + = new TreeTableColumn<>("First Name"); + + TreeTableColumn lastNameCol + = new TreeTableColumn<>("Last Name"); + + TreeTableColumn descriptionCol + = new TreeTableColumn<>("Description"); + + firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory("firstName")); + descriptionCol.setCellValueFactory(new TreeItemPropertyValueFactory("description")); + lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory("lastName")); + + treeTableView.getColumns().addAll(firstNameCol, descriptionCol, lastNameCol); + treeTableView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); + + Person person = new Person("John", "Currently wearing brown pants", "Doe" ); + TreeItem itemRoot = new TreeItem(person); + treeTableView.setRoot(itemRoot); + + scene = new Scene(treeTableView, SCENE_WIDTH, SCENE_HEIGHT); + stage.setScene(scene); + stage.initStyle(StageStyle.UNDECORATED); + stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(startupLatch::countDown)); + stage.setAlwaysOnTop(true); + stage.show(); + } + } + + public static final class Person { + + private String firstName; + private String description; + private String lastName; + + public Person(String firstName, String description, String lastName) { + this.firstName = firstName; + this.description = description; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + } +}