I implemented the remaining missing pieces for the AccessibleJComponent,
so in theory accessibility for Swing should somewhat work now.

I came across some oddities, like AccessibleAWTContainer also having a
field accessibleContainerHandler, AccessibleAWTComponent having a field
accessibleAWTFocusHandler, which both seem to overlap with the
AccessibleJComponent fields. I suppose the AccessibleJComponent fields
were there first and are now left in place so that binary compatibility
is not affected. I added @specnotes all over the place.

Also, I reverted the getAccessibleStateSet() method to simply return
super. The only state handled that I attributed to JComponent is opaque,
I really didn't knew that java.awt.Component also has this property.
Since we already handle this in AccessibleAWTComponent, we do not need
to handle it here too.

2006-04-05  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/JComponent.java
        (accessibleContext): Fixed API doc for this field.
        (AccessibleJComponent.AccessibleFocusHandler): Fixed API docs.
        (AccessibleJComponent.AccessibleFocusHandler.focusGained):
        Implemented and added API docs.
        (AccessibleJComponent.AccessibleFocusHandler.focusLost):
        Implemented and added API docs.
        (AccessibleJComponent.AccessibleContainerHandler): Fixed API docs.
        (AccessibleJComponent.AccessibleContainerHandler.componentAdded):
        Implemented and added API docs.
       
(AccessibleJComponent.AccessibleContainerHandler.componentRemoved):
        Implemented and added API docs.
        (AccessibleJComponent.accessibleContainerHandler): Added API docs.
        (AccessibleJComponent.accessibleFocusHandler): Added API docs.
        (AccessibleJComponent.addPropertyChangeListener): Added API docs.
        (AccessibleJComponent.removePropertyChangeListener): Added API
docs.
        (AccessibleJComponent.getAccessibleStateSet): Simply return
        super here. Added comment about this.


/Roman
Index: javax/swing/JComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.112
diff -u -1 -0 -r1.112 JComponent.java
--- javax/swing/JComponent.java	5 Apr 2006 18:56:04 -0000	1.112
+++ javax/swing/JComponent.java	5 Apr 2006 21:39:26 -0000
@@ -98,85 +98,170 @@
  * implemented elsewhere.
  *
  * @author Ronald Veldema (rveldema&064;cs.vu.nl)
  * @author Graydon Hoare (graydon&064;redhat.com)
  */
 public abstract class JComponent extends Container implements Serializable
 {
   private static final long serialVersionUID = -7908749299918704233L;
 
   /** 
-   * Accessibility support is currently missing.
+   * The accessible context of this <code>JComponent</code>.
    */
   protected AccessibleContext accessibleContext;
 
   /**
    * Basic accessibility support for <code>JComponent</code> derived
    * widgets.
    */
   public abstract class AccessibleJComponent 
     extends AccessibleAWTContainer
     implements AccessibleExtendedComponent
   {
     /**
-     * Accessibility support for <code>JComponent</code>'s focus handler.
+     * Receives notification if the focus on the JComponent changes and
+     * fires appropriate PropertyChangeEvents to listeners registered with
+     * the AccessibleJComponent.
      */
     protected class AccessibleFocusHandler 
       implements FocusListener
     {
+      /**
+       * Creates a new AccessibleFocusHandler.
+       */
       protected AccessibleFocusHandler()
       {
-        // TODO: Implement this properly.
+        // Nothing to do here.
       }
+
+      /**
+       * Receives notification when the JComponent gained focus and fires
+       * a PropertyChangeEvent to listeners registered on the
+       * AccessibleJComponent with a property name of
+       * [EMAIL PROTECTED] AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and a new value
+       * of [EMAIL PROTECTED] AccessibleState#FOCUSED}.
+       */
       public void focusGained(FocusEvent event)
       {
-        // TODO: Implement this properly.
+        AccessibleJComponent.this.firePropertyChange
+          (AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null,
+           AccessibleState.FOCUSED);
       }
+
+      /**
+       * Receives notification when the JComponent lost focus and fires
+       * a PropertyChangeEvent to listeners registered on the
+       * AccessibleJComponent with a property name of
+       * [EMAIL PROTECTED] AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and an old value
+       * of [EMAIL PROTECTED] AccessibleState#FOCUSED}.
+       */
       public void focusLost(FocusEvent valevent)
       {
-        // TODO: Implement this properly.
+        AccessibleJComponent.this.firePropertyChange
+          (AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
+           AccessibleState.FOCUSED, null);
       }
     }
 
     /**
-     * Accessibility support for <code>JComponent</code>'s container handler.
+     * Receives notification if there are child components are added or removed
+     * from the JComponent and fires appropriate PropertyChangeEvents to
+     * interested listeners on the AccessibleJComponent.
      */
     protected class AccessibleContainerHandler 
       implements ContainerListener
     {
+      /**
+       * Creates a new AccessibleContainerHandler.
+       */
       protected AccessibleContainerHandler()
       {
-        // TODO: Implement this properly.
+        // Nothing to do here.
       }
+
+      /**
+       * Receives notification when a child component is added to the
+       * JComponent and fires a PropertyChangeEvent on listeners registered
+       * with the AccessibleJComponent with a property name of
+       * [EMAIL PROTECTED] AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
+       *
+       * @param event the container event
+       */
       public void componentAdded(ContainerEvent event)
       {
-        // TODO: Implement this properly.
+        Component c = event.getChild();
+        if (c != null && c instanceof Accessible)
+          {
+            AccessibleContext childCtx = c.getAccessibleContext();
+            AccessibleJComponent.this.firePropertyChange
+              (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, childCtx);
+          }
       }
-      public void componentRemoved(ContainerEvent valevent)
+
+      /**
+       * Receives notification when a child component is removed from the
+       * JComponent and fires a PropertyChangeEvent on listeners registered
+       * with the AccessibleJComponent with a property name of
+       * [EMAIL PROTECTED] AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
+       *
+       * @param event the container event
+       */
+      public void componentRemoved(ContainerEvent event)
       {
-        // TODO: Implement this properly.
+        Component c = event.getChild();
+        if (c != null && c instanceof Accessible)
+          {
+            AccessibleContext childCtx = c.getAccessibleContext();
+            AccessibleJComponent.this.firePropertyChange
+              (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, childCtx, null);
+          }
       }
     }
 
     private static final long serialVersionUID = -7047089700479897799L;
-  
+
+    /**
+     * Receives notification when a child component is added to the
+     * JComponent and fires a PropertyChangeEvent on listeners registered
+     * with the AccessibleJComponent.
+     *
+     * @specnote AccessibleAWTContainer has a protected field with the same
+     *           name. Looks like a bug or nasty misdesign to me.
+     */
     protected ContainerListener accessibleContainerHandler;
+
+    /**
+     * Receives notification if the focus on the JComponent changes and
+     * fires appropriate PropertyChangeEvents to listeners registered with
+     * the AccessibleJComponent.
+     *
+     * @specnote AccessibleAWTComponent has a protected field
+     *           accessibleAWTFocusHandler. Looks like a bug or nasty misdesign
+     *           to me.
+     */
     protected FocusListener accessibleFocusHandler;
 
+    /**
+     * Creates a new AccessibleJComponent.
+     */
     protected AccessibleJComponent()
     {
-      // nothing to do here
+      // Nothing to do here.
     }
 
     /**
      * Adds a property change listener to the list of registered listeners.
      *
+     * This sets up the [EMAIL PROTECTED] #accessibleContainerHandler} and
+     * [EMAIL PROTECTED] #accessibleFocusHandler} fields and calls
+     * <code>super.addPropertyChangeListener(listener)</code>.
+     *
      * @param listener the listener to add
      */
     public void addPropertyChangeListener(PropertyChangeListener listener)
     {
       // Tests seem to indicate that this method also sets up the other two
       // handlers.
       if (accessibleContainerHandler == null)
         {
           accessibleContainerHandler = new AccessibleContainerHandler();
           addContainerListener(accessibleContainerHandler);
@@ -185,20 +270,24 @@
         {
           accessibleFocusHandler = new AccessibleFocusHandler();
           addFocusListener(accessibleFocusHandler);
         }
       super.addPropertyChangeListener(listener);
     }
 
     /**
      * Removes a property change listener from the list of registered listeners.
      *
+     * This uninstalls the [EMAIL PROTECTED] #accessibleContainerHandler} and
+     * [EMAIL PROTECTED] #accessibleFocusHandler} fields and calls
+     * <code>super.removePropertyChangeListener(listener)</code>.
+     *
      * @param listener the listener to remove
      */
     public void removePropertyChangeListener(PropertyChangeListener listener)
     {
       // Tests seem to indicate that this method also resets the other two
       // handlers.
       if (accessibleContainerHandler != null)
         {
           removeContainerListener(accessibleContainerHandler);
           accessibleContainerHandler = null;
@@ -241,26 +330,24 @@
       return super.getAccessibleChild(i);
     }
 
     /**
      * Returns the accessible state set of this component.
      *
      * @return the accessible state set of this component
      */
     public AccessibleStateSet getAccessibleStateSet()
     {
-      AccessibleStateSet state = super.getAccessibleStateSet();
-      if (isOpaque())
-        {
-          state.add(AccessibleState.OPAQUE);
-        }
-      return state;
+      // TODO: The only JComponent property that is (theoretically) handled
+      // here seems to be 'opaque'. However, we already handle this in
+      // AccessibleAWTComponent and do not need to handle it here too.
+      return super.getAccessibleStateSet();
     }
 
     /**
      * Returns the localized name for this object. Generally this should
      * almost never return [EMAIL PROTECTED] Component#getName()} since that is not
      * a localized name. If the object is some kind of text component (like
      * a menu item), then the value of the object may be returned. Also, if
      * the object has a tooltip, the value of the tooltip may also be
      * appropriate.
      *

Reply via email to