1 7 package java.awt; 8 9 import java.awt.event.KeyEvent ; 10 import java.awt.event.InputEvent ; 11 import java.util.Collections ; 12 import java.util.HashMap ; 13 import java.util.Map ; 14 import java.util.StringTokenizer ; 15 import java.io.Serializable ; 16 import java.security.AccessController ; 17 import java.security.PrivilegedAction ; 18 import java.lang.reflect.Constructor ; 19 import java.lang.reflect.InvocationTargetException ; 20 import java.lang.reflect.Modifier ; 21 import java.lang.reflect.Field ; 22 23 49 public class AWTKeyStroke implements Serializable { 50 static final long serialVersionUID = -6430539691155161871L; 51 52 private static Map cache; 53 private static AWTKeyStroke cacheKey; 54 private static Constructor ctor = getCtor(AWTKeyStroke .class); 55 private static Map modifierKeywords; 56 61 private static VKCollection vks; 62 63 private char keyChar = KeyEvent.CHAR_UNDEFINED; 64 private int keyCode = KeyEvent.VK_UNDEFINED; 65 private int modifiers; 66 private boolean onKeyRelease; 67 68 static { 69 70 Toolkit.loadLibraries(); 71 } 72 73 102 protected AWTKeyStroke() { 103 } 104 105 119 protected AWTKeyStroke(char keyChar, int keyCode, int modifiers, 120 boolean onKeyRelease) { 121 this.keyChar = keyChar; 122 this.keyCode = keyCode; 123 this.modifiers = modifiers; 124 this.onKeyRelease = onKeyRelease; 125 } 126 127 146 protected static void registerSubclass(Class <?> subclass) { 147 if (subclass == null) { 148 throw new IllegalArgumentException ("subclass cannot be null"); 149 } 150 if (AWTKeyStroke.ctor.getDeclaringClass().equals(subclass)) { 151 return; 153 } 154 if (!AWTKeyStroke .class.isAssignableFrom(subclass)) { 155 throw new ClassCastException ("subclass is not derived from AWTKeyStroke"); 156 } 157 158 Constructor ctor = getCtor(subclass); 159 160 String couldNotInstantiate = "subclass could not be instantiated"; 161 162 if (ctor == null) { 163 throw new IllegalArgumentException (couldNotInstantiate); 164 } 165 try { 166 AWTKeyStroke stroke = (AWTKeyStroke )ctor.newInstance(null); 167 if (stroke == null) { 168 throw new IllegalArgumentException (couldNotInstantiate); 169 } 170 } catch (NoSuchMethodError e) { 171 throw new IllegalArgumentException (couldNotInstantiate); 172 } catch (ExceptionInInitializerError e) { 173 throw new IllegalArgumentException (couldNotInstantiate); 174 } catch (InstantiationException e) { 175 throw new IllegalArgumentException (couldNotInstantiate); 176 } catch (IllegalAccessException e) { 177 throw new IllegalArgumentException (couldNotInstantiate); 178 } catch (InvocationTargetException e) { 179 throw new IllegalArgumentException (couldNotInstantiate); 180 } 181 182 synchronized (AWTKeyStroke .class) { 183 AWTKeyStroke.ctor = ctor; 184 cache = null; 185 cacheKey = null; 186 } 187 } 188 189 193 private static Constructor getCtor(final Class clazz) 194 { 195 Object ctor = AccessController.doPrivileged(new PrivilegedAction () { 196 public Object run() { 197 try { 198 Constructor ctor = clazz.getDeclaredConstructor(null); 199 if (ctor != null) { 200 ctor.setAccessible(true); 201 } 202 return ctor; 203 } catch (SecurityException e) { 204 } catch (NoSuchMethodException e) { 205 } 206 return null; 207 } 208 }); 209 return (Constructor )ctor; 210 } 211 212 private static synchronized AWTKeyStroke getCachedStroke 213 (char keyChar, int keyCode, int modifiers, boolean onKeyRelease) 214 { 215 if (cache == null) { 216 cache = new HashMap (); 217 } 218 219 if (cacheKey == null) { 220 try { 221 cacheKey = (AWTKeyStroke )ctor.newInstance(null); 222 } catch (InstantiationException e) { 223 assert(false); 224 } catch (IllegalAccessException e) { 225 assert(false); 226 } catch (InvocationTargetException e) { 227 assert(false); 228 } 229 } 230 cacheKey.keyChar = keyChar; 231 cacheKey.keyCode = keyCode; 232 cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers)); 233 cacheKey.onKeyRelease = onKeyRelease; 234 235 AWTKeyStroke stroke = (AWTKeyStroke )cache.get(cacheKey); 236 if (stroke == null) { 237 stroke = cacheKey; 238 cache.put(stroke, stroke); 239 cacheKey = null; 240 } 241 242 return stroke; 243 } 244 245 253 public static AWTKeyStroke getAWTKeyStroke(char keyChar) { 254 return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false); 255 } 256 257 292 public static AWTKeyStroke getAWTKeyStroke(Character keyChar, 293 int modifiers) { 294 if (keyChar == null) { 295 throw new IllegalArgumentException ("keyChar cannot be null"); 296 } 297 return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED, 298 modifiers, false); 299 } 300 301 342 public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers, 343 boolean onKeyRelease) { 344 return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, 345 onKeyRelease); 346 } 347 348 387 public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) { 388 return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, 389 false); 390 } 391 392 406 public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) { 407 int id = anEvent.getID(); 408 switch(id) { 409 case KeyEvent.KEY_PRESSED: 410 case KeyEvent.KEY_RELEASED: 411 return getCachedStroke(KeyEvent.CHAR_UNDEFINED, 412 anEvent.getKeyCode(), 413 anEvent.getModifiers(), 414 (id == KeyEvent.KEY_RELEASED)); 415 case KeyEvent.KEY_TYPED: 416 return getCachedStroke(anEvent.getKeyChar(), 417 KeyEvent.VK_UNDEFINED, 418 anEvent.getModifiers(), 419 false); 420 default: 421 return null; 423 } 424 } 425 426 453 public static AWTKeyStroke getAWTKeyStroke(String s) { 454 if (s == null) { 455 throw new IllegalArgumentException ("String cannot be null"); 456 } 457 458 final String errmsg = "String formatted incorrectly"; 459 460 StringTokenizer st = new StringTokenizer (s, " "); 461 462 int mask = 0; 463 boolean released = false; 464 boolean typed = false; 465 boolean pressed = false; 466 467 if (modifierKeywords == null) { 468 synchronized (AWTKeyStroke .class) { 469 if (modifierKeywords == null) { 470 Map uninitializedMap = new HashMap (8, 1.0f); 471 uninitializedMap.put("shift", 472 new Integer (InputEvent.SHIFT_DOWN_MASK 473 |InputEvent.SHIFT_MASK)); 474 uninitializedMap.put("control", 475 new Integer (InputEvent.CTRL_DOWN_MASK 476 |InputEvent.CTRL_MASK)); 477 uninitializedMap.put("ctrl", 478 new Integer (InputEvent.CTRL_DOWN_MASK 479 |InputEvent.CTRL_MASK)); 480 uninitializedMap.put("meta", 481 new Integer (InputEvent.META_DOWN_MASK 482 |InputEvent.META_MASK)); 483 uninitializedMap.put("alt", 484 new Integer (InputEvent.ALT_DOWN_MASK 485 |InputEvent.ALT_MASK)); 486 uninitializedMap.put("altGraph", 487 new Integer (InputEvent.ALT_GRAPH_DOWN_MASK 488 |InputEvent.ALT_GRAPH_MASK)); 489 uninitializedMap.put("button1", 490 new Integer (InputEvent.BUTTON1_DOWN_MASK)); 491 uninitializedMap.put("button2", 492 new Integer (InputEvent.BUTTON2_DOWN_MASK)); 493 uninitializedMap.put("button3", 494 new Integer (InputEvent.BUTTON3_DOWN_MASK)); 495 modifierKeywords = 496 Collections.synchronizedMap(uninitializedMap); 497 } 498 } 499 } 500 501 int count = st.countTokens(); 502 503 for (int i = 1; i <= count; i++) { 504 String token = st.nextToken(); 505 506 if (typed) { 507 if (token.length() != 1 || i != count) { 508 throw new IllegalArgumentException (errmsg); 509 } 510 return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED, 511 mask, false); 512 } 513 514 if (pressed || released || i == count) { 515 if (i != count) { 516 throw new IllegalArgumentException (errmsg); 517 } 518 519 String keyCodeName = "VK_" + token; 520 int keyCode = getVKValue(keyCodeName); 521 522 return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, 523 mask, released); 524 } 525 526 if (token.equals("released")) { 527 released = true; 528 continue; 529 } 530 if (token.equals("pressed")) { 531 pressed = true; 532 continue; 533 } 534 if (token.equals("typed")) { 535 typed = true; 536 continue; 537 } 538 539 Integer tokenMask = (Integer )modifierKeywords.get(token); 540 if (tokenMask != null) { 541 mask |= tokenMask.intValue(); 542 } else { 543 throw new IllegalArgumentException (errmsg); 544 } 545 } 546 547 throw new IllegalArgumentException (errmsg); 548 } 549 550 private static VKCollection getVKCollection() { 551 if (vks == null) { 552 vks = new VKCollection(); 553 } 554 return vks; 555 } 556 562 private static int getVKValue(String key) { 563 VKCollection vkCollect = getVKCollection(); 564 565 Integer value = vkCollect.findCode(key); 566 567 if (value == null) { 568 int keyCode = 0; 569 final String errmsg = "String formatted incorrectly"; 570 571 try { 572 keyCode = KeyEvent .class.getField(key).getInt(KeyEvent .class); 573 } catch (NoSuchFieldException nsfe) { 574 throw new IllegalArgumentException (errmsg); 575 } catch (IllegalAccessException iae) { 576 throw new IllegalArgumentException (errmsg); 577 } 578 value = new Integer (keyCode); 579 vkCollect.put(key, value); 580 } 581 return value.intValue(); 582 } 583 584 590 public final char getKeyChar() { 591 return keyChar; 592 } 593 594 600 public final int getKeyCode() { 601 return keyCode; 602 } 603 604 610 public final int getModifiers() { 611 return modifiers; 612 } 613 614 621 public final boolean isOnKeyRelease() { 622 return onKeyRelease; 623 } 624 625 634 public final int getKeyEventType() { 635 if (keyCode == KeyEvent.VK_UNDEFINED) { 636 return KeyEvent.KEY_TYPED; 637 } else { 638 return (onKeyRelease) 639 ? KeyEvent.KEY_RELEASED 640 : KeyEvent.KEY_PRESSED; 641 } 642 } 643 644 650 public int hashCode() { 651 return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) + 652 (onKeyRelease ? 1 : 2); 653 } 654 655 661 public final boolean equals(Object anObject) { 662 if (anObject instanceof AWTKeyStroke ) { 663 AWTKeyStroke ks = (AWTKeyStroke )anObject; 664 return (ks.keyChar == keyChar && ks.keyCode == keyCode && 665 ks.onKeyRelease == onKeyRelease && 666 ks.modifiers == modifiers); 667 } 668 return false; 669 } 670 671 680 public String toString() { 681 if (keyCode == KeyEvent.VK_UNDEFINED) { 682 return getModifiersText(modifiers) + "typed " + keyChar; 683 } else { 684 return getModifiersText(modifiers) + 685 (onKeyRelease ? "released" : "pressed") + " " + 686 getVKText(keyCode); 687 } 688 } 689 690 static String getModifiersText(int modifiers) { 691 StringBuffer buf = new StringBuffer (); 692 693 if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) { 694 buf.append("shift "); 695 } 696 if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) { 697 buf.append("ctrl "); 698 } 699 if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) { 700 buf.append("meta "); 701 } 702 if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) { 703 buf.append("alt "); 704 } 705 if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) { 706 buf.append("altGraph "); 707 } 708 if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) { 709 buf.append("button1 "); 710 } 711 if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) { 712 buf.append("button2 "); 713 } 714 if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) { 715 buf.append("button3 "); 716 } 717 718 return buf.toString(); 719 } 720 721 static String getVKText(int keyCode) { 722 VKCollection vkCollect = getVKCollection(); 723 Integer key = new Integer (keyCode); 724 String name = vkCollect.findName(key); 725 if (name != null) { 726 return name.substring(3); 727 } 728 int expected_modifiers = 729 (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL); 730 731 Field [] fields = KeyEvent .class.getDeclaredFields(); 732 for (int i = 0; i < fields.length; i++) { 733 try { 734 if (fields[i].getModifiers() == expected_modifiers 735 && fields[i].getType() == Integer.TYPE 736 && fields[i].getName().startsWith("VK_") 737 && fields[i].getInt(KeyEvent .class) == keyCode) 738 { 739 name = fields[i].getName(); 740 vkCollect.put(name, key); 741 return name.substring(3); 742 } 743 } catch (IllegalAccessException e) { 744 assert(false); 745 } 746 } 747 return "UNKNOWN"; 748 } 749 750 756 protected Object readResolve() throws java.io.ObjectStreamException { 757 synchronized (AWTKeyStroke .class) { 758 Class newClass = getClass(); 759 if (!newClass.equals(ctor.getDeclaringClass())) { 760 registerSubclass(newClass); 761 } 762 return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); 763 } 764 } 765 766 private static int mapOldModifiers(int modifiers) { 767 if ((modifiers & InputEvent.SHIFT_MASK) != 0) { 768 modifiers |= InputEvent.SHIFT_DOWN_MASK; 769 } 770 if ((modifiers & InputEvent.ALT_MASK) != 0) { 771 modifiers |= InputEvent.ALT_DOWN_MASK; 772 } 773 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) { 774 modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; 775 } 776 if ((modifiers & InputEvent.CTRL_MASK) != 0) { 777 modifiers |= InputEvent.CTRL_DOWN_MASK; 778 } 779 if ((modifiers & InputEvent.META_MASK) != 0) { 780 modifiers |= InputEvent.META_DOWN_MASK; 781 } 782 783 modifiers &= InputEvent.SHIFT_DOWN_MASK 784 | InputEvent.ALT_DOWN_MASK 785 | InputEvent.ALT_GRAPH_DOWN_MASK 786 | InputEvent.CTRL_DOWN_MASK 787 | InputEvent.META_DOWN_MASK 788 | InputEvent.BUTTON1_DOWN_MASK 789 | InputEvent.BUTTON2_DOWN_MASK 790 | InputEvent.BUTTON3_DOWN_MASK; 791 792 return modifiers; 793 } 794 795 private static int mapNewModifiers(int modifiers) { 796 if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) { 797 modifiers |= InputEvent.SHIFT_MASK; 798 } 799 if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) { 800 modifiers |= InputEvent.ALT_MASK; 801 } 802 if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) { 803 modifiers |= InputEvent.ALT_GRAPH_MASK; 804 } 805 if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) { 806 modifiers |= InputEvent.CTRL_MASK; 807 } 808 if ((modifiers & InputEvent.META_DOWN_MASK) != 0) { 809 modifiers |= InputEvent.META_MASK; 810 } 811 812 return modifiers; 813 } 814 815 } 816 817 class VKCollection { 818 Map code2name; 819 Map name2code; 820 821 public VKCollection() { 822 code2name = new HashMap (); 823 name2code = new HashMap (); 824 } 825 826 public synchronized void put(String name, Integer code) { 827 assert((name != null) && (code != null)); 828 assert(findName(code) == null); 829 assert(findCode(name) == null); 830 code2name.put(code, name); 831 name2code.put(name, code); 832 } 833 834 public synchronized Integer findCode(String name) { 835 assert(name != null); 836 return (Integer )name2code.get(name); 837 } 838 839 public synchronized String findName(Integer code) { 840 assert(code != null); 841 return (String )code2name.get(code); 842 } 843 } 844 845 | Popular Tags |