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