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.java.javafx.scene;
  27 
  28 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
  29 import com.sun.javafx.scene.control.infrastructure.KeyModifier;
  30 import javafx.application.Platform;
  31 import javafx.scene.Group;
  32 import javafx.scene.Scene;
  33 import javafx.scene.control.Button;
  34 import javafx.scene.control.ToggleButton;
  35 import javafx.scene.control.ToggleGroup;
  36 import javafx.scene.input.KeyCode;
  37 import javafx.scene.input.KeyCodeCombination;
  38 import javafx.scene.layout.GridPane;
  39 import javafx.scene.layout.Pane;
  40 import javafx.scene.layout.Priority;
  41 import javafx.scene.layout.HBox;
  42 import javafx.scene.layout.VBox;
  43 import javafx.scene.layout.StackPane;
  44 import javafx.scene.paint.Color;
  45 import javafx.scene.shape.Rectangle;
  46 import javafx.stage.Stage;
  47 import java.util.ArrayList;
  48 import java.util.List;
  49 import org.junit.Test;
  50 import testharness.VisualTestBase;
  51 import static org.junit.Assert.assertEquals;
  52 
  53 /**
  54  * A visual styling regression has been fixed under JDK8183100.
  55  * This test validates it.
  56  */
  57 public class JDK8183100Test extends VisualTestBase {
  58 
  59     private Stage testStage;
  60     private Scene testScene;
  61     private int count = 0;
  62     private final double TOLERANCE = 0.07;
  63     static List<TabContents> TAB_CONTENTS = new ArrayList<>();
  64 
  65     class TabContents extends StackPane {
  66         public TabContents() {
  67             // It is important that this node has some styling,
  68             // either via setStyle() or getStyleClass().add().
  69             setStyle("-fx-background-color: blue");
  70 
  71             Platform.runLater(() -> {
  72                 TAB_CONTENTS.add(this);
  73                 TAB_CONTENTS.forEach(TabContents::fillWithFreshYellowPane);
  74             });
  75         }
  76 
  77         void fillWithFreshYellowPane() {
  78             Pane yellowPane = new Pane();
  79             yellowPane.setStyle("-fx-background-color: yellow");
  80             getChildren().setAll(yellowPane);
  81         }
  82     }
  83 
  84     @Test(timeout=15000)
  85     public void stackPaneColorTest() {
  86         final int WIDTH = 200;
  87         final int HEIGHT = 100;
  88 
  89         // Top half of the app: Horizontal navigation bar above the application.
  90         Button addTabButton = new Button("Add tab");
  91         HBox tabBar = new HBox(addTabButton);
  92 
  93         // Bottom half of the app: The actual tab contents.
  94         StackPane container = new StackPane();
  95 
  96         // It is important that this node has some styling,
  97         // either via setStyle() or getStyleClass().add().
  98         container.setStyle("-fx-background-color: red");
  99         VBox.setVgrow(container, Priority.ALWAYS);
 100 
 101         VBox root = new VBox(tabBar, container);
 102 
 103         ToggleGroup group = new ToggleGroup();
 104 
 105         addTabButton.setOnAction(unused -> {
 106             ToggleButton tb = new ToggleButton("Tab "+count);
 107             count++;
 108 
 109             TabContents contents = new TabContents();
 110             runAndWait(() -> {
 111                 tb.setToggleGroup(group);
 112                 tb.setSelected(true);
 113                 tabBar.getChildren().add(tb);
 114 
 115                 // Immediately select the new tab...
 116                 container.getChildren().setAll(contents);
 117             });
 118 
 119             // Add key accelerator for 'Tab 0' button only
 120             if (count == 1) {
 121                 tb.getScene().getAccelerators().put(
 122                     new KeyCodeCombination(KeyCode.DIGIT0, KeyCodeCombination.CONTROL_DOWN),
 123                     new Runnable() {
 124                         @Override public void run() {
 125                            tb.fire();
 126                         }
 127                     });
 128             }
 129 
 130             tb.setOnAction(actionEvent -> {
 131                 container.getChildren().setAll(contents);
 132             });
 133         });
 134 
 135         runAndWait(() -> {
 136             testStage = getStage();
 137             testScene = new Scene(root, WIDTH, HEIGHT);
 138 
 139             testStage.setScene(testScene);
 140 
 141             // Add key accelerator for addTabButton
 142             addTabButton.getScene().getAccelerators().put(
 143             new KeyCodeCombination(KeyCode.A, KeyCodeCombination.CONTROL_DOWN),
 144             new Runnable() {
 145                 @Override public void run() {
 146                     addTabButton.fire();
 147                 }
 148             });
 149 
 150             testStage.show();
 151         });
 152 
 153         waitFirstFrame();
 154 
 155         KeyEventFirer keyboard = new KeyEventFirer(testScene);
 156 
 157         // Add 3 buttons by pressing Ctrl+A on keyboard
 158         for (int i = 0; i < 3; i++) {
 159             keyboard.doKeyPress(KeyCode.A, KeyModifier.CTRL);
 160             assertEquals(i+1, count);
 161         }
 162 
 163         // Select Tab0 by pressing Ctrl+0
 164         runAndWait(() -> {
 165             keyboard.doKeyPress(KeyCode.DIGIT0, KeyModifier.CTRL);
 166         });
 167 
 168         runAndWait(() -> {
 169             Color color = getColor(testScene, 100, 50); // center pixel of scene
 170             assertColorEquals(Color.YELLOW, color, TOLERANCE);
 171         });
 172     }
 173 }
 174