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." 82 + c.getName() 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 return source.equals(o); 168 } 169 170 171 // Accessible methods 172 173 /** 174 * Returns this object. 175 */ 176 public AccessibleContext getAccessibleContext() { 177 return this; 178 } 179 180 // AccessibleContext methods 181 182 /** 183 * Get the accessible name of this object. 184 * 185 * @return the localized name of the object; can be null if this object 186 * does not have a name 187 */ 188 public String getAccessibleName() { 189 if (source instanceof MenuItem) { 190 return ((MenuItem) source).getLabel(); 191 } else if (source instanceof Component) { 192 return ((Component) source).getName(); 193 } else { 194 return null; 195 } 196 } 197 198 /** 199 * Set the name of this object. 200 */ 201 public void setAccessibleName(String s) { 202 if (source instanceof MenuItem) { 203 ((MenuItem) source).setLabel(s); 204 } else if (source instanceof Component) { 205 ((Component) source).setName(s); 206 } 207 } 208 209 /** 210 * Get the accessible description of this object. 211 * 212 * @return the description of the object; can be null if this object does 213 * not have a description 214 */ 215 public String getAccessibleDescription() { 216 return null; 217 } 218 219 /** 220 * Set the accessible description of this object. 221 * 222 * @param s the new localized description of the object 223 */ 224 public void setAccessibleDescription(String s) { 225 } 226 227 /** 228 * Get the role of this object. 229 * 230 * @return an instance of AccessibleRole describing the role of the object 231 */ 232 public AccessibleRole getAccessibleRole() { 233 return AccessibleRole.UNKNOWN; 234 } 235 236 237 /** 238 * Get the state of this object, given an already populated state. 239 * This method is intended for use by subclasses so they don't have 240 * to check for everything. 241 * 242 * @return an instance of {@code AccessibleStateSet} 243 * containing the current state of the object 244 */ 245 public AccessibleStateSet getAccessibleStateSet() { 246 AccessibleStateSet states = new AccessibleStateSet(); 247 if (source instanceof Component) { 248 Component c = (Component) source; 249 for (Container p = c.getParent(); p != null; p = p.getParent()) { 250 if (p instanceof Window) { 251 if (((Window)p).getFocusOwner() == c) { 252 states.add(AccessibleState.FOCUSED); 253 } 254 } 255 } 256 } 257 if (isEnabled()) { 258 states.add(AccessibleState.ENABLED); 259 } 260 if (isFocusTraversable()) { 261 states.add(AccessibleState.FOCUSABLE); 262 } 263 if (source instanceof MenuItem) { 264 states.add(AccessibleState.FOCUSABLE); 265 } 266 return states; 267 } 268 269 /** 270 * Get the accessible parent of this object. 271 * 272 * @return the accessible parent of this object; can be null if this 273 * object does not have an accessible parent 274 */ 275 public Accessible getAccessibleParent() { 276 if (accessibleParent != null) { 277 return accessibleParent; 278 } else if (source instanceof Component) { 279 return getAccessible(((Component) source).getParent()); 280 } else { 281 return null; 282 } 283 } 284 285 /** 286 * Get the index of this object in its accessible parent. 287 * 288 * @return -1 of this object does not have an accessible parent; otherwise, 289 * the index of the child in its accessible parent 290 */ 291 public int getAccessibleIndexInParent() { 292 if (source instanceof Component) { 293 Container parent = ((Component) source).getParent(); 294 if (parent != null) { 295 Component ca[] = parent.getComponents(); 296 for (int i = 0; i < ca.length; i++) { 297 if (source.equals(ca[i])) { 298 return i; 299 } 300 } 301 } 302 } 303 return -1; 304 } 305 306 /** 307 * Returns the number of accessible children in the object. 308 * 309 * @return the number of accessible children in the object 310 */ 311 public int getAccessibleChildrenCount() { 312 if (source instanceof Container) { 313 Component[] children = ((Container) source).getComponents(); 314 int count = 0; 315 for (int i = 0; i < children.length; i++) { 316 Accessible a = getAccessible(children[i]); 317 if (a != null) { 318 count++; 319 } 320 } 321 return count; 322 } else { 323 return 0; 324 } 325 } 326 327 /** 328 * Return the nth accessible child of the object. 329 * 330 * @param i zero-based index of child 331 * @return the nth accessible child of the object 332 */ 333 public Accessible getAccessibleChild(int i) { 334 if (source instanceof Container) { 335 Component[] children = ((Container) source).getComponents(); 336 int count = 0; 337 338 for (int j = 0; j < children.length; j++) { 339 Accessible a = getAccessible(children[j]); 340 if (a != null) { 341 if (count == i) { 342 AccessibleContext ac = a.getAccessibleContext(); 343 if (ac != null) { 344 ac.setAccessibleParent(this); 345 } 346 return a; 347 } else { 348 count++; 349 } 350 } 351 } 352 } 353 return null; 354 } 355 356 /** 357 * Gets the {@code Locale} of the component. If the component does not have a 358 * locale, the locale of its parent is returned. 359 * 360 * @return the {@code Locale} of the object 361 */ 362 public Locale getLocale() throws IllegalComponentStateException { 363 if (source instanceof Component) { 364 return ((Component) source).getLocale(); 365 } else { 366 return null; 367 } 368 } 369 370 /** 371 * Add a {@code PropertyChangeListener} to the listener list. The listener 372 * is registered for all properties. 373 */ 374 public void addPropertyChangeListener(PropertyChangeListener l) { 375 } 376 377 /** 378 * Remove the {@code PropertyChangeListener} from the listener list. 379 */ 380 public void removePropertyChangeListener(PropertyChangeListener l) { 381 } 382 383 // AccessibleComponent methods 384 385 /** 386 * Get the background {@code Color} of this object. 387 * 388 * @return if supported, the background {@code Color} of the object; 389 * otherwise, null 390 * 391 */ 392 public Color getBackground() { 393 if (source instanceof Component) { // MenuComponent doesn't do background 394 return ((Component) source).getBackground(); 395 } else { 396 return null; 397 } 398 } 399 400 /** 401 * Set the background {@code Color} of this object. 402 * 403 * @param c the new {@code Color} for the background 404 */ 405 public void setBackground(Color c) { 406 if (source instanceof Component) { // MenuComponent doesn't do background 407 ((Component) source).setBackground(c); 408 } 409 } 410 411 /** 412 * Get the foreground {@code Color} of this object. 413 * 414 * @return if supported, the foreground {@code Color} of the object; otherwise, null 415 */ 416 public Color getForeground() { 417 if (source instanceof Component) { // MenuComponent doesn't do foreground 418 return ((Component) source).getForeground(); 419 } else { 420 return null; 421 } 422 } 423 424 /** 425 * Set the foreground {@code Color} of this object. 426 * 427 * @param c the new {@code Color} for the foreground 428 */ 429 public void setForeground(Color c) { 430 if (source instanceof Component) { // MenuComponent doesn't do foreground 431 ((Component) source).setForeground(c); 432 } 433 } 434 435 /** 436 * Get the {@code Cursor} of this object. 437 * 438 * @return if supported, the Cursor of the object; otherwise, null 439 */ 440 public Cursor getCursor() { 441 if (source instanceof Component) { // MenuComponent doesn't do cursor 442 return ((Component) source).getCursor(); 443 } else { 444 return null; 445 } 446 } 447 448 /** 449 * Set the {@code Cursor} of this object. 450 * @param c the new {@code Cursor} for the object 451 */ 452 public void setCursor(Cursor c) { 453 if (source instanceof Component) { // MenuComponent doesn't do cursor 454 ((Component) source).setCursor(c); 455 } 456 } 457 458 /** 459 * Get the {@code Font} of this object. 460 * 461 * @return if supported, the {@code Font} for the object; otherwise, null 462 */ 463 public Font getFont() { 464 if (source instanceof Component) { 465 return ((Component) source).getFont(); 466 } else if (source instanceof MenuComponent) { 467 return ((MenuComponent) source).getFont(); 468 } else { 469 return null; 470 } 471 } 472 473 /** 474 * Set the {@code Font} of this object. 475 * 476 * @param f the new {@code Font} for the object 477 */ 478 public void setFont(Font f) { 479 if (source instanceof Component) { 480 ((Component) source).setFont(f); 481 } else if (source instanceof MenuComponent) { 482 ((MenuComponent) source).setFont(f); 483 } 484 } 485 486 /** 487 * Get the {@code FontMetrics} of this object. 488 * 489 * @param f the {@code Font} 490 * @return if supported, the {@code FontMetrics} the object; otherwise, null 491 * @see #getFont 492 */ 493 public FontMetrics getFontMetrics(Font f) { 494 if (source instanceof Component) { 495 return ((Component) source).getFontMetrics(f); 496 } else { 497 return null; 498 } 499 } 500 501 /** 502 * Determine if the object is enabled. 503 * 504 * @return true if object is enabled; otherwise, false 505 */ 506 public boolean isEnabled() { 507 if (source instanceof Component) { 508 return ((Component) source).isEnabled(); 509 } else if (source instanceof MenuItem) { 510 return ((MenuItem) source).isEnabled(); 511 } else { 512 return true; 513 } 514 } 515 516 /** 517 * Set the enabled state of the object. 518 * 519 * @param b if true, enables this object; otherwise, disables it 520 */ 521 public void setEnabled(boolean b) { 522 if (source instanceof Component) { 523 ((Component) source).setEnabled(b); 524 } else if (source instanceof MenuItem) { 525 ((MenuItem) source).setEnabled(b); 526 } 527 } 528 529 /** 530 * Determine if the object is visible. 531 * 532 * @return true if object is visible; otherwise, false 533 */ 534 public boolean isVisible() { 535 if (source instanceof Component) { 536 return ((Component) source).isVisible(); 537 } else { 538 return false; 539 } 540 } 541 542 /** 543 * Set the visible state of the object. 544 * 545 * @param b if true, shows this object; otherwise, hides it 546 */ 547 public void setVisible(boolean b) { 548 if (source instanceof Component) { 549 ((Component) source).setVisible(b); 550 } 551 } 552 553 /** 554 * Determine if the object is showing. This is determined by checking 555 * the visibility of the object and ancestors of the object. 556 * 557 * @return true if object is showing; otherwise, false 558 */ 559 public boolean isShowing() { 560 if (source instanceof Component) { 561 return ((Component) source).isShowing(); 562 } else { 563 return false; 564 } 565 } 566 567 /** 568 * Checks whether the specified {@code Point} is within this 569 * object's bounds, where the {@code Point} is relative to the coordinate 570 * system of the object. 571 * 572 * @param p the {@code Point} relative to the coordinate system of the object 573 * @return true if object contains {@code Point}; otherwise false 574 */ 575 public boolean contains(Point p) { 576 if (source instanceof Component) { 577 return ((Component) source).contains(p); 578 } else { 579 return false; 580 } 581 } 582 583 /** 584 * Returns the location of the object on the screen. 585 * 586 * @return location of object on screen; can be null if this object 587 * is not on the screen 588 */ 589 public Point getLocationOnScreen() { 590 if (source instanceof Component) { 591 return ((Component) source).getLocationOnScreen(); 592 } else { 593 return null; 594 } 595 } 596 597 /** 598 * Returns the location of the object relative to parent. 599 * 600 * @return location of object relative to parent; can be null if 601 * this object or its parent are not on the screen 602 */ 603 public Point getLocation() { 604 if (source instanceof Component) { 605 return ((Component) source).getLocation(); 606 } else { 607 return null; 608 } 609 } 610 611 /** 612 * Sets the location of the object relative to parent. 613 */ 614 public void setLocation(Point p) { 615 if (source instanceof Component) { 616 ((Component) source).setLocation(p); 617 } 618 } 619 620 /** 621 * Returns the current bounds of this object. 622 * 623 * @return current bounds of object; can be null if this object 624 * is not on the screen 625 */ 626 public Rectangle getBounds() { 627 if (source instanceof Component) { 628 return ((Component) source).getBounds(); 629 } else { 630 return null; 631 } 632 } 633 634 /** 635 * Sets the current bounds of this object. 636 */ 637 public void setBounds(Rectangle r) { 638 if (source instanceof Component) { 639 ((Component) source).setBounds(r); 640 } 641 } 642 643 /** 644 * Returns the current size of this object. 645 * 646 * @return current size of object; can be null if this object is 647 * not on the screen 648 */ 649 public Dimension getSize() { 650 if (source instanceof Component) { 651 return ((Component) source).getSize(); 652 } else { 653 return null; 654 } 655 } 656 657 /** 658 * Sets the current size of this object. 659 */ 660 public void setSize(Dimension d) { 661 if (source instanceof Component) { 662 ((Component) source).setSize(d); 663 } 664 } 665 666 /** 667 * Returns the accessible child contained at the local coordinate 668 * Point, if one exists. 669 * 670 * @return the Accessible at the specified location, if it exists 671 */ 672 public Accessible getAccessibleAt(Point p) { 673 if (source instanceof Component) { 674 Component c = ((Component) source).getComponentAt(p); 675 if (c != null) { 676 return (getAccessible(c)); 677 } 678 } 679 return null; 680 } 681 682 /** 683 * Returns whether this object can accept focus or not. 684 * 685 * @return true if object can accept focus; otherwise false 686 */ 687 public boolean isFocusTraversable() { 688 if (source instanceof Component) { 689 return ((Component) source).isFocusTraversable(); 690 } else { 691 return false; 692 } 693 } 694 695 /** 696 * Requests focus for this object. 697 */ 698 public void requestFocus() { 699 if (source instanceof Component) { 700 ((Component) source).requestFocus(); 701 } 702 } 703 704 /** 705 * Adds the specified {@code FocusListener} to receive focus events from 706 * this component. 707 * 708 * @param l the focus listener 709 */ 710 public synchronized void addFocusListener(FocusListener l) { 711 if (source instanceof Component) { 712 ((Component) source).addFocusListener(l); 713 } 714 } 715 716 /** 717 * Removes the specified focus listener so it no longer receives focus 718 * events from this component. 719 * 720 * @param l the focus listener; this method performs no function, nor does it 721 * throw an exception if the listener specified was not previously added 722 * to this component; if listener is null, no exception is thrown and no 723 * action is performed. 724 */ 725 public synchronized void removeFocusListener(FocusListener l) { 726 if (source instanceof Component) { 727 ((Component) source).removeFocusListener(l); 728 } 729 } 730 }