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 test.javafx.scene.input;
  27 
  28 import static javafx.scene.input.KeyCombination.ALT_DOWN;
  29 import static javafx.scene.input.KeyCombination.CONTROL_ANY;
  30 import static javafx.scene.input.KeyCombination.CONTROL_DOWN;
  31 import static javafx.scene.input.KeyCombination.SHIFT_ANY;
  32 import static javafx.scene.input.KeyCombination.SHIFT_DOWN;
  33 import static org.junit.Assert.assertEquals;
  34 import static org.junit.Assert.assertFalse;
  35 import static org.junit.Assert.assertTrue;
  36 
  37 import java.util.HashMap;
  38 import java.util.Map;
  39 
  40 import javafx.event.Event;
  41 import javafx.scene.input.KeyCombination.ModifierValue;
  42 
  43 import org.junit.AfterClass;
  44 import org.junit.BeforeClass;
  45 import org.junit.Test;
  46 
  47 import test.com.sun.javafx.pgstub.StubToolkit;
  48 import com.sun.javafx.scene.input.KeyCodeMap;
  49 import com.sun.javafx.tk.Toolkit;
  50 import javafx.scene.input.KeyCharacterCombination;
  51 import javafx.scene.input.KeyCode;
  52 import javafx.scene.input.KeyCodeCombination;
  53 import javafx.scene.input.KeyCombination;
  54 import javafx.scene.input.KeyEvent;
  55 
  56 
  57 public class KeyCombinationTest {
  58     final KeyEvent ctrlAltQEvent = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  59             "q", null, KeyCodeMap.valueOf(0x51), false, true, true, false);
  60 
  61     final KeyEvent ctrlAltQUpEvent = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_RELEASED, 
  62             "q", null, KeyCodeMap.valueOf(0x51), false, true, true, false);
  63 
  64     final KeyEvent ctrlShiftQEvent = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  65             "Q", null, KeyCodeMap.valueOf(0x51), true, true, false, false);
  66 
  67     final KeyEvent ctrlAltShiftQEvent = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  68             "Q", null, KeyCodeMap.valueOf(0x51), true, true, true, false);
  69 
  70     final KeyEvent alt2Event = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  71             "2", null, KeyCodeMap.valueOf(0x32), false, false, true, false);
  72 
  73     final KeyEvent altShift2Event = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  74             "@", null, KeyCodeMap.valueOf(0x32), true, false, true, false);
  75 
  76     final KeyEvent altSoftkey0Event = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  77             "~", null, KeyCodeMap.valueOf(0x1000), false, false, true, false);
  78 
  79     final KeyEvent altShiftSoftkey0Event = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  80             "~", null, KeyCodeMap.valueOf(0x1000), true, false, true, false);
  81 
  82     final KeyEvent altShiftPlusEvent = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  83             "~", null, KeyCodeMap.valueOf(0x209), true, false, true, false);
  84 
  85     final KeyEvent altShiftQuoteEvent = new KeyEvent(null, Event.NULL_SOURCE_TARGET, KeyEvent.KEY_PRESSED, 
  86             "~", null, KeyCodeMap.valueOf(0xDE), true, false, true, false);
  87 
  88     @BeforeClass
  89     public static void setUpCharToKeyCodeMap() {
  90         final Map<String, KeyCode> charToKeyCodeMap =
  91                 new HashMap<String, KeyCode>();
  92 
  93         // LATIN SMALL LETTER Q
  94         charToKeyCodeMap.put("q", KeyCode.Q);
  95 
  96         // LATIN CAPITAL LETTER Q
  97         charToKeyCodeMap.put("Q", KeyCode.Q);
  98 
  99         // LETTER +
 100         charToKeyCodeMap.put("+", KeyCode.PLUS);
 101 
 102         // LETTER '
 103         charToKeyCodeMap.put("'", KeyCode.QUOTE);
 104 
 105         // LATIN SMALL LETTER E WITH CARON
 106         charToKeyCodeMap.put("\u011b", KeyCode.DIGIT2);
 107 
 108         // CYRILLIC SMALL LETTER SHORT I
 109         charToKeyCodeMap.put("\u0439", KeyCode.Q);
 110 
 111         // CYRILLIC CAPITAL LETTER SHORT I
 112         charToKeyCodeMap.put("\u0419", KeyCode.Q);
 113 
 114         // MUSICAL SYMBOL G CLEF
 115         charToKeyCodeMap.put("\ud834\udd1e", KeyCode.SOFTKEY_0);
 116         
 117         ((StubToolkit) Toolkit.getToolkit()).setCharToKeyCodeMap(
 118                 charToKeyCodeMap);
 119     }
 120 
 121     @AfterClass
 122     public static void tearDownCharToKeyCodeMap() {
 123         ((StubToolkit) Toolkit.getToolkit()).setCharToKeyCodeMap(null);
 124     }
 125 
 126     @Test
 127     public void testSimpleKeyCodeCombination() {
 128         KeyCombination ctrlAltQ = new KeyCodeCombination(KeyCode.Q,
 129                                                          CONTROL_DOWN,
 130                                                          ALT_DOWN);
 131 
 132         KeyCombination altCtrlQ = new KeyCodeCombination(KeyCode.Q,
 133                                                          ALT_DOWN,
 134                                                          CONTROL_DOWN);
 135 
 136         KeyCombination ctrlShiftQ = new KeyCodeCombination(KeyCode.Q,
 137                                                            CONTROL_DOWN,
 138                                                            SHIFT_DOWN);
 139 
 140         KeyCombination ctrlAltShiftQ = new KeyCodeCombination(KeyCode.Q,
 141                                                               CONTROL_DOWN,
 142                                                               ALT_DOWN,
 143                                                               SHIFT_DOWN);
 144 
 145         KeyCombination ctrlQ = new KeyCodeCombination(KeyCode.DIGIT0,
 146                                                       CONTROL_DOWN);
 147 
 148         KeyCombination ctrlAltA = new KeyCodeCombination(KeyCode.A,
 149                                                          CONTROL_DOWN,
 150                                                          ALT_DOWN);
 151 
 152         assertTrue(ctrlAltQ.match(ctrlAltQEvent));
 153         assertFalse(ctrlAltQ.match(ctrlShiftQEvent));
 154         assertTrue(altCtrlQ.match(ctrlAltQEvent));
 155         assertFalse(altCtrlQ.match(ctrlShiftQEvent));
 156         assertFalse(ctrlShiftQ.match(ctrlAltQEvent));
 157         assertTrue(ctrlShiftQ.match(ctrlShiftQEvent));
 158         assertFalse(ctrlAltShiftQ.match(ctrlAltQEvent));
 159         assertFalse(ctrlAltShiftQ.match(ctrlShiftQEvent));
 160         assertFalse(ctrlQ.match(ctrlAltQEvent));
 161         assertFalse(ctrlQ.match(ctrlShiftQEvent));
 162         assertFalse(ctrlAltA.match(ctrlAltQEvent));
 163         assertFalse(ctrlAltA.match(ctrlShiftQEvent));
 164         assertTrue(ctrlAltQ.match(ctrlAltQUpEvent));
 165     }
 166 
 167     @Test
 168     public void testKeyCodeCombinationWithIgnore() {
 169         KeyCombination ctrlAltQ = new KeyCodeCombination(KeyCode.Q,
 170                                                          CONTROL_DOWN,
 171                                                          ALT_DOWN);
 172 
 173         KeyCombination ctrlAltIShiftQ = new KeyCodeCombination(KeyCode.Q,
 174                                                                CONTROL_DOWN,
 175                                                                ALT_DOWN,
 176                                                                SHIFT_ANY);
 177 
 178         KeyCombination ctrlAltShiftQ = new KeyCodeCombination(KeyCode.Q,
 179                                                               CONTROL_DOWN,
 180                                                               ALT_DOWN,
 181                                                               SHIFT_DOWN);
 182 
 183         assertTrue(ctrlAltQ.match(ctrlAltQEvent));
 184         assertFalse(ctrlAltQ.match(ctrlAltShiftQEvent));
 185         assertFalse(ctrlAltShiftQ.match(ctrlAltQEvent));
 186         assertTrue(ctrlAltShiftQ.match(ctrlAltShiftQEvent));
 187         assertTrue(ctrlAltIShiftQ.match(ctrlAltQEvent));
 188         assertTrue(ctrlAltIShiftQ.match(ctrlAltShiftQEvent));
 189     }
 190 
 191     @Test
 192     public void testKeyCodeCombinationFromString() {
 193         KeyCombination ctrlAltQ =
 194                 KeyCombination.keyCombination("Ctrl + ALT+Q");
 195 
 196         KeyCombination altCtrlQ = 
 197                 KeyCombination.keyCombination("alt+CtRL  + q");
 198 
 199         KeyCombination ctrlShiftQ = 
 200                 KeyCombination.keyCombination("ctrl+shift+Q");
 201 
 202         KeyCombination ctrlAltShiftQ =
 203                 KeyCombination.keyCombination("ctrl + Alt + shift + Q");
 204 
 205         KeyCombination ctrlQ = KeyCombination.keyCombination("  ctrl+Q  ");
 206 
 207         KeyCombination ctrlAltA = KeyCombination.keyCombination("ctrl+alt+A");
 208 
 209         KeyCombination ctrlIgnoreAltShiftQ =
 210                 KeyCombination.keyCombination("Ctrl + ignore Alt + Shift + Q");
 211         
 212         KeyCombination ctrlIgnoreAltShiftQWithWS1=
 213                 KeyCombination.keyCombination("Ctrl\t \t\n\f\r\u000B+ \t\n\f \r\u000Bignore Alt\n+ Shift\f + Q");
 214 
 215         KeyCombination ctrlIgnoreAltShiftQWithWS2 =
 216                 KeyCombination.keyCombination("Ctrl\r+ignore Alt\u000B+Shift +Q");
 217 
 218         assertTrue(ctrlAltQ.match(ctrlAltQEvent));
 219         assertFalse(ctrlAltQ.match(ctrlShiftQEvent));
 220         assertTrue(altCtrlQ.match(ctrlAltQEvent));
 221         assertFalse(altCtrlQ.match(ctrlShiftQEvent));
 222         assertFalse(ctrlShiftQ.match(ctrlAltQEvent));
 223         assertTrue(ctrlShiftQ.match(ctrlShiftQEvent));
 224         assertFalse(ctrlAltShiftQ.match(ctrlAltQEvent));
 225         assertFalse(ctrlAltShiftQ.match(ctrlShiftQEvent));
 226         assertFalse(ctrlQ.match(ctrlAltQEvent));
 227         assertFalse(ctrlQ.match(ctrlShiftQEvent));
 228         assertFalse(ctrlAltA.match(ctrlAltQEvent));
 229         assertFalse(ctrlAltA.match(ctrlShiftQEvent));
 230         assertTrue(ctrlAltQ.match(ctrlAltQUpEvent));
 231         assertTrue(ctrlIgnoreAltShiftQ.match(ctrlShiftQEvent));
 232         assertTrue(ctrlIgnoreAltShiftQ.match(ctrlAltShiftQEvent));
 233         assertTrue(ctrlIgnoreAltShiftQWithWS1.match(ctrlAltShiftQEvent));
 234         assertTrue(ctrlIgnoreAltShiftQWithWS2.match(ctrlAltShiftQEvent));
 235     }
 236 
 237     @Test
 238     public void testKeyCharacterCombinationFromString() {
 239         KeyCombination ctrlAltQ = 
 240                 KeyCombination.keyCombination("Ctrl + ALT+'Q'");
 241 
 242         KeyCombination altCtrlQ = 
 243                 KeyCombination.keyCombination("alt+CtRL  + 'q'");
 244 
 245         KeyCombination altLatinSmallEWithCaron =
 246                 KeyCombination.keyCombination("alt+\u011b");
 247 
 248         KeyCombination shiftAltLatinSmallEWithCaron =
 249                 KeyCombination.keyCombination("shift+alt+'\u011b'");
 250 
 251         KeyCombination ctrlShiftCyrillicSmallI =
 252                 KeyCombination.keyCombination("ctrl+shift+\u0439");
 253 
 254         KeyCombination ctrlShiftCyrillicCapitalI =
 255                 KeyCombination.keyCombination("  ctrl+ shift+  \u0419");
 256 
 257         KeyCombination ctrlAltShiftCyrillicSmallI =
 258                 KeyCombination.keyCombination("ctrl + Alt + shift + \u0439");
 259 
 260         KeyCombination altIgnoreShiftMusicalSymbolGClef =
 261                 KeyCombination.keyCombination(
 262                     "Alt + ignore shift + \ud834\udd1e ");
 263 
 264         KeyCombination altShiftPlus =
 265                 KeyCombination.keyCombination("Shift + Alt+'+'");
 266 
 267         KeyCombination altShiftQuote1 =
 268                 KeyCombination.keyCombination("Shift + Alt + '\\''");
 269 
 270         KeyCombination altShiftQuote2 =
 271                 KeyCombination.keyCombination("'\\''+Shift+Alt");
 272 
 273         assertTrue(ctrlAltQ.match(ctrlAltQEvent));
 274         assertFalse(ctrlAltQ.match(ctrlShiftQEvent));
 275         assertTrue(altCtrlQ.match(ctrlAltQEvent));
 276         assertFalse(altCtrlQ.match(ctrlShiftQEvent));
 277         assertTrue(altLatinSmallEWithCaron.match(alt2Event));
 278         assertFalse(altLatinSmallEWithCaron.match(altShift2Event));
 279         assertFalse(shiftAltLatinSmallEWithCaron.match(alt2Event));
 280         assertTrue(shiftAltLatinSmallEWithCaron.match(altShift2Event));
 281         assertTrue(ctrlShiftCyrillicSmallI.match(ctrlShiftQEvent));
 282         assertFalse(ctrlShiftCyrillicSmallI.match(ctrlAltShiftQEvent));
 283         assertTrue(ctrlShiftCyrillicCapitalI.match(ctrlShiftQEvent));
 284         assertFalse(ctrlShiftCyrillicCapitalI.match(ctrlAltShiftQEvent));
 285         assertFalse(ctrlAltShiftCyrillicSmallI.match(ctrlShiftQEvent));
 286         assertTrue(ctrlAltShiftCyrillicSmallI.match(ctrlAltShiftQEvent));
 287         assertTrue(altIgnoreShiftMusicalSymbolGClef.match(altSoftkey0Event));
 288         assertTrue(
 289                 altIgnoreShiftMusicalSymbolGClef.match(altShiftSoftkey0Event));
 290         assertTrue(altShiftPlus.match(altShiftPlusEvent));
 291         assertTrue(altShiftQuote1.match(altShiftQuoteEvent));
 292         assertTrue(altShiftQuote2.match(altShiftQuoteEvent));
 293     }
 294 
 295     @Test
 296     public void testGetName() {
 297         KeyCombination ctrlAltVKQ = new KeyCodeCombination(KeyCode.Q,
 298                                                            CONTROL_DOWN,
 299                                                            ALT_DOWN);
 300 
 301         KeyCombination ctrlAltQ = new KeyCharacterCombination("q",
 302                                                               CONTROL_DOWN,
 303                                                               ALT_DOWN);
 304 
 305         KeyCombination ctrlIgnoreShiftA = new KeyCharacterCombination(
 306                                                 "a",
 307                                                 CONTROL_DOWN,
 308                                                 SHIFT_ANY);
 309 
 310         KeyCombination altQuote = new KeyCharacterCombination(
 311                                                 "'",
 312                                                 ALT_DOWN);
 313 
 314         assertEquals("Ctrl+Alt+Q", ctrlAltVKQ.getName());
 315         assertEquals("Ctrl+Alt+'q'", ctrlAltQ.getName());
 316         assertEquals("Ignore Shift+Ctrl+'a'", ctrlIgnoreShiftA.getName());
 317         assertEquals("Alt+'\\''", altQuote.getName());
 318     }
 319 
 320     @Test
 321     public void testKeyCombinationWithShortcutModifier() {
 322         final KeyEvent ctrlC = new KeyEvent(
 323                                    KeyEvent.KEY_PRESSED,
 324                                    "c", null, KeyCodeMap.valueOf(0x43),
 325                                    false, true, false, false);
 326         final KeyEvent metaC = new KeyEvent(
 327                                    KeyEvent.KEY_PRESSED,
 328                                    "c", null, KeyCodeMap.valueOf(0x43),
 329                                    false, false, false, true);
 330         final KeyEvent metaAltC = new KeyEvent(
 331                                    KeyEvent.KEY_PRESSED,
 332                                       "c", null, KeyCodeMap.valueOf(0x43),
 333                                       false, false, true, true);
 334 
 335         final KeyCombination shortcutC =
 336                 KeyCombination.keyCombination("Shortcut+C");
 337         final KeyCombination altIgnoreShortcutC =
 338                 KeyCombination.keyCombination("Alt+Ignore Shortcut+C");
 339 
 340         final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
 341 
 342         toolkit.setPlatformShortcutKey(KeyCode.SHORTCUT);
 343         assertFalse(shortcutC.match(ctrlC));
 344         assertFalse(shortcutC.match(metaC));
 345         assertFalse(shortcutC.match(metaAltC));
 346         assertFalse(altIgnoreShortcutC.match(ctrlC));
 347         assertFalse(altIgnoreShortcutC.match(metaC));
 348         assertFalse(altIgnoreShortcutC.match(metaAltC));
 349 
 350         toolkit.setPlatformShortcutKey(KeyCode.CONTROL);
 351         assertTrue(shortcutC.match(ctrlC));
 352         assertFalse(shortcutC.match(metaC));
 353         assertFalse(shortcutC.match(metaAltC));
 354         assertFalse(altIgnoreShortcutC.match(ctrlC));
 355         assertFalse(altIgnoreShortcutC.match(metaC));
 356         assertFalse(altIgnoreShortcutC.match(metaAltC));
 357 
 358         toolkit.setPlatformShortcutKey(KeyCode.META);
 359         assertFalse(shortcutC.match(ctrlC));
 360         assertTrue(shortcutC.match(metaC));
 361         assertFalse(shortcutC.match(metaAltC));
 362         assertFalse(altIgnoreShortcutC.match(ctrlC));
 363         assertFalse(altIgnoreShortcutC.match(metaC));
 364         assertTrue(altIgnoreShortcutC.match(metaAltC));
 365     }
 366 
 367     @Test(expected=NullPointerException.class)
 368     public void constructor1ShouldThrowNPEForNullKeyCode() {
 369         new KeyCodeCombination(null, ModifierValue.UP,
 370                                      ModifierValue.UP,
 371                                      ModifierValue.UP,
 372                                      ModifierValue.UP,
 373                                      ModifierValue.UP);
 374     }
 375 
 376     @Test(expected=NullPointerException.class)
 377     public void constructor1ShouldThrowNPEForNullKeyCharacter() {
 378         new KeyCharacterCombination(null, ModifierValue.UP,
 379                                           ModifierValue.UP,
 380                                           ModifierValue.UP,
 381                                           ModifierValue.UP,
 382                                           ModifierValue.UP);
 383     }
 384 
 385     @Test(expected=NullPointerException.class)
 386     public void constructor1ShouldThrowNPEForNullModifier() {
 387         new KeyCodeCombination(KeyCode.Q, ModifierValue.UP,
 388                                           null,
 389                                           ModifierValue.UP,
 390                                           ModifierValue.UP,
 391                                           ModifierValue.UP);
 392     }
 393 
 394     @Test(expected=IllegalArgumentException.class)
 395     public void constructor1ShouldThrowIAEForModifierKeyCode() {
 396         new KeyCodeCombination(KeyCode.SHIFT, ModifierValue.UP,
 397                                               ModifierValue.UP,
 398                                               ModifierValue.UP,
 399                                               ModifierValue.UP,
 400                                               ModifierValue.UP);
 401     }
 402 
 403     @Test(expected=IllegalArgumentException.class)
 404     public void constructor1ShouldThrowIAEForUndefinedKeyCode() {
 405         new KeyCodeCombination(KeyCode.UNDEFINED, ModifierValue.UP,
 406                                                   ModifierValue.UP,
 407                                                   ModifierValue.UP,
 408                                                   ModifierValue.UP,
 409                                                   ModifierValue.UP);
 410     }
 411 
 412     @Test(expected=NullPointerException.class)
 413     public void constructor2ShouldThrowNPEForNullKeyCode() {
 414         new KeyCodeCombination(null);
 415     }
 416 
 417     @Test(expected=NullPointerException.class)
 418     public void constructor2ShouldThrowNPEForNullKeyCharacter() {
 419         new KeyCharacterCombination(null);
 420     }
 421 
 422     @Test(expected=NullPointerException.class)
 423     public void constructor2ShouldThrowNPEForNullModifier() {
 424         new KeyCharacterCombination("q", ALT_DOWN, null, SHIFT_ANY);
 425     }
 426 
 427     @Test(expected=IllegalArgumentException.class)
 428     public void constructor2ShouldThrowIAEForModifierKeyCode() {
 429         new KeyCodeCombination(KeyCode.CONTROL);
 430     }
 431 
 432     @Test(expected=IllegalArgumentException.class)
 433     public void constructor2ShouldThrowIAEForUndefinedKeyCode() {
 434         new KeyCodeCombination(KeyCode.UNDEFINED);
 435     }
 436 
 437     @Test(expected=IllegalArgumentException.class)
 438     public void constructor2ShouldThrowIAEForDuplicateModifiers() {
 439         new KeyCodeCombination(KeyCode.Q, 
 440                                ALT_DOWN,
 441                                CONTROL_DOWN,
 442                                ALT_DOWN);
 443     }
 444 
 445     @Test(expected=IllegalArgumentException.class)
 446     public void constructor2ShouldThrowIAEForConflictingModifiers() {
 447         new KeyCodeCombination(KeyCode.Q,  
 448                                SHIFT_DOWN,
 449                                CONTROL_ANY,
 450                                SHIFT_ANY);
 451     }
 452 
 453     @Test(expected=IllegalArgumentException.class)
 454     public void keyCombinationShouldThrowIAEForDuplicateModifiers() {
 455         KeyCombination.keyCombination("Ctrl + Shift + Ctrl + Q");
 456     }
 457 
 458     @Test(expected=IllegalArgumentException.class)
 459     public void keyCombinationShouldThrowIAEForConflictingModifiers() {
 460         KeyCombination.keyCombination("Ctrl + Ignore Shift + Alt + Shift + Q");
 461     }
 462 
 463     @Test(expected=IllegalArgumentException.class)
 464     public void keyCombinationShouldThrowIAEForMissingMainKey() {
 465         KeyCombination.keyCombination("Ctrl + Shift");
 466     }
 467 
 468     @Test(expected=IllegalArgumentException.class)
 469     public void keyCombinationShouldThrowIAEForUndefinedMainKey() {
 470         KeyCombination.keyCombination("Ctrl + Shift + Undefined");
 471     }
 472 
 473     @Test(expected=IllegalArgumentException.class)
 474     public void keyCombinationShouldThrowIAEForExtraMainKey1() {
 475         KeyCombination.keyCombination("Ctrl + Shift + Q + 'W'");
 476     }
 477 
 478     @Test(expected=IllegalArgumentException.class)
 479     public void keyCombinationShouldThrowIAEForExtraMainKey2() {
 480         KeyCombination.keyCombination("Ctrl + Shift + 'W' + Q");
 481     }
 482 
 483     @Test(expected=IllegalArgumentException.class)
 484     public void keyCombinationShouldThrowIAEForInvalidSyntax1() {
 485         KeyCombination.keyCombination("  +  Ctrl + Q");
 486     }
 487 
 488     @Test(expected=IllegalArgumentException.class)
 489     public void keyCombinationShouldThrowIAEForInvalidSyntax2() {
 490         KeyCombination.keyCombination("Ctrl ++ Q");
 491     }
 492 
 493     @Test(expected=IllegalArgumentException.class)
 494     public void keyCombinationShouldThrowIAEForInvalidSyntax3() {
 495         KeyCombination.keyCombination("Ctrl + Q +");
 496     }
 497 
 498     @Test(expected=IllegalArgumentException.class)
 499     public void keyCombinationShouldThrowIAEForUnclosedQuote() {
 500         KeyCombination.keyCombination("Quote '");
 501     }
 502 
 503     @Test
 504     public void keyCombinationShouldUseUnparseableStringAsCharacter() {
 505         KeyCombination multiChar = KeyCombination.keyCombination("Alt'Q'\\'");
 506         assertEquals("Alt'Q'\\'",
 507                 ((KeyCharacterCombination) multiChar).getCharacter());
 508     }
 509 
 510 
 511 
 512 
 513     // ------ Tests for getDisplayText() method
 514 
 515     private void assertPlatformEquals(String expectedWin, String expectedMac, String actual) {
 516         if (com.sun.javafx.PlatformUtil.isMac()) {
 517             assertEquals(expectedMac, actual);
 518         } else {
 519             assertEquals(expectedWin, actual);
 520         }
 521     }
 522 
 523     private void assertPlatformEquals(KeyCombination expectedWin, KeyCombination expectedMac, KeyCombination actual) {
 524         if (com.sun.javafx.PlatformUtil.isMac()) {
 525             assertEquals(expectedMac.getDisplayText(), actual.getDisplayText());
 526         } else {
 527             assertEquals(expectedWin.getDisplayText(), actual.getDisplayText());
 528         }
 529     }
 530 
 531     /*
 532      * check that a KeyCombination constructed with a KeyCodeCombination
 533      * and one constucted with a KeyCharacterCombination will have
 534      * the same text if they are for the same key.
 535      */
 536     @Test public void SameDisplayStringKeyCombinationForCharOrCode() {
 537         KeyCodeCombination acceleratorKeyComboACode = new KeyCodeCombination(KeyCode.A, KeyCombination.CONTROL_DOWN);
 538         KeyCharacterCombination acceleratorKeyComboAChar = new KeyCharacterCombination("A", KeyCombination.CONTROL_DOWN);
 539         assertEquals(acceleratorKeyComboACode.getDisplayText(), acceleratorKeyComboAChar.getDisplayText());
 540     }
 541 
 542     /*
 543      * check that an accelerator constructed with a Shortcut
 544      * displays appropriate platform text.
 545      */
 546     @Test public void checkShortcutModifierChangesDisplayString() {
 547         KeyCombination acceleratorShortcutA = KeyCodeCombination.keyCombination("Shortcut+A");
 548 
 549         // on Windows / Unix shortcut maps to ctrl
 550         KeyCodeCombination acceleratorControlA = new KeyCodeCombination(KeyCode.A, KeyCombination.CONTROL_DOWN);
 551 
 552         // on Mac it maps to meta
 553         KeyCodeCombination acceleratorMetaA = new KeyCodeCombination(KeyCode.A, KeyCombination.META_DOWN);
 554 
 555         assertPlatformEquals(acceleratorControlA, acceleratorMetaA, acceleratorShortcutA);
 556     }
 557 
 558     @Test public void validStringForNonKeyCode() {
 559         KeyCharacterCombination acceleratorKeyCombo = new KeyCharacterCombination("[");
 560         assertEquals("[", acceleratorKeyCombo.getDisplayText());
 561     }
 562 
 563     /*
 564      * check that the KeyCodeCombination for KeyCode.DELETE produces something printable.
 565      * We only display the unicode DELETE char on mac, otherwise we use "Delete".
 566      */
 567     @Test public void validStringForDELETE() {
 568         KeyCodeCombination keyComboDELETE = new KeyCodeCombination(KeyCode.DELETE);
 569         assertPlatformEquals("Delete", "\u2326", keyComboDELETE.getDisplayText());
 570     }
 571 }