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.MenuBar;
18import mx.core.UIComponent;
19import mx.core.mx_internal;
20import mx.events.MenuEvent;
21
22use namespace mx_internal;
23
24/**
25 *  MenuBarAccImpl is a subclass of AccessibilityImplementation
26 *  which implements accessibility for the MenuBar class.
27 */
28public class MenuBarAccImpl extends AccImpl
29{
30    include "../core/Version.as";
31
32	//--------------------------------------------------------------------------
33	//
34	//  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_FOCUSABLE:uint = 0x00100000;
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_SELECTABLE:uint = 0x00200000;
67
68	/**
69	 *  @private
70	 */
71	private static const STATE_SYSTEM_UNAVAILABLE:uint = 0x00000001;
72
73	/**
74	 *  @private
75	 */
76	private static const EVENT_OBJECT_FOCUS:uint = 0x8005;
77
78	/**
79	 *  @private
80	 */
81	private static const EVENT_SYSTEM_MENUEND:uint = 0x00000005;
82
83	/**
84	 *  @private
85	 */
86	private static const EVENT_SYSTEM_MENUSTART:uint = 0x00000004;
87
88	/**
89	 *  @private
90	 */
91	private static const EVENT_OBJECT_SELECTION:uint = 0x8006;
92
93	//--------------------------------------------------------------------------
94	//
95	//  Class methods
96	//
97	//--------------------------------------------------------------------------
98
99	/**
100	 *  Enables accessibility in the MenuBar class.
101	 *
102	 *  <p>This method is called by application startup code
103	 *  that is autogenerated by the MXML compiler.
104	 *  Afterwards, when instances of MenuBar are initialized,
105	 *  their <code>accessibilityImplementation</code> property
106	 *  will be set to an instance of this class.</p>
107	 */
108	public static function enableAccessibility():void
109	{
110		MenuBar.createAccessibilityImplementation =
111			createAccessibilityImplementation;
112	}
113
114	/**
115	 *  @private
116	 *  Creates a MenuBar's AccessibilityImplementation object.
117	 *  This method is called from UIComponent's
118	 *  initializeAccessibility() method.
119	 */
120	mx_internal static function createAccessibilityImplementation(
121								component:UIComponent):void
122	{
123		component.accessibilityImplementation =
124			new MenuBarAccImpl(component);
125	}
126
127	//--------------------------------------------------------------------------
128	//
129	//  Constructor
130	//
131	//--------------------------------------------------------------------------
132
133	/**
134	 *  Constructor.
135	 *
136	 *  @param master The UIComponent instance that this AccImpl instance
137	 *  is making accessible.
138	 */
139	public function MenuBarAccImpl(master:UIComponent)
140	{
141		super(master);
142
143		role = 0x02; // ROLE_SYSTEM_MENUBAR
144	}
145
146	//--------------------------------------------------------------------------
147	//
148	//  Overridden properties: AccImpl
149	//
150	//--------------------------------------------------------------------------
151
152	//----------------------------------
153	//  eventsToHandle
154	//----------------------------------
155
156	/**
157	 *  @private
158	 *	Array of events that we should listen for from the master component.
159	 */
160	override protected function get eventsToHandle():Array
161	{
162		return super.eventsToHandle.concat(
163			[ "menuShow", "menuHide", "focusIn", "focusOut" ]);
164	}
165
166	//--------------------------------------------------------------------------
167	//
168	//  Overridden methods: AccessibilityImplementation
169	//
170	//--------------------------------------------------------------------------
171
172	/**
173	 *  Gets the role for the component.
174	 *
175	 *  @param childID uint
176	 */
177	override public function get_accRole(childID:uint):uint
178	{
179		return childID == 0 ? role : ROLE_SYSTEM_MENUITEM;
180	}
181
182	/**
183	 *  @private
184	 *  IAccessible method for returning the state of the MenuItem.
185	 *  States are predefined for all the components in MSAA.
186	 *  Values are assigned to each state.
187	 *  Depending upon the listItem being Selected, Selectable,
188	 *  Invisible, Offscreen, a value is returned.
189	 *
190	 *  @param childID uint
191	 *
192	 *  @return State uint
193	 */
194	override public function get_accState(childID:uint):uint
195	{
196		var accState:uint = getState(childID);
197
198		if (childID > 0)
199		{
200			var menuBar:MenuBar = MenuBar(master);
201
202			var index:int = childID - 1;
203
204			if (!menuBar.menuBarItems[index] || !menuBar.menuBarItems[index].enabled)
205			{
206				accState |= STATE_SYSTEM_UNAVAILABLE;
207			}
208			else
209			{
210				accState |= STATE_SYSTEM_SELECTABLE | STATE_SYSTEM_FOCUSABLE;
211
212				// if (menuBar.getMenuAt(index))
213				accState |= STATE_SYSTEM_HASPOPUP;
214
215				if (index == menuBar.selectedIndex)
216					accState |= STATE_SYSTEM_HOTTRACKED | STATE_SYSTEM_FOCUSED;
217			}
218		}
219		return accState;
220	}
221
222	/**
223	 *  @private
224	 *  IAccessible method for returning the Default Action.
225	 *
226	 *  @param childID uint
227	 *
228	 *  @return name of default action.
229	 */
230	override public function get_accDefaultAction(childID:uint):String
231	{
232		if (childID == 0)
233			return null;
234
235		return childID - 1 == MenuBar(master).selectedIndex ? "Close" : "Open";
236	}
237
238	/**
239	 *  @private
240	 *  IAccessible method for executing the Default Action.
241	 *
242	 *  @param childID uint
243	 */
244	override public function accDoDefaultAction(childID:uint):void
245	{
246		if (childID > 0)
247		{
248			var index:int = childID - 1;
249			//MenuBar(master).selectedIndex = index;
250			//MenuBar(master).showMenu(index);
251		}
252	}
253
254 	/**
255	 *  @private
256	 *  Method to return an array of childIDs.
257	 *
258	 *  @return Array
259	 */
260	override public function getChildIDArray():Array
261	{
262		var n:int = MenuBar(master).menuBarItems ?
263					MenuBar(master).menuBarItems.length :
264					0;
265
266		return createChildIDArray(n);
267	}
268
269 	/**
270	 *  @private
271	 *  IAccessible method for returning the bounding box of the MenuBarItem.
272	 *
273	 *  @param childID uint
274	 *
275	 *  @return Location Object
276	 */
277	override public function accLocation(childID:uint):*
278	{
279		//should check that this is returning the needed component
280		return MenuBar(master).menuBarItems[childID - 1];
281		//return MenuBar(master).getMenuBarItemAt(childID - 1);
282	}
283
284	/**
285	 *  @private
286	 *  IAccessible method for returning the childFocus of the List.
287	 *
288	 *  @param childID uint
289	 *
290	 *  @return focused childID.
291	 */
292	override public function get_accFocus():uint
293	{
294		var index:int = MenuBar(master).selectedIndex;
295
296		return index >= 0 ? index + 1 : 0;
297	}
298
299	//--------------------------------------------------------------------------
300	//
301	//  Overridden methods: AccImpl
302	//
303	//--------------------------------------------------------------------------
304
305	/**
306	 *  @private
307	 *  IAccessible method for returning the name of the MenuBar
308	 *  which is spoken out by the screen reader.
309	 *  The MenuItem should return the label as the name
310	 *  and MenuBar should return the name specified in the Accessibility Panel.
311	 *
312	 *  @param childID uint
313	 *
314	 *  @return Name String
315	 */
316	override protected function getName(childID:uint):String
317	{
318		if (childID == 0)
319			return "";
320
321		var menuBar:MenuBar = MenuBar(master);
322
323		var index:int = childID - 1;
324
325		if (menuBar.menuBarItems && menuBar.menuBarItems.length > index)
326		{
327			if (menuBar.menuBarItems[index] && menuBar.menuBarItems[index].data)
328				return menuBar.itemToLabel(menuBar.menuBarItems[index].data);
329		}
330
331		return "";
332	}
333
334	//--------------------------------------------------------------------------
335	//
336	//  Overridden event handlers: AccImpl
337	//
338	//--------------------------------------------------------------------------
339
340	/**
341	 *  @private
342	 *  Override the generic event handler.
343	 *  All AccImpl must implement this
344	 *  to listen for events from its master component.
345	 */
346	override protected function eventHandler(event:Event):void
347	{
348		// Let AccImpl class handle the events
349		// that all accessible UIComponents understand.
350		$eventHandler(event);
351
352		switch (event.type)
353		{
354			case "menuShow":
355			{
356				var index:int = MenuBar(master).selectedIndex;
357
358				// since all the menu events are also received by Menubar.
359				if (index >= 0 && !MenuEvent(event).menu.parentMenu)
360				{
361					var childID:uint = index + 1;
362
363					Accessibility.sendEvent(master, childID,
364											EVENT_OBJECT_FOCUS);
365
366					Accessibility.sendEvent(master, childID,
367											EVENT_OBJECT_SELECTION);
368				}
369
370				break;
371			}
372
373			case "menuHide":
374			{
375				if (!MenuEvent(event).menu.parentMenu)
376					Accessibility.sendEvent(master, 0, EVENT_SYSTEM_MENUEND);
377				break;
378			}
379
380			case "focusIn":
381			{
382				Accessibility.sendEvent(master, 0, EVENT_SYSTEM_MENUSTART);
383				break;
384			}
385
386			case "focusOut":
387			{
388				if (MenuBar(master).selectedIndex == -1)
389					Accessibility.sendEvent(master, 0, EVENT_SYSTEM_MENUEND);
390				break;
391			}
392		}
393	}
394}
395
396}
397