/* Copyright (c) 2009 Yahoo! Inc. All rights reserved. The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license */ package com.yahoo.astra.fl.accessibility { import com.yahoo.astra.accessibility.EventTypes; import com.yahoo.astra.accessibility.ObjectRoles; import com.yahoo.astra.accessibility.ObjectStates; import com.yahoo.astra.fl.controls.TabBar; import com.yahoo.astra.fl.controls.tabBarClasses.TabButton; import fl.accessibility.AccImpl; import fl.core.UIComponent; import flash.accessibility.Accessibility; import flash.events.Event; /** * The TabBarAccImpl class, also called the TabBar Accessibility Implementation class, * is used to make a TabBar component accessible. * * @see com.yahoo.astra.fl.controls.TabBar */ public class TabBarAccImpl extends AccImpl { //-------------------------------------- // Class Properties //-------------------------------------- /** * @private * Static variable triggering the hookAccessibility() method. * This is used for initializing TabBarAccImpl class to hook its * createAccessibilityImplementation() method to TabBar class * before it gets called from UIComponent. */ private static var accessibilityHooked:Boolean = hookAccessibility(); //-------------------------------------- // Class Methods //-------------------------------------- /** * @private * Static method for swapping the createAccessibilityImplementation() * method of TabBar with the TabBarAccImpl class. */ private static function hookAccessibility():Boolean { TabBar.createAccessibilityImplementation = createAccessibilityImplementation; return true; } /** * @private * Method for creating the Accessibility class. * This method is called from UIComponent. * * @param component The UIComponent instance that this AccImpl instance * is making accessible. */ public static function createAccessibilityImplementation(component:UIComponent):void { component.accessibilityImplementation = new TabBarAccImpl(component); } /** * Enables accessibility for a TabBar component. * This method is required for the compiler to activate * the accessibility classes for a component. */ public static function enableAccessibility():void { //do nothing } //-------------------------------------- // Constants //-------------------------------------- /** * @private */ private static const MAX_NUM:uint = 100000; //-------------------------------------- // Constructor //-------------------------------------- /** * @private * * Creates a new TabBar Accessibility Implementation. * * @param master The UIComponent instance that this AccImpl instance * is making accessible. */ public function TabBarAccImpl(master:UIComponent) { super(master); this.role = ObjectRoles.ROLE_SYSTEM_PAGETABLIST; } //-------------------------------------- // Properties //-------------------------------------- /** * @private * Array of events that we should listen for from the master component. */ override protected function get eventsToHandle():Array { return super.eventsToHandle.concat([ Event.CHANGE, "focusUpdate" ]); } //-------------------------------------- // Public Methods //-------------------------------------- /** * @private * Gets the role for the component. * * @param childID The child id. * * @return Role. */ override public function get_accRole(childID:uint):uint { if(childID == 0) { return this.role; } //tabs use this role: return ObjectRoles.ROLE_SYSTEM_PAGETAB; } /** * @private * IAccessible method for returning the state of the Tabs. * States are predefined for all the components in MSAA. Values are assigned to each state. * Depending upon the Tab being Focusable, Focused and Moveable, a value is returned. * * @param childID The child id. * * @return State. */ override public function get_accState(childID:uint):uint { var accState:uint = getState(childID); var tabBar:TabBar = TabBar(master); if(childID > 0) { accState = ObjectStates.STATE_SYSTEM_SELECTABLE | ObjectStates.STATE_SYSTEM_FOCUSABLE; var index:int = childID < MAX_NUM ? childID - 1 : childID - MAX_NUM - 1; if(index == tabBar.selectedIndex) { accState |= ObjectStates.STATE_SYSTEM_SELECTED; } if(index == tabBar.focusIndex) { accState |= ObjectStates.STATE_SYSTEM_FOCUSED; } } return accState; } /** * @private * IAccessible method for returning the Default Action. * * @param childID uint * * @return DefaultAction. */ override public function get_accDefaultAction(childID:uint):String { return "Switch"; } /** * @private * IAccessible method for executing the Default Action. * * @param childID uint */ override public function accDoDefaultAction(childID:uint):void { if(childID > 0) { var index:int = childID < MAX_NUM ? childID - 1 : childID - MAX_NUM - 1; TabBar(master).selectedIndex = index; } } /** * @private * Method to return the childID Array. * * @return Array */ override public function getChildIDArray():Array { var childIDs:Array = []; var n:int = TabBar(master).numChildren; for(var i:int = 0; i < n; i++) { childIDs[i] = i + 1; } return childIDs; } /** * @private * IAccessible method for returning the bounding box of the Tabs. * * @param childID The child id * * @return Object Location */ override public function accLocation(childID:uint):* { var index:int = childID < MAX_NUM ? childID - 1 : childID - MAX_NUM - 1; return TabBar(master).getChildAt(index); } /** * @private * IAccessible method for returning the childFocus of the TabBar. * * @param childID uint * * @return focused childID. */ override public function get_accFocus():uint { var index:int = TabBar(master).focusIndex; if(index >= 0) { return index + 1; } return 0; } //-------------------------------------- // Protected Methods //-------------------------------------- /** * @private * method for returning the name of the Tab * which is spoken out by the screen reader. * * @param childID The child id. * * @return Name */ override protected function getName(childID:uint):String { if(childID == 0) { return ""; } var name:String; var tabBar:TabBar = TabBar(master); // Assuming childID is always ItemID + 1 // because getChildIDArray is not always invoked. var index:int = childID < MAX_NUM ? childID - 1 : childID - MAX_NUM - 1; var item:TabButton = TabButton(tabBar.getChildAt(index)); name = item.label; return name; } /** * @private * Override the generic event handler. * All AccImpl must implement this to listen for events * from its master component. */ override protected function eventHandler(event:Event):void { switch (event.type) { case "change": this.updateSelection(TabBar(master).selectedIndex); break; case "focusUpdate": this.updateFocus(TabBar(master).focusIndex); break; } } /** * @private * Tells the client that a tab has been selected. */ protected function updateSelection(index:int):void { if(index < 0 || !Accessibility.active) { return; } var childID:uint = index + 1; Accessibility.sendEvent(master, childID, EventTypes.EVENT_OBJECT_FOCUS); Accessibility.sendEvent(master, childID, EventTypes.EVENT_OBJECT_SELECTION); //Accessibility.updateProperties(); } /** * @private * Tells the client that a tab has been focused. */ protected function updateFocus(index:int):void { if(index < 0 || !Accessibility.active) { return; } var childID:uint = index + 1; Accessibility.sendEvent(master, childID, EventTypes.EVENT_OBJECT_FOCUS); //Accessibility.updateProperties(); } } }