1////////////////////////////////////////////////////////////////////////////////
2//
3//  ADOBE SYSTEMS INCORPORATED
4//  Copyright 2003-2007 Adobe Systems Incorporated
5//  All Rights Reserved.
6//
7//  NOTICE: Adobe permits you to use, modify, and distribute this file
8//  in accordance with the terms of the license agreement accompanying it.
9//
10////////////////////////////////////////////////////////////////////////////////
11
12package mx.accessibility
13{
14
15import flash.accessibility.Accessibility;
16import flash.events.Event;
17import mx.controls.Menu;
18import mx.core.UIComponent;
19import mx.core.mx_internal;
20import mx.events.MenuEvent;
21
22use namespace mx_internal;
23
24/**
25 *  MenuAccImpl is a subclass of AccessibilityImplementation
26 *  which implements accessibility for the Menu class.
27 */
28public class MenuAccImpl extends ListBaseAccImpl
29{
30    include "../core/Version.as";
31
32	//--------------------------------------------------------------------------
33	//
34	//  Class constants
35	//
36	//--------------------------------------------------------------------------
37
38	/**
39	 *  @private
40	 */
41	private static const ROLE_SYSTEM_MENUITEM:uint = 0x0C;
42
43	/**
44	 *  @private
45	 */
46	private static const STATE_SYSTEM_CHECKED:uint = 0x00000010;
47
48	/**
49	 *  @private
50	 */
51	private static const STATE_SYSTEM_FOCUSED:uint = 0x00000004;
52
53	/**
54	 *  @private
55	 */
56	private static const STATE_SYSTEM_HASPOPUP:uint = 0x40000000;
57
58	/**
59	 *  @private
60	 */
61	private static const STATE_SYSTEM_HOTTRACKED:uint = 0x00000080;
62
63	/**
64	 *  @private
65	 */
66	private static const STATE_SYSTEM_UNAVAILABLE:uint = 0x00000001;
67
68	/**
69	 *  @private
70	 */
71	private static const EVENT_OBJECT_FOCUS:uint = 0x8005;
72
73	/**
74	 *  @private
75	 */
76	private static const EVENT_OBJECT_SELECTION:uint = 0x8006;
77
78	/**
79	 *  @private
80	 */
81	private static const EVENT_SYSTEM_MENUPOPUPSTART:uint = 0x00000006;
82
83	/**
84	 *  @private
85	 */
86	private static const EVENT_SYSTEM_MENUPOPUPEND:uint = 0x00000007;
87
88	//--------------------------------------------------------------------------
89	//
90	//  Class methods
91	//
92	//--------------------------------------------------------------------------
93
94	/**
95	 *  Enables accessibility in the Menu class.
96	 *
97	 *  <p>This method is called by application startup code
98	 *  that is autogenerated by the MXML compiler.
99	 *  Afterwards, when instances of Menu are initialized,
100	 *  their <code>accessibilityImplementation</code> property
101	 *  will be set to an instance of this class.</p>
102	 */
103	public static function enableAccessibility():void
104	{
105		Menu.createAccessibilityImplementation =
106			createAccessibilityImplementation;
107	}
108
109	/**
110	 *  @private
111	 *  Creates a Menu's AccessibilityImplementation object.
112	 *  This method is called from UIComponent's
113	 *  initializeAccessibility() method.
114	 */
115	mx_internal static function createAccessibilityImplementation(
116								component:UIComponent):void
117	{
118		component.accessibilityImplementation =
119			new MenuAccImpl(component);
120	}
121
122	//--------------------------------------------------------------------------
123	//
124	//  Constructor
125	//
126	//--------------------------------------------------------------------------
127
128	/**
129	 *  Constructor.
130	 *
131	 *  @param master The UIComponent instance that this AccImpl instance
132	 *  is making accessible.
133	 */
134	public function MenuAccImpl(master:UIComponent)
135	{
136		super(master);
137
138		role = 0x0B; // ROLE_SYSTEM_MENUPOPUP
139	}
140
141	//--------------------------------------------------------------------------
142	//
143	//  Overridden properties: AccImpl
144	//
145	//--------------------------------------------------------------------------
146
147	//----------------------------------
148	//  eventsToHandle
149	//----------------------------------
150
151	/**
152	 *  @private
153	 *	Array of events that we should listen for from the master component.
154	 */
155	override protected function get eventsToHandle():Array
156	{
157		return super.eventsToHandle.concat(
158			[ "itemRollOver", "menuShow", "menuHide" ]);
159	}
160
161	//--------------------------------------------------------------------------
162	//
163	//  Overridden methods: AccessibilityImplementation
164	//
165	//--------------------------------------------------------------------------
166
167	/**
168	 *  @private
169	 *  Gets the role for the component.
170	 *
171	 *  @param childID children of the component
172	 */
173	override public function get_accRole(childID:uint):uint
174	{
175		return childID == 0 ? role : ROLE_SYSTEM_MENUITEM;
176	}
177
178	/**
179	 *  @private
180	 *  IAccessible method for returning the state of the Menu.
181	 *  States are predefined for all the components in MSAA.
182	 *  Values are assigned to each state.
183	 *  Depending upon the menuItem being Selected, Selectable,
184	 *  Invisible, Offscreen, a value is returned.
185	 *
186	 *  @param childID uint
187	 *
188	 *  @return State uint
189	 */
190	override public function get_accState(childID:uint):uint
191	{
192		var accState:uint = getState(childID);
193
194		if (childID > 0 && childID < 100000)
195		{
196			var item:Object = Menu(master).dataProvider[childID - 1];
197
198			if (!Menu(master).dataDescriptor.isEnabled(item))
199			{
200				accState |= STATE_SYSTEM_UNAVAILABLE;
201				return accState;
202			}
203
204			//if (Menu(master).dataDescriptor.isFocused(item))
205			accState |= STATE_SYSTEM_HOTTRACKED | STATE_SYSTEM_FOCUSED;
206
207			if (Menu(master).dataDescriptor.isToggled(item))
208				accState |= STATE_SYSTEM_CHECKED;
209
210			if (Menu(master).dataDescriptor.isBranch(item))
211				accState |= STATE_SYSTEM_HASPOPUP;
212		}
213		return accState;
214	}
215
216	/**
217	 *  @private
218	 *  IAccessible method for returning the Default Action.
219	 *
220	 *  @param childID uint
221	 *
222	 *  @return focused childID.
223	 */
224	override public function get_accDefaultAction(childID:uint):String
225	{
226		if (childID == 0)
227			return null;
228
229		var item:Object = Menu(master).dataProvider[childID - 1];
230
231		return Menu(master).dataDescriptor.isBranch(item) ? "Open" : "Execute";
232	}
233
234	//--------------------------------------------------------------------------
235	//
236	//  Overridden methods: AccImpl
237	//
238	//--------------------------------------------------------------------------
239
240	/**
241	 *  @private
242	 *  method for returning the name of the MenuItem
243	 *  which is spoken out by the screen reader
244	 *  The MenuItem should return the label as the name
245	 *  and Menu should return the name specified in the Accessibility Panel.
246	 *
247	 *  @param childID uint
248	 *
249	 *  @return Name String
250	 */
251	override protected function getName(childID:uint):String
252	{
253		if (childID == 0)
254			return "";
255
256		var menu:Menu = Menu(master);
257
258		var item:Object = menu.dataProvider[childID - 1];
259
260		return menu.itemToLabel(item);
261	}
262
263	//--------------------------------------------------------------------------
264	//
265	//  Overridden event handlers: AccImpl
266	//
267	//--------------------------------------------------------------------------
268
269	/**
270	 *  @private
271	 *  Override the generic event handler.
272	 *  All AccImpl must implement this
273	 *  to listen for events from its master component.
274	 */
275	override protected function eventHandler(event:Event):void
276	{
277		// Let AccImpl class handle the events
278		// that all accessible UIComponents understand.
279		$eventHandler(event);
280
281		var index:int = 0;
282		var childID:uint;
283
284		switch (event.type)
285		{
286			case MenuEvent.ITEM_ROLL_OVER:
287			{
288				index = MenuEvent(event).index;
289				if (index >= 0)
290				{
291					childID = index + 1;
292
293					Accessibility.sendEvent(MenuEvent(event).menu, childID,
294											EVENT_OBJECT_FOCUS);
295
296					Accessibility.sendEvent(MenuEvent(event).menu, childID,
297											EVENT_OBJECT_SELECTION);
298				}
299				break;
300			}
301
302			case MenuEvent.ITEM_CLICK:
303			{
304				index = MenuEvent(event).menu.selectedIndex;
305				if (index >= 0)
306				{
307					childID = index + 1;
308
309					Accessibility.sendEvent(MenuEvent(event).menu, childID,
310											EVENT_OBJECT_FOCUS);
311
312					Accessibility.sendEvent(MenuEvent(event).menu, childID,
313											EVENT_OBJECT_SELECTION);
314				}
315				break;
316			}
317
318			case MenuEvent.MENU_SHOW:
319			{
320				Accessibility.sendEvent(MenuEvent(event).menu, 0,
321										EVENT_SYSTEM_MENUPOPUPSTART);
322				break;
323			}
324
325			case MenuEvent.MENU_HIDE:
326			{
327				Accessibility.sendEvent(MenuEvent(event).menu, 0,
328										EVENT_SYSTEM_MENUPOPUPEND);
329				break;
330			}
331		}
332	}
333}
334
335}
336