changeset 10873:f82a2e491b72

8192800: Table auto resize ignores column resize policy Reviewed-by: kcr
author pkbalakr
date Tue, 13 Mar 2018 15:20:46 +0530
parents a78490a8d5fa
children bfcdf46bbe23
files modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java tests/system/src/test/java/test/robot/javafx/scene/tableview/TableViewResizeColumnToFitContentTest.java tests/system/src/test/java/test/robot/javafx/scene/treetableview/TreeTableViewResizeColumnToFitContentTest.java
diffstat 3 files changed, 418 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java	Mon Mar 12 21:32:16 2018 +0530
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableSkinUtils.java	Tue Mar 13 15:20:46 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -140,11 +140,22 @@
 
         // RT-23486
         maxWidth += padding;
-        if(tv.getColumnResizePolicy() == TableView.CONSTRAINED_RESIZE_POLICY) {
-            maxWidth = Math.max(maxWidth, tc.getWidth());
+        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);
         }
-
-        TableColumnBaseHelper.setWidth(tc, maxWidth);
     }
 
 
@@ -215,11 +226,22 @@
 
         // RT-23486
         maxWidth += padding;
-        if(ttv.getColumnResizePolicy() == TreeTableView.CONSTRAINED_RESIZE_POLICY) {
-            maxWidth = Math.max(maxWidth, tc.getWidth());
+        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);
         }
-
-        TableColumnBaseHelper.setWidth(tc, maxWidth);
     }
 
     public static ObjectProperty<Callback<ResizeFeaturesBase,Boolean>> columnResizePolicyProperty(TableViewSkinBase<?,?,?,?,?> tableSkin) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/test/robot/javafx/scene/tableview/TableViewResizeColumnToFitContentTest.java	Tue Mar 13 15:20:46 2018 +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<TableObject> 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<TableObject, String> 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<String> firstNameProperty;
+        private final SimpleObjectProperty<String> lastNameProperty;
+        private final SimpleObjectProperty<String> 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	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/test/robot/javafx/scene/treetableview/TreeTableViewResizeColumnToFitContentTest.java	Tue Mar 13 15:20:46 2018 +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.robot.javafx.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<Person> 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<Person, String> firstNameCol
+                    = new TreeTableColumn<>("First Name");
+
+            TreeTableColumn<Person, String> lastNameCol
+                    = new TreeTableColumn<>("Last Name");
+
+            TreeTableColumn<Person, String> descriptionCol
+                    = new TreeTableColumn<>("Description");
+
+            firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
+            descriptionCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("description"));
+            lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName"));
+
+            treeTableView.getColumns().addAll(firstNameCol, descriptionCol, lastNameCol);
+            treeTableView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
+
+            Person person = new Person("John", "Currently wearing brown pants", "Doe" );
+            TreeItem<Person> itemRoot = new TreeItem<Person>(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;
+        }
+    }
+}