[opened accessibility door] IBM Guidelines for Writing Accessible Applications Using 100% Pure Javatm Version 1.1 7 December 1998 © Copyright IBM Corporation 1998 The most current version of these guidelines is maintained at: [1]http://www.austin.ibm.com/sns/access.html Document Author: Richard S. Schwerdtfeger Senior Software Engineer and Lead Architect IBM Special Needs Systems e-mail: [2]schwer@us.ibm.com Reviewers: [3]IBM Special Needs Systems Review Team Table of Contents * [4]Acknowledgments * [5]Notices * [6]1.0 Executive Summary * [7]2.0 Introduction + [8]2.1 Disability Needs + [9]2.2 Why Java for Accessibility? * [10]3.0 Essential Accessibility Programming Practices + [11]3.1 Making the Keyboard Accessible (Mouseless operation) + [12]3.2 Using Images, Audio, and Video + [13]3.3 Providing Focus + [14]3.4 Using Alerts and Dialogs + [15]3.5 Using AWT and Native Windowing Invocations + [16]3.6 Multi-Threading Your Application - Be Access Aware + [17]3.7 Provide a Logical Component Layout * [18]4.0 Java Foundation Classes (JFC) - A Foundation for Accessibility + [19]4.1 Why Use the JFC? * [20]5.0 Using JFC to Build Accessible Applications + [21]5.1 Setting up the JFC Development Environment + [22]5.2 Using the JFC Components Unmodified + [23]5.3 Enhancing JTextComponents o [24]5.3.1 AttributeSet, MutableAttributeSet, and StyleConstants Classes + [25]5.4 Changing Data Models and Cell Renderers + [26]5.5 Creating New Components Based on the JFC + [27]5.6 Requesting the Focus + [28]5.7 Providing an Accessible Layout + [29]5.8 Preparing for Future JFC Accessibility Features * [30]6.0 The Accessibility API + [31]6.1 Interface Accessible o [32]6.1.1 Interfaces o [33]6.1.2 Using Interface Accessible + [34]6.2 AccessibleContext o [35]6.2.1 Basic Accessible Information # [36]6.2.1.1 AccessibleName # [37]6.2.1.2 AccessibleDescription # [38]6.2.1.3 AccessibleValue # [39]6.2.1.4 Locale # [40]6.2.1.5 AccessibleSelection # [41]6.2.1.6 AccessibleComponent # [42]6.2.1.7 AccessibleText @ [43]6.2.1.7.1 Text Attributes @ [44]6.2.1.7.2 Embedding Objects @ [45]6.2.1.7.3 Referencing the Indexed Character String @ [46]6.2.1.7.4 Caret Position and SelectedText @ [47]6.2.1.7.5 Property Changes o [48]6.2.2 Parent/Child Information # [49]6.2.2.1 getAccessibleChild(n) # [50]6.2.2.2 getAccessibleChildCount() # [51]6.2.2.3 getAccessibleParent() # [52]6.2.2.4 getAccessibleIndexInParent() o [53]6.2.3 Role and State Information # [54]6.2.3.1 AccessibleRole # [55]6.2.3.2 AccessibleState o [56]6.2.4 Property Change Notification o [57]6.2.5 National Language Information # [58]6.2.5.1 AccessibleBundle # [59]6.2.5.2 AccessibleResourceBundle o [60]6.2.6 AccessibleAction o [61]6.2.7 Miscellaneous Information # [62]6.2.7.1 AccessibleHypertext # [63]6.2.7.2 AccessibleHyperlink + [64]6.3 Hints, Tips, and Words of Wisdom o [65]6.3.1 Managing Children o [66]6.3.2 Peered Objects o [67]6.3.3 Menus o [68]6.3.4 Text Components o [69]6.3.5 Keyboard Usability Issues * [70]7.0 Java Development Tool Designers * [71]8.0 Testing for Accessibility * [72]9.0 Online Information and Help * [73]10.0 Future Discussions * [74]11.0 Appendix + [75]11.1 Keyboard Binding o [76]11.1.1 JFC Keyboard Bindings for Windows95/NT Components o [77]11.1.2 Difference Evaluation: JFC Keyboard Bindings for Windows95/NT and CDE/Motif o [78]11.1.3 Reserved Key Mappings for Mobility Access Features + [79]11.2 Accessibility References + [80]11.3 Trademarks + [81]11.4 Feedback [82]Acknowledgments The Java Accessibility API is a broad effort that includes contributions from a number of groups. We in the [83]IBM Special Needs Systems group would like to thank the people in the following groups for contributing to and supporting the Java Accessibility API effort: * [84]Sun Microsystems Accessibility Group * [85]Sun Microsystems Swing team * [86]Trace Research and Development Center at the University of Wisconsin - Madison * [87]Adaptive Technology Resource Centre at the University of Toronto * [88]IBM Corporation [89]IBM Special Needs Systems Review Team These guidelines are a result of contributions, technical edits, and suggestions from members of the IBM Special Needs Systems group, including: * Phill Jenkins * Dr. James W. Thatcher * Larry Weiss * Frances Hayden * Roger McKay * Ellen Eggers * Priscila Vicente I would especially like to thank Sun Microsystem's Peter Korn for reviewing the guidelines and Earl Johnson for driving the Javatm accessibility effort at Sun. There are few companies who have so strongly supported people with special needs. Sun Microsystems, like IBM, is one of those companies. Earl Johnson is the driving force behind Sun's accessibility efforts. Thank you Earl! [90]Notices THIS DOCUMENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. All statements regarding future intent are subject to change or withdrawal without notice and represent goals and objectives only. Information in this document about non-IBM products was obtained from the suppliers of those products, published announcement material, or other publicly available sources. The information contained in this document represents the current views of IBM on the issues discussed as of the date of publication. IBM cannot guarantee the accuracy of any information after the date of publication. [91]1.0 Executive Summary Application developers should consider the special needs of disabled users when they develop software programs in Java. In these guidelines, we discuss the following topics: * Essential accessibility programming practices that, if used, make applications easy for disabled people to use. * The Java Foundation Classes (JFC), also known as Swing, and their implementation of accessibility methods in the user interface components. Application developers should take advantage of this easy way to incorporate accessibility into their designs. * The Java Accessibility API. If developers choose to create components themselves, they should implement this API. These topics are covered in detail with supporting rationale, citing specific Java code. Examples are provided where appropriate. These guidelines highlight the Java accessibility features and give you and your team guidance for creating accessible Java-based software. This is the industry's first set of 100% pure Java application development guidelines for accessibility. The guidelines are designed to be interactive, available online, and easy to update. You can print the guidelines document, but the online version at the IBM Special Needs Systems web site ([92]http://www.austin.ibm.com/sns/access.html) will be continually updated and is more helpful because of hyperlinks pointing to additional information. [93]2.0 Introduction When you write a Java application, think about the fact that a disabled person might use your product. Imagine users who cannot use their hands or eyes--that means they cannot use a mouse, type on a keyboard, see a screen, or read a printed User's Guide. Even though a person might be the most qualified person for a position, that person might be overlooked because of a limitation using the computer or your application. Over the years, disabled users and Assistive Technology Vendors (ATVs) have invented incredibly clever work-arounds for these problems. Voice input replaced the mouse, mouth sticks and switches replaced the keyboard, text-to-speech synthesis replaced the screen, and online books replaced printed books. Lest you think only hardware is inaccessible, think again. Software has its share of problems too. Operating systems and application programs often include unintentional roadblocks to people who have disabilities. Some examples: * Programs that provide only mouse input (impossible for people who are blind or who use voice control) * Programs that use audio-only messages (individuals who are deaf cannot hear the messages - this also applies to people with systems that do not have sound capability). * Operating systems that define Ctrl+Alt+Del to reboot the system (try doing this with only one hand). The following section discusses disability issues, in detail, to lead to a better understanding of how to make an accessible Java solution. [94]2.1 Disability Needs You can build accessibility into Java software and make it easier for assistive technologies to access. The following describes what disabled users need: Users who are blind or who have low vision need: * Keyboard alternatives to the mouse (mouseless operation). * Text descriptions of graphics and video. * To know which object has focus and when the focus changes. * To know the default action and how to take that action. * Online documentation. * Screen magnification. * High color contrast. Users who are deaf or hard of hearing need: * A visual indication of any sound. * Text captioning of multimedia presentations. * Text description of significant audio. Users who are mobility impaired need: * Voice or assistive device input, instead of keyboard or mouse input. * Ways to "get around" multiple key inputs. * Online documentation. Users who have multiple disabilities need: * Combinations of solutions; for example, speech output and voice input that do not conflict. [95]2.2 Why Java for Accessibility? Java was first developed for use in small appliances. It has since evolved into a language that enables applications to run on multiple operating systems and hardware platforms. Because Java runs virtually everywhere, it was enthusiastically adopted for Web and Internet applications. Traditional graphical user interface (GUI) based operating systems now need to support legacy software that is not object-oriented. This introduces inconsistency in the ability to provide accessibility information, and therefore leads to reverse-engineered access solutions, which are not always accurate. Java is object-oriented from the ground up. This provides a mechanism for application components to export accessibility information about themselves to assistive technologies. Java's characteristics and these factors make it ideal for developing industry standards for accessible solutions. The software engineers at Sun and IBM who are developing Java technology are well aware of accessibility issues. They are consulting with disabled customers, and business, education, and rehabilitation experts in the computer accessibility community. They are also conducting extensive reviews and beta testing of their code. As a result, many accessibility features are already built into Java and more features are expected. If you exploit the Java accessibility features when you develop software, you win in three ways. First, the features are easy enough to incorporate that you won't expend lots of development resource. Second, your software will be universally accessible; customers of all abilities will be able to work with it. Third, features that are designed specifically for disabled users often make the product more usable for non-disabled users as well. For example, if you "keyboard-enable" your application so that it is easier for blind users to read with their screen readers, it will be easier for people who use voice control software as well. Assistive Technology Vendors (ATVs) are winners too. If you implement your application using the Java accessibility features, ATVs have a much easier time making their products work with yours. IBM took advantage of this technology. The IBM Self Voicing Kit for Java (SVK) will soon be released on the [96]IBM alphaWorks site. The SVK includes: * Software to automatically speak your accessible Java application * An extended user interface for blind user access * IBM's new Access Engine technology for multi-platform accessibility * A built-in accessibility test tool * Documentation for extending the self voicing user interface for your application * This document The SVK and its Access Engine, formerly known as the Java-based screen reader technology, is the industry's first cross-platform assistive technology that can also be used for mainstream computer users. It is designed to allow developers to build and deploy accessible solutions for disabled and non-disabled users. [97]3.0 Essential Accessibility Programming Practices In this section, you will find a list of specific practices that are absolutely essential for making your Java applications accessible. [98]3.1 Making the Keyboard Accessible (Mouseless Operation) Mouse usage fundamentally depends on visual feedback of the location of the mouse pointer on the screen. Therefore, blind users, who might depend on the software for employment, cannot use a mouse. The blind user depends on the keyboard for navigation. Keyboard navigation is also necessary when window or program controls, such as the tool bar, menus, or buttons are beyond the visible screen display, and therefore, cannot be accessed with the mouse. Without keyboard access, the application is inaccessible to both sighted and non-sighted users in this situation. Other examples include automated software, test cases, and voice-activated software that navigate the application programmatically simulating keyboard events. Accessible software includes keyboard equivalents for all actions or functions of the application, for example, keyboard equivalents for all mouse actions including, but not limited to, buttons, scroll windows, text-entry fields, and pop-up menus. The application must provide pull-down menu equivalents for icon functions (menu, tool, and format bars) and ensure keyboard access to these pull-down menus. Traditional "usable" software ensures the opposite is also provided - visible pull-down menu equivalents for all short-cut keys and tool bar functions. Important: The application must not interfere with existing accessibility features built into the operating system, such as Sticky Keys, Slow Keys, and Repeat Keys. It's easy to check if keyboard access is available in an application - have the test team use the product without the mouse. See [99]section 11.1 Keyboard Binding for example key mappings to navigate in and out of applications. See [100]section 6.3.5 Keyboard Usability Issues for usability issues related to keyboard enabling your application. [101]3.2 Using Images, Audio, and Video When using multimedia in your application, you need to incorporate the following functionality: * Visual indication of sound and audio cues. Example: Visual message as well as a sound beep when notifying the user. * Text captioning of the voice track in audio and video content. Example: Provide visual text captioning when playing audio files. * Descriptive graphics for significant audio. Example: Provide a visual graphic for a progress indication done with sound. * Descriptive text for significant video. Example: Provide a visual text description of what is happening in a tutorial's video segment. [102]3.3 Providing Focus Access devices and software, as well as disabled users, need to know where keyboard input focus is directed in an application. It is imperative that you always give input focus to the object on which you want the user to operate. For example, consider the situation where an application brings up its own custom dialog and you have a blind user at the helm. The first thing the blind user wants to do is use the assistive technology screen reader program to speak what object he is on. If there is no sound, the blind user might start typing keys to hear where he is or if the application will respond. When nothing speaks, the user's only resort might be to use the mouse, which is impossible for a blind user to use. Please provide keyboard input focus to make your application accessible. [103]3.4 Using Alerts and Dialogs Dialogs and Alerts should be built based on the Java accessibility development methodology described in these guidelines. Dialogs and Alerts often require special system features to maintain the modality of those windows. It is recommended that you build these application features from JFC components, such as JDialog. These components are made to work with assistive technologies so that the software can track the user's input focus. While other mechanisms might appear to work visually, they might not be programmatically accessible. [104]3.5 Using AWT and Native Windowing Invocations To date, most Java Abstract Window Toolkit (AWT) components resort to a process called "peering." This means that AWT components, such as dialogs, buttons, menus, and File Dialogs use the native windowing system to do the drawing and much of the component state management. This means that most accessibility information is lost to Java assistive technology software. The new Java Accessibility API has not been implemented in the AWT library. We recommend you develop Java applications using the methodology outlined in these guidelines. Specifically, these guidelines recommend that you start building your application using Java Foundation Classes (JFC/Swing), rather than the AWT. [105]3.6 Multi-Threading Your Application - Be Access Aware Many applications written today are single-threaded. This is, in part, to simplify the development effort. In other cases, the developer wants to easily inhibit an application from being navigated while another task is being executed. For example, when a client application is requesting an action from a remote server, it might not want the user to make a selection while this is going on. The problem with this approach is that if the critical task you are executing is blocked or inhibited waiting for a task to complete, nothing else gets to run. In the client/server example, you need to ask yourself: What happens when the server does not respond? When there is an assistive technology running in the background, and you prohibit other threads from executing, or you severely inhibit the time they have to run, you inhibit the disabled user from accessing your software. Important: Design your application to be adequately multi-threaded to allow assistive technologies to have adequate time to assist the disabled user. Be access aware. [106]3.7 Provide a Logical Component Layout Blind users of your application want to be able to navigate your application through the keyboard and through speech. To day there is not a common mechanism to specifically define this logical layout. To solve this problem you need to add components to your application in a logical order so that a disabled user could have your application logically read to them. A recommended means to accomplish this is defined in [107]section 5.7 Providing an Accessible Layout. [108]4.0 Java Foundation Classes (JFC) - A Foundation for Accessibility In February of 1997, Sun Microsystems and IBM began a collaboration to solve the problem of access-enabling software as applications are being developed. Their goal was to develop an accessibility API that application developers could implement on Java class libraries to make them accessible. Sun wrote the Accessibility API and implemented it on their Java Foundation Classes. IBM Special Needs Systems helped define and implement the API, and tested the JFC implementation with the Access Engine technology in IBM's Self Voicing Kit. [block diagram of JFC structure] FIGURE 1.0 JFC Architecture JFC includes the Swing components. Swing is an enhancement of - not a replacement for - the Abstract Windowing Toolkit (AWT), which you are probably familiar with in JDK 1.1.x. An important difference between Swing and AWT is that Swing creates its components using Pluggable "Look & Feel" (PLAF) modules that do not use native code. As shown in Figure 1.0 above, Swing sits atop of part, but not all, of the AWT components. Swing sits on a number of the APIs that implement the various parts of AWT, including Java2D, Drag-and-Drop, and the Accessibility API. Sun Microsystems has now integrated JFC/Swing directly into JDK 1.2. A key feature of the PLAF is that it enables developers to swap the Look and Feel of the user interface. This feature allows a developer to create a Look and Feel which can be "directly accessible" to a specific disability. For example you could create an audio, Braille, or other alternative user interface to your application. The Sun accessibility group also added a mechanism to the JFC called the Multiplexed UI, which is an extension to the PLAF. The Multiplexed UI allows developers and assistive technologies to add multiple alternative user interfaces to the JFC component library when a Java Virtual Machine (JVM) starts. The Multiplexed UI also makes multi-modal access features, such as hands-free voice access to applications that both disabled and non-disabled people alike use, possible for very little development effort. [109]4.1 Why Use the JFC? The "already-implemented" Accessibility API and the Multiplexed UI features of the JFC are why we urge you to use the JFC to build your applications. [110]Figure 1.1 highlights the JFC accessible component architecture and [111]Figure 1.2 shows how an assistive technology views the "Big Picture". The JFC lets you: * Quickly develop accessible applications that can be made multi-modal accessible without changing the "look and feel" of your application. * Write an accessible application that is accessible, independent of the operating system and windowing environment. If you choose to create your own class library, implement the Java Accessibility API on your class library components. To build an accessible application with the least amount of effort do the following: 1. Wherever possible, use JFC components to build your application, as described in [112]section 5.0 Using the JFC to Build Accessible Applications. 2. If the rich class library in the JFC does not have a component that meets your needs, create your hybrid component from the JFC JComponent class. Implement the Accessibility API on your component, as described in [113]section 6.0 The Accessibility API. The JFC comes with source and there are many examples on which to base your implementation. 3. If steps 1 and 2 do not meet your needs, implement the Accessibility API on your class library or component. 4. Follow the check list in [114]section 8.0 Testing for Accessibility. [115]5.0 Using the JFC to Build Accessible Applications If you are a typical engineer and take a glance at this text, you'll find it is easier to use the JFC than to implement the Accessibility API. Make it easy on yourself and use the JFC! This section discusses how you use the JFC to build your accessible Java application. It is broken down as follows: * Setting up the JFC Development Environment * Using the JFC Components Unmodified * Enhancing JTextComponents * Changing Data Models and Cell Renderers * Creating New Components Based on the JFC * Preparing for Future JFC Accessibility Features [116]5.1 Setting up the JFC Development Environment The first step toward writing accessible Java applications is to download and install the following software development kits: Software URL Java Development Kit 1.1.7a or later [117]http://java.sun.com/products/jdk/ JFC (Swing) 1.1 [118]http://java.sun.com/products/jfc/ Java Access Utilities Package (jaccess-1.1) [119]http://java.sun.com/products/jfc/ FIGURE 2.0 JFC development environment On these sites, there is a reference to the different versions of the listed development kits. If the required kit is an Early Access version, you are asked to log in to the Java Developer Connection Site before downloading the selected development kit. Please register and download the files needed. Registration is free. If the kit is not an Early Access version, you simply need to download the files. Swing is included in the JFC class library. Note: Sun has announced that JDK 1.2 will have Swing integrated into it, so you will not have to perform separate downloads. Although JFC 1.1 for JDK 1.1.x included the Accessibility API, it does not include Java2D or Drag-and-Drop. [120]5.2 Using the JFC Components Unmodified The JFC is an extremely rich class library that has implemented both keyboard accessibility as well as the accessibility API. If you use JFC "as is", there are only a few simple things you need to do: * Provide Descriptive Component Text: Set the accessible description on all components; see [121]section 6.2.1.2 AccessibleDescription. Hint: Some JFC components use the tool tip for this information in the absence of you setting an accessible description. So, if you already set the tool tip text, this task might be complete. * Describe Icons and Graphics: + For JLabels and JButton classes that contain only images, set the AccessibleName; see [122]section 6.2.1.1 AccessibleName. + Whenever you use a JFC setIcon method, use a JFC ImageIcon. Whenever you use a JFC ImageIcon, use its setDescription method to help blind users. ImageIcons are used in a variety of components, ranging from JFC buttons to labels. You must also remember to do this with images inserted into a JTextComponent or with JFC components sub-classed from JTextComponent. * Label Components: When a JLabel is used to label another component, call its setLabelFor method to set the component it is labeling. This can be null if this does not label a component. When you use setLabelFor, the component you label (e.g. a JTextField) will get the AccessibleName and AccessibleDescription of the JLabel. If both the displayedMnemonic and labelFor properties are set, the label requests focus to the component specified by the labelFor property when the mnemonic is activated. [123]Section 5.6 Requesting the Focus provides details about requesting the keyboard focus. * Enable Keyboard Access: + Set Mnemonics on Components: Mnemonics are keyboard equivalents for component activation, for example Alt-F for File. Whenever you have a component that supports a setMnemonic method, set the mnemonic to a unique key sequence to activate the object. Although JFC supports F10 to bring you to a menu bar, there are situations where you might have two menu bars. In these cases it is not clear to the disabled user which menu bar will receive focus when the user presses F10. It is important that you always set the mnemonic for the first JMenuBar entry to allow a disabled user to get there using the keyboard. + Set Keyboard Accelerators in Menus: JMenuItem components provide a setAccelerator method to let you set a keyboard accelerator key. This lets the user activate a menu item without going through the menu. When possible, it is a good, but not mandatory practice, to provide keyboard accelerators. a good rule to use is to always set a keyboard accelerator for menu items that appear visually on a tool bar. + Keyboard Activation of Child JFrames or JInternalFrames: If you build a Java application or applet that manages child frames, provide a keyboard equivalent to let the user cycle the focus to each child frame, or let the user access these frames from a main menu. * Group Objects Inside Named Panels: It is important for you to logically group components and assign that grouping a name. This facilitates navigation of your application. You can accomplish this by adding components to JPanels and setting the AccessibleName on the JPanel. If you use a JPanel with a JFC TitledBorder, there is no reason to set the accessible name because the JFC will do it for you. * Set the Focus: Make sure some component in your application has the input focus at all times. When keyboard enabling your application, this should take care of itself. Most of the JFC components implement focus setting to support keyboard navigation. * Be Sufficiently Multi-Threaded: Make sure your program is adequately multi-threaded to prevent a situation that inhibits a concurrent assistive technology from running. For example, if your client application is dependent on a server action, design your software to let other threads run, even if you are waiting for the server to respond. * Provide an Accessible Layout: When developing the visual layout of your components, provide a logical layout which is determined by the order in which your components are added. The logical layout effects the keyboard tabbing sequence and the order an assistive technology uses to read your application. Assistive Technologies can use the order with which components are added to determine the logical order to use to speak application components. This is also an order for which the Java keyboard tabbing sequence depends. See [124]section 5.7 Providing an Accessible Layout for more details. In short, these simple programming functions let you meet essential accessibility programming requirements. JFC takes care of the rest! [125]5.3 Enhancing JTextComponents JTextComponent is a class with an extendable document model. Each element within the document model needs only to support a common element interface. The element could be anything from another JFC component to simple text. Furthermore, the document model itself has a pre-defined interface. This design allows you to embed documents within documents, insert other complex components, and so on. What enables assistive technologies, such as a blind screen reader product, to decipher this is: * Maintaining the Accessible and AccessibleText interfaces support in JTextComponents. * Maintaining the Accessible and AccessibleHypertext interfaces for JTextComponents supporting hypertext. * Standardizing attributes using the Swing AttributeSet and StyleConstants classes for each indexed character. Unless you modify the JTextComponent, AccessibleText or AccessibleHyperlink implementations, these interfaces still allow an assistive technology to read your "basic" document. JTextComponent implements AccessibleHypertext on Swing editor kits that supports hypertext, allowing assistive technology to enumerate and activate the links in your document. Developers can also break the accessibility of documents by improperly implementing the AttributeSet and its attribute elements. [126]5.3.1 AttributeSet, MutableAttributeSet, and StyleConstants Classes AttributeSet and MutableAttributeSet are JFC classes that define an interface to an attribute set. StyleConstants defines a common set of attributes for the attribute set. Without a known set of attributes, assistive technologies will not know what to do with your document, much the same way that component technology fails without a set of standards. In implementing your AttributeSet for document elements, it is important that you define attributes using those pre-defined in the StyleConstants class. Use the following list of Key/Value pairs: StyleConstant Attribute Keys Class Definition for the Value ALIGN_CENTER Boolean ALIGN_JUSTIFIED Boolean ALIGN_RIGHT Boolean Alignment ALIGN_CENTER, ALIGN_JUSTIFIED, or ALIGN_RIGHT Background Color BidiLevel Integer Bidirectional level as assigned by the Unicode bidi algorithm Bold Boolean ComponentAttribute Component or JComponent that must implement Accessible ComponentElementName String ComposedTextAttribute AttributedString that represents the composed text. FirstLineIndent Float FontFamily String FontSize Integer Foreground Color IconAttribute ImageIcon IconElementName String Italic Boolean LeftIndent Float LineSpacing Float Model Attribute Object defining the model for embedded objects that have a model view separation. NameAttribute String Orientation String representation of orientation ResolveAttribute AttributeSet RightIndent Right SpaceAbove Float SpaceBelow Float StrikeThrough Boolean Subscript Boolean Superscript Boolean Tabset TabSet Underline Boolean Table 3.0 AttributeSet Key/Value Pairs Defined in StyleConstants.java If you are converting an existing program to JFC, the AttributeSet and MutableAttribute interfaces should allow you to convert your existing document structure to a JFC implementation. These interfaces provide for text runs, and embedded components. StyleConstants.java has a provision for embedded components that allows you to embed components in your document elements; you can add things like spreadsheets, and tables. Furthermore, you can define your own user interface using JFC to give whatever look you want to your document. Also, JFC comes with source to show you different implementations other than plain text areas. Important: It is essential that when you add components to your document model, the components implement the Accessible Interface. If you use standard JFC components, they already do. It is helpful if you name the set of attributes as they pertain to specific sets within your document. For example, if you are building a web browser, the NameAttribute for

may be the string "

." This can help an assistive technologies tailor themselves for your application. For example, an assistive technology for the blind user could be designed to navigate the HTML tags of a web document. [127]5.4 Changing Data Models and Cell Renderers The root component class is called JComponent and is a descendant of the AWT container class. JComponent is the root class of almost all JFC classes. The design of each component is based on the Model-View-Controller (MVC) architecture. Each component is broken into three parts: * Model or "data" portion of the component. * User Interface or "look and feel" portion, also called the view. * Controller portion, which manipulates the components. Implementation of the Accessibility API is triggered from the "data portion" of each JFC component. This lets you implement an accessible application without affecting its "look and feel." When developing your application using the JFC, it is important that you avoid modifying or replacing the "data model portion" of each component with your own. You run the risk of improperly implementing methods that are required to support the interfaces and this could break the accessibility features of the component. Another JFC concept is a cell renderer. A cell renderer is an interface that a JFC component uses to define a component drawing object within a list of elements. For example, the JFC uses ListCellRenderers for JList elements and TableCellRenderers for JTable elements. For a given cell renderer, a method is provided to return a component configured for a given element, like getListCellRendererComponent in the JList component. If you change the cell renderer for a JFC component, make sure it implements Accessible. If you implement your cell renderer on an existing JFC component, you can configure your cell renderer for the given element and reuse an already accessible component. An example of this is how JList uses JLabel to render its children. [128]5.5 Creating New Components Based on the JFC If you need to build completely new components, use JComponent because you pick up accessibility information and methods from its internal abstract class AccessibleJComponent. AccessibleJComponent, in fact implements [129]AccessibleComponent, see section 6.2.1.6.. To complete the implementation of the Accessibility API on your JComponent, follow the guidelines in [130]section 6.0 The Accessibility API. [131]5.6 Requesting the Focus There are a number of ways to request the focus in the JFC. The standard way is to have a particular component execute the java.awt.Component requestFocus method. In most cases, this is done automatically for you in Swing by implementing the [132]Keyboard Usability Issues, see section 6.3.5.. Swing might not automatically request the focus when you give your Java application the focus by activating your window. This occurs when you are running another application and you click on your Java application with the mouse, or you use Alt+F6 to switch to your window. When this happens, your application becomes "active", but does not necessarily receive the focus. Correct this by creating a "default focus" of your choosing. Two methods of achieving this are as follows: Using the Window Activation Trigger to Set the Focus: JFrame jf = new JFrame(); //Create a Frame JButton myButton = new JButton(); //Create a JButton Component //(could use a different component) //Add the button the root pane jf.getRootPane().add(myButtton); // Add a Window listener to the JFrame that requests the button to have focus // when the window is activated jf.addWindowListener(new java.awt.event.WindowListener() { void windowActivate() { myButton.requestFocus(); //Note: Do this if focus // has never been set before in your window . // Swing remembers the last focus set. } ... } jf.show(); // Show the Window Using the javax.swing.JRootPane setDefaultButton Method: If you want a JButton to have the default focus in a window, you can use the JRootPane component of any JFrame to set the focus to a default button found in the JRootPane as follows: JFrame jf = new JFrame(); //Create a frame JButton myButton = new JButton(); //Create a JButton Component jf.getRootPane().add(myButtton); // Add the button the root Pane jf.getRootPane().setDefaultButton(myButtton); // Give the button the default fo cus jf.show(); // Show the window [133]5.7 Providing an Accessible Layout Developers typically add components to their application by considering only the visual layout, and not the logical layout that a blind user or asssistive technology reads. For example, in most cases, you would not want your menu bar to be read last. Most component libraries today do not allow you, the developer, to define the logical ordering. Until a better solution is devised, we recommend that when adding components to containers, add them in the logical order as they should be read on the screen. For example, if you are using an AWT border layout, you could add components as follows: public class BorderTest extends Frame implements Accessible{ public BorderTest () { AccessiblePanel p = new AccessiblePanel(); p.setLayout(new BorderLayout(); p.add(new MyAccessibleButton("Left"); p.add(new MyAcessibleButton("Bottom"); p.add(new MyAcessibleButton("Right"); p.add(new MyAcessibleButton("Top"); add("North", p); } AccessibleContext getAccesibleContext() { ... } } Child enumeration in Java enumerates the children in the order that you added them. By merely changing the order in which you add the components, you can enable the assistive technology to read the components in the appropriate order, as shown in the following sample code, and still accomplish the same visual effect: p.add(new MyAcessibleButton("Top"); p.add(new MyAccessibleButton("Left"); p.add(new MyAcessibleButton("Right"); p.add(new MyAcessibleButton("Bottom"); [134]5.8 Preparing for Future JFC Accessibility Features One feature not available in the first Java Accessibility API is support for tables. An AccessibleTable interface is now under review. Its first implementation will be on JTable. If possible, it is recommended that when using tables in your application, you use the JTable class provided in the JFC. When the AccessibleTable interface is implemented, your application should be able to pick up the table accessibility information. Another Accessibility API extension being reviewed is an AccessibleDocument interface for advanced dyslexic and mobility impaired access. Watch the IBM and Sun web sites for announcements about these interfaces. [135]6.0 The Accessibility API The Java Accessibility API is a set of interfaces and classes designed by the Sun Microsystems Accessibility Group, IBM Special Needs Systems, Trace Research and Development Center of the University of Wisconsin at Madison, and other leading accessibility organizations. The Java Accessibility API defines a common signature, which can be implemented on application components, giving them a known interface to allow assistive technologies to extract the accessibility information from the application. The Java Accessibility API is shipped with JFC and can be found in the javax.accessibility package. JFC runs with the latest JDK 1.1.x. The Java Accessibility API is now integrated into JDK 1.2. [136]6.1 Interface Accessible This section covers what a Java interface is and how you use the interface to give objects an accessible signature. [137]6.1.1 Interfaces For those new to Java, an interface is a defined signature of methods and properties that can be implemented by a particular class. As a developer, if you were to "implement" the interface on your particular class, you would need to provide all the methods and properties as defined by the signature. Failure to meet the interface specification would result in compilation errors. In Java, an assistive technology can examine if an object is an instance of a particular interface using the instanceof operator. The first interface we will describe tells us whether an object has implemented the basic Accessibility API. [138]6.1.2 Using Interface Accessible Accessible is an interface that you need to apply to your class file to let assistive technologies know if you have implemented the Accessibility API. The following Java code example shows you how to implement Accessible on your own custom component. import java.awt; import javax.accessibility; class MyButton implements Accessible extends Component{ AccessibleContext getAccessibleContext() { ... } } Figure 4.0 Implementation of Accessible The Accessible interface provides a method that returns the AccessibleContext. The AccessibleContext provides the most basic accessibility information needed for any component. The object that getAccessibleContext() returns also implements more detailed accessibility information based on the role of the GUI class being used. Some of the methods that AccessibleContext defines, return a null value because they really do not apply. For example, there is no reason to implement the AccessibleText interface on a scroll bar. One way to maintain the AccessibleContext is by keeping an internal class inside your GUI class file, which keeps track of the accessibility information. When asked to provide the AccessibleContext, you simply provide the reference to your internal AccessibleContext. [139]6.2 AccessibleContext AccessibleContext is an abstract class that must be maintained by each GUI object making up your program. It contains much of the accessibility information. Table 3.1 shows the methods AccessibleContext supports and their descriptions. Method Description addPropertyChangeListener(PropertyChangeListener) Adds a PropertyChangeListener to the listener list. firePropertyChange(String property, Object oldValue, Object newValue) Supports reporting bound property changes. getAccessibleAction() Gets the AccessibleAction associated with this object that supports one or more actions. getAccessibleChild(int) Returns the specified Accessible child of the object. getAccessibleChildrenCount() Returns the number of Accessible children of the object. getAccessibleComponent() Gets the AccessibleComponent associated with this object. getAccessibleDescription() Gets the AccessibleDescription property of this object. getAccessibleIndexInParent() Gets the 0-based index of this object in its accessible parent. getAccessibleName() Gets the AccessibleName property of this object. getAccessibleParent() Gets the AccessibleParent of this object. getAccessibleRole() Get the role of this object. getAccessibleSelection() Gets the AccessibleSelection associated with this object. getAccessibleStateSet() Get the state set of this object. getAccessibleText() Gets the AccessibleText associated with this Component. Note: If this text should also include hypertext links, this method should return an AccessibleHypertext object. getAccessibleValue() Gets the AccessibleValue associated with this object. getLocale() Gets the locale of the component. removePropertyChangeListener(PropertyChangeListener listener) Removes a PropertyChangeListener from the listener list. setAccessibleDescription(String description) Sets the accessible description of this object. setAccessibleName(String name) Sets the localized accessible name of this object. setAccessibleParent(Accessible parent) Sets the accessible Parent of this object. Table 3.1 AccessibleContext Abstract Class Methods Assistive technologies can easily use AccessibleContext. For example, by querying AccessibleContext, an assistive technology program can know about and announce changes in a text field. Section 6.2 provides information to help you implement AccessibleContext in your library. The following topics are covered: * [140]6.2.1 Basic Accessible Information + [141]6.2.1.1 AccessibleName + [142]6.2.1.2 AccessibleDescription + [143]6.2.1.3 AccessibleValue + [144]6.2.1.4 Locale + [145]6.2.1.5 AccessibleSelection + [146]6.2.1.6 AccessibleComponent + [147]6.2.1.7 AccessibleText * [148]6.2.2 Parent/Child Information + [149]6.2.2.1 getAccessibleChild(n) + [150]6.2.2.2 getAccessibleChildCount() + [151]6.2.2.3 getAccessibleParent() + [152]6.2.2.4 getAccessibleIndexInParent() * [153]6.2.3 Role and State Information + [154]6.2.3.1 AccessibleRole + [155]6.2.3.2 AccessibleState * [156]6.2.4 Property Change Notification * [157]6.2.5 National Language Information + [158]6.2.5.1 AccessibleBundle + [159]6.2.5.2 AccessibleResourceBundle * [160]6.2.6 AccessibleAction * [161]6.2.7 Miscellaneous Information + [162]6.2.7.1 AccessibleHypertext + [163]6.2.7.2 AccessibleHyperlink [164]6.2.1 Basic Accessible Information This section describes: * AccessibleName * AccessibleDescription * AccessibleValue * Locale * AccessibleSelection * AccessibleComponent * AccessibleText [165]6.2.1.1 AccessibleName AccessibleName is simply the name of the object. Here are some general rules to follow for setting the AccessibleName: * As a general default, when creating your accessible Component, the getAccessibleName method should return the text that appears on the screen for simple classes. Examples of these simple classes are labels, push buttons, check boxes, menu items, simple tab pane entries, and spin buttons. If someone else will reuse this component, you should allow setAccessibleName to override the default. * For complex classes that contain a collection of components (children), such as list boxes, tab panes, combo boxes, menus, and so on, you can return null, unless the application developer explicitly uses the setAccessibleName method. The application developer might have an explicit function for your component and would need to set the name. For example, the developer might configure your combo box to contain the months of the year, in which case, the developer would set the AccessibleName to months. * When you change the AccessibleName, be sure to fire the ACCESSIBLE_NAME_PROPERTY as described in [166]section 6.2.4 Property Change Notification [167]6.2.1.2 AccessibleDescription AccessibleDescription is a text description of an object's purpose. For example, if you had a table in your application containing your current month's categorized cash flow, you should provide a text description using AccessibleDescription. To write a class file that is accessible, follow these rules: * As a default, if your GUI objects include the notion of tooltips and you can access the tooltip text, return the tool tip if the application has not set up an accessible description. Note: Swing components do this for you. * Allow an application developer, using your class file, to replace your default AccessibleDescription using the setAccessibleDescription method. * When you change the AccessibleDescription, be sure to fire the ACCESSIBLE_DESCRIPTION_PROPERTY as described in [168]section 6.2.4 Property Change Notification. * Keep the description short. * Set the description based on locale. If you need to use an existing Accessible class file to build an application, and the default accessible description does not accurately describe the function of the Accessible object, set the accessible description in that class file. [169]6.2.1.3 AccessibleValue Use AccessibleValue only for a specific set of object types, that provide a range of values and a current setting. Otherwise, return null for this value. Scroll bars, sliders, and progress bars, where the current value needs to be acquired, are examples of objects needing an AccessibleValue setting. AccessibleValue supports the methods in Table 5.0. Method Description getCurrentAccessibleValue() Gets the value of this object as a java.lang.Number. getMaximumAccessibleValue() Gets the maximum value of this object as a java.lang.Number. getMinimumAccessibleValue() Gets the minimum value of this object as a java.lang.Number. setCurrentAccessibleValue(Number) Sets the current value of this object as a java.lang.Number. Table 5.0 AccessibleValue Interface Methods Important: Whenever the current accessible value changes, you need to fire the ACCESSIBLE_VALUE_CHANGE property change in the AccessibleContext. In a progress bar, this happens when the progress bar increases its current value. For more information about firing this property change, see [170]section 6.2.4 Property Change Notification. [171]6.2.1.4 Locale This is the current locale for which your component was written. See the JDK for a more detailed description. Low-vision assistive technology uses this information to determine how to speak your application. When you extend either the AWT Component class or JComponent, to make your custom Component, you can return the Locale in AccessibleContext using the getLocale method in java.awt.Component. [172]6.2.1.5 AccessibleSelection AccessibleSelection is a collection of the selected accessible children for your object. AccessibleSelection maintains an internal vector of selected items. The collection is referenced by an index from 0 to the n-1 selection. The n-1 selection is the last selected item and is where the user would have the current input focused. For example, if your object is a list box, this would maintain the collection of currently selected entries as proxied by your list box. AccessibleSelection is an extremely important feature when supporting the Accessibility API. It allows assisitve technology to tell the user what is currently selected. AccessibleSelection would be applied to lists, menus, the list in a combo box, selected minimized windows inside a Desktop Manager window, and so on. AccessibleSelection supports the methods listed in Table 6.0. Method Description addAccessibleSelection(int) Adds the selected item in the object to the object's selection. clearAccessibleSelection() Clears the selection in the object, so that nothing in the object is selected. getAccessibleSelection(int) Returns an Accessible object representing the selected item in the object. getAccessibleSelectionCount() Returns the number of items currently selected. isAccessibleChildSelected(int) Returns true if the current child of this object is selected. Otherwise, returns False. removeAccessibleSelection(int) Removes the selected item in the object from the object's selection. selectAllAccessibleSelection() Causes every selected item in the object to be selected if the object supports multiple selections. Table 6.0 AccessibleSelection Interface Methods Important: When changes occur in the AccessibleSelection, you need to fire the ACCESSIBLE_SELECTION_PROPERTY property change event in the AccessibleContext. For non-AccessibleText components, you also need to fire an [173]ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY property change event when the current ACTIVE child changes. This allows an assistive technology to process multiple selected items while keeping track of the current active selected item. For more information about firing this property change, see [174]section 6.2.4 Property Change Notification. [175]6.2.1.6 AccessibleComponent AccessibleComponent is the accessible JDK component associated with this accessible object. AccessibleComponent defines a standard interface for assistive technologies to directly interact with an object's associated component. It provides a framework for modifying and querying standard component settings as well as asking questions about a component's children. AccessibleComponent applies to objects that have an associated component, like the base components for a given GUI framework. An example is the JFC JComponent class. AccessibleComponent supports the methods listed in Table 7.0. Method Description addFocusListener(FocusListener) Adds the specified focus listener to receive focus events from this component. contains(Point) Checks whether the specified point is within this object's bounds (the point's x and y coordinates are defined to be relative to the coordinate system of the object). getAccessibleAt(Point) Returns the Accessible child, if one exists, contained at the local coordinate Point. getBackground() Gets the background color. getBounds() Get the object's bounds as a Rectangle object. getCursor() Gets the Mouse Cursor. getFont() Gets the Font. getFontMetrics(Font) Gets the FontMetrics. getForeground() Gets the foreground color. getLocation() Gets the object's location relative to the parent as a point specifying the object's top-left corner in the screen's coordinate space. getLocationOnScreen() Returns the object's Point location on the screen. getSize() Returns the object's size as a Dimension object. isEnabled() Determines if the object is enabled. isFocusTraversable() Returns whether this object can accept focus or not. isShowing() Determines if the component is showing. isVisible() Determines if the component is visible. removeFocusListener(FocusListener) Removes the specified focus listener so it no longer receives focus events from this component. requestFocus() Requests focus for this object. setBackground(Color) Sets the background color. setBounds(Rectangle) Sets the object's bounds as a Rectangle object. setCursor(Cursor) Sets the Mouse Cursor. setEnabled(boolean) Sets the enabled state. setFont(Font) Sets the Font. setForeground(Color) Sets the foreground color. setLocation(Point) Sets the object's location relative to the parent. setSize(Dimension) Resizes the object so that it has width and height. setVisible(boolean) Sets the visible state. Table 7.0 AccessibleComponent Interface Methods When you are programming the AccessibleContext, you will find that you can retrieve much of the AccessibleComponent information directly from the actual associated JDK awt.Component and JFC base javax.swing.JComponent class. In the case of JFC, the base JComponent class has an internal abstract class called AccessibleJComponent. AccessibleJComponent has many of the methods needed to support AccessibleComponent because the information can be acquired directly from JComponent. The AccessibleComponent interface is taken from awt.Component, not javax.swing.JComponent. Therefore, the code in AccessibleJComponent could be trivially placed in a non-JFC component, which extends awt.Component to help create a custom, non-JFC accessible component. The code snippets in Figure 8.0 appear in JComponent.java Class JComponent { protected AccessibleContext accessibleContext = null; /** * Get the AccessibleContext associated with this * JComponent * * @return the AccessibleContext of this JComponent */ public AccessibleContext getAccessibleContext() { return accessibleContext; } public abstract class AccessibleJComponent extends AccessibleContext implements Serializable, AccessibleComponent { /** * Get the AccessibleComponent associated with * this object if one exists. Otherwise return * null. **/ public AccessibleComponent getAccessibleComponent() { return this; } /** * Get the Font of this object. * * @return the Font,if supported, for the object; * otherwise, null */ public Font getFont() { return JComponent.this.getFont(); } /** * Set the Font of this object. * * @param f the new Font for the object */ public void setFont(Font f) { JComponent.this.setFont(f); } /** * Set the enabled state of the object. * * @param b if true, enables this object; * otherwise, disables it */ public void setEnabled(boolean b) { boolean old = JComponent.this.isEnabled(); JComponent.this.setEnabled(b); if (b != old) { if (accessibleContext != null) { if (b) { accessibleContext.firePropertyChange( AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.ENABLED); } else { accessibleContext.firePropertyChange( AccessibleContext.ACCESSIBLE_STATE_PROPERTY, AccessibleState.ENABLED, null); } } } } public String getAccessibleDescription() { if (accessibleDescription != null) { return accessibleDescription; } else { try { String ttt = getToolTipText(null); if (ttt != null) { return ttt; } } catch (Exception e) { } } return null; } . . . } } Figure 8.0 Example Code found in JFC's JComponent for Supporting AccessibleComponent Information The sample code in Figure 9.0 demonstrates the structure for building an accessible component when using the JFC JComponent as a base. Because the internal JComponent class, AccessibleJComponent, extends AccessibleContext, you automatically get the AccessibleComponent methods. class MyButton extends JComponent implements Accessible{ String ButtonText; AccessibleContext GetAccessibleContext() { If accessibleContext != null AccessibleContext == new MyAccessibleComponent(); } class MyAccessibleButton extends AccessibleJComponent() { String AccessibleName(); . . . getAccessibleName() { if (AccessibileName == null) return ButtonText; else return AccessibleName; } } } Figure 9.0 Sample Code Demonstrating the Use of JComponent to Support Accessible Component Although we have selected to show JComponent as the foundation for building an accessible component, you can also use the JDK Component class. Many of the methods such as getFont in AccessibleComponent can be acquired from java.awt.Component. Important: When building applications using JFC, it is recommended that you start from JComponent or another existing JFC component to build your new, custom Accessible component. When building non-JFC applications you should start by building off the JDK Component class or a descendant of it. [176]6.2.1.7 AccessibleText AccessibleText is used for providing detailed access to complex and editable text documents and text fields. Examples of this are text edit fields, text areas, WYSIWYG web browser and word processing client areas, and mail program client areas. These areas often involve the use of a caret for entering text when they are in an editable state. AccessibleContext should return null for AccessibleText in the case of scroll bars, check boxes, and so on. AccessibleText interface (Table 10) provides a mechanism for assistive technologies to gain access to documents by defining a character-indexed mechanism for traversing documents in your program. The predecessors of the Accessibility API relied on an Off-Screen model (text-database reconstruction) of the desktop to provide access to program documents. This was unreliable and often the biggest causes for delay in providing access to a new GUI-based windowing system. The AccessibleText approach is truly state-of-the-art in access technology and it is one that facilitates multi-modal access to applications by mainstream users. Method Description getAfterIndex(int part, int index) Returns the String after a given index based on the part defined in 6.2.1.7.3. getAtIndex(int part, int index) Returns the String at a given index based on the part defined in 6.2.1.7.3. getBeforeIndex(int part, int index) Returns the String before a given index based on the part defined in 6.2.1.7.3. getCaretPosition() Returns the zero-based offset of the caret. getCharacterAttribute(int index) Returns the AttributeSet for a given character (at a given index). getCharacterBounds(int index) Determines the bounding box of the character at the given index into the string. getCharCount() Returns the number of characters (valid indicies). getIndexAtPoint(Point) Given a point in local coordinates, returns the zero-based index of the character under that Point. getSelectedText() Returns the portion of the text that is selected. getSelectionEnd() Returns the end offset within the selected text. getSelectionStart() Returns the start offset within the selected text. Table 10.0 AccessibleText Interface Methods [177]6.2.1.7.1 Text Attributes To implement AccessibleText you will need to examine how you have built your document model. Most document models are designed based on how they handle paragraphs, runs of text with common properties, an embedded graphic, and so on. The HTML web page is the epitome of a complex document as it also allows the document to be interactive. In fact, a web browser may have to handle an embedded Java applet. The idea here is to convert your document to a text representation. To do this, you need to know more about the attribute set associated with each character and how the attribute set is used to embed complex components and icons. When an assistive technology wishes to get the set of attributes for a given index, it will call the AccessibleText method getCharacterAttribute(int index) for the given character index. This returns an object of class AttributeSet that maintains a database of key/value pairs as defined in Table 3.0 for the StyleConstants class. To get the background color for a character index in your document it would issue the following set of calls: import javax.swing.text.StyleConstants; import javax.swing.text.AttributeSet; import javax.swing.accessibility.*; Color getColor(Accessible yourComponent, int index) { Color bg = null; AccessibleContext ac = yourComponent.getAccessibleContext(); AccessibleText at = ac.getAccessibleText(); // Get the Attribute Set AttributeSet aset = at.getCharacterAttribute(index); // Get the background color bg = (Color) aSet.getAttribute(StyleConstants.Background); while (bg == null) { //No background color here: Check the Parent //Attribute Set aSet = (AttributeSet) aSet.getAttribute(StyleConstants.ResolveAttribut e); if (aSet != null) { bg = (Color) aSet.getAttribute(StyleConstants.Background); if (bg != null) break; } else break; } /* When no background color exists in the */ /* AttributeSet Tree, get the the color */ /* from the accessible component */ if (bg == null) { AccessibleComponent acx = ac.getAccessibleComponent(); bg = acx.getBackground(); } return bg; // return the background color } Figure 11.0 Retrieving the Background Color from AccessibleText Examining Figure 11.0 we can see how an assistive technology program will search the attribute set tree looking for the background color attribute. When it finds the information, it will stop the search. Otherwise, it will get the information from the AccessibleComponent. When storing runs of attributes in your attribute set, use AttributeSet. To make life easy, the Sun folks have provided you with a class called SimpleAttributeSet in the JFC. This supports the descendant AttributeSet interface for adding attributes to it called MutableAttributeSet. Like AttributeSet, MutableAttributeSet is a JFC interface. If you wanted to create an HTML document, where the default colors were black on white. You would create your default attribute set as follows: SimpleAttributeSet DefaultAttributeSet; DefaultAttibuteSet.add(StyleConstants.Foreground, Color.black); DefaultAttibuteSet.add(StyleConstants.Background, Color.white); //Give the run a name LinkAttribute.Set.add(StyleConstants.NameAttribute,""); If your browser which controlled the document drawing detected a hypertext link in the input stream, where the hypertext foreground color was to be blue and the text underlined, you would create an AttributeSet run and add it as follows: // Create an Attribute Set run with blue, underlined // Foreground text SimpleAttributeSet LinkAttributeSet = New SimpleAttributeSet(); LinkAttributeSet.add(StyleConstants.Foreground, Color.blue) LinkAttributeSet.add(StyleConstants.Underline, new Boolean(true)); //Give the run a name LinkAttribute.Set.add(StyleConstants.NameAttribute,""); // Set the Resolving Parent, so the assistive technology can determine the back ground color LinkAttributeSet.setResolveParent(DefaultAttributeSet); Now, you simply have to store this AttributeSet with the specified run of text in your document, based on your document data model. When assistive technology goes to index the text in your document to grab the AttributeSet, you will be ready with the information. Furthermore, you will have the attribute information available to draw the run yourself. [178]6.2.1.7.2 Embedding Objects Your document may contain an "embedded" complex document or non-text object that identifies a special component to be handled by your application. For this, simply provide a blank character for the object's index position, reference the Component which draws it in the AttributeSet, just like attributes for font, foreground color, and so on. The Component referenced in the attributes needs to implement the Accessibility API. An example could be the inclusion of a JTable. Another example may be a JLabel containing a bit map. This design allows assistive technologies to scan or browse your document. If the user wishes to focus on the embedded object he can focus and expand his view of the document to that component or ignore it entirely. // Create an Attribute Set run with blue, underlined // Foreground text SimpleAttributeSet TableAttributeSet = New SimpleAttributeSet(); TableAttributeSet.add(StyleConstants.ComponentAttribute, new JTable()); //Give the list of components a name TableAttributeSet.add(StyleConstants.ComponentElementName, "Table of Contents") ; //Give the run a name TableAttribute.Set.add(StyleConstants.NameAttribute,""); //Set the Resolving Parent, so assistive technologies can determine the backgro und color LinkAttributeSet.setResolveParent(DefaultAttributeSet); To embed icons, simply follow the same procedure for using a blank character to represent the indexed character for the icon. In the attribute, create a run, which sets the run AttributeSet information as follows: Attribute Value StyleConstants.NameAttribute "" StyleConstants.IconElementName URL String for the Icon StyleConstants.IconAttribute (Icon)new ImageIcon(URL, Description); Table 12: Sample Attributes for Embedding Icons in Attribute Sets Now that you know how to embed objects, the question is when to embed objects. To answer this question, put yourself in a blind user's shoes. This user wants to be able to read your document in a browsing fashion. When he runs across a new paragraph he may want to know that it is a new paragraph, but he does not want to deal with it like an embedded document. Consider embedded documents as document parts you may want to skip over in when casually browsing. Examples of true embedded documents are tables, a Java applet used to show a MPEG video and so on. If the user wants to expand his view on this embedded object, he can ask his Java screen reading application to expand the view on that Component. The Component could be a text area in an HTML Form. In this case, the user could detect from the run that a text area exists and can choose to expand his view on the text area. The embedded object should have implemented Accessible and its AccessibleContext should support AccessibleText. [179]6.2.1.7.3 Referencing the Indexed Character String As shown in [180]section 6.2.1.7 AccessibleText, access to text, through the AccessibleText interface is based on a character index and the part of text you want to retrieve around that index. At a given character index, the caller requests the corresponding word, character, or sentence based on the method and part definitions of AccessibleText.CHARACTER, AccessibleText.WORD, or AccessibleText.SENTENCE, respectively. [181]6.2.1.7.4 Caret Position and SelectedText The AccesibleText interface refers to offsets for these values (the character index for these items in your AccessibleText document). The definition of the Caret is obvious, but to avoid confusion, SelectedText is the text the user has highlighted often for cutting, pasting, and deleting. Important: If you are developing a new accessible text class (non-JFC), please remember to keyboard-enable selecting text. This accomplished by the user holding the shift key down at the caret position and moving the arrow keys, pressing the PAGE-UP, END, HOME, or PAGE-DOWN in succession. A good way to verify your keyboard accessibility is to unplug your mouse and try to navigate the text object yourself. [182]6.2.1.7.5 Property Changes The three property changes you must fire for AccessibleText are: * ACCESSIBLE_TEXT_PROPERTY (text data changes) * ACCESSIBLE_SELECTION_PROPERTY (highlighting text) * ACCESSIBLE_CARET_PROPERTY (caret moves) Your AccessibleText implementation should fire these changes from the firePropertyChange method in your implementation of AccessibleContext. Important: Do not fire ACCESSIBLE_VISIBLE_DATA_PROPERTY for AccessibleText Components. Use the ACCESSIBLE_TEXT_PROPERTY instead. Firing both will result in sending unneeded property change events to assistive technologies. For a detailed description of firing these property changes see [183]section 6.2.4 Property Change Notification. [184]6.2.2 Parent/Child Information The way assistive technologies gather and organize information about your program is by assembling the list of components making up your application from the parent/child hierarchy. A simplistic example of this is when an assistive technology program listens for a focus change. When this occurs, the assistive technology program would go up the parent tree, from the focused component, until it reaches the window frame. It then recursively enumerates all the visible and showing children making up the active program. The assistive technology program now has a list of all the components making up your application and it can organize them based on its representation of the screen. At this point, the assistive technology communicates with them individually through the Accessibility API. This is why it is important that you provide parent/child information for each of your objects. Note: Many GUI components act as a proxy for their children. In this case, their children are specialized objects responsible for their rendering and all focus management and input is managed by the proxying parent component. As a result, these children cannot be enumerated using the standard JDK methods for enumerating children. To facilitate assistive technology access to your program it is important that you support the methods, listed in this section, for all GUI objects and that all GUI objects implement the Accessibility API. An example where a parent proxies for its children is the way a JFC JList component treats its list entries. Each entry is treated as an accessible child who is told to draw by the JList component. This section describes the following methods: * AccessibleChild * AccessibleChildCount * AccessibleParent * AccessibleIndexInParent Important: Whenever an Accessible object adds or removes an AccessibleChild, it must fire an ACCESSIBLE_CHILD_PROPERTY change to notify an assistive technology when its Accessible children change. Furthermore, this information should be reflected in the AccessibleChildCount. [185]6.2.2.1 getAccessibleChild(n) This function returns the nth immediate child that implements the Accessibility API. [186]6.2.2.2 getAccessibleChildCount() getAccessibleChildCount returns the number of immediate children that implement the Accessibility API. If you had a list box with ten entries, you would have 10 accessible children. [187]6.2.2.3 getAccessibleParent() AccessibleParent returns the parent object that implements the Accessibility API. If there is no Accessible parent this method should return null. [188]6.2.2.4 getAccessibleIndexInParent() When implementing AccessibleContext, this method returns the index of the AccessibleContext in its parent's Accessible child list. An example is a list box. If your list box had 10 entries, the number of accessible children would be 10. The nth child of the list box would be the nth entry in the list box. When assistive technology queries the nth entry in the list box, the result should support the Accessibility API. When assistive technology asks for the AccessibleParent of the entry from its AccessibleContext, it should return the list box object. [189]6.2.3 Role and State Information Role and state information describes the unique features of an object. By defining an object's role you describe the object's generic function in the system independent of its class name. The object's role enables assistive technology to decide how to present the object and to tell the user what it is. The state naturally describes the current state of the object. For example, if the object is a check box it may be in the "checked" state or if it is a text area it is important to know if it is in the "editable" state. This section describes the following: * AccessibleRole * AccessibleState * AccessibleStateSet [190]6.2.3.1 AccessibleRole AccessibleRole is the basic role of an application component. The role describes the generic function of the component; such as "push button," "table," or "list." In older windowing systems like Windows 3.XÒ or Presentation Manager, assistive technology programs used to use the class name to provide the role information about a GUI object. This was often unusable because applications would subclass standard windowing components and give them obscure class names. By providing standard role information you can provide the user with familiar information about the object's function within your program. For example, if you sub-classed an AWT button class with a class called foobarpbutton, the role would still be AccessibleRole.PUSH_BUTTON. This class provides a set of strongly typed constants enumerating common object roles. AccessibleRole is a descendant of AccessibleBundle See [191]section 6.2.5.1 AccessibleBundle. Therefore, it inherits the toDisplayString(Locale) method allowing you to obtain the localized string based on a locale-independent key from a predefined AccessibleBundle containing the keys defined in this class. A public constructor for this class has been purposely omitted and applications should use one of the constants from this class. If the constants in this class are not sufficient to describe the role of an object, a subclass should be generated from this class and it should provide constants in a similar manner. The generic enumerated roles are largely based on classes provided in JFC's rich GUI component class library. Table 13 contains a pre-defined set of AccessibleRoles and their brief descriptions: AccessibleRole Description ALERT An object used to alert the user, such as a warning message. AWT_COMPONENT An AWT component, but nothing else is known about it. CHECK_BOX A check box. In the generic sense, this is a choice that can be checked or unchecked and provides a separate indication of the current state. COLUMN_HEADER The header for a column of data. COMBO_BOX A combination of a text field and drop-down list. DESKTOP_ICON An iconified internal frame in a DESKTOP_PANE. DESKTOP_PANE This is normally used as the parent of internal frames to provide a pluggable desktop manager object to the internal frames or iconified internal frames. DIALOG A dialog box. DIRECTORY_PANE A generic container providing directory information. FILE_CHOOSER A dialog box used to choose a file. FILLER An object that fills up space in a user interface. FRAME A window frame. GLASS_PANE A transparent window container which does not contain a frame. INTERNAL_FRAME A frame-like object that is clipped by a desktop pane or parent pane window. A familiar example would be the program group windows in the Windows 3.1tm Program Manager or an individual document frame in a multi-document application such as a word processor. LABEL A display object used to show a short text string, an image, or both. A label does not react to input events. LAYERED_PANE A specialized pane that allows its children to be drawn in layers, providing a form of stacking order. For example, you may have a stack of child Container windows where the layered pane would determine which layer in the stack would be drawn in the appropriate Z-order. LIST An object containing a list of selectable items. This usually describes a list box. MENU An object, that when selected, displays a vertical pop-up list of menu items. MENU_BAR The top-level container of menu and menu items. MENU_ITEM A Menu or Menu Bar entry. OPTION_PANE A specialized pane whose primary use is inside a dialog. PAGE_TAB A Tab in a Page Tab List. PAGE_TAB_LIST A set of selectable notebook tabs. Each tab contains a graphic and/or text name. PANEL A rectangular area in an application which controls the layout of its children. PASSWORD_TEXT A text object used for passwords, or other places where the text contents are not shown widely to the user. POPUP_MENU A modal list of menus, which can be popped to the highest Z-order of visibility. PROGRESS_BAR An object which graphically depicts the progress of a desired operation in the form of a bar scale. For example, it would be used to the progress of an install program. PUSH_BUTTON A simple push button. RADIO_BUTTON An implementation of a radio button -- an item that can be selected or deselected, and which displays its state to the user. ROOT_PANE This is a top-level container pane for an application whose definition is derived from the JFC root pane. ROW_HEADER An object that defines a row label (like in a table or spreadsheet). SCROLL_BAR A horizontal or vertical scroll bar used to scroll an area on the screen. SCROLL_PANE A pane that allows horizontal or vertical scrolling of its contents through the use of optional horizontal and vertical scroll bars. SEPARATOR An implementation of a Menu Separator. SLIDER A control that lets the user select a value from a bounded interval. SPLIT_PANE A glass pane divided into two equal areas with a separator. SWING_COMPONENT A JFC component having no user-definable role. TABLE A table of data consisting of row and column information. TEXT A document or edit field containing only text. TOGGLE_BUTTON A generic button which can be either locked on or off. TOOL_BAR A bar of selectable button objects, each providing a unique function. TOOL_TIP Text description. TREE An object displaying a visible tree representation such as a file directory. UNKNOWN An object having either no user-definable or provided AccessibleRole. VIEWPORT An object which maintains the state of a screen transfer area from an off screen bitmap like the Xtm Windows System backing store. WINDOW An object that is responsible for receiving user input from the native windowing system. This is usually a JDK window. Table 13: Pre-Defined AccessibleRoles Although it is possible to subclass AccessibleRole and extend it to add new objects, it is preferable that you use one of the predefined roles when supporting the AccessibleContext method getAccessibleRole and augment the role though the accessible description. If you need additional roles, you should submit your request to access@sun.com to augment the standard AccessibleRole list. For example, your program may use a thermometer object to display the temperature. An option would be to use the PROGRESS_BAR accessible role and set the AccessibleDescription to "Thermometer." [192]6.2.3.2 AccessibleState Use AccessibleState to describe a particular state of a component. The actual state of the component is defined as an AccessibleStateSet, which is a collection of an object's AccessibleStates. The constants in this class present a strongly typed enumeration of common object states. AccessibleState is a descendant of AccessibleBundle. See [193]section 6.2.5.1 AccessibleBundle. Therefore, it inherits the toDisplayString(Locale) method. This allows you to obtain the localized string, based on a locale-independent key, from a predefined AccessibleBundle containing the keys defined in this class. A public constructor for this class has been purposely omitted, and applications should use one of the constants from this class. If the constants in this class are not sufficient, create a subclass from this class, and provide constants in a similar manner. The generic enumerated states that this class provides are largely based on classes provided in JFC's rich GUI component class library. AccessibleState Description ACTIVE Indicates whether an application is active. Example: Top-level frames use ACTIVE to indicate that it or one of its children has focus. The ACTIVE state is also set for Accessible descendents found in objects, such as a list when a child is the current Active descendent. See [194]ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY. ARMED Indicates that the user input is currently directed to that object and it is "armed for selection." Example: a highlighted menu item or a pressed push button. BUSY Indicates if the object is currently busy and it is not responding to user input. Example: an application displays the hourglass. CHECKED Indicates whether an object is in the checked state. Example: radio buttons and check boxes. COLLAPSED Indicates this object is collapsed, such as when a tree branch is collapsed. EDITABLE Indicates whether a text or document area is in an editable state. ENABLED Indicates if an object is enabled. An object that normally responds to user input and can be set to not respond to user input (disabled state) would support this state. Example: a menu item - this state would be removed if it was grayed out. EXPANDABLE Indicates this object allows progressive disclosure of its children. EXPANDED Indicates this object is expanded. FOCUSABLE Indicates whether the object is capable of receiving input focus. FOCUSED Indicates whether the current object has input focus. HORIZONTAL Indicates whether the object is in a horizontal state. Examples: scroll bars, sliders, progress bars, and scroll panes. ICONIFIED Indicates whether the frame object is in an iconified or minimized state. MODAL A window's state such that when an application window is "modal," the user cannot switch to another window within the application until after the window is destroyed or set to non-modal. Example: dialog boxes. MULTI_LINE Indicates this (text) object can contain multiple lines of text, such as a multi-line edit field. MULTISELECTABLE Indicates whether the given container is in a state supporting selection of more than one of its Accessible Children. Example: a list box. OPAQUE Indicates whether a component paints every pixel within its rectangular region. A non-opaque component paints only some of its pixels, allowing the pixels underneath it to "show through." A component that does not fully paint its pixels therefore provides a degree of transparency. PRESSED Indicates whether the object is currently depressed. Example: a push button. RESIZABLE Indicates whether the object is resizable. Example: a frame uses this. SELECTABLE Indicates if the object is selectable. Example: a toggle button. SELECTED Indicates if the object is currently selected. Example: a selected check box menu item. SHOWING Equivalent to the isShowing state in the JDK component - indicates if the object is showing on the screen. Example: a pop-up menu. When it has not been popped up it is visible but not showing. SINGLE_LINE Indicates this (text) object can contain only a single line of text, such as single-line edit field. TRANSIENT Indicates that this object is transient. This also notifies an assistive technology to not add listeners to the object because it will never generate events. Examples of transient objects are those found in collective Swing components, such as lists, tables, and trees. In these cases, Accessible children are created by a single cell-renderer that creates transient accessible children for an assistive technology based on the child index. When you create an Accessible object in response to a requested proxied "Accessible" child, and this child is only created to fulfill the request, you should include AccessibleState.TRANSIENT in the child's AccessibleStateSet. This tells the assistive technology to monitor its proxying parent for changes to its children, rather than the transient child. In the case of JFC, this is often done for cell renderer objects. VERTICAL Indicates whether the object is in a vertical state. Examples: scroll bars, sliders, progress bars, and scroll panes. VISIBLE Equivalent to the isVisible state in the JDK component - indicates if the object will be visible when "shown" on the screen. An object needs to be visible and showing to be displayed. Table 14: Pre-Defined AccessibleStates Note: Whenever a change in AccessibleState occurs in an object, you need to fire an appropriate property change in AccessibleContext. AccessibleStateSet: AccessibleStateSet maintains a collection of the AccessibleState settings for a given Accessible object. It has methods for you to add or remove AccessibleStates to its collection. An assistive technology would query the current AccessibleStateSet to determine the state of an object. It is important that you maintain the set of state information for each Accessible object. Examples of state information are "checked" for a check box, or "vertical" for a scroll bar. See the previous section for a more detailed description of the AccessibleState. The AccessibleStateSet class supports the methods listed in Table 15. Method Description add(AccessibleState) Adds a new state to the current state set if it is not already present. addAll(AccessibleState[]) Adds an array of Accessible states to the existing state set. clear() Removes all the states from the current state set. contains(AccessibleState) Determines if the AccessibleState passed is in the state set. remove(AccessibleState) Removes a state from the current state set. toArray() Returns the current state set as an array of AccessibleState. toString() Returns a localized String representing the current state set using the default locale. Table 15: AccessibleStateSet Methods To modify the state set, check to see if the AccessibleStateSet contains the AccessibleState. Then, add or remove the AccessibleState, as needed. Important: Whenever you add or remove states to the AccessibleStateSet, you must fire an ACCESSIBLE_STATE_PROPERTY change event in AccessibleContext, as described in [195]section 6.2.4. Property Change Notification. [196]6.2.4 Property Change Notification The Java Bean APIs (Java's software component model) support a common object-oriented feature called properties. Properties are specific attributes of an object. The Java bean API has added the ability for an object to notify registered listeners when one of its properties change. The Accessibility API has incorporated this feature to enable assistive technology to be notified when specific property data changes. This enables assistive technology programs to passively monitor your application. Property change notification is handled through your implementation of AccessibleContext. Assistive technology programs will register listeners with the AccessibleContext object you have written to monitor accessibility specific information. These familiar Java bean methods are used to manage property changes in the AccessibleContext: firePropertyChange(String propertyName, Object oldValue, Object newValue): Fires the specified property change (propertyName) with the old and new values to registered listeners. addPropertyChangeListener(PropertyChangeListener listener): Adds an object supporting the PropertyChangeListener interface described in the Java bean package. removePropertyChangeListener(PropertyChangeListener listener): Removes an object supporting the PropertyChangeListener interface described in the Java bean package. The following is a list of Accessibility properties you must support: ACCESSIBLE_DESCRIPTION_PROPERTY: When a change in the accessible description occurs, you must fire this property change event to registered listeners. To fire the this property change event, the following mechanism is required, where oldDescription and newDescription are of class String: firePropertyChange( AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY, oldDescription, newDescription); ACCESSIBLE_NAME_PROPERTY: When a change in the accessible name occurs, you must fire this property change event to registered listeners, where oldName an newName are of class String. firePropertyChange( AccessibleContext.ACCESSIBLE_NAME_PROPERTY, oldName, newName); ACCESSIBLE_SELECTION_PROPERTY: When a change occurs to your AccessibleSelection collection object, you need to fire this property change event to registered listeners. Selection change event data, when implemented, usually involves complex collection objects and, as such, it is both inefficient and unnecessary for you to figure old and new values when firing the property change. To fire a selection property change, the following mechanism is required where selectedText is a string: firePropertyChange( AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, null, selectedText); If the selection change involves a collection of selected items, use the following mechanism: firePropertyChange( AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, new Boolean(false), new Boolean(true)); Where a collection is involved, the assistive technology acquires the selection information from the AccessibleSelection information of the component that is generating the property change event. ACCESSIBLE_STATE_PROPERTY: When a change occurs to your AccessibleStateSet collection object, you need to fire this property change event to registered listeners. AccessibleState changes are basically State flag toggles. When firing this property value of the old or new value will be null if the respective value is off or the AccessibleState constant if the value is on. For example, if an entry field was switched to the Editable state, the property firing in the AccessibleContext should be implemented as follows: firePropertyChange( AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.EDITABLE); ACCESSIBLE_TEXT_PROPERTY: When a change occurs to the data in your AccessibleText object, you need to fire this property change event to registered listeners. Whenever the object making up your document change (text is replaced, added, or deleted, objects are embedded, etc.) you would fire this property change. You would not do so for attributes of the data. For example, changing the font would not result in a property change event. firePropertyChange( AccessibleContext.ACCESSIBLE_TEXT_PROPERTY, new Boolean(false), new Boolean(true)); ACCESSIBLE_VALUE_PROPERTY: When a change occurs to the current value in your AccessibleValue object, you need to fire this property change event to registered listeners. AccessibleValues are set for objects that support a value and value range setting components such as scroll bars, sliders, and progress bars. firePropertyChange( AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, new Integer(oldValue), new Integer(newValue)); ACCESSIBLE_VISIBLE_DATA_PROPERTY: When a change occurs to the data in the visible portion of your object, you need to fire this property change event to registered listeners. This applies to the text changing in your checkbox, a change in your list box's data, and so on. This is an extremely important property, because many assistive technologies store the visible data information in their own data structures, to give their own "look and feel" of your program. For example, the Access Engine technology in IBM's SVK sorts its information in row/column format. firePropertyChange( AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, new Boolean(false), new Boolean(true)); This property change applies to all components except those that implement AccessibleText. ACCESSIBLE_CARET_PROPERTY: When a caret change occurs in Accessible objects supporting AccessibleText, this property should be fired when the caret changes position. The position old and new values passed should be an Integer object containing the old and new values for the character index for the caret. firePropertyChange( AccessibleContext.ACCESSIBLE_CARET_PROPERTY, new Integer(oldposition), new Integer(newposition)); ACCESSIBLE_CHILD_PROPERTY: When a child is added or removed from an Accessible object, this Accessible object should fire property change. If an Accessible object is being added, the old value is null and the new value is the Accessible child. If an Accessible child is being removed, the old value is the Accessible child and the new value is null. Adding: firePropertyChange( AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, (Accessible) childadded); Removing: firePropertyChange( AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, (Accessible) childremoved, null); ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY: A constant used to determine when the active descendant of a component has changed. The active descendant is used for objects such as list, tree, tab pane, and table, which might have transient children. When the active descendant has changed, the old value of the property change event is the Accessible representing the previous active child. The new value is the Accessible representing the current active child. firePropertyChange( AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, (Accessible) previous active child, (Accessible) current active child); Important: In objects like lists, trees, and so on, it is often possible to select multiple items. In these cases, the items are often represented as highlighted text. It is either the currently Active child or the last one that had the user's focus that is considered the active descendant. The AccessibleState of this descendant should have its AccessibleStateSet include AccessibleState.ACTIVE. This is represented, graphically, on many systems as the moving dotted box around the list element you are currently operating on. [197]6.2.5 National Language Information This section describes the following two class files, which come with the Accessibility API to allow it to support localized Role and State information: * AccessibleBundle * AccessibleResourceBundle Normally, you should not need to extend or modify these files. You should use the standard Accessible Role and State definitions defined in the Accessibility API. If however, you need to have additional Roles or States, consider the following: * An assistive technology will likely have not seen them before and therefore they will not be readily accessible. * You will need to create new files, which are descendants of AccessibleRole, AccessibleState, AccessibleBundle, and AccessibleResourceBundle to accommodate your new roles and states. * If you do the latter, Sun does not guarantee the data in the AccessibleResourceBundle class. This contains all the key/localized string information for each AccessibleRole and AccessibleState. This could break the accessibility of your application in later releases of the Accessibility API. We strongly recommend: * Do not create your own AccessibleRole and AccessibleState information for your application. Use those provided for by Sun. * If you have a need to add additional Role and State information, make a request to the Sun Accessibility group for incorporation in a later release of the Sun Java Accessibility API. [198]6.2.5.1 AccessibleBundle As stated earlier, AccessibleRole and AccessibleState are descendants of AccessibleBundle. AccessibleBundle supports the methods listed in Table 16. Method Description toDisplayString() Returns the localized String describing the key using the default locale. toDisplayString(Locale) Obtains the key as a localized string. See the JDK for a detailed description of Locale. toDisplayString(String ResourceBundleName, Locale) Obtains the key as a localized string, based on the fully-qualified resource bundle file name and the Locale. toString() Gets the localized string describing the key using the default locale. Table 16: AccessibleBundle Methods The source for this class is in the javax.accessibility package source included in the JFC. [199]6.2.5.2 AccessibleResourceBundle This contains all the key/localized string information for each AccessibleRole and AccessibleState. The source for this class is in the javax.accessibility package source included in the JFC. [200]6.2.6 AccessibleAction It is often difficult for people with disabilities to navigate an application. For example, it is difficult to impossible for blind computer users to use a mouse. It is also difficult for a sighted user to determine the hot spots on an image map found on a web page. Voice navigation systems, initially used by mobility impaired users, need to convert voice commands to actions. The right way to implement voice control of a GUI is not by simulating keyboard and mouse actions because there is no description of the actions available, and the simulation can be difficult. For these reasons, the AccessibleAction object was created. AccessibleAction contains a collection of description/action entries to allow assistive technologies to select and perform a given object's action(s). Note: For objects that have no action, like a label or title bar, AccessibleContext would return null for the AccessibleAction. The AccessibleAction interface you would implement is described in Table 17. Method Description doAccessibleAction(int) Performs the specified action on the object. getAccessibleActionCount() Returns the number of accessible actions available in this object. If there is more than one, the first one is the "default" action. getAccessibleActionDescription(int) Returns a description of the specified action of the object. Table 17: AccessibleAction Methods An example of AccessibleAction for a tree element might be: * getAccesibleActionCount returns 1. * getAccessibleAccessibleDescription[0] = "ToggleExpand". * doAccessibleAction(0): expand or collapse the tree element based on the state of the element. Important: If you have a component or component element that can be activated by the mouse or keyboard, you must provide an AccessibleAction for it, otherwise it is not accessible. [201]6.2.7 Miscellaneous Information The following are specialized interfaces that do not fit into one if the categories above. This section describes: * AccessibleHypertext * AccessibleHyperlink [202]6.2.7.1 AccessibleHypertext Many applications implement hypertext-type interfaces to create richly linked documents. Some of the most fundamental applications for text are help systems. In a help system, a specific piece of text or an image is visibly augmented to indicate that if you select that area, you will access more information about that topic. This concept is expanded to the Web, where images and text in web pages link you to documents on either your machine or another machine. AccessibleHypertext is a Java interface extension to AccessibleText that enables you to provide a document interface that facilitates access to hyperlinks. If you have an application component that contains Hypertext, you must implement AccessibleHypertext on that component. Because AccessibleHypertext extends AccessibleText, only the added methods for AccessibleHypertext are described in Table 18. Method Description getLink(int) Returns the nth AccessibleHyperlink of this hypertext document. getLinkCount() Returns the number of links within this document. getLinkIndex(int) Returns the index into an internally stored array of AccessibleHyperlink objects based on the AccessibleText document character index. If no link exists at this character index, the result returned is -1. Table 18: AccessibleHypertext Methods By providing the AccessibilityHypertext interface, you are enabling a disabled user to: * Quickly access the hypertext links for an entire document. * Determine whether a given document index contains a hypertext link. * Select and activate any of the set of links at the specific document index. * Enable assistive technologies, such as technologies for mobility impairments and the blind, to access a hypertext document without using a mouse. One example is hands free navigation without a mouse, for example, through a voice recognition interface. The accessible hyperlink that this interface returns is described in [203]section 6.2.7.2 AccessibleHyperlink. [204]6.2.7.2 AccessibleHyperlink An AccessibleHyperlink defines a link or collection of links. It is an abstract Java class that extends AccessibleAction. Because it extends AccessibleAction, it provides a mechanism for describing each link element and how to activate the element. Like AccessibleAction, each link is referenced through a zero-based index (0 through n-1). This is particularly important for image maps found on web pages. On a web page, an image map might contain clickable hot areas that act as hyperlinks to other documents. AccessibleHyperlink is described in Table 19. Method Description isValid() This indicates whether the link is still valid with respect to the AccessibleHypertext it references. This method returns true if the link is valid and false if it is not. A link is invalid (return false) if the underlying text changed, such as when a link is followed. getAccessibleActionCount() Returns the number of accessible actions available in this link. For HTML image maps, this equals the number of links for a given image map. If there is more than one, the first is not considered the "default" action. Typically, links have one Accessible action. doAccessibleAction(int) Performs the action specifed by index passed for this link. getAccessibleActionDescription(int) Returns a String description for the indexed action. The description should be set to the anchoring text. In the case of an HTML link like IBM Special Needs Home Page, the value returned should be "IBM Special Needs Home Page". If this were an image, for example, a
   picture of Rich, the result returned would be the ALT text "a picture of Rich". getAccessibleActionObject(int) Gets an object that represents the link action for the given link. Using the example from the previous method for a text link, you would want to return new java.net.URL (http://www.ibm.com/sns). getAccessibleActionAchor() Returns an object that represents the link anchor, as appropriate for that link. For example, from the image map example in getAccessibleDescription, this would return ImageIcon(phillricho.gif, "Phill and Rich's Picture"). getStartIndex() Gets the character index within the hypertext document at which this link begins. getStopIndex() Gets the character index within the hypertext document at which this link ends. Table 19: AccessibleHyperlink Methods [205]6.3 Hints, Tips, and Words of Wisdom When determining how to implement code, it is always good to see how someone else accomplished the task. The JFC comes complete with source. Because the JFC has implemented the Accessibility API, in most cases, this is an excellent place to start. Furthermore, the JFC also includes the Accessibility API source. See [206]section 6.2.5.1 AccessibleBundle for some excellent examples. JFC Component Type of Example JList Example of a Proxying component for a list of Accessible Children. JTextComponent, JEditorPane Examples of AccessibleText and AccessibleText implementation for presenting HTML text. JLabel Simple implemenation of the Accessibility API. JProgressBar Implementation of AccessibleValue. JComponent AccessibleJComponent internal class implementation of the AccessibleContext abstract class. AbstractButton Implementation of AccessibleAction for activating a JFC button. Table 20: Example Accessibility API Implementations The next two sections are problem areas you are likely to run into when trying to make application components accessible: * Managing Children - Proxied Objects * Peered Objects [207][208][209][210][211]6.3.1 Managing Children Proxied objects are lightweight objects whose placement, drawing directives, and response to input are guided by a parent object. An example is the JFC implementation of cell renderers for list box. In a JFC list box, each list entry is created through the use of a single ListCellRenderer. The JList component tells it where to draw, when to "appear" selected, and so on. The JList component does not care what the cell renderer draws in it as long as it does what it is told. The cell render does not receive focus from the windowing system, even though JList may ask it to appear focused. If you are familiar with X Window System programming, you should recognize these lightweight objects as similar to "gadgets." The JFC JTabbedPane component presents a different parent/child relationship that might best be described as a limited proxy. In the case of notebook page tabs, you know you will be dealing with a limited number of children. Here, the tabs are not actually components, but merely visual page tab elements with a reference to the component to be shown, based on the page tab selected. Because the list of elements is small, and generally persistent, it is easier to maintain a vector of accessible objects representing each page tab. When assistive technology requests an accessible child, JTabbedPane merely goes to the internal vector of accessible page tab objects and returns the corresponding object. Parents, who do not proxy for their children, need only worry about keyboard navigation to the children and providing the list of children. Here are some basic rules to follow when managing children: * Make sure the children implement Accessible. * If the children are selectable, a proxying parent should: + Implement AccessibleSelection. This is not the case when the parent does not proxy for the child. + The children must indicate the state AccessibleState.SELECTED in their AccessibleStateSet when selected. * Proxying parents managing states for their children should fire Accessible Property change events for their children. This is very important for proxying components that manage large lists of children. Assistive technology developers would like to avoid adding PropertyChangeListeners to each list entry. * When managing focus for a child, make sure the children are accessible via the keyboard. * Make sure the parent reports the children (0 through n-1) in the logical order they appear and are navigable via the keyboard. * Make sure all property change events are fired. If you have a child whose text changes, make sure to fire an ACCESSIBLE_DATA_VISIBLE_PROPERTY property change unless the child implements AccessibleText. AccessibleText should fire the ACCESSIBLE_TEXT_PROPERTY. [212]6.3.2 Peered Objects Peered objects translate to GUI objects in the underlying operating system. For example, most AWT components fall into this category; an AWT button translates to a button on the underlying Windows operating system. It will be very difficult, perhaps impossible, without help from both the Java side and the underlying operating system to make peered objects accessible on the Java side. In most instances, the data does not reside on the Java side of the wall. In the case of Windowstm or OS/2tm, it means that you need to provide numerous methods to get the data back to the Java side of the wall from the native DLL. This may be simple for small items like labels and buttons, but for more complex items like file dialogs and WYSIWIG documents, it is a difficult task. The most expedient solution is to use JFC and not peered objects. [213]6.3.3 Menus Menus are usually the most specialized part of a GUI application due to performance issues and constant access by the user. They are often the most distinguishing features of a GUI environment. This means they are usually treated as a special case item by assistive technologies. If you decide to use a new menuing system, you probably will no longer work with assistive technology. Important: Use JFC's menu components. Assistive technologies are familiar with them. [214]6.3.4 Text Components Using JFC's JTextComponent is ideal, but implementing AccessibleText on components like these is a minimum. This is especially important for editable text areas. [215]6.3.5 Keyboard Usability Issues [216]Section 11.1.1 JFC Keyboard Binding contains keyboard assignments for the Java Foundation Classes. You can use the bindings as a foundation to keyboard enable your application. When you keyboard enable your application, the following keyboard usability issues need to be considered: Keyboard Bindings In Java, you never know what system your application might run on. Therefore, you must consider how keyboard conflicts might affect the usability of your keyboard implementation. Take the following steps to prevent conflicts with the underlying operating environment: * Make sure the keyboard bindings you select do not conflict with system keyboard mappings of the underlying operating system. For example, Ctrl+Alt+Del might cause you to reboot or offer a shutdown option on some systems. * Make sure the keyboard bindings you select do not interfere with the reserved mobility access keyboard modifiers for your operating system. See [217]section 11.1.3 Reserved Key Mappings for Mobility Access Features. Navigation Order It is important that application developers maintain a logical keyboard navigation order. The navigation order is defined as the order with which you use the keyboard to navigate between components and component elements in your graphical program. Navigation is accomplished by tabbing between components or groups, and using the arrow keys within a component group or component's elements. Tabbing The ability to tab between software components is a key feature in the implementation of keyboard accessibility. A component is inclusive in the tabbing order when added to a panel and its isFocusTraversable() method returns true. A component can be removed from the tabbing order by simply extending the component, overloading this method, and returning false. Excessive use of tabbing can reduce the usability of software for both disabled and non-disabled users. As a developer, you need to determine the point at which tabbing gets in the way and provide a keyboard alternative. This is done through the use of keyboard Mnemonics and Accelerators. Use of Mnemonics and Accelerators Class libraries, like the Java Foundation Classes, should provide for keyboard mnemonics and accelerators in their design. In the case of JFC keyboard mnemonics, all visible items on the screen that set a mnemonic for a component can have the component activated via the ALT+mnemonic. It is important that all visible menu items in an application's menubar be activated via the keyboard. In JFC, this is accomplished by setting the mnemonics for those menu items. To set a mnemonic, pass a Java virtual key as defined in java.awt.KeyEvent. For example, to set the mnemonic to ALT+F, use: JMenu myMenu = new JMenu(); myMenu.setMnemonic(java.awt.event.KeyEvent.VK_F); Additionally, menu items can have accelerators set to activate the action they perform via the keyboard. It is important that frequently used actions, like those found in a tool bar, have menu items with assigned with an accelerator. To assign the Alt+1 accelerator to a menu item, use the Swing KeyStroke class to create the key stroke, and pass it to the JMenuItem setAccelerator method as follows: JMenuItem myItem = new JMenuItem(); myItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MAS K)); For components that do not specifically have a setMnemonic, the JLabel componet in JFC has a method called setDisplayedMnemonic. Use the method to change the focus to the component it is labeling, as defined in the setLabelFor method. Here is a code example: JLabel mylabel = new JLabel("File Name"); //Create a JLabel JTextField myfield = new JTextField("MyFilename"); //Create a JTextFie ld mylabel.setLabelFor(myfield); //Associate label w ith text field mylabel.setDisplayedMnemonic(java.awt.event.KeyEvent.VK_F); //Set ALT+F for the text field Tab Groupings Buttons of common functionality, such as a set of radio buttons used to set the location of a panel (top left, bottom left, and so on.), should be grouped together so the first element of the visible group can be tabbed to. The arrow keys can be used to navigate to each end of the group. Quick Access to Keyboard Navigation Documentation A serious problem with many software applications is that documentation for keyboard access features is non-existent. Documenting the features in print format does not help blind users. To correct this problem, documentation about accessibility features should be available electronically in the application's accessible help facility, and a user should be able to activate the help using the keyboard, typically the F1 key. In the case of blind users, they can use the same screen reader program to access the help facility that they use to access the application. It also improves usability to define a "Keys Help" section in your help facility. Maintain Consistent Keyboard Navigation Definitions For usability reasons, most software needs to have product features that are consistent between releases. For example, Lotus maintained the same keyboard accelerators when converting the 123 spreadsheet product from DOS to Windows. The same is true for keyboard access. Imagine the difficulty for blind users you swapped the cut and paste keyboard keys. When considering your keyboard interface definition, start by using the Common User Access (CUA) guidelines. Veteran disabled computer users grew up with versions of CUA on most graphical systems, including OS/2, Windows, the X Windows system, and DOS. The appendix has sample keyboard settings for other operating systems that shows the influence of CUA keyboard navigation on modern day operating systems. [218]7.0 Java Development Tool Designers Powerful tools for building Java applications, including next-generation tools, such as IBM's Visual Age for Java, are featured on the IBM Java Developers' tools website: [219]http://www.ibm.com/java/tools/tools.html. IBM Visual Age for Java 2.0 includes the Swing class files. Use the class files and these guidelines to create accessible Java applications. Guidelines are under development for tool designers for a later release of this document that will better facilitate and perhaps automate some of the building of accessible Java applications. [220]8.0 Testing for Accessibility Today, there are several ways to test your application for accessibility. The first method is to unplug your mouse and try to navigate your application without a mouse. This approach will uncover where you need to implement keyboard access and how to do it in a way that is usable. [221]Section 6.3.5 Keyboard Usability Issues will help you in your implementation. The second way to test your application for accessibility is to use an accessibility test tool. Currently, the Sun Microsystems Java Accessibility Utilities contain a set of tools which you can use to help test the accessibility of your application. For example, the Explorer tool will display each component's accessibility information (e.g. AccessbleName and AccessibleDescription). You can find the utilities at [222]http://java.sun.com/products/jfc/#download-access. The third way to test your application for accessibility is to test your application with an assistive technology that presents your application in the form needed for a specific disability. The IBM Self Voicing Kit for Java (SVK) will be soon be available for download from the [223]IBM alphaWorks site. Follow the testing checklist when writing your Java application. Accessibility Test Checklist 1. Fully test your application using only the keyboard. Ensure you set the keyboard focus to a component when a window is activated. 2. Use the demo tools provided in the Java Accessibility Utilities package, to ensure that all relevant information is available on components. + Ensure that each relevant component has implemented Accessible + Ensure that each accessibility field is filled in appropriately + Ensure there is an accessible action for components you can activate with mouse or keyboard 3. Use IBM's Self Voicing Kit (SVK) to test your application for Accessibility + Use the F7 Key to launch the Accessibility Test Tool to analyze each component for accessibility o Ensure that each relevant component has implemented Accessible o Ensure that each accessibility field is filled in appropriately o Ensure there is an accessible action for components you can activate with mouse or keyboard o Ensure sure there the each component which performs a user function can be accessed through the keyboard o Ensure sure that component labels are set properly + Use the Speech Output and/or output window to make sure text and components are spoken properly o Ensure sure that text is echoed when you type characters o Ensure sure that highlighted text is spoken o Ensure sure that component labels are spoken o Ensure sure icon descriptions are set and spoken by the SVK + Use the F8 Key on each component to verify that the Accessible Action works as you intended + Use the F6 Key make sure that all text and components are read in the visible parts of your application + In the absence of a speech output mechanism use the SVK output window to verify the text that should be spoken [224]9.0 Online Information and Help When developing documentation for your application in HTML, please follow the Web accessibility guidelines found on the IBM Special Needs Systems web site: [225]http://www.austin.ibm.com/sns/access.html. The World Wide Web Consortium (W3C) publishes the official guidelines at [226]http://www.w3.org/WAI. [227]10.0 Future Discussions Java is still new and the following areas of accessibility are planned to be addressed in future issues: * Multimedia framework - closed captioning * AccessibleTable - advanced accessible table access * JavaOStm - operating system accessibility features * Guidelines for Java development tool designers [228]11.0 Appendix The appendix describes keyboard bindings, accessibility references and trademarks. [229]11.1 Keyboard Bindings Keyboard bindings are partially implemented in JFC. There are some components with a question mark next to them, which indicates the binding might be modified. This section will change if and when the components change. Thes keyboard bindings are also under review by IBM Special Needs Systems and other industry experts, such as the Trace Research and Development Center. [230]11.1.1 JFC Keyboard Bindings for Windows95/NT Components This seperate document contains a list of the [231]keyboard bindings for JFC components on the Windows 95/NT platform. [232]11.1.2 Difference Evaluation: JFC Keyboard Bindings for Windows95/NT and CDE/Motif This seperate document contains a list of the [233]differences between the keyboard bindings for JFC components on the Windows 95/NT and the CDE/Motif platform. [234]11.1.3 Reserved Key Mappings for Mobility Access Features These keys are reserved for assistive technologies that assist mobility impaired users. Keyboard Mappings Mobility Access Feature 5 consecutive clicks of Shift key On/Off for StickyKeys Shift key held down for 8 seconds On/Off for SlowKeys and RepeatKeys 6 consecutive clicks of Control key On/Off for screen reader numeric keypad 6 consecutive clicks of Alt key Future Access use Table 21: Reserved Key Mappings for Mobility Access Features [235][236][237][238][239]11.2 Accessibility References "IBM Accessibility Guidelines" IBM Special Needs Systems [240]http://www.austin.ibm.com/sns/access.html "Making the GUI Talk" Richard S. Schwerdtfeger, IBM. [241]ftp://ftp.software.ibm.com/sns/sr-os2/sr2doc/guitalk.txt Off-Screen Model Technology and GUI Screen Readers "Towards Accessible Human-Computer Interaction" Eric Bergman, Earl Johnson, Sun Microsytems. [242]http://www.sun.com/tech/access/updt.HCI.advance.html "Accessibility Quick Reference Guide" Sun Microsystems. [243]http://www.sun.com/tech/access/access.quick.ref.html "Java Development Kit" Sun Microsystems. [244]http://java.sun.com/products/jdk/ "Java Foundation Class" Sun Microsystems. [245]http://java.sun.com/products/jfc/ [246][247][248][249][250]11.3 Trademarks IBMÒ, OS/2Ò, AIXÒ, AS/400Ò, Screen ReaderÒ, and Visual AgeÒ are trademarks or registered trademarks of International Business Machines Corporation in the United States and/or other countries. Lotustm is a trademark of Lotus Development Corporation in the United States and/or other countries. Tivolitm is a trademark of Tivoli Systems Inc. in the United States and/or other countries. MicrosoftÒ, WindowsÒ, Windows95Ò, and WindowsNTÒ are registered trademarks of Microsoft Corporation. Sun Microsystemstm, Javatm, 100%Pure Javatm, JavaOStm, and Solaristm are trademarks of Sun Microsystems Inc. Other company, product, and service names may be trademarks or service marks of others. [251]11.4 Feedback Please e-mail feedback to IBM Special Needs Systems at [252]snsinfo@us.ibm.com. [253]Valid HTML 4.0![254]Bobby approved! Ó Copyright IBMÒ Corporation 1998 - End of Document -