1 /*
   2  * Copyright (c) 2011, 2014, 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 javafx.scene.control;
  27 
  28 import com.sun.javafx.event.EventUtil;
  29 import com.sun.javafx.pgstub.StubScene;
  30 
  31 import javafx.beans.property.BooleanProperty;
  32 import javafx.beans.property.SimpleBooleanProperty;
  33 import javafx.scene.Group;
  34 import javafx.scene.Scene;
  35 import javafx.scene.input.KeyCode;
  36 import javafx.scene.input.KeyEvent;
  37 
  38 import org.junit.Before;
  39 import org.junit.Test;
  40 
  41 import static junit.framework.Assert.assertEquals;
  42 import static junit.framework.Assert.assertNotNull;
  43 import static org.junit.Assert.*;
  44 
  45 public class ToggleGroupTest {
  46     private ToggleButton b1, b2, b3, b4;
  47     private ToggleGroup g1, g2;
  48 
  49     private ToggleButton make(String s) {
  50         final ToggleButton btn = new ToggleButton(s);
  51         btn.setId(s);
  52         return btn;
  53     }
  54 
  55     private boolean isMember(ToggleButton b, ToggleGroup g) {
  56         for (Toggle t : g.getToggles()) {
  57             if (t == b) return true;
  58         }
  59         return false;
  60     }
  61 
  62     private boolean isNotMember(ToggleButton b, ToggleGroup g) {
  63         return !isMember(b, g);
  64     }
  65 
  66     @Before public void setup() {
  67         b1 = make("one");
  68         b2 = make("two");
  69         b3 = make("three");
  70         b4 = make("four");
  71         g1 = new ToggleGroup();
  72         g2 = new ToggleGroup();
  73     }
  74 
  75     // really a test of ToggleButton, not ToggleGroup
  76     @Test public void testButtonInit() {
  77         assertFalse(b1.isSelected());
  78         assertNull(b1.getToggleGroup());
  79     }
  80 
  81     @Test public void testGroupInit() {
  82         assertTrue(g1.getToggles().isEmpty());
  83         assertNull(g1.getSelectedToggle());
  84     }
  85 
  86     @Test public void testGroupMembership() {
  87         b1.setToggleGroup(g1);
  88         b2.setToggleGroup(g2);
  89         b3.setToggleGroup(g1);
  90         b4.setToggleGroup(g2);
  91 
  92         assertTrue(isMember(b1, g1));
  93         assertTrue(isMember(b2, g2));
  94         assertTrue(isMember(b3, g1));
  95         assertTrue(isMember(b4, g2));
  96 
  97         b3.setToggleGroup(null);
  98         b4.setToggleGroup(g1);
  99 
 100         assertTrue(isNotMember(b3, g1));
 101         assertTrue(isMember(b4, g1));
 102         assertTrue(isNotMember(b4, g2));
 103     }
 104 
 105     @Test public void testSelectAfterAdding() {
 106         b1.setToggleGroup(g1);
 107         b2.setToggleGroup(g1);
 108         b3.setToggleGroup(g1);
 109 
 110         b1.setSelected(true);
 111         assertTrue(b1.isSelected());
 112         assertEquals(b1, g1.getSelectedToggle());
 113         b2.setSelected(true);
 114         assertFalse(b1.isSelected());
 115         assertTrue(b2.isSelected());
 116         assertEquals(b2, g1.getSelectedToggle());
 117     }
 118 
 119     @Test public void testSelectBeforeAdding1() {
 120         b2.setSelected(true);
 121         b1.setToggleGroup(g1);
 122         b2.setToggleGroup(g1);
 123         b3.setToggleGroup(g1);
 124 
 125         assertFalse(b1.isSelected());
 126         assertTrue(b2.isSelected());
 127         assertFalse(b3.isSelected());
 128         assertEquals(b2, g1.getSelectedToggle());
 129     }
 130 
 131     @Test public void testSelectBeforeAdding2() {
 132         b2.setSelected(true);
 133         b3.setSelected(true);
 134         b1.setToggleGroup(g1);
 135         b2.setToggleGroup(g1);
 136         b3.setToggleGroup(g1);
 137 
 138         assertFalse(b1.isSelected());
 139         assertFalse(b2.isSelected());
 140         assertTrue(b3.isSelected());
 141         assertEquals(b3, g1.getSelectedToggle());
 142     }
 143 
 144     @Test public void testDeselect() {
 145         b2.setSelected(true);
 146         b1.setToggleGroup(g1);
 147         b2.setToggleGroup(g1);
 148         b3.setToggleGroup(g1);
 149         b2.setSelected(false);
 150 
 151         assertFalse(b1.isSelected());
 152         assertFalse(b2.isSelected());
 153         assertFalse(b3.isSelected());
 154         assertNull(g1.getSelectedToggle());
 155     }
 156 
 157     @Test public void testSetSelected() {
 158         b1.setToggleGroup(g1);
 159         b2.setToggleGroup(g1);
 160         b3.setToggleGroup(g1);
 161 
 162         g1.selectToggle(b1);
 163         assertEquals(b1, g1.getSelectedToggle());
 164         assertTrue(b1.isSelected());
 165         assertFalse(b2.isSelected());
 166         assertFalse(b3.isSelected());
 167 
 168         g1.selectToggle(b2);
 169         assertEquals(b2, g1.getSelectedToggle());
 170         assertFalse(b1.isSelected());
 171         assertTrue(b2.isSelected());
 172         assertFalse(b3.isSelected());
 173 
 174         g1.selectToggle(null);
 175         assertNull(g1.getSelectedToggle());
 176         assertFalse(b1.isSelected());
 177         assertFalse(b2.isSelected());
 178         assertFalse(b3.isSelected());
 179     }
 180 
 181     @Test public void testSetSelectedWrongGroup() {
 182         b1.setToggleGroup(g1);
 183         b2.setToggleGroup(g1);
 184         b3.setToggleGroup(g2);
 185         b4.setToggleGroup(g2);
 186         g1.selectToggle(b1);
 187         g2.selectToggle(b3);
 188 
 189         assertTrue(b1.isSelected());
 190         assertFalse(b2.isSelected());
 191         assertTrue(b3.isSelected());
 192         assertFalse(b4.isSelected());
 193         assertEquals(b1, g1.getSelectedToggle());
 194         assertEquals(b3, g2.getSelectedToggle());
 195 
 196         // this is illegal, nothing should change
 197         g2.selectToggle(b2);
 198 
 199         assertTrue(b1.isSelected());
 200         assertFalse(b2.isSelected());
 201         assertTrue(b3.isSelected());
 202         assertFalse(b4.isSelected());
 203         assertEquals(b1, g1.getSelectedToggle());
 204         assertEquals(b3, g2.getSelectedToggle());
 205     }
 206 
 207     @Test public void testSetSelectedWrongGroup2() {
 208         b1.setToggleGroup(g1);
 209         b2.setToggleGroup(g1);
 210         b3.setToggleGroup(g2);
 211         b4.setToggleGroup(g2);
 212         g1.selectToggle(b1);
 213         g2.selectToggle(b3);
 214 
 215         assertTrue(b1.isSelected());
 216         assertFalse(b2.isSelected());
 217         assertTrue(b3.isSelected());
 218         assertFalse(b4.isSelected());
 219         assertEquals(b1, g1.getSelectedToggle());
 220         assertEquals(b3, g2.getSelectedToggle());
 221 
 222         // this is illegal, nothing should change
 223         g2.selectToggle(b1);
 224 
 225         assertTrue(b1.isSelected());
 226         assertFalse(b2.isSelected());
 227         assertTrue(b3.isSelected());
 228         assertFalse(b4.isSelected());
 229         assertEquals(b1, g1.getSelectedToggle());
 230         assertEquals(b3, g2.getSelectedToggle());
 231     }
 232 
 233     // RT-3977
 234     @Test public void testAddMultipleSelected() {
 235         b1.setSelected(true);
 236         b2.setSelected(true);
 237         b3.setSelected(true);
 238         b1.setToggleGroup(g1);
 239         b2.setToggleGroup(g1);
 240         b3.setToggleGroup(g1);
 241 
 242         assertFalse(b1.isSelected());
 243         assertFalse(b2.isSelected());
 244         assertTrue(b3.isSelected());
 245         assertEquals(b3, g1.getSelectedToggle());
 246     }
 247 
 248     // remove an unselected button
 249     // remove selected button
 250     @Test public void testRemoveSelected() {
 251         b1.setToggleGroup(g1);
 252         b2.setToggleGroup(g1);
 253         b3.setToggleGroup(g1);
 254         b2.setSelected(true);
 255 
 256         b2.setToggleGroup(g2);
 257         assertFalse(b1.isSelected());
 258         assertTrue(b2.isSelected());
 259         assertFalse(b3.isSelected());
 260         assertNull(g1.getSelectedToggle());
 261         assertEquals(b2, g2.getSelectedToggle());
 262     }
 263 
 264     @Test public void testRemoveUnselected() {
 265         b1.setToggleGroup(g1);
 266         b2.setToggleGroup(g1);
 267         b3.setToggleGroup(g1);
 268         b2.setSelected(true);
 269 
 270         b3.setToggleGroup(g2);
 271         assertFalse(b1.isSelected());
 272         assertTrue(b2.isSelected());
 273         assertFalse(b3.isSelected());
 274         assertEquals(b2, g1.getSelectedToggle());
 275     }
 276 
 277     @Test public void selectButtonInToggleGroupThenUnselectIt_ToggleGroup_getSelectedToggle_ShouldReturnNull() {
 278         b1.setToggleGroup(g1);
 279         b2.setToggleGroup(g1);
 280         assertFalse(b1.isSelected());
 281         assertFalse(b2.isSelected());
 282         assertNull(g1.getSelectedToggle());
 283 
 284         b1.setSelected(true);
 285         assertTrue(b1.isSelected());
 286         assertSame(b1, g1.getSelectedToggle());
 287 
 288         b1.setSelected(false);
 289         assertFalse(b1.isSelected());
 290         assertFalse(b2.isSelected());
 291         assertNull(g1.getSelectedToggle());
 292     }
 293 
 294     @Test public void settingSelectedToggleAndThenCreatingAModelAndReadingTheValueStillWorks() {
 295         b1.setToggleGroup(g1);
 296         b2.setToggleGroup(g1);
 297         b3.setToggleGroup(g1);
 298         g1.selectToggle(b1);
 299         assertSame(b1, g1.selectedToggleProperty().get());
 300         assertTrue(b1.isSelected());
 301     }
 302 
 303 //    if (old == null || old.getToggleGroup() == ToggleGroup.this || !old.isSelected())
 304 //    @Test public void foo() {
 305 //        // old != null
 306 //        // old.getToggleGroup() != this
 307 //        // old.isSelected (or is it, old is not selected?)
 308 //        b1.setToggleGroup(g1);
 309 //        b2.setToggleGroup(g1);
 310 //        b1.setSelected(true);
 311 //        b1.setToggleGroup(g2);
 312 //        assertNull(g1.getSelectedToggle());
 313 //        assertTrue(b1.isSelected());
 314 //        assertFalse(b2.isSelected());
 315 //    }
 316 
 317     // I just removed support for binding the "selectedToggle" property of the ToggleGroup.
 318     // This was done because, as the following tests were beginning to demonstrate, the
 319     // ToggleGroup simply begins to fail in its function as a mechanism for enforcing
 320     // mutual exclusivity when you allow it to be bound. Likewise, the ability to
 321     // bind the "selected" state of the individual Toggles is also suspect, for the same
 322     // reason. Although since a Toggle (such as a RadioButton) doesn't have to be placed
 323     // into a ToggleGroup, it does make sense to allow that to be bound. In which case,
 324     // if two bound toggles are in the same ToggleGroup, then while both of the Toggles
 325     // may claim to be selected, the ToggleGroup will only allow one of them (and it
 326     // might be arbitrary as to which it is) to be bound.
 327 
 328     // I just want to make sure, really, that there is no exception here in this case and
 329     // that one of the "selected" toggles is actually selected
 330     @Test public void bindingTwoTogglesSelectedBothToTrueResultsInOnlyOneBeingSelectedOnTheToggleGroup() {
 331         BooleanProperty selected = new SimpleBooleanProperty(true);
 332         b1.setToggleGroup(g1);
 333         b2.setToggleGroup(g1);
 334         b3.setToggleGroup(g1);
 335         b1.selectedProperty().bind(selected);
 336         b2.selectedProperty().bind(selected);
 337         assertTrue(b1.isSelected());
 338         assertTrue(b2.isSelected());
 339         assertTrue(g1.getSelectedToggle() == b1 || g1.getSelectedToggle() == b2);
 340     }
 341 
 342     // Basically, if you manually bind the "selected" state of an external toggle, it doesn't really
 343     // impact what the selected item is in the toggle group. It is simply, the last toggle to be set
 344     // true, wins, as far as the toggle group is concerned.
 345     @Test public void bindingTwoTogglesSelectedBothToTrueAndManuallySelectingAThirdResultsInTheThirdBeingSelected() {
 346         BooleanProperty selected = new SimpleBooleanProperty(true);
 347         b1.setToggleGroup(g1);
 348         b2.setToggleGroup(g1);
 349         b3.setToggleGroup(g1);
 350         b1.selectedProperty().bind(selected);
 351         b2.selectedProperty().bind(selected);
 352         g1.selectToggle(b3);
 353         assertTrue(b1.isSelected());
 354         assertTrue(b2.isSelected());
 355         assertTrue(b3.isSelected());
 356         assertSame(b3, g1.getSelectedToggle());
 357     }
 358 
 359     @Test public void settingTheSelectedToggleAndThenBindingAnotherToTrueResultsInTheBoundToggleBeingSelected() {
 360         BooleanProperty selected = new SimpleBooleanProperty(true);
 361         b1.setToggleGroup(g1);
 362         b2.setToggleGroup(g1);
 363         b3.setToggleGroup(g1);
 364         g1.selectToggle(b3);
 365         b1.selectedProperty().bind(selected);
 366         assertTrue(b1.isSelected());
 367         assertFalse(b3.isSelected());
 368         assertEquals(b1, g1.getSelectedToggle());
 369     }
 370 
 371     @Test public void addingTogglesUsingToggleGroupGetToggles() {
 372         g1.getToggles().add(b1);
 373         g1.getToggles().add(b2);
 374         assertTrue(isMember(b1, g1));
 375         assertTrue(isMember(b2, g1));
 376     }
 377 
 378     @Test public void addingTogglesUsingToggleGroupGetTogglesAndToggleSetToggleGroup() {
 379         g1.getToggles().add(b1);
 380         g1.getToggles().add(b2);
 381         b3.setToggleGroup(g1);
 382         assertTrue(isMember(b1, g1));
 383         assertTrue(isMember(b2, g1));
 384         assertTrue(isMember(b3, g1));
 385     }
 386 
 387     @Test public void removingTogglesUsingToggleGroupGetToggles() {
 388         g1.getToggles().add(b1);
 389         g1.getToggles().remove(b2);
 390         assertTrue(isMember(b1, g1));
 391         assertTrue(isNotMember(b2, g1));
 392     }
 393 
 394     @Test public void removingTogglesUsingToggleGroupGetTogglesAndToggleSetToggleGroup() {
 395         g1.getToggles().add(b1);
 396         g1.getToggles().remove(b2);
 397         b3.setToggleGroup(g1);
 398         assertTrue(isMember(b1, g1));
 399         assertTrue(isNotMember(b2, g1));
 400         assertTrue(isMember(b3, g1));
 401     }
 402 
 403     @Test public void addingTogglesUsingToggleGroupGetTogglesSetAll() {
 404         g1.getToggles().setAll(b1, b2, b3);
 405         assertTrue(isMember(b1, g1));
 406         assertTrue(isMember(b2, g1));
 407         assertTrue(isMember(b3, g1));
 408     }
 409 
 410     @Test public void addingTogglesUsingToggleGroupGetTogglesSetAllAndSet() {
 411         g1.getToggles().setAll(b1, b2, b3);
 412         g1.getToggles().set(0, b4);
 413         assertTrue(isNotMember(b1, g1));
 414         assertTrue(isMember(b2, g1));
 415         assertTrue(isMember(b3, g1));
 416         assertTrue(isMember(b4, g1));
 417     }
 418 
 419     @Test public void addingTogglesUsingToggleGroupGetTogglesSetAllTwice() {
 420         g1.getToggles().setAll(b1, b2);
 421         g1.getToggles().setAll(b3, b4);
 422         assertTrue(isNotMember(b1, g1));
 423         assertTrue(isNotMember(b2, g1));
 424         assertTrue(isMember(b3, g1));
 425         assertTrue(isMember(b4, g1));
 426     }
 427 
 428     @Test public void addingTogglesUsingToggleGroupGetTogglesSetAllAndAddAll() {
 429         g1.getToggles().setAll(b1, b2);
 430         g1.getToggles().addAll(b3, b4);
 431         assertTrue(isMember(b1, g1));
 432         assertTrue(isMember(b2, g1));
 433         assertTrue(isMember(b3, g1));
 434         assertTrue(isMember(b4, g1));
 435     }
 436 
 437     @Test public void addingDuplicateTogglesUsingToggleGroupGetTogglesAddAllAndSetToggleGroup() {
 438         b1.setToggleGroup(g1);
 439         try {
 440             g1.getToggles().addAll(b1, b2);
 441             fail("Duplicates are not allowed");
 442         } catch(IllegalArgumentException iae) {            
 443             assertNotNull(iae);
 444         }        
 445     }
 446 
 447     @Test public void addingDuplicateTogglesUsingToggleGroupGetTogglesSetAllTwice() {
 448         g1.getToggles().setAll(b1, b2);
 449         g1.getToggles().setAll(b1, b3, b4);
 450         assertTrue(isMember(b1, g1));
 451         assertTrue(isNotMember(b2, g1));
 452         assertTrue(isMember(b3, g1));
 453         assertTrue(isMember(b4, g1));
 454     }
 455 
 456     @Test public void addingFromOneTogglesUsingToggleGroupGetTogglesToAnother() {
 457         g1.getToggles().setAll(b1, b2);
 458         g2.getToggles().setAll(b1, b3);
 459         assertTrue(isNotMember(b1, g1));
 460         assertTrue(isMember(b1, g2));
 461         assertTrue(isMember(b2, g1));
 462         assertTrue(isMember(b3, g2));
 463     }
 464 
 465     @Test public void arrowKeysSelectTogglesTogetherWithFocus() {
 466 
 467         Group root = new Group();
 468 
 469         Scene scene = new Scene(root);
 470         root.getChildren().addAll(b1, b2, b3);
 471         root.applyCss(); // Initilize the skin
 472 
 473         g1.getToggles().setAll(b1, b2, b3);
 474 
 475         g1.selectToggle(b1);
 476 
 477         assertTrue(b1.isSelected());
 478         assertFalse(b2.isSelected());
 479         assertFalse(b3.isSelected());
 480 
 481         EventUtil.fireEvent(new KeyEvent(null, b1, KeyEvent.KEY_PRESSED, "", "", KeyCode.RIGHT, false, false, false, false),
 482                 b1);
 483 
 484         assertFalse(b1.isSelected());
 485         assertTrue(b2.isSelected());
 486         assertFalse(b3.isSelected());
 487 
 488         EventUtil.fireEvent(new KeyEvent(null, b2, KeyEvent.KEY_PRESSED, "", "", KeyCode.DOWN, false, false, false, false),
 489                 b2);
 490 
 491         assertFalse(b1.isSelected());
 492         assertFalse(b2.isSelected());
 493         assertTrue(b3.isSelected());
 494 
 495         EventUtil.fireEvent(new KeyEvent(null, b3, KeyEvent.KEY_PRESSED, "", "", KeyCode.UP, false, false, false, false),
 496                 b3);
 497 
 498         assertFalse(b1.isSelected());
 499         assertTrue(b2.isSelected());
 500         assertFalse(b3.isSelected());
 501 
 502         EventUtil.fireEvent(new KeyEvent(null, b2, KeyEvent.KEY_PRESSED, "", "", KeyCode.LEFT, false, false, false, false),
 503                 b2);
 504 
 505         assertTrue(b1.isSelected());
 506         assertFalse(b2.isSelected());
 507         assertFalse(b3.isSelected());
 508     }
 509 
 510     @Test public void testSelectingTwiceIsNop() {
 511         b1.setToggleGroup(g1);
 512         b2.setToggleGroup(g1);
 513 
 514         assertFalse(b1.isSelected());
 515         assertFalse(b2.isSelected());
 516 
 517         g1.selectToggle(b1);
 518         assertTrue(b1.isSelected());
 519         assertFalse(b2.isSelected());
 520         assertEquals(g1.getSelectedToggle(), b1);
 521 
 522         g1.selectToggle(b1);
 523         assertTrue(b1.isSelected());
 524         assertFalse(b2.isSelected());
 525         assertEquals(g1.getSelectedToggle(), b1);
 526     }
 527     
 528     @Test public void testProperties() {
 529         javafx.collections.ObservableMap<Object, Object> properties = g1.getProperties();
 530 
 531         /* If we ask for it, we should get it.
 532          */
 533         assertNotNull(properties);
 534 
 535         /* What we put in, we should get out.
 536          */
 537         properties.put("MyKey", "MyValue");
 538         assertEquals("MyValue", properties.get("MyKey"));
 539 
 540         /* If we ask for it again, we should get the same thing.
 541          */
 542         javafx.collections.ObservableMap<Object, Object> properties2 = g1.getProperties();
 543         assertEquals(properties2, properties);
 544 
 545         /* What we put in to the other one, we should get out of this one because
 546          * they should be the same thing.
 547          */
 548         assertEquals("MyValue", properties2.get("MyKey"));
 549     }
 550 }