/*
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.Menu;
import com.yahoo.astra.fl.controls.menuClasses.MenuCellRenderer;
import com.yahoo.astra.fl.events.MenuEvent;
import fl.accessibility.ListAccImpl;
import fl.core.UIComponent;
import flash.accessibility.Accessibility;
import flash.events.Event;
/**
* The MenuAccImpl class is used to make a Menu component accessible.
*
*
A Menu reports the role ObjectRoles.ROLE_SYSTEM_MENUPOPUP
(0x0b) to a screen
* reader. Items of a Menu report the role ObjectRoles.ROLE_SYSTEM_MENUITEM
(0x0c).
*
*
* @see com.yahoo.astra.fl.controls.Menu Menu
* @see http://msdn.microsoft.com/en-us/library/ms697502(VS.85).aspx Microsoft Accessibility Developer Center User Interface Element Reference: Pop-Up Menu
*
* @author Alaric Cole
*/
public class MenuAccImpl extends ListAccImpl
{
//--------------------------------------------------------------------------
//
// Class initialization
//
//--------------------------------------------------------------------------
/**
* Static variable triggering the hookAccessibility()
method.
* This is used for initializing MenuAccImpl
class to hook its
* createAccessibilityImplementation()
method to the Menu
class
* before it gets called when UIComponent
invokes the initializeAccessibility()
method.
*
* @see fl.accessibility.UIComponent#createAccessibilityImplementation()
* @see fl.accessibility.UIComponent#initializeAccessibility()
* @see fl.accessibility.UIComponent#initialize()
*/
private static var accessibilityHooked:Boolean = hookAccessibility();
/**
* Static method that swaps the createAccessibilityImplementation()
* method of UIComponent
subclass with the appropriate AccImpl
subclass.
*
* @see fl.accessibility.UIComponent#createAccessibilityImplementation()
* @see fl.accessibility.UIComponent#initializeAccessibility()
* @see fl.accessibility.UIComponent#initialize()
*/
private static function hookAccessibility():Boolean
{
Menu.createAccessibilityImplementation = createAccessibilityImplementation;
return true;
}
/**
* Method for creating the Accessibility Implementation class for a component.
* This method is called by the initializeAccessibility()
method for the UIComponent
subclass when the component initalizes.
* All AccImpl
subclasses must implement this method
*
* @param component The UIComponent instance that this MenuAccImpl instance makes accessible.
*
* @see fl.accessibility.AccImpl#createAccessibilityImplementation()
* @see fl.core.UIComponent#createAccessibilityImplementation()
* @see fl.core.UIComponent#initalizeAccessibility()
* @see fl.core.UIComponent#initialize()
*/
public static function createAccessibilityImplementation(component:UIComponent):void
{
component.accessibilityImplementation = new MenuAccImpl(component);
}
/**
* Method call for enabling accessibility for a component.
* This method is required for the compiler to activate the accessibility classes for a component.
*
*/
public static function enableAccessibility():void
{
}
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Creates a new MenuAccImpl instance for the specified Menu component.
*
* @param master The UIComponent instance that this MenuAccImpl instance is making accessible.
*
*/
public function MenuAccImpl(master:UIComponent)
{
super(master);
role = ObjectRoles.ROLE_SYSTEM_MENUPOPUP;
}
/**
* @inheritDoc
*/
override protected function get eventsToHandle():Array
{
return super.eventsToHandle.concat([ MenuEvent.ITEM_ROLL_OVER, MenuEvent.ITEM_ROLL_OUT,
MenuEvent.MENU_SHOW, MenuEvent.MENU_HIDE, MenuEvent.ITEM_CLICK ]);
}
/**
* @inheritDoc
* @see http://msdn.microsoft.com/en-us/library/ms697502(VS.85).aspx Microsoft Accessibility Developer Center User Interface Element Reference: Pop-Up Menu
*/
override public function get_accRole(childID:uint):uint
{
//if it's the first child, it's the Menu
if (childID == 0)
{
return role;
}
//greater than zero, and it's a menu item
return ObjectRoles.ROLE_SYSTEM_MENUITEM;
}
/**
* @inheritDoc
*/
override public function get_accValue(childID:uint):String
{
if (childID > 0)
return "";
var menu:Menu = Menu(master);
var accValue:String = "";
var selectedIndex:int = menu.selectedIndex;
if (selectedIndex > -1)
{
var item:Object = menu.dataProvider.getItemAt(selectedIndex);
accValue = menu.itemToLabel(item);
}
return accValue;
}
/**
* @inheritDoc
*/
override public function get_accState(childID:uint):uint
{
var accState:uint = getState(childID);
if (childID > 0 && childID < 100000)
{
var item:Object = Menu(master).dataProvider.getItemAt(childID - 1);
var menu:Menu = Menu(master);
var menuItem:MenuCellRenderer = menu.itemToCellRenderer(item) as MenuCellRenderer;
if(!menuItem.enabled)
{
accState |= ObjectStates.STATE_SYSTEM_UNAVAILABLE;
return accState;
}
accState |= ObjectStates.STATE_SYSTEM_HOTTRACKED | ObjectStates.STATE_SYSTEM_FOCUSED;
//determine if it is a checkbox menu item
if (menuItem.data.selected)
accState |= ObjectStates.STATE_SYSTEM_CHECKED;
//if it has a submenu
if (menuItem.data.data)
accState |= ObjectStates.STATE_SYSTEM_HASPOPUP;
}
return accState;
}
/**
* @inheritDoc
*/
override public function get_accDefaultAction(childID:uint):String
{
if (childID == 0)
return null;
var item:Object = Menu(master).dataProvider.getItemAt(childID - 1);
var menuItem:MenuCellRenderer = Menu(master).itemToCellRenderer(item) as MenuCellRenderer;
return menuItem.data.data ? "Open" : "Execute";
}
/**
* @inheritDoc
*/
override protected function getName(childID:uint):String
{
if (childID == 0 || childID > 100000)
return "";
var name:String;
var menu:Menu = Menu(master);
var item:Object = menu.dataProvider.getItemAt(Math.max(childID - 1, 0));
name = menu.itemToLabel(item);
return name;
}
/**
* @inheritDoc
*/
override protected function eventHandler(event:Event):void
{
var index:int = 0;
var childID:uint;
switch (event.type)
{
case MenuEvent.ITEM_ROLL_OVER:
{
index = MenuEvent(event).index;
if (index >= 0)
{
if(Accessibility.active)
{
childID = index + 1;
Accessibility.sendEvent(MenuEvent(event).menu, childID, EventTypes.EVENT_OBJECT_FOCUS, true);
Accessibility.sendEvent(MenuEvent(event).menu, childID, EventTypes.EVENT_OBJECT_SELECTION, true);
Accessibility.sendEvent(MenuEvent(event).menu, childID, EventTypes.EVENT_OBJECT_MENUPOPUPSTART, true);
}
}
break;
}
case MenuEvent.ITEM_CLICK:
{
index = MenuEvent(event).menu.selectedIndex;
if (index >= 0)
{
if(Accessibility.active)
{
childID = index + 1;
Accessibility.sendEvent(MenuEvent(event).menu, childID, EventTypes.EVENT_OBJECT_FOCUS);
Accessibility.sendEvent(MenuEvent(event).menu, childID, EventTypes.EVENT_OBJECT_SELECTION);
}
}
break;
}
case MenuEvent.MENU_SHOW:
{
if(Accessibility.active)
{
{
Accessibility.sendEvent(MenuEvent(event).menu, 0,
EventTypes.EVENT_OBJECT_MENUPOPUPSTART, true);
}
}
break;
}
case MenuEvent.MENU_HIDE:
{
if(Accessibility.active)
{
if(!MenuEvent(event).menu.parentMenu)
Accessibility.sendEvent(MenuEvent(event).menu, 0, EventTypes.EVENT_OBJECT_MENUPOPUPEND);
}
break;
}
case "change":
index = Menu(master).selectedIndex;
if (index >= 0)
{
if(Accessibility.active)
{
childID = index + 1;
Accessibility.sendEvent(Menu(master), childID, EventTypes.EVENT_OBJECT_FOCUS);
Accessibility.sendEvent(Menu(master), childID, EventTypes.EVENT_OBJECT_SELECTION);
}
}
break;
}
}
}
}