1 /*
   2  * Copyright (c) 2010, 2017, 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.scene.control;
  27 
  28 import javafx.scene.control.skin.MenuButtonSkin;
  29 import com.sun.javafx.tk.Toolkit;
  30 import javafx.beans.property.SimpleObjectProperty;
  31 import javafx.geometry.Side;
  32 import javafx.scene.Scene;
  33 import javafx.scene.Group;
  34 import javafx.scene.control.ContentDisplay;
  35 import javafx.scene.control.Button;
  36 import javafx.scene.control.MenuButton;
  37 import javafx.scene.control.MenuItem;
  38 import javafx.scene.layout.VBox;
  39 import javafx.scene.shape.Rectangle;
  40 import javafx.stage.Stage;
  41 import javafx.event.Event;
  42 import javafx.event.EventHandler;
  43 
  44 import org.junit.Before;
  45 import org.junit.Test;
  46 
  47 import static org.junit.Assert.*;
  48 
  49 /**
  50  *
  51  * @author lubermud
  52  */
  53 public class MenuButtonTest {
  54     private MenuButton menuButton;
  55 
  56     @Before public void setup() {
  57         menuButton = new MenuButton();
  58     }
  59 
  60     @Test public void defaultConstructorShouldHaveNoGraphic() {
  61         assertNull(menuButton.getGraphic());
  62     }
  63 
  64     @Test public void defaultConstructorShouldHaveNullString() {
  65         assertEquals("", menuButton.getText());
  66     }
  67 
  68     @Test public void oneArgConstructorShouldHaveNoGraphic1() {
  69         MenuButton mb2 = new MenuButton(null);
  70         assertNull(mb2.getGraphic());
  71     }
  72 
  73     @Test public void oneArgConstructorShouldHaveNoGraphic2() {
  74         MenuButton mb2 = new MenuButton("");
  75         assertNull(mb2.getGraphic());
  76     }
  77 
  78     @Test public void oneArgConstructorShouldHaveNoGraphic3() {
  79         MenuButton mb2 = new MenuButton("Hello");
  80         assertNull(mb2.getGraphic());
  81     }
  82 
  83     @Test public void oneArgConstructorShouldHaveSpecifiedString1() {
  84         MenuButton mb2 = new MenuButton(null);
  85         assertEquals("", mb2.getText());
  86     }
  87 
  88     @Test public void oneArgConstructorShouldHaveSpecifiedString2() {
  89         MenuButton mb2 = new MenuButton("");
  90         assertEquals("", mb2.getText());
  91     }
  92 
  93     @Test public void oneArgConstructorShouldHaveSpecifiedString3() {
  94         MenuButton mb2 = new MenuButton("Hello");
  95         assertEquals("Hello", mb2.getText());
  96     }
  97 
  98     @Test public void twoArgConstructorShouldHaveSpecifiedGraphic1() {
  99         MenuButton mb2 = new MenuButton(null, null);
 100         assertNull(mb2.getGraphic());
 101     }
 102 
 103     @Test public void twoArgConstructorShouldHaveSpecifiedGraphic2() {
 104         Rectangle rect = new Rectangle();
 105         MenuButton mb2 = new MenuButton("Hello", rect);
 106         assertSame(rect, mb2.getGraphic());
 107     }
 108 
 109     @Test public void twoArgConstructorShouldHaveSpecifiedString1() {
 110         MenuButton mb2 = new MenuButton(null, null);
 111         assertEquals("", mb2.getText());
 112     }
 113 
 114     @Test public void twoArgConstructorShouldHaveSpecifiedString2() {
 115         Rectangle rect = new Rectangle();
 116         MenuButton mb2 = new MenuButton("Hello", rect);
 117         assertEquals("Hello", mb2.getText());
 118     }
 119 
 120     @Test public void getItemsDefaultNotNull() {
 121         assertNotNull(menuButton.getItems());
 122     }
 123 
 124     @Test public void getItemsDefaultSizeZero() {
 125         assertEquals(0, menuButton.getItems().size());
 126     }
 127 
 128     @Test public void getItemsAddable() {
 129         menuButton.getItems().add(new MenuItem());
 130         assertTrue(menuButton.getItems().size() > 0);
 131     }
 132 
 133     @Test public void getItemsClearable() {
 134         menuButton.getItems().add(new MenuItem());
 135         menuButton.getItems().clear();
 136         assertEquals(0, menuButton.getItems().size());
 137     }
 138 
 139     @Test public void defaultIsShowingFalse() {
 140         assertFalse(menuButton.isShowing());
 141     }
 142 
 143     @Test public void showIsShowingTrue() {
 144         menuButton.show();
 145         assertTrue(menuButton.isShowing());
 146     }
 147 
 148     @Test public void hideIsShowingFalse1() {
 149         menuButton.hide();
 150         assertFalse(menuButton.isShowing());
 151     }
 152 
 153     @Test public void hideIsShowingFalse2() {
 154         menuButton.show();
 155         menuButton.hide();
 156         assertFalse(menuButton.isShowing());
 157     }
 158 
 159     @Test public void getUnspecifiedShowingProperty1() {
 160         assertNotNull(menuButton.showingProperty());
 161     }
 162 
 163     @Test public void getUnspecifiedShowingProperty2() {
 164         MenuButton mb2 = new MenuButton("", null);
 165         assertNotNull(mb2.showingProperty());
 166     }
 167 
 168     @Test public void unsetShowingButNotNull() {
 169         menuButton.showingProperty();
 170         assertNotNull(menuButton.isShowing());
 171     }
 172 
 173     @Test public void menuButtonIsFiredIsNoOp() {
 174         menuButton.fire(); // should throw no exceptions, if it does, the test fails
 175     }
 176 
 177     @Test public void defaultPopupSide() {
 178         assertEquals(Side.BOTTOM, menuButton.getPopupSide());
 179         assertEquals(Side.BOTTOM, menuButton.popupSideProperty().get());
 180     }
 181 
 182     @Test public void setNullPopupSide() {
 183         menuButton.setPopupSide(null);
 184         assertNull(menuButton.getPopupSide());
 185     }
 186 
 187     @Test public void setSpecifiedPopupSide() {
 188         Side side = Side.TOP;
 189         menuButton.setPopupSide(side);
 190         assertSame(side, menuButton.getPopupSide());
 191     }
 192 
 193     @Test public void getUnspecifiedPopupSideProperty1() {
 194         assertNotNull(menuButton.popupSideProperty());
 195     }
 196 
 197     @Test public void getUnspecifiedPopupSideProperty2() {
 198         MenuButton mb2 = new MenuButton("", null);
 199         assertNotNull(mb2.popupSideProperty());
 200     }
 201 
 202     @Test public void unsetPopupSideButNotNull() {
 203         menuButton.popupSideProperty();
 204         assertNotNull(menuButton.getPopupSide());
 205     }
 206 
 207     @Test public void popupSideCanBeBound() {
 208         Side side = Side.TOP;
 209         SimpleObjectProperty<Side> other = new SimpleObjectProperty<Side>(menuButton, "popupSide", side);
 210         menuButton.popupSideProperty().bind(other);
 211         assertSame(side, menuButton.getPopupSide());
 212     }
 213 
 214     //TODO: test show()/isShowing() for disabled=true
 215     //TODO: test MenuButton.impl_getPsuedoClassState
 216 
 217     @Test
 218     public void test_RT_21894() {
 219 
 220         // Bug reproduces by setting opacity on the MenuButton
 221         // then moving focus on and off the MenuButton
 222         final MenuButton mb = new MenuButton();
 223         mb.setText("SomeText");
 224 
 225         MenuButtonSkin mbs = new MenuButtonSkin(mb);
 226         mb.setSkin(mbs);
 227 
 228         Button other = new Button("other");
 229         // Doesn't have to be done this way, but this more closely duplicates
 230         // the example code in the bug report.
 231         other.setOnAction(t -> {
 232             mb.setOpacity(.5);
 233         });
 234 
 235         VBox vbox = new VBox();
 236         vbox.getChildren().addAll(mb, other);
 237         Scene scene = new Scene(vbox, 300, 300);
 238         Stage stage = new Stage();
 239         stage.setScene(scene);
 240         stage.show();
 241         stage.requestFocus();
 242 
 243         other.requestFocus();
 244         assertFalse(mb.isFocused());
 245 
 246         // set opacity on MenuButton
 247         other.fire();
 248 
 249         // focus on MenuButton
 250         mb.requestFocus();
 251         assertTrue(mb.isFocused());
 252 
 253         // give css a chance to run
 254         Toolkit.getToolkit().firePulse();
 255 
 256         // focus off the MenuButton
 257         other.requestFocus();
 258         assertFalse(mb.isFocused());
 259 
 260         // give css a chance to run
 261         Toolkit.getToolkit().firePulse();
 262 
 263         // MenuButton should still be 50%
 264         assertEquals(.5, mb.getOpacity(), 0.00001);
 265 
 266     }
 267 
 268     @Test public void testSetContentDisplayGraphicOnly() {
 269         Button btn = new Button("1234");
 270 
 271         MenuButton mb1 = new MenuButton("Sample Text", btn);
 272         mb1.setStyle("-fx-label-padding:0;");
 273         mb1.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
 274 
 275         MenuButton mb2 = new MenuButton("Sample Text", btn);
 276         mb2.setStyle("-fx-label-padding:100;");
 277         mb2.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
 278 
 279         Scene scene = new Scene(new Group(mb1, mb2), 400, 400);
 280         Stage stage = new Stage();
 281         stage.setScene(scene);
 282         stage.show();
 283         Toolkit.getToolkit().firePulse();
 284 
 285         // label-padding should not affect GRAPHIC_ONLY MenuButton size
 286         assertEquals(mb1.getWidth(), mb2.getWidth(), 0.00001);
 287         assertEquals(mb1.getHeight(), mb2.getHeight(), 0.00001);
 288     }
 289 
 290     int onShowingPass;
 291     int onShownPass;
 292     int onHidingPass;
 293     int onHiddenPass;
 294     // Test for JDK-8175963
 295     @Test public void test_jdk_addOnShowHideEvents() {
 296         onShowingPass = 0;
 297         onShownPass = 0;
 298         onHidingPass = 0;
 299         onHiddenPass = 0;
 300         MenuItem it1 = new MenuItem("1");
 301         MenuButton mbtn = new MenuButton("MenuButton", null, it1);
 302 
 303         for (int i = 0; i < 5; ++i) {
 304             mbtn.addEventHandler(MenuButton.ON_SHOWING, event -> {
 305                 assertEquals("event is not of type MenuButton.ON_SHOWING",
 306                     event.getEventType(), MenuButton.ON_SHOWING);
 307                 onShowingPass++;
 308             });
 309             mbtn.addEventHandler(MenuButton.ON_SHOWN, event -> {
 310                 assertEquals("event is not of type MenuButton.ON_SHOWN",
 311                     event.getEventType(), MenuButton.ON_SHOWN);
 312                 onShownPass++;
 313             });
 314             mbtn.addEventHandler(MenuButton.ON_HIDING, event -> {
 315                 assertEquals("event is not of type MenuButton.ON_HIDING",
 316                     event.getEventType(), MenuButton.ON_HIDING);
 317                 onHidingPass++;
 318             });
 319             mbtn.addEventHandler(MenuButton.ON_HIDDEN, event -> {
 320                 assertEquals("event is not of type  MenuButton.ON_HIDDEN",
 321                     event.getEventType(), MenuButton.ON_HIDDEN);
 322                 onHiddenPass++;
 323             });
 324         }
 325 
 326         mbtn.show();
 327         mbtn.hide();
 328 
 329         assertTrue("MenuButton.ON_SHOWING event should be received 5 times. but received: "
 330                     + onShowingPass + " times.", (5 == onShowingPass));
 331         assertTrue("MenuButton.ON_SHOWN event should be received 5 times. but received: "
 332                     + onShownPass + " times.", (5 == onShownPass));
 333         assertTrue("MenuButton.ON_HIDING event should be received 5 times. but received: "
 334                     + onHidingPass + " times.", (5 == onHidingPass));
 335         assertTrue("MenuButton.ON_HIDDEN event should be received 5 times. but received: "
 336                     + onHiddenPass + " times.", (5 == onHiddenPass));
 337     }
 338 
 339 
 340     // Test for JDK-8177633
 341     @Test public void test_jdk_setOnShowHideEvents() {
 342         onShowingPass = 0;
 343         onShownPass = 0;
 344         onHidingPass = 0;
 345         onHiddenPass = 0;
 346         MenuItem it1 = new MenuItem("1");
 347         MenuButton mbtn = new MenuButton("MenuButton", null, it1);
 348         for (int i = 0; i < 5; ++i) {
 349             mbtn.setOnShowing(event -> {
 350                 assertEquals("event is not of type MenuButton.ON_SHOWING",
 351                     event.getEventType(), MenuButton.ON_SHOWING);
 352                 onShowingPass++;;
 353             });
 354             mbtn.setOnShown(event -> {
 355                 assertEquals("event is not of type MenuButton.ON_SHOWN",
 356                     event.getEventType(), MenuButton.ON_SHOWN);
 357                 onShownPass++;
 358             });
 359             mbtn.setOnHiding(event -> {
 360                 assertEquals("event is not of type MenuButton.ON_HIDING",
 361                     event.getEventType(), MenuButton.ON_HIDING);
 362                 onHidingPass++;
 363             });
 364             mbtn.setOnHidden(event -> {
 365                 assertEquals("event is not of type MenuButton.ON_HIDDEN",
 366                     event.getEventType(), MenuButton.ON_HIDDEN);
 367                 onHiddenPass++;
 368             });
 369         }
 370 
 371         mbtn.show();
 372         mbtn.hide();
 373 
 374         assertTrue("MenuButton.ON_SHOWING event should be received only once. but received: "
 375                     + onShowingPass + " times.", (1 == onShowingPass));
 376         assertTrue("MenuButton.ON_SHOWN event should be received only once. but received: "
 377                     + onShownPass + " times.", (1 == onShownPass));
 378         assertTrue("MenuButton.ON_HIDING event should be received only once. but received: "
 379                     + onHidingPass + " times.", (1 == onHidingPass));
 380         assertTrue("MenuButton.ON_HIDDEN event should be received only once. but received: "
 381                     + onHiddenPass + " times.", (1 == onHiddenPass));
 382     }
 383 }