topical media & game development
student-ar-fl-accessibility-DataGridAccImpl.ax
student-ar-fl-accessibility-DataGridAccImpl.ax
[swf]
flex
// Copyright 2007. Adobe Systems Incorporated. All Rights Reserved.
package fl.accessibility {
import flash.events.Event;
import flash.accessibility.Accessibility;
import fl.events.DataGridEvent;
import fl.controls.listClasses.ICellRenderer;
import fl.controls.SelectableList;
import fl.controls.DataGrid;
import fl.core.UIComponent;
The @ax-student-ar-fl-accessibility-DataGridAccImpl class, also called the DataGrid Accessibility Implementation class,
is used to make a DataGrid component accessible.
<p>The @ax-student-ar-fl-accessibility-DataGridAccImpl class supports system roles, object-based events, and states.</p>
<p>A DataGrid reports the role <code>ROLE_SYSTEM_LIST</code> (0x21) to a screen
reader. Items of a DataGrid report the role <code>ROLE_SYSTEM_LISTITEM</code> (0x22).</p>
<p>A DataGrid reports the following states to a screen reader:</p>
<ul>
<li><code>STATE_SYSTEM_NORMAL</code> (0x00000000)</li>
<li><code>STATE_SYSTEM_UNAVAILABLE</code> (0x00000001)</li>
<li><code>STATE_SYSTEM_FOCUSED</code> (0x00000004)</li>
<li><code>STATE_SYSTEM_FOCUSABLE</code> (0x00100000)</li>
</ul>
<p>Additionally, items of a DataGrid report the following states:</p>
<ul>
<li><code>STATE_SYSTEM_SELECTED</code> (0x00000002)</li>
<li><code>STATE_SYSTEM_FOCUSED</code> (0x00000004)</li>
<li><code>STATE_SYSTEM_INVISIBLE</code> (0x00008000)</li>
<li><code>STATE_SYSTEM_OFFSCREEN</code> (0x00010000)</li>
<li><code>STATE_SYSTEM_SELECTABLE</code> (0x00200000)</li>
</ul>
<p>A DataGrid dispatches the following events to a screen reader:</p>
<ul>
<li><code>EVENT_OBJECT_FOCUS</code> (0x8005)</li>
<li><code>EVENT_OBJECT_SELECTION</code> (0x8006)</li>
<li><code>EVENT_OBJECT_STATECHANGE</code> (0x800A)</li>
<li><code>EVENT_OBJECT_NAMECHANGE</code> (0x800C)</li>
</ul>
see: fl.controls.DataGrid DataGrid
@langversion 3.0
@playerversion Flash 9.0.28.0
public class @ax-student-ar-fl-accessibility-DataGridAccImpl extends SelectableListAccImpl {
@private
Static variable triggering the <code>hookAccessibility()</code> method.
This is used for initializing @ax-student-ar-fl-accessibility-DataGridAccImpl class to hook its
<code>createAccessibilityImplementation()</code> method to DataGrid class
before it gets called from UIComponent.
@langversion 3.0
@playerversion Flash 9.0.28.0
private static var accessibilityHooked:Boolean = hookAccessibility();
@private
Static method for swapping the <code>createAccessibilityImplementation()</code>
method of DataGrid with the @ax-student-ar-fl-accessibility-DataGridAccImpl class.
@langversion 3.0
@playerversion Flash 9.0.28.0
private static function hookAccessibility():Boolean {
DataGrid.createAccessibilityImplementation = createAccessibilityImplementation;
return true;
}
//--------------------------------------------------------------------------
// Class constants
//--------------------------------------------------------------------------
@private
Role of listItem.
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const ROLE_SYSTEM_LISTITEM:uint = 0x22;
@private
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const STATE_SYSTEM_FOCUSED:uint = 0x00000004;
@private
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const STATE_SYSTEM_INVISIBLE:uint = 0x00008000;
@private
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const STATE_SYSTEM_OFFSCREEN:uint = 0x00010000;
@private
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const STATE_SYSTEM_SELECTABLE:uint = 0x00200000;
@private
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const STATE_SYSTEM_SELECTED:uint = 0x00000002;
@private
Event emitted if 1 item is selected.
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const EVENT_OBJECT_FOCUS:uint = 0x8005;
@private
Event emitted if 1 item is selected.
@langversion 3.0
@playerversion Flash 9.0.28.0
private static const EVENT_OBJECT_SELECTION:uint = 0x8006;
//--------------------------------------------------------------------------
// Class methods
//--------------------------------------------------------------------------
@private
Method for creating the Accessibility class.
This method is called from UIComponent.
parameter: component The UIComponent instance that this AccImpl instance
is making accessible.
@langversion 3.0
@playerversion Flash 9.0.28.0
public static function createAccessibilityImplementation(component:UIComponent):void {
component.accessibilityImplementation = new @ax-student-ar-fl-accessibility-DataGridAccImpl(component);
}
Enables accessibility for a DataGrid component.
This method is required for the compiler to activate
the accessibility classes for a component.
@langversion 3.0
@playerversion Flash 9.0.28.0
public static function enableAccessibility():void {
}
//--------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------
@private
@internal Nivesh says: I don't think we should document the constructors
for the accessibility classes. End-users just have to call the
static enableAccessibility method. They don't really create an
instance of the classes.
Creates a new List Accessibility Implementation.
parameter: master The UIComponent instance that this AccImpl instance
is making accessible.
@langversion 3.0
@playerversion Flash 9.0.28.0
public function @ax-student-ar-fl-accessibility-DataGridAccImpl(master:UIComponent) {
super(master);
}
//--------------------------------------------------------------------------
// Overridden properties: AccImpl
//--------------------------------------------------------------------------
@private
Array of events that we should listen for from the master component.
@langversion 3.0
@playerversion Flash 9.0.28.0
override protected function get eventsToHandle():Array {
return super.eventsToHandle.concat([ DataGridEvent.ITEM_FOCUS_IN ]);
}
//--------------------------------------------------------------------------
// Overridden methods: AccessibilityImplementation
//--------------------------------------------------------------------------
@private
Gets the role for the component.
parameter: childID Children of the component
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function get_accRole(childID:uint):uint {
if (childID == 0) {
return role;
}
return ROLE_SYSTEM_LISTITEM;
}
@private
IAccessible method for returning the value of the ListItem/DataGrid
which is spoken out by the screen reader
The DataGrid should return the name of the currently selected item
with m of n string as value when focus moves to DataGrid.
parameter: childID
returns: Name
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function get_accValue(childID:uint):String {
var accValue:String;
var dataGrid:DataGrid = DataGrid(master);
if (childID == 0) {
var row:int;
var item:Object;
var columns:Array;
var n:int;
var i:int;
if (!dataGrid.editable) {
row = dataGrid.selectedIndex;
if (row > -1) {
item = getItemAt(row);
if (item is String) {
accValue = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length + " " + item;
} else {
accValue = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length;
columns = dataGrid.columns;
n = columns.length;
for (i = 0; i < n; i++) {
accValue += " " + columns[i].headerText + " " + columns[i].itemToLabel(item);
}
}
}
} else {
var coord:Object = dataGrid.editedItemPosition;
if (coord) {
row = coord.rowIndex;
var col:int = coord.columnIndex;
item = getItemAt(row);
if (item is String) {
accValue = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length + " " + item;
} else {
columns = dataGrid.columns;
var itemName:String = columns[col].itemToLabel(item);
var headerText:String = columns[col].headerText;
accValue = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length;
n = columns.length;
for (i = 0; i < n; i++) {
accValue += " " + columns[i].headerText + " " + columns[i].itemToLabel(item);
}
accValue += ", Editing " + headerText + " " + itemName;
}
}
}
}
return accValue;
}
@private
IAccessible method for returning the state of the grid item.
States are predefined for all the components in MSAA.
Values are assigned to each state.
Depending upon the GridItem being Selected, Selectable, Invisible,
Offscreen, a value is returned.
parameter: childID uint
returns: State uint
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function get_accState(childID:uint):uint {
var dataGrid:DataGrid = DataGrid(master);
var accState:uint = getState(childID);
var row:int;
var col:int;
if (childID > 0) {
var index:int = childID - 1;
if (!dataGrid.editable) {
row = index;
if (row < dataGrid.verticalScrollPosition || row >= dataGrid.verticalScrollPosition + dataGrid.rowCount) {
accState |= (STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_INVISIBLE);
} else {
accState |= STATE_SYSTEM_SELECTABLE;
var item:Object = dataGrid.getItemAt(row);
var selItems:Array = dataGrid.selectedIndices;
for(var i:int = 0; i < selItems.length; i++) {
if(selItems[i] == row) {
accState |= STATE_SYSTEM_SELECTED | STATE_SYSTEM_FOCUSED;
break;
}
}
}
} else {
row = Math.floor(index / dataGrid.columns.length);
col = index % dataGrid.columns.length;
if (row < dataGrid.verticalScrollPosition || row >= dataGrid.verticalScrollPosition + dataGrid.rowCount) {
accState |= (STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_INVISIBLE);
} else if (dataGrid.columns[col].editable) {
accState |= STATE_SYSTEM_SELECTABLE;
var coord:Object = dataGrid.editedItemPosition;
if (coord && coord.rowIndex == row && coord.columnIndex == col) {
accState |= STATE_SYSTEM_SELECTED | STATE_SYSTEM_FOCUSED;
}
}
}
}
return accState;
}
@private
IAccessible method for executing the Default Action.
parameter: childID uint
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function accDoDefaultAction(childID:uint):void {
var dataGrid:DataGrid = DataGrid(master);
if (childID > 0) {
// Assuming childID is always ItemID + 1
// because getChildIDArray may not always be invoked.
var index:int = childID - 1;
// index is the (0 based) index of the elements after the headers
if (!dataGrid.editable) {
// index is the row id
dataGrid.selectedIndex = index;
} else {
var row:int = Math.floor(index / dataGrid.columns.length);
var col:int = index % dataGrid.columns.length;
dataGrid.editedItemPosition = { rowIndex: row, columnIndex: col };
}
}
}
@private
Method to return an array of childIDs.
returns: Array
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function getChildIDArray():Array {
var childIDs:Array = [];
var dataGrid:DataGrid = DataGrid(master);
if (dataGrid.dataProvider) {
// 0 is DataGrid, 1 to columnCount * Rows -> ItemRenderers
var n:int = 0;
if (!dataGrid.editable) {
// non editable case (itemRenderers)
n = dataGrid.dataProvider.length;
} else {
// editable case (rows)
n = dataGrid.columns.length * dataGrid.dataProvider.length;
}
for (var i:int = 0; i < n; i++) {
childIDs[i] = i + 1;
}
}
return childIDs;
}
@private
IAccessible method for returning the bounding box of the GridItem.
parameter: childID uint
returns: Location Object
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function accLocation(childID:uint):* {
var dataGrid:DataGrid = DataGrid(master);
if(childID > 0) {
var index:int = childID - 1;
var row:int;
var col:int;
var item:Object;
if (!dataGrid.editable) {
row = index
if (row < dataGrid.verticalScrollPosition || row >= dataGrid.verticalScrollPosition + dataGrid.rowCount) {
return null;
}
item = dataGrid.getItemAt(row);
return dataGrid.itemToCellRenderer(item);
} else {
row = Math.floor(index / dataGrid.columns.length);
col = index % dataGrid.columns.length;
if (row < dataGrid.verticalScrollPosition || row >= dataGrid.verticalScrollPosition + dataGrid.rowCount) {
return null;
}
item = dataGrid.getItemAt(row);
return dataGrid.itemToCellRenderer(item);
}
}
return dataGrid;
}
@private
IAccessible method for returning the childFocus of the DataGrid.
parameter: childID uint
returns: focused childID.
@langversion 3.0
@playerversion Flash 9.0.28.0
override public function get_accFocus():uint {
var dataGrid:DataGrid = DataGrid(master);
if (!dataGrid.editable) {
var index:uint = dataGrid.selectedIndex;
return (index >= 0) ? index + 1 : 0;
} else {
var coord:Object = dataGrid.editedItemPosition;
if (!coord) {
return 0;
}
var row:int = coord.rowIndex;
var col:int = coord.columnIndex;
return dataGrid.columns.length * row + col + 1;
}
}
//--------------------------------------------------------------------------
// Overridden methods: AccImpl
//--------------------------------------------------------------------------
@private
method for returning the name of the DataGrid/ListItem
which is spoken out by the screen reader
The ListItem should return the label as the name with m of n string and
DataGrid should return the name specified in the AccessibilityProperties.
parameter: childID uint
returns: Name
@langversion 3.0
@playerversion Flash 9.0.28.0
override protected function getName(childID:uint):String {
// 0 -> DataGrid
if (childID == 0) {
return "";
}
var name:String;
var dataGrid:DataGrid = DataGrid(master);
// 1 to columnCount * Rows -> ItemRenderers
if (childID > 0) {
// assuming childID is always ItemID + 1
// because getChildIDArray may not always be invoked.
var index:int = childID - 1;
// index is the (0 based) index of the elements after the headers
var row:int
var item:Object;
var columns:Array;
var n:int;
var i:int;
if (!dataGrid.editable) {
// index is the row id
row = index;
item = getItemAt(index);
if (item is String) {
name = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length + " " + item;
} else {
name = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length;
columns = dataGrid.columns;
n = columns.length;
for (i = 0; i < n; i++) {
name += " " + columns[i].headerText + " " + columns[i].itemToLabel(item);
}
}
} else {
row = Math.floor(index / dataGrid.columns.length);
var col:int = index % dataGrid.columns.length;
item = getItemAt(row);
if (item is String) {
name = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length + " " + item;
} else {
columns = dataGrid.columns;
var itemName:String = columns[col].itemToLabel(item);
var headerText:String = columns[col].headerText;
name = "Row " + (row + 1) + " of " + dataGrid.dataProvider.length;
n = columns.length;
for (i = 0; i < columns.length; i++) {
name += " " + columns[i].headerText + " " + columns[i].itemToLabel(item);
}
name += ", Editing " + headerText + " " + itemName;
}
}
}
return name;
}
//--------------------------------------------------------------------------
// Overridden event handlers: AccImpl
//--------------------------------------------------------------------------
@private
Override the generic event handler.
All AccImpl must implement this to listen
for events from its master component.
@langversion 3.0
@playerversion Flash 9.0.28.0
override protected function eventHandler(event:Event):void {
var dataGrid:DataGrid = DataGrid(master);
switch (event.type) {
case "change":
if (Accessibility.active && !dataGrid.editable) {
var index:int = dataGrid.selectedIndex;
if (index >= 0) {
var childID:uint = index + 1;
Accessibility.sendEvent(dataGrid, childID, EVENT_OBJECT_FOCUS);
Accessibility.sendEvent(dataGrid, childID, EVENT_OBJECT_SELECTION);
}
}
break;
case DataGridEvent.ITEM_FOCUS_IN:
if (Accessibility.active && dataGrid.editable) {
var item:int = int(DataGridEvent(event).rowIndex);
var col:int = DataGridEvent(event).columnIndex;
Accessibility.sendEvent(dataGrid, dataGrid.columns.length * item + col + 1, EVENT_OBJECT_FOCUS);
Accessibility.sendEvent(dataGrid, dataGrid.columns.length * item + col + 1, EVENT_OBJECT_SELECTION);
}
break;
}
}
//--------------------------------------------------------------------------
// Methods
//--------------------------------------------------------------------------
@private
@langversion 3.0
@playerversion Flash 9.0.28.0
private function getItemAt(index:int):Object {
var dataGrid:DataGrid = DataGrid(master);
return dataGrid.getItemAt(index);
}
}
}
(C) Æliens
27/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.