| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package spark.accessibility |
| { |
| |
| import flash.accessibility.AccessibilityImplementation; |
| import flash.display.Graphics; |
| import flash.display.InteractiveObject; |
| import flash.display.Sprite; |
| import flash.events.Event; |
| |
| import mx.accessibility.AccConst; |
| import mx.accessibility.AccImpl; |
| import mx.core.UIComponent; |
| import mx.core.mx_internal; |
| import mx.events.ResizeEvent; |
| |
| import spark.components.Panel; |
| import spark.events.SkinPartEvent; |
| |
| use namespace mx_internal; |
| |
| /** |
| * PanelAccImpl is the accessibility implementation class |
| * for spark.components.Panel. |
| * |
| * <p>When a Spark Panel is created, |
| * the <code>accessibilityImplementation</code> property |
| * of a special child Sprite is set to an instance of this class. |
| * The Flash Player then uses this class to allow MSAA clients |
| * such as screen readers to see and manipulate the Panel. |
| * See the mx.accessibility.AccImpl and |
| * flash.accessibility.AccessibilityImplementation classes |
| * for background information about accessibility implementation |
| * classes and MSAA.</p> |
| * |
| * <p><b>Children</b></p> |
| * |
| * <p>A Panel has no MSAA children. |
| * All children of the actual Panel are siblings of the Panel |
| * in the FlashPlayer's MSAA tree, because Flash Player |
| * does not support objects with accessibility implementations |
| * having children with their own accessibility implementations.</p> |
| * |
| * <p>The PanelAccImpl is set as the <code>accessibilityImplementation</code> |
| * of the <code>titleDisplay</code> object because setting it on the Panel |
| * itself would not allow the Panel's children to be exposed in MSAA. |
| * Because of this an invisible rectangle is drawn in the |
| * <code>titleDisplay</code> making it the same size as the Panel as a whole |
| * so that the MSAA Location is the bounding rectangle of the entire Panel. |
| * Screen readers like JAWS rely on the MSAA Location to announce whether |
| * some component is in the grouping since the MSAA structure is flat.</p> |
| * |
| * <p><b>Role</b></p> |
| * |
| * <p>The MSAA Role of a Panel is ROLE_SYSTEM_GROUPING.</p> |
| * |
| * <p><b>Name</b></p> |
| * |
| * <p>The MSAA Name of a Panel is, by default, the title that it displays. |
| * To override this behavior, set the Panel's <code>accessibilityName</code> |
| * property.</p> |
| * |
| * <p>When the Name changes, |
| * a Panel dispatches the MSAA event EVENT_OBJECT_NAMECHANGE.</p> |
| * |
| * <p><b>Description</b></p> |
| * |
| * <p>The MSAA Description of a Panel is, by default, the empty string, |
| * but you can set the Panel's <code>accessibilityDescription</code> |
| * property.</p> |
| * |
| * <p><b>State</b></p> |
| * |
| * <p>The MSAA State of a Panel is always STATE_SYSTEM_NORMAL, |
| * indicating that no state flags are set.</p> |
| * |
| * <p>Since the state does not change, |
| * a Panel does not dispatch the MSAA event EVENT_OBJECT_STATECHANGE.</p> |
| * |
| * <p><b>Value</b></p> |
| * |
| * <p>The MSAA Value of a Panel is always the empty string.</p> |
| * |
| * <p><b>Location</b></p> |
| * |
| * <p>The MSAA Location of a Panel is its bounding rectangle.</p> |
| * |
| * <p><b>Default Action</b></p> |
| * |
| * <p>A Panel does not have an MSAA DefaultAction .</p> |
| * |
| * <p><b>Focus</b></p> |
| * |
| * <p>A Panel does not accept focus.</p> |
| * |
| * <p><b>Selection</b></p> |
| * |
| * <p>A Panel does not support selection in the MSAA sense.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public class PanelAccImpl extends AccImpl |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Enables accessibility in the Panel class. |
| * |
| * <p>This method is called by application startup code |
| * that is autogenerated by the MXML compiler. |
| * Afterwards, when instances of Panel are initialized, |
| * the <code>accessibilityImplementation</code> property |
| * of a special first child Sprite will be set to an instance |
| * of this class. |
| * If the PanelAccImpl were attached to the Panel itself |
| * the accessibility implementations of the Panel's children |
| * would be ignored.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public static function enableAccessibility():void |
| { |
| Panel.createAccessibilityImplementation = |
| createAccessibilityImplementation; |
| } |
| |
| /** |
| * @private |
| * Creates Panel's AccessibilityImplementation object. |
| * This method is called from Panel's initializeAccessibility() method. |
| */ |
| mx_internal static function createAccessibilityImplementation( |
| component:UIComponent):void |
| { |
| // The PanelAccImpl is attached |
| // not to the Panel but to a special child Sprite. |
| // If it were attached to the Panel itself, |
| // the AccessibilityImplementations of the Panel's |
| // children would be ignored. |
| var accImpl:PanelAccImpl = new PanelAccImpl(component); |
| accImpl.attach(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @param master The UIComponent instance that this AccImpl instance |
| * is making accessible. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public function PanelAccImpl(master:UIComponent) |
| { |
| super(master); |
| |
| role = AccConst.ROLE_SYSTEM_GROUPING; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * A Sprite which gets added to the Panel for the sole purpose |
| * of holding the PanelAccImpl. |
| * We have to make sure that the size of this Sprite is the same |
| * as the size of the Panel so that the MSAA Location is correct. |
| */ |
| mx_internal var accImplSprite:Sprite; |
| |
| /** |
| * @private |
| * If the titleDisplay keeps an acc impl, it shows up as an accessible |
| * object, in addition to the accImplSprite. |
| * To prevent this, we remove the acc impl from the titleDisplay |
| * and park it here. |
| */ |
| private var titleDisplayAccImpl:AccessibilityImplementation; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties: AccImpl |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // eventsToHandle |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Array of events that we should listen for from the master component. |
| */ |
| override protected function get eventsToHandle():Array |
| { |
| return super.eventsToHandle.concat([ ResizeEvent.RESIZE, |
| SkinPartEvent.PART_ADDED, |
| SkinPartEvent.PART_REMOVED ]); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: AccessibilityImplementation |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * IAccessible method for returning the state of the Panel. |
| * States are predefined for all the components in MSAA. Values are assigned to each state. |
| * Depending upon the Panel being Focusable, Focused and Moveable, a value is returned. |
| * |
| * @param childID:int |
| * |
| * @return State:uint |
| */ |
| override public function get_accState(childID:uint):uint |
| { |
| var accState:uint = getState(childID); |
| |
| return accState; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: AccImpl |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * method for returning the name of the Panel |
| * which is spoken out by the screen reader |
| * The Panel should return the Title as the name. |
| * |
| * @param childID:uint |
| * |
| * @return Name:String |
| */ |
| override protected function getName(childID:uint):String |
| { |
| return Panel(master).title; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * The AccessibilityImplementation is placed |
| * not on the Panel but on a special child Sprite. |
| * If it were placed on the Panel itself, |
| * the AccessibilityImplementations of the Panel's |
| * children would be ignored. |
| */ |
| mx_internal function attach():Sprite |
| { |
| var panel:Panel = Panel(master); |
| |
| // Create a Sprite. |
| accImplSprite = new Sprite(); |
| |
| // Add the Sprite as the first child of the component. |
| panel.$addChildAt(accImplSprite, 0); |
| |
| // Attach this acc impl to this Sprite. |
| accImplSprite.accessibilityImplementation = this; |
| |
| // Remove and save the titleDisplay's acc impl |
| // so that a screen reader doesn't read the title twice. |
| if (panel.titleDisplay) |
| { |
| titleDisplayAccImpl = |
| InteractiveObject(panel.titleDisplay).accessibilityImplementation; |
| InteractiveObject(panel.titleDisplay).accessibilityImplementation = null; |
| } |
| |
| if (panel.tabIndex > 0 && accImplSprite.tabIndex == -1) |
| accImplSprite.tabIndex = panel.tabIndex; |
| |
| return accImplSprite; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden event handlers: AccImpl |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @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 |
| { |
| super.eventHandler(event); |
| |
| var titleDisplay:InteractiveObject; |
| |
| switch (event.type) |
| { |
| case ResizeEvent.RESIZE: |
| { |
| // In the accImplSprite, draw an invisible unfilled rect |
| // around the bounds of the entire Panel. |
| // This is for accessibility; the accImplSprite of the Panel |
| // has an AccessibilityImplementation (see PanelAccImpl) |
| // which makes it act like a grouping (ROLE_SYSTEM_GROUPING) |
| // for the controls inside the panel. |
| // Drawing this rect makes the accLocation rect of the grouping |
| // enclose the controls inside the grouping, |
| // even though it is a sibling of them, not their parent. |
| // (This is because the Player doesn't support Sprites |
| // with AccessibilityImplementations inside other Sprites |
| // with AccessibilityImplementations; the accessible objects |
| // in a Flash SWF are a flat list, not a hierarchy.) |
| var panel:Panel = Panel(master); |
| var g:Graphics = accImplSprite.graphics; |
| g.clear(); |
| g.lineStyle(0, 0x000000, 0); |
| g.drawRect(0, 0, panel.width, panel.height); |
| break; |
| } |
| |
| case SkinPartEvent.PART_ADDED: |
| { |
| titleDisplay = Panel(master).titleDisplay as InteractiveObject; |
| if (SkinPartEvent(event).instance == titleDisplay) |
| { |
| titleDisplayAccImpl = titleDisplay.accessibilityImplementation; |
| titleDisplay.accessibilityImplementation = null; |
| } |
| break; |
| } |
| |
| case SkinPartEvent.PART_REMOVED: |
| { |
| titleDisplay = Panel(master).titleDisplay as InteractiveObject; |
| if (SkinPartEvent(event).instance == titleDisplay) |
| { |
| titleDisplay.accessibilityImplementation = titleDisplayAccImpl; |
| titleDisplayAccImpl = null; |
| } |
| break; |
| } |
| } |
| } |
| } |
| |
| } |