Index: ChangeLog =================================================================== RCS file: /cvsroot/classpath/classpath/ChangeLog,v retrieving revision 1.2448 diff -u -3 -p -u -r1.2448 ChangeLog --- ChangeLog 31 Aug 2004 22:17:29 -0000 1.2448 +++ ChangeLog 1 Sep 2004 01:31:27 -0000 @@ -1,3 +1,9 @@ +2004-09-01 Andrew John Hughes
+ + * java/awt/MenuComponent.java, java/awt/MenuBar.java + Implementation of accessibility classes and methods + for these two components. + 2004-08-31 Mark Wielaard * NEWS: Add new news. Index: java/awt/Component.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v retrieving revision 1.39 diff -u -3 -p -u -r1.39 Component.java --- java/awt/Component.java 8 Aug 2004 13:01:35 -0000 1.39 +++ java/awt/Component.java 1 Sep 2004 01:31:29 -0000 @@ -4498,7 +4498,7 @@ p *MenuBar
.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ {
+ /* Create the context */
+ accessibleContext = new AccessibleAWTMenuBar();
+ }
+ return accessibleContext;
+}
+
+/**
+ * This class provides accessibility support for AWT menu bars.
+ *
+ * @author Andrew John Hughes
+ */
+protected class AccessibleAWTMenuBar
+ extends AccessibleAWTMenuComponent
+{
+
+ /**
+ * Compatible with JDK 1.4.2 revision 5
+ */
+ private static final long serialVersionUID = -8577604491830083815L;
+
+ /**
+ * This is the default constructor, which simply calls the default
+ * constructor of the superclass.
+ */
+ protected AccessibleAWTMenuBar()
+ {
+ super();
+ }
+
+ /**
+ * Returns the accessible role relating to the menu bar.
+ *
+ * @return AccessibleRole.MENU_BAR
.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU_BAR;
+ }
+
+} // class AccessibleAWTMenuBar
+
} // class MenuBar
Index: java/awt/MenuComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/MenuComponent.java,v
retrieving revision 1.14
diff -u -3 -p -u -r1.14 MenuComponent.java
--- java/awt/MenuComponent.java 26 Dec 2003 16:37:27 -0000 1.14
+++ java/awt/MenuComponent.java 1 Sep 2004 01:31:29 -0000
@@ -38,15 +38,23 @@ exception statement from your version. *
package java.awt;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
import java.awt.peer.MenuComponentPeer;
import java.io.Serializable;
-
-// FIXME: Java 1.0 event model unimplemented
+import java.util.Locale;
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleStateSet;
/**
- * This is the superclass of all non-menu AWT widgets.
+ * This is the superclass of all menu AWT widgets.
*
* @author Aaron M. Renn (address@hidden)
+ * @author Andrew John Hughes
*/
public abstract class MenuComponent implements Serializable
{
@@ -59,31 +67,100 @@ public abstract class MenuComponent impl
private static final long serialVersionUID = -4536902356223894379L;
/*************************************************************************/
-
+
/*
* Instance Variables
*/
- // FIXME: missing serialized fields `nameExplicitlySet',
- // `newEventsOnly', and `accessibleContext'.
-
-// The font for this component
-private Font font;
-
-// The name of the component
-private String name;
-
-// The parent of this component
-transient MenuContainer parent;
-
-// The native peer for this componet
-transient MenuComponentPeer peer;
-
-// The synchronization locking object for this component
-private transient Object tree_lock = this;
+/**
+ * The font for this component.
+ *
+ * @see #getFont()
+ * @see #setFont(java.awt.Font)
+ * @serial the component's font.
+ */
+ private Font font;
-// The toolkit for this object
-private static transient Toolkit toolkit = Toolkit.getDefaultToolkit();
+ /**
+ * The name of the component.
+ *
+ * @see #getName()
+ * @see #setName(String)
+ * @serial the component's name.
+ */
+ private String name;
+
+ /**
+ * The parent of this component.
+ *
+ * @see #getParent()
+ * @see #setParent(java.awt.MenuContainer)
+ * @serial ignored.
+ */
+ transient MenuContainer parent;
+
+ /**
+ * The native peer for this component.
+ *
+ * @see #getPeer()
+ * @see #setPeer(java.awt.peer.MenuComponentPeer)
+ * @serial ignored.
+ */
+ transient MenuComponentPeer peer;
+
+ /**
+ * The synchronization locking object for this component.
+ *
+ * @serial ignored.
+ */
+ private transient Object tree_lock = this;
+
+ /**
+ * The toolkit for this object.
+ *
+ * @see #getToolkit()
+ * @serial ignored.
+ */
+ private static transient Toolkit toolkit = Toolkit.getDefaultToolkit();
+
+ /**
+ * The accessible context for this component.
+ *
+ * @see #getAccessibleContext()
+ * @serial the accessibility information for this component.
+ */
+ private AccessibleContext accessibleContext;
+
+ /**
+ * Was the name of the component set? This value defaults
+ * to false and becomes true after a call to setName()
.
+ * Please note that this does not guarantee that name will then
+ * be non-null, as this may be the value passed to setName()
.
+ *
+ * @see #setName(String)
+ * @serial true if the name value has been explicitly set by calling
+ * setName()
.
+ */
+ private boolean nameExplicitlySet;
+
+ /**
+ * Does this component handle new events? Events will be handled
+ * by this component if this is true. Otherwise, they will be forwarded
+ * up the component hierarchy.
+ *
+ * @see #dispatchEvent(AWTEvent)
+ * @serial true if events are to be processed locally.
+ */
+ private boolean newEventsOnly;
+
+ /**
+ * The focus listener chain handler which deals with focus events for
+ * the accessible context of this component.
+ *
+ * @see AccessibleAWTMenuComponent#addFocusListener(java.awt.event.FocusListener)
+ * @serial ignored.
+ */
+ private transient FocusListener focusListener;
/*************************************************************************/
@@ -157,6 +234,7 @@ public void
setName(String name)
{
this.name = name;
+ nameExplicitlySet = true;
}
/*************************************************************************/
@@ -260,13 +338,14 @@ setTreeLock(Object tree_lock)
* AWT 1.0 event dispatcher.
*
* @deprecated Deprecated in favor of dispatchEvent()
.
+ * @return true if the event was dispatched, false otherwise.
*/
public boolean
postEvent(Event event)
{
- return(false);
+ // This is overridden by subclasses that support events.
+ return false;
}
-
/*************************************************************************/
/**
@@ -274,17 +353,35 @@ postEvent(Event event)
*
* @param event The event to dispatch
*/
-public final void
-dispatchEvent(AWTEvent event)
+public final void dispatchEvent(AWTEvent event)
{
// See comment in Component.dispatchEvent().
dispatchEventImpl(event);
}
-void
-dispatchEventImpl(AWTEvent e)
+
+/**
+ * Implementation of dispatchEvent. Allows trusted package classes
+ * to dispatch additional events first. This implementation first
+ * translates event
to an AWT 1.0 event and sends the
+ * result to address@hidden #postEvent}. The event is then
+ * passed on to address@hidden #processEvent} for local processing.
+ *
+ * @param event the event to dispatch.
+ */
+void dispatchEventImpl(AWTEvent event)
{
+ Event oldStyleEvent;
+
// This is overridden by subclasses that support events.
+ /* Convert AWT 1.1 event to AWT 1.0 event */
+ oldStyleEvent = Component.translateEvent(event);
+ if (oldStyleEvent != null)
+ {
+ postEvent(oldStyleEvent);
+ }
+ /* Do local processing */
+ processEvent(event);
}
/*************************************************************************/
@@ -298,6 +395,25 @@ dispatchEventImpl(AWTEvent e)
protected void
processEvent(AWTEvent event)
{
+ /*
+ Pass a focus event to the focus listener for
+ the accessibility context.
+ */
+ if (event instanceof FocusEvent)
+ {
+ if (focusListener != null)
+ {
+ switch (event.id)
+ {
+ case FocusEvent.FOCUS_GAINED:
+ focusListener.focusGained((FocusEvent) event);
+ break;
+ case FocusEvent.FOCUS_LOST:
+ focusListener.focusLost((FocusEvent) event);
+ break;
+ }
+ }
+ }
}
/*************************************************************************/
@@ -316,15 +432,884 @@ toString()
/*************************************************************************/
/**
- * Returns a debugging string for this component
- */
+ * Returns a debugging string for this component
+ */
protected String
paramString()
{
return "name=" + getName();
}
-// Accessibility API not yet implemented.
-// public AccessibleContext getAccessibleContext()
+/**
+ * Gets the AccessibleContext associated with this MenuComponent
.
+ * As an abstract class, we return null. Concrete subclasses should return
+ * their implementation of the accessibility context.
+ *
+ * @return null.
+ */
+
+public AccessibleContext getAccessibleContext()
+{
+ return null;
+}
+
+/**
+ * This class provides a base for the accessibility support of menu
+ * components.
+ *
+ * @author Andrew John Hughes
+ */
+protected abstract class AccessibleAWTMenuComponent
+ extends AccessibleContext
+ implements Serializable, AccessibleComponent, AccessibleSelection
+{
+
+ /**
+ * Compatible with JDK 1.4.2 revision 5
+ */
+ private static final long serialVersionUID = -4269533416223798698L;
+
+ /**
+ * This is the default constructor. It should be called by
+ * concrete subclasses to ensure necessary groundwork is completed.
+ */
+ protected AccessibleAWTMenuComponent()
+ {
+ }
+
+ /**
+ * Replaces or supplements the component's selection with the
+ * Accessible
child at the supplied index. If
+ * the component supports multiple selection, the child is
+ * added to the current selection. Otherwise, the current
+ * selection becomes the specified child. If the child is
+ * already selected, nothing happens.
+ * getBounds()
method. Subclasses
+ * must provide the bounding rectangle via getBounds()
+ * in order for this method to work.
+ *
+ * @param point the point to check against this component.
+ * @return true if the point is within this component.
+ * @see #getBounds()
+ */
+ public boolean contains(Point point)
+ {
+ /*
+ We can simply return the result of a
+ test for containment in the bounding rectangle
+ */
+ return getBounds().contains(point);
+ }
+
+ /**
+ * Returns the Accessible
child of this component present
+ * at the specified point. The supplied co-ordinates are
+ * assumed to be relative to the co-ordinate system of this
+ * component (the parent of any returned accessible). Thus,
+ * the point (0,0) is the upper left corner of this menu
+ * component.
+ * Accessible
child at the supplied
+ * index within the list of children of this component.
+ * Accessible
child
+ * to retrieve.
+ * @return null.
+ */
+ public Accessible getAccessibleChild(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the number of children of this component which
+ * implement the Accessible
interface. If
+ * all children of this component are accessible, then
+ * the returned value will be the same as the number of
+ * children.
+ * AccessibleComponent
associated
+ * with this accessible context and its component. As the
+ * context itself implements AccessibleComponent
,
+ * this is the return value.
+ *
+ * @return the context itself.
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the accessible name for this menu component. This
+ * is the name given to the component, which may be null if
+ * not set using setName()
.
+ * MenuContainer
+ * is not Accessible
.
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return -1;
+ }
+
+ /**
+ * Returns the accessible name of this component. This
+ * is the name given to the component, which may be null if
+ * not set using setName()
.
+ * Accessible
parent of this component.
+ * As the parent of a MenuComponent
is a
+ * MenuContainer
, which doesn't implement
+ * Accessible
, this method returns null.
+ *
+ * @return null.
+ */
+ public Accessible getAccessibleParent()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the accessible role of this component.
+ * AccessibleRole.AWT_COMPONENT
,
+ * as the abstract component has no specific role. This
+ * method should be overridden by concrete subclasses, so
+ * as to return an appropriate role for the component.
+ *
+ * @return AccessibleRole.AWT_COMPONENT
.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.AWT_COMPONENT;
+ }
+
+ /**
+ * Retrieves the AccessibleSelection
associated
+ * with this accessible context and its component. As the
+ * context itself implements AccessibleSelection
,
+ * this is the return value.
+ *
+ * @return the context itself.
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /**
+ * Retrieves the Accessible
selected child
+ * at the specified index. If there are no selected children
+ * or the index is outside the range of selected children,
+ * null is returned. Please note that the index refers
+ * to the index of the child in the list of selected
+ * children, and not the index of the child in
+ * the list of all Accessible
children.
+ * Accessible
+ * child.
+ */
+ public Accessible getAccessibleSelection(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns a count of the number of Accessible
+ * children of this component which are currently selected.
+ * If there are no children currently selected, 0 is returned.
+ * PropertyChangeListener
s.
+ *
+ * @return an empty AccessibleStateSet
.
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return new AccessibleStateSet();
+ }
+
+ /**
+ * Returns the background color of the component, or null
+ * if this property is unsupported.
+ * Rectangle
which represents the
+ * bounds of this component. The returned rectangle has the
+ * height and width of the component's bounds, and is positioned
+ * at a location relative to this component's parent, the
+ * MenuContainer
. null is returned if bounds
+ * are not supported by the component.
+ * Cursor
displayed when the pointer
+ * is positioned over this component. Alternatively, null
+ * is returned if the component doesn't support the cursor
+ * property.
+ * Font
used for text created by this component.
+ *
+ * @return the current font.
+ * @see #setFont(java.awt.Font)
+ */
+ public Font getFont()
+ {
+ return MenuComponent.this.getFont();
+ }
+
+ /**
+ * Retrieves information on the rendering and metrics of the supplied
+ * font. If font metrics are not supported by this component, null
+ * is returned.
+ * FontMetrics
. Concrete subclasses may
+ * find it more efficient to invoke their peer class directly, if one
+ * is available.
+ *
+ * @param font the font about which to retrieve rendering and metric
+ * information.
+ * @return the metrics of the given font, as provided by the system
+ * toolkit.
+ * @throws NullPointerException if the supplied font was null.
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return MenuComponent.this.getToolkit().getFontMetrics(font);
+ }
+
+ /**
+ * Returns the foreground color of the component, or null
+ * if this property is unsupported.
+ * getBounds()
method. Subclasses
+ * must provide the bounding rectangle via getBounds()
+ * in order for this method to work.
+ *
+ * @return the location of the component, relative to its parent.
+ * @see #setLocation(java.awt.Point)
+ */
+ public Point getLocation()
+ {
+ /* Simply return the location of the bounding rectangle */
+ return getBounds().getLocation();
+ }
+
+ /**
+ * Returns the location of the component, with co-ordinates
+ * relative to the screen. Thus, the point (0,0) is the upper
+ * left corner of the screen. null is returned if the component
+ * is either not on screen or if this property is unsupported.
+ * getBounds()
method. Subclasses
+ * must provide the bounding rectangle via getBounds()
+ * in order for this method to work.
+ *
+ * @return the size of the component.
+ * @see #setSize(java.awt.Dimension)
+ */
+ public Dimension getSize()
+ {
+ /* Simply return the size of the bounding rectangle */
+ return getBounds().getSize();
+ }
+
+ /**
+ * Returns true if the accessible child specified by the supplied index
+ * is currently selected.
+ * isShowing()
should be
+ * used.
+ * Accessible
child.
+ */
+ public void removeAccessibleSelection(int index)
+ {
+ /* Subclasses with children should implement this */
+ }
+
+ /**
+ * Removes the specified focus listener from the list of registered
+ * focus listeners for this component.
+ *
+ * @param listener the listener to remove.
+ */
+ public void removeFocusListener(FocusListener listener)
+ {
+ /* Remove the focus listener from the chain */
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ /**
+ * Requests that this component gains focus. This depends on the
+ * component being focus traversable.
+ * Accessible
children of this component which
+ * it is possible to select. The component needs to support multiple
+ * selections.
+ * addAccessibleSelection
to
+ * add each Accessible
child to the selection. The last
+ * Accessible
component is thus selected for components
+ * which don't support multiple selections. Concrete implementations should
+ * override this with a more appopriate and efficient implementation, which
+ * properly takes into account the ability of the component to support multiple
+ * selections.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ /* Simply call addAccessibleSelection() on all accessible children */
+ for (int a = 0; a < getAccessibleChildrenCount(); ++a)
+ {
+ addAccessibleSelection(a);
+ }
+ }
+
+ /**
+ * Sets the background color of the component to that specified.
+ * Unspecified behaviour occurs when null is given as the new
+ * background color.
+ * getBounds()
.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param rectangle a rectangle which specifies the new bounds of
+ * the component.
+ * @see #getBounds()
+ */
+ public void setBounds(Rectangle rectangle)
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Sets the Cursor
used when the pointer is positioned over the
+ * component. Unspecified behaviour occurs when null is given as the new
+ * cursor.
+ * Font
used for text created by this component.
+ * Unspecified behaviour occurs when null is given as the new
+ * font.
+ *
+ * @param font the new font to use for text.
+ * @see #getFont()
+ */
+ public void setFont(Font font)
+ {
+ /* Call the method of the enclosing component */
+ MenuComponent.this.setFont(font);
+ }
+
+ /**
+ * Sets the foreground color of the component to that specified.
+ * Unspecified behaviour occurs when null is given as the new
+ * background color.
+ * getBounds()
method. Subclasses
+ * must provide the bounding rectangle via getBounds()
+ * in order for this method to work.
+ *
+ * @param point the location of the component, relative to its parent.
+ * @see #getLocation()
+ */
+ public void setLocation(Point point)
+ {
+ getBounds().setLocation(point);
+ }
+
+ /**
+ * Sets the size of the component.
+ * getBounds()
method. Subclasses
+ * must provide the bounding rectangle via getBounds()
+ * in order for this method to work.
+ *
+ * @param size the new size of the component.
+ * @see #getSize()
+ */
+ public void setSize(Dimension size)
+ {
+ getBounds().setSize(size);
+ }
+
+ /**
+ * Sets the visibility state of the component. A component may
+ * be visible but not drawn on the screen if one of its parent
+ * components is not visible. To determine if the component is
+ * actually drawn on screen, isShowing()
should be
+ * used.
+ *