| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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.components.supportClasses |
| { |
| |
| import flash.display.DisplayObject; |
| |
| import mx.core.FlexVersion; |
| import mx.core.UIComponent; |
| import mx.core.mx_internal; |
| |
| import spark.components.Group; |
| import spark.core.DisplayObjectSharingMode; |
| import spark.core.IGraphicElement; |
| import spark.skins.IHighlightBitmapCaptureClient; |
| |
| use namespace mx_internal; |
| |
| /** |
| * The Skin class defines the base class for all skins used by skinnable components. |
| * The SkinnableComponent class defines the base class for skinnable components. |
| * |
| * <p>You typically write the skin classes in MXML, as the followiong example shows:</p> |
| * |
| * <pre> <?xml version="1.0"?> |
| * <Skin xmlns="http://ns.adobe.com/mxml/2009"> |
| * |
| * <Metadata> |
| * <!-- Specify the component that uses this skin class. --> |
| * [HostComponent("my.component.MyComponent")] |
| * </Metadata> |
| * |
| * <states> |
| * <!-- Specify the states controlled by this skin. --> |
| * </states> |
| * |
| * <!-- Define skin. --> |
| * |
| * </Skin></pre> |
| * |
| * @see mx.core.SkinnableComponent |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public class Skin extends Group implements IHighlightBitmapCaptureClient |
| { |
| include "../../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public function Skin() |
| { |
| super(); |
| } |
| |
| /** |
| * List of id's of items that should be excluded when rendering the focus ring. |
| * Only items of type DisplayObject or GraphicElement should be excluded. Items |
| * of other types will be ignored. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public function get focusSkinExclusions():Array |
| { |
| return null; |
| } |
| |
| private static var exclusionAlphaValues:Array; |
| |
| /** |
| * Called before a bitmap capture is made for this skin. The default implementation |
| * excludes items in the <code>focusSkinExclusions</code> array. |
| * |
| * @return <code>true</code> if the component must be redrawn. Otherwise, <code>false</code>. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function beginHighlightBitmapCapture():Boolean |
| { |
| var exclusions:Array = focusSkinExclusions; |
| if (!exclusions) |
| { |
| if (("hostComponent" in this) && this["hostComponent"] is SkinnableComponent) |
| exclusions = SkinnableComponent(this["hostComponent"]).suggestedFocusSkinExclusions; |
| } |
| var exclusionCount:Number = (exclusions == null) ? 0 : exclusions.length; |
| |
| /* we'll store off the previous alpha of the exclusions so we |
| can restore them when we're done |
| */ |
| exclusionAlphaValues = []; |
| var needRedraw:Boolean = false; |
| |
| for (var i:int = 0; i < exclusionCount; i++) |
| { |
| // skip if the part isn't there |
| if (!(exclusions[i] in this)) |
| continue; |
| |
| var ex:Object = this[exclusions[i]]; |
| /* we're going to go under the covers here to try and modify alpha with the least |
| amount of disruption to the component. For UIComponents, we go to Sprite's alpha property; |
| */ |
| if (ex is UIComponent) |
| { |
| exclusionAlphaValues[i] = (ex as UIComponent).$alpha; |
| (ex as UIComponent).$alpha = 0; |
| } |
| else if (ex is DisplayObject) |
| { |
| exclusionAlphaValues[i] = (ex as DisplayObject).alpha; |
| (ex as DisplayObject).alpha = 0; |
| } |
| else if (ex is IGraphicElement) |
| { |
| /* if we're lucky, the IGE has its own DisplayObject, and we can just trip its alpha. |
| If not, we're going to have to set it to 0, and force a redraw of the whole component */ |
| var ge:IGraphicElement = ex as IGraphicElement; |
| if (ge.displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT) |
| { |
| exclusionAlphaValues[i] = ge.displayObject.alpha; |
| ge.displayObject.alpha = 0; |
| } |
| else |
| { |
| exclusionAlphaValues[i] = ge.alpha; |
| ge.alpha = 0; |
| needRedraw = true; |
| } |
| } |
| } |
| |
| /* if we excluded an IGE without its own DO, we need to update the component before grabbing the bitmap */ |
| return needRedraw; |
| } |
| |
| /** |
| * Called after a bitmap capture is made for this skin. The default implementation |
| * restores the items in the <code>focusSkinExclusions</code> array. |
| * |
| * @return <code>true</code> if the component must be redrawn. Otherwise, <code>false</code>. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 2.5 |
| * @productversion Flex 4.5 |
| */ |
| public function endHighlightBitmapCapture():Boolean |
| { |
| var exclusions:Array = focusSkinExclusions; |
| if (!exclusions) |
| { |
| if ("hostComponent" in this && this["hostComponent"] is SkinnableComponent) |
| exclusions = SkinnableComponent(this["hostComponent"]).suggestedFocusSkinExclusions; |
| } |
| var exclusionCount:Number = (exclusions == null) ? 0 : exclusions.length; |
| var needRedraw:Boolean = false; |
| |
| for (var i:int=0; i < exclusionCount; i++) |
| { |
| // skip if the part isn't there |
| if (!(exclusions[i] in this)) |
| continue; |
| |
| var ex:Object = this[exclusions[i]]; |
| if (ex is UIComponent) |
| { |
| (ex as UIComponent).$alpha = exclusionAlphaValues[i]; |
| } |
| else if (ex is DisplayObject) |
| { |
| (ex as DisplayObject).alpha = exclusionAlphaValues[i]; |
| } |
| else if (ex is IGraphicElement) |
| { |
| var ge:IGraphicElement = ex as IGraphicElement; |
| if (ge.displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT) |
| { |
| ge.displayObject.alpha = exclusionAlphaValues[i]; |
| } |
| else |
| { |
| ge.alpha = exclusionAlphaValues[i]; |
| needRedraw = true; |
| } |
| } |
| } |
| |
| exclusionAlphaValues = null; |
| |
| return needRedraw; |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function initializeAccessibility():void |
| { |
| // Do nothing. Skins shouldn't support accessibility |
| } |
| |
| /** |
| * @private |
| * Make the component's explicitMinWidth property override its skin's. |
| * This is useful for cases where the skin's minWidth constrains |
| * the skin's measured size. In those cases the user could set |
| * explicit limits on the component itself thus relaxing the |
| * hard-coded limits in the skin. See SDK-24741. |
| */ |
| override public function get explicitMinWidth():Number |
| { |
| if (parent is SkinnableComponent) |
| { |
| var parentExplicitMinWidth:Number = SkinnableComponent(parent).explicitMinWidth; |
| if (!isNaN(parentExplicitMinWidth)) |
| return parentExplicitMinWidth; |
| } |
| return super.explicitMinWidth; |
| } |
| |
| /** |
| * @private |
| * Make the component's explicitMinWidth property override its skin's. |
| * This is useful for cases where the skin's minWidth constrains |
| * the skin's measured size. In those cases the user could set |
| * explicit limits on the component itself thus relaxing the |
| * hard-coded limits in the skin. See SDK-24741. |
| */ |
| override public function get explicitMinHeight():Number |
| { |
| if (parent is SkinnableComponent) |
| { |
| var parentExplicitMinHeight:Number = SkinnableComponent(parent).explicitMinHeight; |
| if (!isNaN(parentExplicitMinHeight)) |
| return parentExplicitMinHeight; |
| } |
| return super.explicitMinHeight; |
| } |
| |
| /** |
| * @private |
| * Make the component's explicitMinWidth property override its skin's. |
| * This is useful for cases where the skin's minWidth constrains |
| * the skin's measured size. In those cases the user could set |
| * explicit limits on the component itself thus relaxing the |
| * hard-coded limits in the skin. See SDK-24741. |
| */ |
| override public function get explicitMaxWidth():Number |
| { |
| if (parent is SkinnableComponent) |
| { |
| var parentExplicitMaxWidth:Number = SkinnableComponent(parent).explicitMaxWidth; |
| if (!isNaN(parentExplicitMaxWidth)) |
| return parentExplicitMaxWidth; |
| } |
| return super.explicitMaxWidth; |
| } |
| |
| /** |
| * @private |
| * Make the component's explicitMinWidth property override its skin's. |
| * This is useful for cases where the skin's minWidth constrains |
| * the skin's measured size. In those cases the user could set |
| * explicit limits on the component itself thus relaxing the |
| * hard-coded limits in the skin. See SDK-24741. |
| */ |
| override public function get explicitMaxHeight():Number |
| { |
| if (parent is SkinnableComponent) |
| { |
| var parentExplicitMaxHeight:Number = SkinnableComponent(parent).explicitMaxHeight; |
| if (!isNaN(parentExplicitMaxHeight)) |
| return parentExplicitMaxHeight; |
| } |
| return super.explicitMaxHeight; |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function canSkipMeasurement():Boolean |
| { |
| if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5) |
| { |
| return super.canSkipMeasurement(); |
| } |
| |
| // Explicit width/height on the skin should mean "the default size". |
| // As such, we should still measure so that we get correct measuredWidth, |
| // measuredHeight, measuredMinWidth, measuredMinHeight. |
| // Look at the SkinnableComponent's measure() to see how these are used. |
| return false; |
| } |
| } |
| |
| } |