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 }