Translator.java revision 14243:2ad92ad4e9a9
1/* 2 * Copyright (c) 2002, 2016, 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 27package com.sun.java.accessibility.util; 28 29import com.sun.java.accessibility.util.internal.*; 30import java.beans.*; 31import java.util.*; 32import java.awt.*; 33import java.awt.event.*; 34// Do not import Swing classes. This module is intended to work 35// with both Swing and AWT. 36// import javax.swing.*; 37import javax.accessibility.*; 38 39/** 40 * <p>The {@code Translator} class provides a translation to interface 41 * {@link javax.accessibility.Accessible Accessible} 42 * for objects that do not implement interface {@code Accessible}. Assistive 43 * technologies can use the {@link #getAccessible getAccessible} class method of 44 * {@code Translator} to obtain an object that implements interface {@code Accessible}. 45 * If the object passed in already implements interface {@code Accessible}, 46 * {@code getAccessible} merely returns the object. 47 * 48 * <p>An example of how an assistive technology might use the {@code Translator} 49 * class is as follows: 50 * 51 * <PRE> 52 * Accessible accessible = Translator.getAccessible(someObj); 53 * // obtain information from the 'accessible' object. 54 * </PRE> 55 * 56 * <P>Note: This implementation is missing many things and is not a recommended way 57 * to implement accessibility features for a toolkit. Instead of relying upon this 58 * code, a toolkit's components should implement interface {@code Accessible} directly. 59 */ 60public class Translator extends AccessibleContext 61 implements Accessible, AccessibleComponent { 62 63 /** The source object needing translating. */ 64 protected Object source; 65 66 /** 67 * Find a translator for this class. If one doesn't exist for this 68 * class explicitly, try its superclass and so on. 69 * 70 * @param c a Class 71 * @return the {@code Translator} Class for the Class passed in 72 */ 73 protected static Class<?> getTranslatorClass(Class<?> c) { 74 Class<?> t = null; 75 if (c == null) { 76 return null; 77 } 78 switch (c.getSimpleName()) { 79 case "Button": 80 t = ButtonTranslator.class; 81 break; 82 case "Checkbox": 83 t = CheckboxTranslator.class; 84 break; 85 case "Label": 86 t = LabelTranslator.class; 87 break; 88 case "List": 89 t = ListTranslator.class; 90 break; 91 case "TextComponent": 92 t = TextComponentTranslator.class; 93 break; 94 } 95 if (t != null) { 96 return t; 97 } else { 98 return getTranslatorClass(c.getSuperclass()); 99 } 100 } 101 102 /** 103 * Obtain an object that implements interface {@code Accessible}. If the object 104 * passed in already implements interface {@code Accessible}, {@code getAccessible} 105 * merely returns the object. 106 * 107 * @param o an Object; if a null is passed in a null is returned 108 * @return an {@code Object}, possibly the {@code Object} passed in, that 109 * implements the {@code Accessible} interface for the {@code Object} 110 * which was passed in 111 */ 112 public static Accessible getAccessible(Object o) { 113 Accessible a = null; 114 115 if (o == null) { 116 return null; 117 } 118 if (o instanceof Accessible) { 119 a = (Accessible)o; 120 } else { 121 Class<?> translatorClass = getTranslatorClass(o.getClass()); 122 if (translatorClass != null) { 123 try { 124 Translator t = (Translator)translatorClass.newInstance(); 125 t.setSource(o); 126 a = t; 127 } catch (Exception e) { 128 } 129 } 130 } 131 if (a == null) { 132 a = new Translator(o); 133 } 134 return a; 135 } 136 137 /** 138 * Create a new {@code Translator}. You must call the {@link #setSource setSource} 139 * method to set the object to be translated after calling this constructor. 140 */ 141 public Translator() { 142 } 143 144 /** 145 * Create a new {@code Translator} with the source object o. 146 * 147 * @param o the Component that does not implement interface 148 * {@link javax.accessibility.Accessible Accessible} 149 */ 150 public Translator(Object o) { 151 source = o; 152 } 153 154 /** 155 * Get the source {@code Object} of the {@code Translator}. 156 * 157 * @return the source {@code Object} of the {@code Translator} 158 */ 159 public Object getSource() { 160 return source; 161 } 162 163 /** 164 * Set the source object of the {@code Translator}. 165 * 166 * @param o the Component that does not implement interface Accessible 167 */ 168 public void setSource(Object o) { 169 source = o; 170 } 171 172 /** 173 * Returns true if this object is the same as the one passed in. 174 * 175 * @param o the {@code Object} to check against 176 * @return true if this is the same object 177 */ 178 public boolean equals(Object o) { 179 if (o instanceof Translator) { 180 return java.util.Objects.equals(source, o); 181 } else { 182 return false; 183 } 184 } 185 186 /** 187 * Return hashcode. 188 * 189 * @return hashcode 190 */ 191 public int hashCode() { 192 return java.util.Objects.hashCode(source); 193 } 194 195 196// Accessible methods 197 198 /** 199 * Returns this object. 200 */ 201 public AccessibleContext getAccessibleContext() { 202 return this; 203 } 204 205// AccessibleContext methods 206 207 /** 208 * Get the accessible name of this object. 209 * 210 * @return the localized name of the object; can be null if this object 211 * does not have a name 212 */ 213 public String getAccessibleName() { 214 if (source instanceof MenuItem) { 215 return ((MenuItem) source).getLabel(); 216 } else if (source instanceof Component) { 217 return ((Component) source).getName(); 218 } else { 219 return null; 220 } 221 } 222 223 /** 224 * Set the name of this object. 225 */ 226 public void setAccessibleName(String s) { 227 if (source instanceof MenuItem) { 228 ((MenuItem) source).setLabel(s); 229 } else if (source instanceof Component) { 230 ((Component) source).setName(s); 231 } 232 } 233 234 /** 235 * Get the accessible description of this object. 236 * 237 * @return the description of the object; can be null if this object does 238 * not have a description 239 */ 240 public String getAccessibleDescription() { 241 return null; 242 } 243 244 /** 245 * Set the accessible description of this object. 246 * 247 * @param s the new localized description of the object 248 */ 249 public void setAccessibleDescription(String s) { 250 } 251 252 /** 253 * Get the role of this object. 254 * 255 * @return an instance of AccessibleRole describing the role of the object 256 */ 257 public AccessibleRole getAccessibleRole() { 258 return AccessibleRole.UNKNOWN; 259 } 260 261 262 /** 263 * Get the state of this object, given an already populated state. 264 * This method is intended for use by subclasses so they don't have 265 * to check for everything. 266 * 267 * @return an instance of {@code AccessibleStateSet} 268 * containing the current state of the object 269 */ 270 public AccessibleStateSet getAccessibleStateSet() { 271 AccessibleStateSet states = new AccessibleStateSet(); 272 if (source instanceof Component) { 273 Component c = (Component) source; 274 for (Container p = c.getParent(); p != null; p = p.getParent()) { 275 if (p instanceof Window) { 276 if (((Window)p).getFocusOwner() == c) { 277 states.add(AccessibleState.FOCUSED); 278 } 279 } 280 } 281 } 282 if (isEnabled()) { 283 states.add(AccessibleState.ENABLED); 284 } 285 if (isFocusTraversable()) { 286 states.add(AccessibleState.FOCUSABLE); 287 } 288 if (source instanceof MenuItem) { 289 states.add(AccessibleState.FOCUSABLE); 290 } 291 return states; 292 } 293 294 /** 295 * Get the accessible parent of this object. 296 * 297 * @return the accessible parent of this object; can be null if this 298 * object does not have an accessible parent 299 */ 300 public Accessible getAccessibleParent() { 301 if (accessibleParent != null) { 302 return accessibleParent; 303 } else if (source instanceof Component) { 304 return getAccessible(((Component) source).getParent()); 305 } else { 306 return null; 307 } 308 } 309 310 /** 311 * Get the index of this object in its accessible parent. 312 * 313 * @return -1 of this object does not have an accessible parent; otherwise, 314 * the index of the child in its accessible parent 315 */ 316 public int getAccessibleIndexInParent() { 317 if (source instanceof Component) { 318 Container parent = ((Component) source).getParent(); 319 if (parent != null) { 320 Component ca[] = parent.getComponents(); 321 for (int i = 0; i < ca.length; i++) { 322 if (source.equals(ca[i])) { 323 return i; 324 } 325 } 326 } 327 } 328 return -1; 329 } 330 331 /** 332 * Returns the number of accessible children in the object. 333 * 334 * @return the number of accessible children in the object 335 */ 336 public int getAccessibleChildrenCount() { 337 if (source instanceof Container) { 338 Component[] children = ((Container) source).getComponents(); 339 int count = 0; 340 for (int i = 0; i < children.length; i++) { 341 Accessible a = getAccessible(children[i]); 342 if (a != null) { 343 count++; 344 } 345 } 346 return count; 347 } else { 348 return 0; 349 } 350 } 351 352 /** 353 * Return the nth accessible child of the object. 354 * 355 * @param i zero-based index of child 356 * @return the nth accessible child of the object 357 */ 358 public Accessible getAccessibleChild(int i) { 359 if (source instanceof Container) { 360 Component[] children = ((Container) source).getComponents(); 361 int count = 0; 362 363 for (int j = 0; j < children.length; j++) { 364 Accessible a = getAccessible(children[j]); 365 if (a != null) { 366 if (count == i) { 367 AccessibleContext ac = a.getAccessibleContext(); 368 if (ac != null) { 369 ac.setAccessibleParent(this); 370 } 371 return a; 372 } else { 373 count++; 374 } 375 } 376 } 377 } 378 return null; 379 } 380 381 /** 382 * Gets the {@code Locale} of the component. If the component does not have a 383 * locale, the locale of its parent is returned. 384 * 385 * @return the {@code Locale} of the object 386 */ 387 public Locale getLocale() throws IllegalComponentStateException { 388 if (source instanceof Component) { 389 return ((Component) source).getLocale(); 390 } else { 391 return null; 392 } 393 } 394 395 /** 396 * Add a {@code PropertyChangeListener} to the listener list. The listener 397 * is registered for all properties. 398 */ 399 public void addPropertyChangeListener(PropertyChangeListener l) { 400 } 401 402 /** 403 * Remove the {@code PropertyChangeListener} from the listener list. 404 */ 405 public void removePropertyChangeListener(PropertyChangeListener l) { 406 } 407 408// AccessibleComponent methods 409 410 /** 411 * Get the background {@code Color} of this object. 412 * 413 * @return if supported, the background {@code Color} of the object; 414 * otherwise, null 415 * 416 */ 417 public Color getBackground() { 418 if (source instanceof Component) { // MenuComponent doesn't do background 419 return ((Component) source).getBackground(); 420 } else { 421 return null; 422 } 423 } 424 425 /** 426 * Set the background {@code Color} of this object. 427 * 428 * @param c the new {@code Color} for the background 429 */ 430 public void setBackground(Color c) { 431 if (source instanceof Component) { // MenuComponent doesn't do background 432 ((Component) source).setBackground(c); 433 } 434 } 435 436 /** 437 * Get the foreground {@code Color} of this object. 438 * 439 * @return if supported, the foreground {@code Color} of the object; otherwise, null 440 */ 441 public Color getForeground() { 442 if (source instanceof Component) { // MenuComponent doesn't do foreground 443 return ((Component) source).getForeground(); 444 } else { 445 return null; 446 } 447 } 448 449 /** 450 * Set the foreground {@code Color} of this object. 451 * 452 * @param c the new {@code Color} for the foreground 453 */ 454 public void setForeground(Color c) { 455 if (source instanceof Component) { // MenuComponent doesn't do foreground 456 ((Component) source).setForeground(c); 457 } 458 } 459 460 /** 461 * Get the {@code Cursor} of this object. 462 * 463 * @return if supported, the Cursor of the object; otherwise, null 464 */ 465 public Cursor getCursor() { 466 if (source instanceof Component) { // MenuComponent doesn't do cursor 467 return ((Component) source).getCursor(); 468 } else { 469 return null; 470 } 471 } 472 473 /** 474 * Set the {@code Cursor} of this object. 475 * @param c the new {@code Cursor} for the object 476 */ 477 public void setCursor(Cursor c) { 478 if (source instanceof Component) { // MenuComponent doesn't do cursor 479 ((Component) source).setCursor(c); 480 } 481 } 482 483 /** 484 * Get the {@code Font} of this object. 485 * 486 * @return if supported, the {@code Font} for the object; otherwise, null 487 */ 488 public Font getFont() { 489 if (source instanceof Component) { 490 return ((Component) source).getFont(); 491 } else if (source instanceof MenuComponent) { 492 return ((MenuComponent) source).getFont(); 493 } else { 494 return null; 495 } 496 } 497 498 /** 499 * Set the {@code Font} of this object. 500 * 501 * @param f the new {@code Font} for the object 502 */ 503 public void setFont(Font f) { 504 if (source instanceof Component) { 505 ((Component) source).setFont(f); 506 } else if (source instanceof MenuComponent) { 507 ((MenuComponent) source).setFont(f); 508 } 509 } 510 511 /** 512 * Get the {@code FontMetrics} of this object. 513 * 514 * @param f the {@code Font} 515 * @return if supported, the {@code FontMetrics} the object; otherwise, null 516 * @see #getFont 517 */ 518 public FontMetrics getFontMetrics(Font f) { 519 if (source instanceof Component) { 520 return ((Component) source).getFontMetrics(f); 521 } else { 522 return null; 523 } 524 } 525 526 /** 527 * Determine if the object is enabled. 528 * 529 * @return true if object is enabled; otherwise, false 530 */ 531 public boolean isEnabled() { 532 if (source instanceof Component) { 533 return ((Component) source).isEnabled(); 534 } else if (source instanceof MenuItem) { 535 return ((MenuItem) source).isEnabled(); 536 } else { 537 return true; 538 } 539 } 540 541 /** 542 * Set the enabled state of the object. 543 * 544 * @param b if true, enables this object; otherwise, disables it 545 */ 546 public void setEnabled(boolean b) { 547 if (source instanceof Component) { 548 ((Component) source).setEnabled(b); 549 } else if (source instanceof MenuItem) { 550 ((MenuItem) source).setEnabled(b); 551 } 552 } 553 554 /** 555 * Determine if the object is visible. 556 * 557 * @return true if object is visible; otherwise, false 558 */ 559 public boolean isVisible() { 560 if (source instanceof Component) { 561 return ((Component) source).isVisible(); 562 } else { 563 return false; 564 } 565 } 566 567 /** 568 * Set the visible state of the object. 569 * 570 * @param b if true, shows this object; otherwise, hides it 571 */ 572 public void setVisible(boolean b) { 573 if (source instanceof Component) { 574 ((Component) source).setVisible(b); 575 } 576 } 577 578 /** 579 * Determine if the object is showing. This is determined by checking 580 * the visibility of the object and ancestors of the object. 581 * 582 * @return true if object is showing; otherwise, false 583 */ 584 public boolean isShowing() { 585 if (source instanceof Component) { 586 return ((Component) source).isShowing(); 587 } else { 588 return false; 589 } 590 } 591 592 /** 593 * Checks whether the specified {@code Point} is within this 594 * object's bounds, where the {@code Point} is relative to the coordinate 595 * system of the object. 596 * 597 * @param p the {@code Point} relative to the coordinate system of the object 598 * @return true if object contains {@code Point}; otherwise false 599 */ 600 public boolean contains(Point p) { 601 if (source instanceof Component) { 602 return ((Component) source).contains(p); 603 } else { 604 return false; 605 } 606 } 607 608 /** 609 * Returns the location of the object on the screen. 610 * 611 * @return location of object on screen; can be null if this object 612 * is not on the screen 613 */ 614 public Point getLocationOnScreen() { 615 if (source instanceof Component) { 616 return ((Component) source).getLocationOnScreen(); 617 } else { 618 return null; 619 } 620 } 621 622 /** 623 * Returns the location of the object relative to parent. 624 * 625 * @return location of object relative to parent; can be null if 626 * this object or its parent are not on the screen 627 */ 628 public Point getLocation() { 629 if (source instanceof Component) { 630 return ((Component) source).getLocation(); 631 } else { 632 return null; 633 } 634 } 635 636 /** 637 * Sets the location of the object relative to parent. 638 */ 639 public void setLocation(Point p) { 640 if (source instanceof Component) { 641 ((Component) source).setLocation(p); 642 } 643 } 644 645 /** 646 * Returns the current bounds of this object. 647 * 648 * @return current bounds of object; can be null if this object 649 * is not on the screen 650 */ 651 public Rectangle getBounds() { 652 if (source instanceof Component) { 653 return ((Component) source).getBounds(); 654 } else { 655 return null; 656 } 657 } 658 659 /** 660 * Sets the current bounds of this object. 661 */ 662 public void setBounds(Rectangle r) { 663 if (source instanceof Component) { 664 ((Component) source).setBounds(r); 665 } 666 } 667 668 /** 669 * Returns the current size of this object. 670 * 671 * @return current size of object; can be null if this object is 672 * not on the screen 673 */ 674 public Dimension getSize() { 675 if (source instanceof Component) { 676 return ((Component) source).getSize(); 677 } else { 678 return null; 679 } 680 } 681 682 /** 683 * Sets the current size of this object. 684 */ 685 public void setSize(Dimension d) { 686 if (source instanceof Component) { 687 ((Component) source).setSize(d); 688 } 689 } 690 691 /** 692 * Returns the accessible child contained at the local coordinate 693 * Point, if one exists. 694 * 695 * @return the Accessible at the specified location, if it exists 696 */ 697 public Accessible getAccessibleAt(Point p) { 698 if (source instanceof Component) { 699 Component c = ((Component) source).getComponentAt(p); 700 if (c != null) { 701 return (getAccessible(c)); 702 } 703 } 704 return null; 705 } 706 707 /** 708 * Returns whether this object can accept focus or not. 709 * 710 * @return true if object can accept focus; otherwise false 711 */ 712 @SuppressWarnings("deprecation") 713 public boolean isFocusTraversable() { 714 if (source instanceof Component) { 715 return ((Component) source).isFocusTraversable(); 716 } else { 717 return false; 718 } 719 } 720 721 /** 722 * Requests focus for this object. 723 */ 724 public void requestFocus() { 725 if (source instanceof Component) { 726 ((Component) source).requestFocus(); 727 } 728 } 729 730 /** 731 * Adds the specified {@code FocusListener} to receive focus events from 732 * this component. 733 * 734 * @param l the focus listener 735 */ 736 public synchronized void addFocusListener(FocusListener l) { 737 if (source instanceof Component) { 738 ((Component) source).addFocusListener(l); 739 } 740 } 741 742 /** 743 * Removes the specified focus listener so it no longer receives focus 744 * events from this component. 745 * 746 * @param l the focus listener; this method performs no function, nor does it 747 * throw an exception if the listener specified was not previously added 748 * to this component; if listener is null, no exception is thrown and no 749 * action is performed. 750 */ 751 public synchronized void removeFocusListener(FocusListener l) { 752 if (source instanceof Component) { 753 ((Component) source).removeFocusListener(l); 754 } 755 } 756} 757