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.robot.javafx.scene.tableview;
  27 
  28 import com.sun.glass.ui.Robot;
  29 import javafx.application.Application;
  30 import javafx.application.Platform;
  31 import javafx.scene.control.TableColumn;
  32 import javafx.scene.control.TableView;
  33 import javafx.scene.Scene;
  34 import javafx.stage.Stage;
  35 import javafx.stage.StageStyle;
  36 import javafx.stage.WindowEvent;
  37 
  38 import javafx.beans.property.SimpleObjectProperty;
  39 import java.util.concurrent.CountDownLatch;
  40 import java.util.concurrent.TimeUnit;
  41 
  42 import org.junit.AfterClass;
  43 import org.junit.Assert;
  44 import org.junit.BeforeClass;
  45 import org.junit.Test;
  46 import static org.junit.Assert.fail;
  47 
  48 /*
  49  * Test to verify TableView resizeColumnToFitContent with
  50  * column resize policy set to CONSTRAINED_RESIZE_POLICY.
  51  */
  52 public class TableViewResizeColumnToFitContentTest {
  53 
  54     static Robot robot;
  55     static TableView<TableObject> table;
  56     static volatile Stage stage;
  57     static volatile Scene scene;
  58     static final int SCENE_WIDTH = 450;
  59     static final int SCENE_HEIGHT = 100;
  60     static CountDownLatch startupLatch;
  61 
  62     public static void main(String[] args) {
  63         TableViewResizeColumnToFitContentTest test =
  64                 new TableViewResizeColumnToFitContentTest();
  65         test.resizeColumnToFitContentTest();
  66     }
  67 
  68     @Test
  69     public void resizeColumnToFitContentTest() {
  70         double colOneWidth = table.getColumns().get(0).getWidth();
  71         double colTwoWidth = table.getColumns().get(1).getWidth();
  72         double colThreeWidth = table.getColumns().get(2).getWidth();
  73         double colsWidthBeforeResize = colOneWidth + colTwoWidth + colThreeWidth;
  74         double colHeaderHeight = 25;
  75         double posX = scene.getWindow().getX() + table.getLayoutX() +
  76                 colOneWidth + colTwoWidth;
  77         double posY = scene.getWindow().getY() + table.getLayoutY() +
  78                 colHeaderHeight / 2;
  79 
  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 != table.getColumns().get(1).getWidth()));
  97         colTwoWidth = table.getColumns().get(1).getWidth();
  98         colThreeWidth = table.getColumns().get(2).getWidth();
  99         double colsWidthAfterResize = colOneWidth + colTwoWidth + colThreeWidth;
 100         Assert.assertEquals("TableView.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                 TableViewResizeColumnToFitContentTest.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             table = new TableView<>();
 140             TableColumn<TableObject, String> column;
 141             column = new TableColumn<>("First Name");
 142             column.setCellValueFactory((d) -> d.getValue().firstNameProperty);
 143             table.getColumns().add(column);
 144 
 145             column = new TableColumn<>("Description");
 146             column.setCellValueFactory((d) -> d.getValue().descriptionProperty);
 147             table.getColumns().add(column);
 148 
 149             column = new TableColumn<>("Last Name");
 150             column.setCellValueFactory((d) -> d.getValue().lastNameProperty);
 151             table.getColumns().add(column);
 152             table.getItems().add(
 153                     new TableObject("John", "Doe", 
 154                             "Currently wearing brown pants"));
 155             table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
 156 
 157             scene = new Scene(table, SCENE_WIDTH, SCENE_HEIGHT);
 158             stage.setScene(scene);
 159             stage.initStyle(StageStyle.UNDECORATED);
 160             stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e
 161                     -> Platform.runLater(startupLatch::countDown));
 162             stage.setAlwaysOnTop(true);
 163             stage.show();
 164         }
 165     }
 166 
 167     private static final class TableObject {
 168 
 169         private final SimpleObjectProperty<String> firstNameProperty;
 170         private final SimpleObjectProperty<String> lastNameProperty;
 171         private final SimpleObjectProperty<String> descriptionProperty;
 172 
 173         public TableObject(String firstName, String lastName, 
 174                 String description) {
 175             this.firstNameProperty = new SimpleObjectProperty<>(firstName);
 176             this.lastNameProperty = new SimpleObjectProperty<>(lastName);
 177             this.descriptionProperty = new SimpleObjectProperty<>(description);
 178         }
 179     }
 180 
 181 }