1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.robot.scene.treetableview;
  27 
  28 import com.sun.glass.ui.Robot;
  29 import javafx.application.Application;
  30 import javafx.application.Platform;
  31 import javafx.scene.control.cell.TreeItemPropertyValueFactory;
  32 import javafx.scene.control.TreeItem;
  33 import javafx.scene.control.TreeTableColumn;
  34 import javafx.scene.control.TreeTableView;
  35 import javafx.scene.Scene;
  36 import javafx.stage.Stage;
  37 import javafx.stage.StageStyle;
  38 import javafx.stage.WindowEvent;
  39 
  40 import java.util.concurrent.CountDownLatch;
  41 import java.util.concurrent.TimeUnit;
  42 
  43 import org.junit.AfterClass;
  44 import org.junit.Assert;
  45 import org.junit.BeforeClass;
  46 import org.junit.Test;
  47 import static org.junit.Assert.fail;
  48 
  49 /*
  50  * Test to verify treeTableView resizeColumnToFitContent with
  51  * column resize policy set to CONSTRAINED_RESIZE_POLICY.
  52  */
  53 public class TreeTableViewResizeColumnToFitContentTest {
  54 
  55     static Robot robot;
  56     static TreeTableView<Person> treeTableView;
  57     static volatile Stage stage;
  58     static volatile Scene scene;
  59     static final int SCENE_WIDTH = 450;
  60     static final int SCENE_HEIGHT = 100;
  61     static CountDownLatch startupLatch;
  62 
  63     public static void main(String[] args) {
  64         TreeTableViewResizeColumnToFitContentTest test =
  65                 new TreeTableViewResizeColumnToFitContentTest();
  66         test.resizeColumnToFitContentTest();
  67     }
  68 
  69     @Test
  70     public void resizeColumnToFitContentTest() {
  71         double colOneWidth = treeTableView.getColumns().get(0).getWidth();
  72         double colTwoWidth = treeTableView.getColumns().get(1).getWidth();
  73         double colThreeWidth = treeTableView.getColumns().get(2).getWidth();
  74         double colsWidthBeforeResize = colOneWidth + colTwoWidth + colThreeWidth;
  75         double colHeaderHeight = 25;
  76         double posX = scene.getWindow().getX() + treeTableView.getLayoutX() +
  77                 colOneWidth + colTwoWidth;
  78         double posY = scene.getWindow().getY() + treeTableView.getLayoutY() +
  79                 colHeaderHeight / 2;
  80         CountDownLatch latch = new CountDownLatch(1);
  81         Platform.runLater(() -> {
  82             robot.mouseMove((int) posX, (int) posY);
  83             robot.mousePress(Robot.MOUSE_LEFT_BTN);
  84             robot.mouseRelease(Robot.MOUSE_LEFT_BTN);
  85             robot.mousePress(Robot.MOUSE_LEFT_BTN);
  86             robot.mouseRelease(Robot.MOUSE_LEFT_BTN);
  87             latch.countDown();
  88         });
  89         waitForLatch(latch, 5, "Timeout while waiting for mouse double click");
  90         try {
  91             Thread.sleep(1000); // Delay for table resizing of table columns.
  92         } catch (Exception e) {
  93             fail("Thread was interrupted." + e);
  94         }
  95         Assert.assertTrue("resizeColumnToFitContent failed",
  96                 (colTwoWidth != treeTableView.getColumns().get(1).getWidth()));
  97         colTwoWidth = treeTableView.getColumns().get(1).getWidth();
  98         colThreeWidth = treeTableView.getColumns().get(2).getWidth();
  99         double colsWidthAfterResize = colOneWidth + colTwoWidth + colThreeWidth;
 100         Assert.assertEquals("TreeTableView.CONSTRAINED_RESIZE_POLICY ignored.",
 101                 colsWidthBeforeResize, colsWidthAfterResize, 0);
 102     }
 103 
 104     @BeforeClass
 105     public static void initFX() {
 106         startupLatch = new CountDownLatch(1);
 107         new Thread(() -> Application.launch(
 108                 TreeTableViewResizeColumnToFitContentTest.TestApp.class,
 109                 (String[]) null)).start();
 110         waitForLatch(startupLatch, 10, "Timeout waiting for FX runtime to start");
 111     }
 112 
 113     @AfterClass
 114     public static void exit() {
 115         Platform.runLater(() -> {
 116             stage.hide();
 117         });
 118         Platform.exit();
 119     }
 120 
 121     public static void waitForLatch(CountDownLatch latch,
 122                                     int seconds, String msg) {
 123         try {
 124             if (!latch.await(seconds, TimeUnit.SECONDS)) {
 125                 fail(msg);
 126             }
 127         } catch (Exception ex) {
 128             fail("Unexpected exception: " + ex);
 129         }
 130     }
 131 
 132     public static class TestApp extends Application {
 133 
 134         @Override
 135         public void start(Stage primaryStage) {
 136             robot = com.sun.glass.ui.Application.GetApplication().createRobot();
 137             stage = primaryStage;
 138 
 139             treeTableView = new TreeTableView<>();
 140             TreeTableColumn<Person, String> firstNameCol
 141                     = new TreeTableColumn<>("First Name");
 142 
 143             TreeTableColumn<Person, String> lastNameCol
 144                     = new TreeTableColumn<>("Last Name");
 145 
 146             TreeTableColumn<Person, String> descriptionCol
 147                     = new TreeTableColumn<>("Description");
 148 
 149             firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
 150             descriptionCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("description"));
 151             lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName"));
 152 
 153             treeTableView.getColumns().addAll(firstNameCol, descriptionCol, lastNameCol);
 154             treeTableView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
 155 
 156             Person person = new Person("John", "Currently wearing brown pants", "Doe" );
 157             TreeItem<Person> itemRoot = new TreeItem<Person>(person);
 158             treeTableView.setRoot(itemRoot);
 159 
 160             scene = new Scene(treeTableView, SCENE_WIDTH, SCENE_HEIGHT);
 161             stage.setScene(scene);
 162             stage.initStyle(StageStyle.UNDECORATED);
 163             stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e ->
 164                     Platform.runLater(startupLatch::countDown));
 165             stage.setAlwaysOnTop(true);
 166             stage.show();
 167         }
 168     }
 169 
 170     public static final class Person {
 171 
 172         private String firstName;
 173         private String description;
 174         private String lastName;
 175 
 176         public Person(String firstName, String description, String lastName) {
 177             this.firstName = firstName;
 178             this.description = description;
 179             this.lastName = lastName;
 180         }
 181 
 182         public String getFirstName() {
 183             return firstName;
 184         }
 185 
 186         public void setFirstName(String firstName) {
 187             this.firstName = firstName;
 188         }
 189 
 190         public String getLastName() {
 191             return lastName;
 192         }
 193 
 194         public void setLastName(String lastName) {
 195             this.lastName = lastName;
 196         }
 197 
 198         public String getDescription() {
 199             return description;
 200         }
 201 
 202         public void setDescription(String description) {
 203             this.description = description;
 204         }
 205     }
 206 }