Return-Path: X-Original-To: apmail-incubator-flex-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-flex-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 3E430DE76 for ; Mon, 6 Aug 2012 21:28:29 +0000 (UTC) Received: (qmail 65902 invoked by uid 500); 6 Aug 2012 21:28:29 -0000 Delivered-To: apmail-incubator-flex-commits-archive@incubator.apache.org Received: (qmail 65876 invoked by uid 500); 6 Aug 2012 21:28:29 -0000 Mailing-List: contact flex-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: flex-dev@incubator.apache.org Delivered-To: mailing list flex-commits@incubator.apache.org Received: (qmail 65869 invoked by uid 99); 6 Aug 2012 21:28:29 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 06 Aug 2012 21:28:29 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 06 Aug 2012 21:28:05 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 9364C2388C79; Mon, 6 Aug 2012 21:26:16 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1370028 [31/43] - in /incubator/flex/whiteboard/cframpton/adobe.next: ./ frameworks/ frameworks/projects/advancedgrids/src/mx/collections/ frameworks/projects/advancedgrids/src/mx/controls/ frameworks/projects/airframework/src/mx/managers/... Date: Mon, 06 Aug 2012 21:26:02 -0000 To: flex-commits@incubator.apache.org From: cframpton@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120806212616.9364C2388C79@eris.apache.org> Modified: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichEditableText.as URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichEditableText.as?rev=1370028&r1=1370027&r2=1370028&view=diff ============================================================================== --- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichEditableText.as (original) +++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichEditableText.as Mon Aug 6 21:25:54 2012 @@ -624,6 +624,11 @@ package spark.components // This TextContainerManager instance persists for the lifetime // of the component. _textContainerManager = createTextContainerManager(); + + // Turn on TextField-like behavior which preserves the selection when text is set. + // If the new text is shorter than the exisiting text, the selection may change. + if (FlexVersion.compatibilityVersion > FlexVersion.VERSION_4_5) + _textContainerManager.preserveSelectionOnSetText = true; // Add event listeners on this component. addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler); @@ -748,11 +753,6 @@ package spark.components /** * @private */ - mx_internal var preserveSelectionOnSetText:Boolean = false; - - /** - * @private - */ mx_internal var passwordChar:String = "*"; /** @@ -2536,9 +2536,6 @@ package spark.components if (textChanged) { - if (FlexVersion.compatibilityVersion > FlexVersion.VERSION_4_5) - preserveSelectionOnSetText = true; - // If the text has linebreaks (CR, LF, or CF+LF) // create a multi-paragraph TextFlow from it // and use the TextFlowTextLineFactory to render it. @@ -2594,8 +2591,6 @@ package spark.components // not the underlying text. if (displayAsPasswordChanged) { - preserveSelectionOnSetText = true; - // If there is any text, convert it to the passwordChar. if (displayAsPassword) { @@ -2624,25 +2619,6 @@ package spark.components displayAsPasswordChanged = false; } - if (preserveSelectionOnSetText) - { - preserveSelectionOnSetText = false; - - if (oldAnchorPosition != -1) - { - // This will return null if editingMode = readOnly which is true when either - // editable is false and/or enabled is false. - var selManager:ISelectionManager = _textContainerManager.beginInteraction(); - - // The visible selection will be refreshed during the update. - if (selManager) - { - selManager.selectRange(oldAnchorPosition, oldActivePosition); - _textContainerManager.endInteraction(); - } - } - } - if (clipAndEnableScrollingChanged) { // The TLF code seems to check for !off. @@ -2679,6 +2655,14 @@ package spark.components verticalScrollPositionChanged = false; } + + // Updating the text programatically removes all child TextLine elements + // before rebuilding the TextFlow, effectively removing all visual elements + // from the display list. This causes any accessibilityImplementation that + // was assigned to the component to be removed. The following line restores + // the accessibilityImplementation if it no longer exists. + if (!accessibilityImplementation) + initializeAccessibility(); } /** @@ -4634,9 +4618,6 @@ package spark.components private function textContainerManager_selectionChangeHandler( event:SelectionEvent):void { - if (preserveSelectionOnSetText) - return; - var oldAnchor:int = _selectionAnchorPosition; var oldActive:int = _selectionActivePosition; Modified: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichText.as URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichText.as?rev=1370028&r1=1370027&r2=1370028&view=diff ============================================================================== --- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichText.as (original) +++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/RichText.as Mon Aug 6 21:25:54 2012 @@ -213,7 +213,6 @@ include "../styles/metadata/AdvancedNonI *
  *  <s:RichText
  *    Properties
- *    fontContext="IFlexModuleFactory"
  *    luminosityClip="false"
  *    luminosityInvert="false"
  *    maskType="MaskType.CLIP"

Modified: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ScrollSnappingMode.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ScrollSnappingMode.as?rev=1370028&r1=1370027&r2=1370028&view=diff
==============================================================================
--- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ScrollSnappingMode.as (original)
+++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ScrollSnappingMode.as Mon Aug  6 21:25:54 2012
@@ -30,6 +30,7 @@ package spark.components
      *  @langversion 3.0
      *  @playerversion AIR 3
      *  @productversion Flex 4.6
+     *
      */
     public final class ScrollSnappingMode
     {

Modified: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/Scroller.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/Scroller.as?rev=1370028&r1=1370027&r2=1370028&view=diff
==============================================================================
--- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/Scroller.as (original)
+++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/Scroller.as Mon Aug  6 21:25:54 2012
@@ -412,6 +412,8 @@ include "../styles/metadata/SelectionFor
  *   Properties
  *    measuredSizeIncludesScrollBars="true"
  *    minViewportInset="0"
+ *    pageScrollingEnabled="false"
+ *    scrollSnappingMode="none"
  *    viewport="null"
  *  
  *    Styles

Modified: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/SkinnableContainer.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/SkinnableContainer.as?rev=1370028&r1=1370027&r2=1370028&view=diff
==============================================================================
--- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/SkinnableContainer.as (original)
+++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/SkinnableContainer.as Mon Aug  6 21:25:54 2012
@@ -19,10 +19,14 @@
 
 package spark.components
 {
+import flash.utils.Dictionary;
+
 import mx.core.ContainerCreationPolicy;
+import mx.core.FlexVersion;
 import mx.core.IDeferredContentOwner;
 import mx.core.IDeferredInstance;
 import mx.core.IFlexModuleFactory;
+import mx.core.ITransientDeferredInstance;
 import mx.core.IVisualElement;
 import mx.core.IVisualElementContainer;
 import mx.core.mx_internal;
@@ -30,6 +34,7 @@ import mx.events.FlexEvent;
 import mx.utils.BitFlagUtil;
 
 import spark.components.supportClasses.SkinnableContainerBase;
+import spark.core.ContainerDestructionPolicy;
 import spark.events.ElementExistenceEvent;
 import spark.layouts.supportClasses.LayoutBase;
 
@@ -439,7 +444,8 @@ public class SkinnableContainer extends 
         
         // Register the _creationPolicy style as inheriting. See the creationPolicy
         // getter for details on usage of this style.
-        styleManager.registerInheritingStyle("_creationPolicy");
+        if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_5_0)
+            styleManager.registerInheritingStyle("_creationPolicy");
     }
     
     //--------------------------------------------------------------------------
@@ -480,6 +486,12 @@ public class SkinnableContainer extends 
         }
     }
     
+    //--------------------------------------------------------------------------
+    //
+    //  IDeferredContentOwner Properties 
+    //
+    //--------------------------------------------------------------------------
+    
     //----------------------------------
     //  creationPolicy
     //----------------------------------
@@ -488,6 +500,7 @@ public class SkinnableContainer extends 
     // When set, the value of the backing store _creationPolicy
     // style is "auto" so descendants inherit the correct value.
     private var creationPolicyNone:Boolean = false;
+    private var _creationPolicy:String = ContainerCreationPolicy.AUTO;
     
     [Inspectable(enumeration="auto,all,none", defaultValue="auto")]
         
@@ -509,12 +522,15 @@ public class SkinnableContainer extends 
         // don't have this property (ie Group).
         // This style is an implementation detail and should be considered
         // private. Do not set it from CSS.
-        var result:String = getStyle("_creationPolicy");
+        var lessThanFlexVersion5:Boolean = FlexVersion.compatibilityVersion < FlexVersion.VERSION_5_0; 
+        var result:String = lessThanFlexVersion5 ? 
+                                getStyle("_creationPolicy") : 
+                                _creationPolicy;
         
         if (result == null)
             result = ContainerCreationPolicy.AUTO;
         
-        if (creationPolicyNone)
+        if (creationPolicyNone && lessThanFlexVersion5)
             result = ContainerCreationPolicy.NONE;
         
         return result;
@@ -525,22 +541,87 @@ public class SkinnableContainer extends 
      */
     public function set creationPolicy(value:String):void
     {
-        if (value == ContainerCreationPolicy.NONE)
+        if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_5_0)
         {
-            // creationPolicy of none is not inherited by descendants.
-            // In this case, set the style to "auto" and set a local
-            // flag for subsequent access to the creationPolicy property.
-            creationPolicyNone = true;
-            value = ContainerCreationPolicy.AUTO;
+            if (value == ContainerCreationPolicy.NONE)
+            {
+                // creationPolicy of none is not inherited by descendants.
+                // In this case, set the style to "auto" and set a local
+                // flag for subsequent access to the creationPolicy property.
+                creationPolicyNone = true;
+                value = ContainerCreationPolicy.AUTO;
+            }
+            else
+            {
+                creationPolicyNone = false;
+            }
+            
+            setStyle("_creationPolicy", value);
+            //Also updates the elementCreationPolicy
+            elementCreationPolicy = value;
         }
         else
         {
-            creationPolicyNone = false;
+            _creationPolicy = value;
         }
         
-        setStyle("_creationPolicy", value);
     }
 
+    /**
+     *  @private
+     */
+    private var _elementCreationPolicy:*;
+    
+    [Inspectable(enumeration="auto,all,none", defaultValue="auto")]
+    
+    /**
+     *  @inheritDoc
+     */
+    public function get elementCreationPolicy():String
+    {
+        // If elementCreationPolicy has been set then use it. Otherwise
+        // fallback to using the deprecated creationPolicy.
+        if (_elementCreationPolicy !== undefined)
+            return _elementCreationPolicy;
+        else
+            return _creationPolicy;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set elementCreationPolicy(value:String):void
+    {
+        _elementCreationPolicy = value;
+    }
+    
+    //----------------------------------
+    //  elementDestructionPolicy
+    //----------------------------------
+    
+    /**
+     *  @private
+     */
+    private var _elementDestructionPolicy:String = ContainerDestructionPolicy.AUTO;
+    
+    [Inspectable(enumeration="always,auto,never", defaultValue="auto")]
+    
+    /**
+     *  @inheritDoc
+     */
+    public function get elementDestructionPolicy():String
+    {
+        return _elementDestructionPolicy;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set elementDestructionPolicy(value:String):void
+    {
+        _elementDestructionPolicy = value;
+    }
+    
     //--------------------------------------------------------------------------
     //
     //  Properties proxied to contentGroup
@@ -907,6 +988,19 @@ public class SkinnableContainer extends 
 
         if (instance == contentGroup)
         {
+            if (_placeHolderGroup)
+            {
+                _placeHolderGroup.removeEventListener(
+                    ElementExistenceEvent.ELEMENT_ADD, contentGroup_elementAddedHandler);
+                _placeHolderGroup.removeEventListener(
+                    ElementExistenceEvent.ELEMENT_REMOVE, contentGroup_elementRemovedHandler);                
+            }
+
+            contentGroup.addEventListener(
+                ElementExistenceEvent.ELEMENT_ADD, contentGroup_elementAddedHandler);
+            contentGroup.addEventListener(
+                ElementExistenceEvent.ELEMENT_REMOVE, contentGroup_elementRemovedHandler);
+            
             if (_contentModified)
             {
                 if (_placeHolderGroup != null)
@@ -921,18 +1015,12 @@ public class SkinnableContainer extends 
                     // copy the mxmlContent from the placeHolderGroup, but we must also 
                     // call removeElement() on those children.
                     
-                    // remove listener prior to removal of elements
-                    // or else we'll accidentally null out the owner field
-                    _placeHolderGroup.removeEventListener(
-                        ElementExistenceEvent.ELEMENT_REMOVE, contentGroup_elementRemovedHandler);
-                    
                     for (var i:int = _placeHolderGroup.numElements; i > 0; i--)
                     {
                         _placeHolderGroup.removeElementAt(0);  
                     }
                     
                     contentGroup.mxmlContent = sourceContent ? sourceContent.slice() : null;
-
                 }
                 else if (_mxmlContent != null)
                 {
@@ -941,6 +1029,8 @@ public class SkinnableContainer extends 
                 }
             }
             
+            _placeHolderGroup = null;
+            
             // copy proxied values from contentGroupProperties (if set) to contentGroup
             
             var newContentGroupProperties:uint = 0;
@@ -959,22 +1049,7 @@ public class SkinnableContainer extends 
                                                                LAYOUT_PROPERTY_FLAG, true);
             }
             
-            contentGroupProperties = newContentGroupProperties;
-            
-            contentGroup.addEventListener(
-                ElementExistenceEvent.ELEMENT_ADD, contentGroup_elementAddedHandler);
-            contentGroup.addEventListener(
-                ElementExistenceEvent.ELEMENT_REMOVE, contentGroup_elementRemovedHandler);
-            
-            if (_placeHolderGroup)
-            {
-                _placeHolderGroup.removeEventListener(
-                    ElementExistenceEvent.ELEMENT_ADD, contentGroup_elementAddedHandler);
-                _placeHolderGroup.removeEventListener(
-                    ElementExistenceEvent.ELEMENT_REMOVE, contentGroup_elementRemovedHandler);
-                
-                _placeHolderGroup = null;
-            }
+            contentGroupProperties = newContentGroupProperties;            
         }
     }
 
@@ -1035,6 +1110,23 @@ public class SkinnableContainer extends 
     //--------------------------------------------------------------------------
 
     /**
+     *  @private 
+     *  Number of items in the cache. Verify that none of the items where
+     *  collected before reusing the cache.
+     */     
+    private var elementCacheCount:int;
+    
+    /**
+     *  @private
+     *  A weak reference dictionary to store children that
+     *  are not being displayed. The garbage collector can
+     *  collect the memory if it needs it. Otherwise the
+     *  children can be re-added to the display list without
+     *  the need to  recreated them.
+     */
+    private var elementCacheDictionary:Dictionary;
+    
+    /**
      *  Create the content for this component. 
      *  When the creationPolicy property is auto or
      *  all, this function is called automatically by the Flex framework.
@@ -1048,6 +1140,55 @@ public class SkinnableContainer extends 
      */
     public function createDeferredContent():void
     {
+        //trace("createDeferredContent");
+        
+        // Restore the content from the cache if possible.
+        if (elementCacheCount)
+        {
+            //trace("createDeferredContent: elementCacheCount = " + elementCacheCount);
+            
+            // Compare the count to the actually number of elements
+            // in the dictionary. If the number of elements are not
+            // the same then destory the cache and create the elements
+            // from scratch.
+            var i:int = 0;
+            var elementVector:Vector. = new Vector.(elementCacheCount, true);
+            for (var o:Object in elementCacheDictionary)
+            {
+                if (i < elementCacheCount)
+                    elementVector[elementCacheDictionary[o]] = o as IVisualElement;
+                
+                i++;
+            }
+            
+            //trace("createDeferredContent: i == elementCacheCount = " + (i == elementCacheCount));
+            if (i == elementCacheCount)
+            {
+                //trace("createDeferredContent: re-add elements from cache.");
+                
+                var n:int = elementCacheCount;
+                mxmlContentCreated = true; // keep the code from recursing back into here.
+                _deferredContentCreated = true; 
+                
+                for (i = 0; i < n; i++)
+                {
+                    addElement(elementVector[i]);                    
+                }
+
+                dispatchEvent(new FlexEvent(FlexEvent.CONTENT_CREATION_COMPLETE));
+            }
+            else
+            {
+                // The cache is missing some pieces to re-create from scratch.
+                //trace("createDeferredContent: could not re-use cache.");
+                mxmlContentCreated = false;
+            }
+
+            elementCacheCount = 0;
+            elementCacheDictionary = null;
+            //trace("removeDeferredContent:   elementCacheDictionary set to null");
+        }
+        
         if (!mxmlContentCreated)
         {
             mxmlContentCreated = true;
@@ -1078,11 +1219,57 @@ public class SkinnableContainer extends 
     }
 
     /**
+     *  Removes the content for this component. The removed content can be 
+     *  cached to improve the performance of re-creating the content. 
+     *
+     *  @param cache If true, then save a reference to the removed content.
+     *  The content is weak referenced and the memory may be garbage collected if
+     *  needed.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 11
+     *  @playerversion AIR 2.7
+     *  @productversion Flex 5
+     */
+    public function removeDeferredContent(cache:Boolean = false):void
+    {
+        //trace("removeDeferredContent: cache= " + cache);
+        
+        if (cache)
+        {
+            //trace("removeDeferredContent:   created elementCacheDictionary");
+            elementCacheDictionary = new Dictionary(true);
+            elementCacheCount = numElements;
+            
+            var n:int = elementCacheCount;
+            
+            for (var i:int = 0; i < n; i++)
+            {
+                // put the element in a weak reference dictionary. If it
+                // is still there when we want to add the child back then
+                // great. Otherwise we will need to instantiate the child
+                // again.
+                var element:IVisualElement = getElementAt(i);
+                elementCacheDictionary[element] = i;
+            }
+        }
+
+        removeAllElements();    
+        
+        // TODO (dloverin): Write comment.
+        if (_mxmlContentFactory is ITransientDeferredInstance)
+            ITransientDeferredInstance(_mxmlContentFactory).reset();
+        mxmlContentCreated = false;
+        _deferredContentCreated = false;
+        
+    }
+    
+    /**
      *  @private
      */
     private function createContentIfNeeded():void
     {
-        if (!mxmlContentCreated && creationPolicy != ContainerCreationPolicy.NONE)
+        if (!mxmlContentCreated && elementCreationPolicy != ContainerCreationPolicy.NONE)
             createDeferredContent();
     }
     

Added: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ToolTip.as
URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ToolTip.as?rev=1370028&view=auto
==============================================================================
--- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ToolTip.as (added)
+++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ToolTip.as Mon Aug  6 21:25:54 2012
@@ -0,0 +1,532 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+
+import flash.display.DisplayObject;
+import flash.display.DisplayObjectContainer;
+import flash.events.Event;
+import flash.geom.ColorTransform;
+import flash.geom.Point;
+
+import mx.core.LayoutDirection;
+import mx.core.mx_internal;
+import mx.effects.Effect;
+import mx.events.EffectEvent;
+import mx.managers.IToolTipManagerClient;
+import mx.styles.StyleProtoChain;
+import mx.utils.PopUpUtil;
+
+import spark.core.IDisplayText;
+import spark.core.IToolTip;
+
+use namespace mx_internal;
+
+/**
+ *  The ToolTip component lets you provide helpful information 
+ *  to your users. 
+ *  When a user moves the mouse cursor over a graphical 
+ *  component, the ToolTip component pops up and displays 
+ *  information about the component. 
+ *  You can use ToolTips to guide 
+ *  users as they work with your application.
+ *
+ *  

The ToolTip component renders a UIComponent's toolTipData + * property in its skin. + * The default skin is ToolTipSkin. + * You can provide a custom skin by changing a UIComponent's toolTipSkin + * style.

+ * + *

The ToolTip component positions itself automatically relative to + * the mouse cursor.

+ * + *

You can customize ToolTip's positioning logic entirely by + * creating a subclass of ToolTip and overriding the + * positionPopUp() method. + * For reference, note that the positionPopUp() method originates + * in ToolTip's base class, SkinnablePopUpContainer.

+ * + *

To customize a ToolTip's open and close transitions, you can + * define state transitions between its open and close states its skin.

+ * + *

By default, the ToolTipManager hides tool tips when the + * mouse cursor leaves the target component or a specified amount of time + * elapses, known as the hide delay. + * If you would the user to interact with the tool tip, such as click a button + * inside it, set its mouseEnabled and mouseChildren properties to true. + * This will keep the tool tip open while the mouse is over it, even if the + * mouse is no longer over the target component.

+ * + *

You should not nest tool tips in tool tips because it is not + * supported. Thus, any components in your tool tip skin should not define + * a toolTip or toolTipData property.

+ * + * @see spark.components.ToolTipPosition + * @see spark.skins.spark.ToolTipSkin + * @see mx.managers.ToolTipManager + * @see spark.components.SkinnablePopUpContainer + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ +public class ToolTip extends SkinnablePopUpContainer implements IToolTip +{ + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * Constructor. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function ToolTip() + { + super(); + + mouseEnabled = false; + mouseChildren = false; + } + + //-------------------------------------------------------------------------- + // + // Variables + // + //-------------------------------------------------------------------------- + + /** + * @private + */ + private var target:IToolTipManagerClient; + + //-------------------------------------------------------------------------- + // + // Skin parts + // + //-------------------------------------------------------------------------- + + //-------------------------- + // labelDisplay + //-------------------------- + + [SkinPart(required="false")] + + /** + * A skin part that defines the tool tip's label. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public var labelDisplay:IDisplayText; + + //-------------------------- + // closedToNormalEffect + //-------------------------- + + [SkinPart(required="false")] + + /** + * FIXME: PARB these SkinParts. + * The effect for the transition between the named states. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public var closedToNormalEffect:Effect; + + //------------------------------------- + // disabledAndClosedToDisabledEffect + //------------------------------------- + + [SkinPart(required="false")] + + /** + * The effect for the transition between the named states. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public var disabledAndClosedToDisabledEffect:Effect; + + //------------------------------------- + // disabledToDisabledAndClosedEffect + //------------------------------------- + + [SkinPart(required="false")] + + /** + * The effect for the transition between the named states. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public var disabledToDisabledAndClosedEffect:Effect; + + //-------------------------- + // normalToClosedEffect + //-------------------------- + + [SkinPart(required="false")] + + /** + * The effect for the transition between the named states. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public var normalToClosedEffect:Effect; + + //---------------------------------------------------------------------- + // + // Properties + // + //---------------------------------------------------------------------- + + //---------------------------------- + // data + //---------------------------------- + + /** + * @private + * Storage for the tool tip data that the tool tip skin will render. + */ + private var _data:Object; + + [Bindable] + + /** + * The data that the tool tip will render in its skin. Data can be a + * String or any arbitrary object. ToolTip will display the + * value returned by the object's toString() method in its + * labelDisplay skin part. You should override this method + * + *

If you decide to use a custom skin without a labelDisplay skin + * part, it is still recommended that you provide a reasonable + * toString() implementation in the data object for accessibility + * reasons.

+ * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public function get data():Object + { + return _data; + } + + /** + * @private + */ + public function set data(value:Object):void + { + _data = value; + + if (labelDisplay) + labelDisplay.text = value.toString(); + } + + //---------------------------------- + // Opening and closing + //---------------------------------- + + /** + * ToolTipManager calls this method to show the tool tip. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public function showToolTip(target:IToolTipManagerClient):void + { + this.target = target; + + open(DisplayObjectContainer(target)); + + if (target.hasEventListener("sparkToolTipShow")) + target.dispatchEvent(new Event("sparkToolTipShow")); + } + + /** + * ToolTipManager calls this method to hide the tool tip. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + public function hideToolTip():void + { + close(); + + if (target.hasEventListener("sparkToolTipHide")) + target.dispatchEvent(new Event("sparkToolTipHide")); + } + + //-------------------------------------------------------------------------- + // + // Overridden methods + // + //-------------------------------------------------------------------------- + + /** + * @private + * Force ToolTip inheritance chain to start at the style root. + */ + override mx_internal function initProtoChain():void + { + StyleProtoChain.initProtoChain(this, false); + } + + /** + * @private + */ + override protected function partAdded(partName:String, instance:Object):void + { + super.partAdded(partName, instance); + + if (instance == labelDisplay && data) + labelDisplay.text = data.toString(); + else if (isOpeningEffect(instance)) + listenToOpeningEffect(Effect(instance)); + else if (isClosingEffect(instance)) + listenToClosingEffect(Effect(instance)); + } + + /** + * @private + */ + override protected function partRemoved(partName:String, instance:Object):void + { + if (isOpeningEffect(instance)) + stopListeningToOpeningEffect(Effect(instance)); + else if (isClosingEffect(instance)) + stopListeningToClosingEffect(Effect(instance)); + } + + /** + * Automatically positions the tool tip above or below the mouse cursor, + * sliding the tool tip into view horizontally if it hangs off the screen. + * + *

This method overrides SkinnablePopUpContainer's implementation.

+ * + *

Subclasses can override this method to define their own positioning + * logic.

+ * + * @see spark.components.SkinnablePopUpContainer + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3 + * @productversion Flex 5.0 + */ + override public function updatePopUpPosition():void + { + var toolTipPosition:Point = new Point(); + + // Position the tool tip vertically, either above or below the + // cursor, depending on how it fits on the screen. + const cursorWidth:Number = 12; + const cursorHeight:Number = 18; + var cursorPosition:Point = getCursorPosition(); + + // If this tool has mouse enabled, place the tool + // tip right at the mouse cursor so that the user can easily enter + // the tool tip area with the mouse from the target component, without + // possibly traversing a different component with a different tool tip. + var toolTipBelowCursorY:Number = mouseEnabled ? + cursorPosition.y : cursorPosition.y + cursorHeight; + var toolTipAboveCursorY:Number = cursorPosition.y - height; + + var fitsBelowCursor:Boolean = + toolTipBelowCursorY + height < screen.height + var fitsAboveCursor:Boolean = + toolTipAboveCursorY > 0; + var fitsNowhere:Boolean = !fitsBelowCursor && !fitsAboveCursor; + + var shouldPositionBelowCursor:Boolean = + fitsBelowCursor || fitsNowhere; + + toolTipPosition.y = shouldPositionBelowCursor ? + toolTipBelowCursorY : toolTipAboveCursorY; + + // Position the tool tip horizontally. + // For LTR layout, put the left edge of the tool tip against the + // left edge of the cursor. + // For RTL layout, put the right edge of the tool tip against the + // right edge of the cursor. + // Note that the tool tip is always positioned in non-mirrored + // screen coordinates. + var isLTR:Boolean = layoutDirection == LayoutDirection.LTR; + toolTipPosition.x = isLTR ? + cursorPosition.x : cursorPosition.x + cursorWidth - width; + + // Slide the tool tip into view horizontally if it's hanging off the + // right or left edges of the screen. + toolTipPosition.x = clamp(toolTipPosition.x, 0, screen.right - width); + + // Submit the tool tip position. + PopUpUtil.applyPopUpTransform(owner, new ColorTransform(), systemManager, this, toolTipPosition); + } + + //-------------------------------------------------------------------------- + // + // Methods + // + //-------------------------------------------------------------------------- + + /** + * @private + * Clamps a value between minimum and maximum values. + */ + private function clamp(value:Number, min:Number, max:Number):Number + { + return Math.max(min, Math.min(value, max)); + } + + /** + * @private + * Returns the mouse cursor position in global coordinates. + */ + private function getCursorPosition():Point + { + var systemManagerAsDisplayObject:DisplayObject = DisplayObject(systemManager); + return new Point( + systemManagerAsDisplayObject.mouseX, + systemManagerAsDisplayObject.mouseY + ); + } + + /** + * @private + */ + private function isOpeningEffect(instance:Object):Boolean + { + return instance == closedToNormalEffect + || instance == disabledAndClosedToDisabledEffect; + } + + /** + * @private + */ + private function isClosingEffect(instance:Object):Boolean + { + return instance == disabledToDisabledAndClosedEffect + || instance == normalToClosedEffect; + } + + /** + * @private + */ + private function listenToOpeningEffect(effect:Effect):void + { + effect.addEventListener(EffectEvent.EFFECT_END, openingEffect_effectEndListener); + } + + /** + * @private + */ + private function listenToClosingEffect(effect:Effect):void + { + effect.addEventListener(EffectEvent.EFFECT_END, closingEffect_effectEndListener); + } + + /** + * @private + */ + private function stopListeningToOpeningEffect(effect:Effect):void + { + effect.removeEventListener(EffectEvent.EFFECT_END, openingEffect_effectEndListener); + } + + /** + * @private + */ + private function stopListeningToClosingEffect(effect:Effect):void + { + effect.removeEventListener(EffectEvent.EFFECT_END, closingEffect_effectEndListener); + } + + //-------------------------------------------------------------------------- + // + // Event Handlers + // + //-------------------------------------------------------------------------- + + /** + * @private + * This method dispatches an internal event when the tool tip is done + * rendering its opening animation. + */ + private function openingEffect_effectEndListener(event:EffectEvent):void + { + addEventListener(Event.ENTER_FRAME, openingEffect_enterFrameListener); + } + + /** + * @private + */ + private function openingEffect_enterFrameListener(event:Event):void + { + removeEventListener(Event.ENTER_FRAME, openingEffect_enterFrameListener); + + if (target.hasEventListener("sparkToolTipShown")) + target.dispatchEvent(new Event("sparkToolTipShown")); + } + + /** + * @private + * This method dispatches an internal event when the tool tip is done + * rendering its closing animation. + */ + private function closingEffect_effectEndListener(event:EffectEvent):void + { + addEventListener(Event.ENTER_FRAME, closingEffect_enterFrameListener); + } + + /** + * @private + */ + private function closingEffect_enterFrameListener(event:Event):void + { + removeEventListener(Event.ENTER_FRAME, closingEffect_enterFrameListener); + + if (target.hasEventListener("sparkToolTipHidden")) + target.dispatchEvent(new Event("sparkToolTipHidden")); + } +} +} Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ToolTip.as ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ToolTip.as ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/VideoPlayer.as URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/VideoPlayer.as?rev=1370028&r1=1370027&r2=1370028&view=diff ============================================================================== --- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/VideoPlayer.as (original) +++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/VideoPlayer.as Mon Aug 6 21:25:54 2012 @@ -1854,7 +1854,7 @@ public class VideoPlayer extends Skinnab } else if (instance == muteButton) { - playButton.removeEventListener(FlexEvent.MUTED_CHANGE, muteButton_mutedChangeHandler); + muteButton.removeEventListener(FlexEvent.MUTED_CHANGE, muteButton_mutedChangeHandler); } else if (instance == volumeBar) { Added: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.as URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.as?rev=1370028&view=auto ============================================================================== --- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.as (added) +++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.as Mon Aug 6 21:25:54 2012 @@ -0,0 +1,1191 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + +import flash.display.DisplayObject; +import flash.events.Event; +import flash.utils.Dictionary; + +import mx.automation.IAutomationObject; +import mx.core.IDeferredContentOwner; +import mx.core.IFactory; +import mx.core.IInvalidating; +import mx.core.INavigatorContent; +import mx.core.ISelectableList; +import mx.core.IUIComponent; +import mx.core.IVisualElement; +import mx.core.IVisualElementContainer; +import mx.core.UIComponent; +import mx.core.mx_internal; +import mx.effects.Effect; +import mx.effects.EffectManager; +import mx.effects.IEffect; +import mx.events.CollectionEvent; +import mx.events.CollectionEventKind; +import mx.events.EffectEvent; +import mx.events.FlexEvent; +import mx.events.PropertyChangeEvent; +import mx.geom.RoundedRectangle; +import mx.states.Transition; + +import spark.components.supportClasses.ViewStackLayout; +import spark.core.ContainerDestructionPolicy; +import spark.events.ElementExistenceEvent; +import spark.events.IndexChangeEvent; +import spark.layouts.supportClasses.LayoutBase; + + +use namespace mx_internal; + +//-------------------------------------- +// Events +//-------------------------------------- + +/** + * Dispatched when the selected child container changes. + * + * @eventType spark.events.IndexChangeEvent.CHANGE + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ +[Event(name="change", type="spark.events.IndexChangeEvent")] + +//-------------------------------------- +// Other metadata +//-------------------------------------- + +[IconFile("ViewStack.png")] + +[Exclude(name="layout", kind="property")] + +/** + * A Spark ViewStack component consists of a collection of child + * components stacked on top of each other, where only one child is visible + * at a time. + * When a different child component is selected, it seems to replace + * the old one because it appears in the same location. + * However, the old child component still exists; it is just invisible. + * + *

Notes: + * The direct children of ViewStack must implement the IVisualElement + * interface. The NavigatorContent component is the recommended + * child component to use with ViewStack.

+ + *

A child component may use deferred instantiation if it implements + * IDeferredContentOwner. When a child's creationPolicy is "auto" + * or "none" is does not create its children. Later, when a child component becomes + * visible, ViewStack will call the child's createDeferredContent + * method to create the child's children.

+ * + *

A ViewStack container does not provide a user interface + * for selecting which child container is currently visible. + * Typically, you set its selectedIndex or + * selectedElement property in ActionScript in response to + * some user action. + * Alternately, you can associate a Spark TabBar or ButtonBar with a ViewStack + * component to provide a navigation interface. + * To do so, specify the ViewStack component as the value of the + * dataProvider property of the TabBar or + * ButtonBar component.

+ * + * To play an effect that provides a transition from one selected component + * to the next override the showSelectedElement method. The + * default implementation of showSelectedElement is to hide the + * previously selected element and show the newly selected element. + * + *

The ViewStack container has the following default sizing characteristics:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
CharacteristicDescription
Default sizeThe width and height of the initial selected child.
Container resizing rulesBy default, ViewStack components are sized only once to fit the size of the + * first selected child. They do not resize when you navigate to another child. + * To force ViewStack containers to resize when you navigate + * to a different child, set the resizeToContent property to true.
Child sizing rulesChildren are sized to their default size. If the child is larger than the ViewStack + * container, it is clipped. If the child is smaller than the ViewStack container, + * it is aligned to the upper-left corner of the ViewStack container.
+ * + * @mxml + * + *

The <s:ViewStack> tag inherits the + * tag attributes of its superclass and adds the following tag attributes:

+ * + *
+ *  <s:ViewStack
+ *    Properties
+ *    resizeToContent="false|true"
+ *    lastSelectedIndex="-1"
+ *    selectedIndex="0"
+ *    
+ *    Events
+ *    change="No default"
+ *    >
+ *      ...
+ *      child tags
+ *      ...
+ *  </s:ViewStack>
+ *  
+ * + * @see spark.components.TabBar + * @see spark.components.ButtonBar + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ +public class ViewStack extends SkinnableContainer implements ISelectableList +{ + include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * Constructor. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public function ViewStack() + { + super(); + + super.layout = new ViewStackLayout(); + + addEventListener(ElementExistenceEvent.ELEMENT_ADD, elementAddHandler); + addEventListener(ElementExistenceEvent.ELEMENT_REMOVE, elementRemoveHandler); + } + + //-------------------------------------------------------------------------- + // + // Variables + // + //-------------------------------------------------------------------------- + + /** + * @private + * If we're in the middle of adding a child + */ + private var addingChildren:Boolean = false; + + /** + * @private + * Remember which child has an overlay mask, if any. + * Used for the dissolve effect. + */ + private var effectOverlayChild:UIComponent; + + /** + * @private + * Keep track of the overlay's targetArea + * Used for the dissolve effect. + */ + private var effectOverlayTargetArea:RoundedRectangle; + + /** + * @private + * Whether a change event has to be dispatched in commitProperties() + */ + private var dispatchChangeEventPending:Boolean = false; + + /** + * @private + * Store the last selectedIndex + */ + private var lastSelectedIndex:int = -1; + + /** + * @private + */ + private var needToInstantiateSelectedChild:Boolean = false; + + /** + * @private + * True if resizeToConent was changed. This means we need to update the + * layout with the new value. + */ + private var resizeToContentChanged:Boolean = false; + + //-------------------------------------------------------------------------- + // + // Overridden properties + // + //-------------------------------------------------------------------------- + + //---------------------------------- + // autoLayout + //---------------------------------- + + /** + * The autoLayout property have been overriden to always + * return true. It cannot be set to false. + */ + override public function get autoLayout():Boolean + { + return true; + } + + /** + * @private + * autoLayout is always true for ViewStack + * and can't be changed by this setter. + * + * We can probably find a way to make autoLayout work with Accordion + * and ViewStack, but right now there are problems if deferred + * instantiation runs at the same time as an effect. (Bug 79174) + */ + override public function set autoLayout(value:Boolean):void + { + } + + //---------------------------------- + // layout + //---------------------------------- + + /** + * @private + */ + override public function set layout(value:LayoutBase):void + { + throw(new Error(resourceManager.getString("components", "layoutReadOnly"))); + } + + //-------------------------------------------------------------------------- + // + // Properties + // + //-------------------------------------------------------------------------- + + //---------------------------------- + // resizeToContent + //---------------------------------- + + /** + * @private + * Storage for the resizeToContent property. + */ + private var _resizeToContent:Boolean = false; + + /** + * If true, the ViewStack container automatically + * resizes to the size of its current child. + * If false, the ViewStack container sizes to the size of + * the first child. Note that by default the content itself does not get + * resized so content that does not fit within the ViewStack will still appear. + * To clip the extra content, you can create a skin for the NavigatorContainer + * and set the clipAndEnableScrolling property on its contentGroup . + * + * @default false + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public function get resizeToContent():Boolean + { + return _resizeToContent; + } + + /** + * @private + */ + public function set resizeToContent(value:Boolean):void + { + _resizeToContent = value; + resizeToContentChanged = true; + invalidateProperties(); + } + + //---------------------------------- + // selectedElement + //---------------------------------- + + [Bindable("valueCommit")] + [Bindable("creationComplete")] + + /** + * A reference to the currently visible child. + * The default is a reference to the first child. + * If there are no children, this property is null. + * + *

Note: You can only set this property in an + * ActionScript statement, not in MXML.

+ * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public function get selectedElement():IVisualElement + { + if (selectedIndex == -1) + return null; + + return IVisualElement(getElementAt(selectedIndex)); + } + + /** + * @private + */ + public function set selectedElement( + value:IVisualElement):void + { + var newIndex:int = getElementIndex(IVisualElement(value)); + + if (newIndex >= 0 && newIndex < numElements) + selectedIndex = newIndex; + } + + //---------------------------------- + // selectedIndex + //---------------------------------- + + /** + * @private + * Storage for the selectedIndex property. + */ + private var _selectedIndex:int = -1; + + /** + * @private + */ + private var proposedSelectedIndex:int = -1; + + /** + * @private + */ + private var showSelectedIndex:Boolean = false; + + [Bindable("change")] + [Bindable("valueCommit")] + [Bindable("creationComplete")] + [Inspectable(category="General")] + + /** + * The zero-based index of the currently visible child. + * The default value is 0, corresponding to the first child. + * If there are no children, the value of this property is -1. + * + *

Note: When you add a new child to a ViewStack + * container, the selectedIndex property is automatically + * adjusted, if necessary, so that the selected child remains selected.

+ * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public function get selectedIndex():int + { + return proposedSelectedIndex == -1 ? + _selectedIndex : + proposedSelectedIndex; + } + + /** + * @private + */ + public function set selectedIndex(value:int):void + { + // Bail if the index isn't changing. + if (value == selectedIndex) + return; + + // ignore, probably coming from tabbar + if (addingChildren) + return; + + // Propose the specified value as the new value for selectedIndex. + // It gets applied later when measure() calls commitSelectedIndex(). + // The proposed value can be "out of range", because the children + // may not have been created yet, so the range check is handled + // in commitSelectedIndex(), not here. Other calls to this setter + // can change the proposed index before it is committed. Also, + // childAddHandler() proposes a value of 0 when it creates the first + // child, if no value has yet been proposed. + proposedSelectedIndex = value; + showSelectedIndex = true; + invalidateProperties(); + + dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); + } + + //-------------------------------------------------------------------------- + // + // Overridden methods: UIComponent + // + //-------------------------------------------------------------------------- + + /** + * @private + */ + override protected function childrenCreated():void + { + super.childrenCreated(); + + // Make sure all the children are not visible after + // creation. + for (var i:int = 0; i < numElements; i++) + { + if (i != selectedElement) + getElementAt(i).visible = false; + } + } + + /** + * @private + */ + override protected function commitProperties():void + { + super.commitProperties(); + + // If the selected index has not been set then default + // to the first element. + if (numElements > 0 && proposedSelectedIndex == -1) + proposedSelectedIndex = 0; + + if (proposedSelectedIndex != -1) + { + commitSelectedIndex(proposedSelectedIndex); + proposedSelectedIndex = -1; + } + + if (needToInstantiateSelectedChild) + { + instantiateSelectedChild(); + needToInstantiateSelectedChild = false; + } + + if (resizeToContentChanged) + { + resizeToContentChanged = false; + ViewStackLayout(layout).resizeToContent = _resizeToContent; + } + + // Dispatch the change event only after the child has been + // instantiated. + if (dispatchChangeEventPending) + { + dispatchChangeEvent(lastSelectedIndex, selectedIndex); + dispatchChangeEventPending = false; + } + + } + + /** + * @private + * Responds to size changes by setting the positions and sizes + * of this container's children. + * For more information about the updateDisplayList() method, + * see the UIComponent.updateDisplayList() method. + * + *

Only one of its children is visible at a time, therefore, + * a ViewStack container positions and sizes only that child.

+ * + *

The selected child is positioned in the ViewStack container's + * upper-left corner, and allows for the ViewStack container's + * padding and borders.

+ * + *

If the selected child has a percentage width or + * height value, it is resized in that direction + * to fill the specified percentage of the ViewStack container's + * content area (i.e., the region inside its padding).

+ * + * @param unscaledWidth Specifies the width of the component, in pixels, + * in the component's coordinates, regardless of the value of the + * scaleX property of the component. + * + * @param unscaledHeight Specifies the height of the component, in pixels, + * in the component's coordinates, regardless of the value of the + * scaleY property of the component. + * + * @see mx.core.UIComponent#updateDisplayList() + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + override protected function updateDisplayList(unscaledWidth:Number, + unscaledHeight:Number):void + { + super.updateDisplayList(unscaledWidth, unscaledHeight); + + if (showSelectedIndex) + { + showSelectedIndex = false; + + showSelectedElement(getLastSelectedElement(), + selectedElement); + } + } + + /** + * @private + * When asked to create an overlay mask, create it on the selected child + * instead. That way, the chrome around the edge of the ViewStack + * (e.g. the tabs in a TabNavigator) is not occluded by the overlay mask + * (Bug 99029) + */ + override mx_internal function addOverlay(color:uint, + targetArea:RoundedRectangle = null):void + { + // As we're switching the currently-selected child, don't + // allow two children to both have an overlay at the same time. + // This is done because it makes accounting a headache. If there's + // a legitimate reason why two children both need overlays, this + // restriction could be relaxed. + if (effectOverlayChild) + removeOverlay(); + + // Remember which child has an overlay, so that we don't inadvertently + // create an overlay on one child and later try to remove the overlay + // of another child. (bug 100731) + effectOverlayChild = (selectedElement as UIComponent); + if (!effectOverlayChild) + return; + + effectOverlayColor = color; + effectOverlayTargetArea = targetArea; + + if ((selectedElement is IDeferredContentOwner) && + IDeferredContentOwner(selectedElement).deferredContentCreated == false) + // No children have been created + { + // Wait for the childrenCreated event before creating the overlay + selectedElement.addEventListener(FlexEvent.INITIALIZE, + initializeHandler); + } + else // Children already exist + { + initializeHandler(null); + } + } + + /** + * @private + */ + override mx_internal function removeOverlay():void + { + if (effectOverlayChild) + { + effectOverlayChild.removeOverlay(); + effectOverlayChild = null; + } + } + + //-------------------------------------------------------------------------- + // + // Overridden methods: SkinnableContainer + // + //-------------------------------------------------------------------------- + + /** + * @private + * + * @langversion 3.0 + * @playerversion Flash 10 + * @playerversion AIR 1.5 + * @productversion Flex 4 + */ + override public function addElementAt(element:IVisualElement, index:int):IVisualElement + { + addingChildren = true; + var obj:IVisualElement = super.addElementAt(element, index); + internalDispatchEvent(CollectionEventKind.ADD, obj, index); + childAddHandler(element); + addingChildren = false; + return obj; + } + + /** + * @private + * + * @langversion 3.0 + * @playerversion Flash 10 + * @playerversion AIR 1.5 + * @productversion Flex 4 + */ + override public function removeElement(element:IVisualElement):IVisualElement + { + var index:int = getElementIndex(element); + var obj:IVisualElement = super.removeElement(element); + internalDispatchEvent(CollectionEventKind.REMOVE, obj, index); + childRemoveHandler(element, index); + return obj; + } + + /** + * @private + * + * @langversion 3.0 + * @playerversion Flash 10 + * @playerversion AIR 1.5 + * @productversion Flex 4 + */ + override public function removeAllElements():void + { + super.removeAllElements(); + internalDispatchEvent(CollectionEventKind.RESET); + } + + //-------------------------------------------------------------------------- + // + // Methods + // + //-------------------------------------------------------------------------- + + /** + * @private + * + * Commits the selected index. This function is called during the commit + * properties phase when the selectedIndex or + * selectedItem property changes. + * + * @param newIndex The selected index. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + protected function commitSelectedIndex(newIndex:int):void + { + // The selectedIndex must be -1 if there are no children, + // even if a selectedIndex has been proposed. + if (numElements == 0) + { + _selectedIndex = -1; + return; + } + + // If there are children, ensure that the new index is in bounds. + if (newIndex < 0) + newIndex = 0; + else if (newIndex > numElements - 1) + newIndex = numElements - 1; + + // Stop all currently playing effects + if (lastSelectedIndex != -1 && lastSelectedIndex < numElements) + { + var lastElement:UIComponent = getElementAt(lastSelectedIndex) as UIComponent; + if (lastElement) + lastElement.endEffectsStarted(); + } + + if (_selectedIndex != -1 && (selectedElement is UIComponent)) + UIComponent(selectedElement).endEffectsStarted(); + + // Remember the old index. + lastSelectedIndex = _selectedIndex; + + // Bail if the index isn't changing. + if (newIndex == lastSelectedIndex) + return; + + // Commit the new index. + _selectedIndex = newIndex; + ViewStackLayout(layout).selectedIndex = newIndex; + + // Only dispatch a change event if we're going to and from + // a valid index + if (lastSelectedIndex != -1 && newIndex != -1) + dispatchChangeEventPending = true; + + showSelectedIndex = true; + needToInstantiateSelectedChild = true; + invalidateProperties(); + } + + /** + * This function is called during the transition of selected elements to + * hide oldSelectedElement and show + * newSelectedElement. This method is also called for + * the selection of the first element in the ViewStack + * component. During the selection of the first element there is no + * previously selected element so the oldSelectedElement + * parameter will be null. + * When this function is called the oldSelectedElement is + * visible (if it exists) and the newSelectedElement is not. + * + * The default behavior of this function is hide + * oldSelectedElement and show newSelectedElement + * by setting their visible properties. + * + * @param oldSelectedElement A reference to the element was selected until + * the last change of selected elements. This reference is + * null during the initial selection of an element in the + * ViewStack component. + * @param newSelectedElement A reference to the element that has been selected + * for display in the ViewStack. + * + */ + protected function showSelectedElement(oldSelectedElement:IVisualElement, + newSelectedElement:IVisualElement):void + { + // The default behavior is to make the oldSelectedElement hidden and + // make the newSelectedElement visible. + if (oldSelectedElement) + oldSelectedElement.visible = false; + + if (newSelectedElement) + newSelectedElement.visible = true; + + selectedElementShown(oldSelectedElement, newSelectedElement); + } + + /** + * This function is called after showSelectedElement() has completed. + * If showSelectedElement() runs an effect this function should + * not be called until after the effect has completed. + * + * @param oldSelectedElement A reference to the element was selected until + * the last change of selected elements. This reference is + * null during the initial selection of an element in the + * ViewStack component. + * @param newSelectedElement A reference to the element that has been selected + * for display in the ViewStack. + * + */ + protected function selectedElementShown(oldSelectedElement:IVisualElement, + newSelectedElement:IVisualElement):void + { + // After the oldSelectedElement is hidden and the newSelectedElement has been + // shown. + // Make sure the visibility of the elements are set. + if (oldSelectedElement) + { + applyDestructionPolicy(); + } + + } + + + /** + * @private + */ + private function getLastSelectedElement():IVisualElement + { + var lastSelectedElement:IVisualElement = null + + if (lastSelectedIndex != -1 + && lastSelectedIndex < numElements + && lastSelectedIndex != selectedIndex) + lastSelectedElement = getElementAt(lastSelectedIndex); + + return lastSelectedElement; + } + + //-------------------------------------------------------------------------- + // + // IList Implementation + // ViewStack implements IList so it can be plugged into a Spark ButtonBar + // + //-------------------------------------------------------------------------- + + /** + * @private + * The IList implementation dispatches change events when + * label or icon properties change. + */ + private function navigatorChildChangedHandler(event:Event):void + { + var pe:PropertyChangeEvent = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE); + pe.source = event.target; + pe.property = (event.type == "labelChanged") ? "label" : "icon"; + + internalDispatchEvent(CollectionEventKind.UPDATE, pe, getElementIndex(event.target as IVisualElement)); + } + + /** + * Dispatches a collection event with the specified information. + * + * @param kind String indicates what the kind property of the event should be + * @param item Object reference to the item that was added or removed + * @param location int indicating where in the source the item was added. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + private function internalDispatchEvent(kind:String, item:Object = null, location:int = -1):void + { + if (hasEventListener(CollectionEvent.COLLECTION_CHANGE)) + { + var event:CollectionEvent = + new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); + event.kind = kind; + event.items.push(item); + event.location = location; + dispatchEvent(event); + } + + // now dispatch a complementary PropertyChangeEvent + if (hasEventListener(PropertyChangeEvent.PROPERTY_CHANGE) && + (kind == CollectionEventKind.ADD || kind == CollectionEventKind.REMOVE)) + { + var objEvent:PropertyChangeEvent = + new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE); + objEvent.property = location; + if (kind == CollectionEventKind.ADD) + objEvent.newValue = item; + else + objEvent.oldValue = item; + dispatchEvent(objEvent); + } + } + + /** + * @private + * IList implementation of length returns numElements + */ + public function get length():int + { + return numElements; + } + + /** + * @private + * IList implementation of addItem calls addChild + */ + public function addItem(item:Object):void + { + addElement(item as IVisualElement); + } + + /** + * @private + * IList implementation of addItemAt calls addChildAt + */ + public function addItemAt(item:Object, index:int):void + { + addElementAt(item as IVisualElement, index); + } + + /** + * @private + * IList implementation of getItemAt calls getElementAt + */ + public function getItemAt(index:int, prefetch:int = 0):Object + { + return getElementAt(index); + } + + /** + * @private + * IList implementation of getItemIndex calls getElementIndex + */ + public function getItemIndex(item:Object):int + { + return getElementIndex(item as IVisualElement); + } + + /** + * @private + * IList implementation of itemUpdated doesn't do anything + */ + public function itemUpdated(item:Object, property:Object = null, + oldValue:Object = null, + newValue:Object = null):void + { + + } + + /** + * @private + * IList implementation of removeAll calls removeAllChildren + */ + public function removeAll():void + { + removeAllElements(); + } + + /** + * @private + * IList implementation of removeItemAt calls removeChildAt + */ + public function removeItemAt(index:int):Object + { + return removeElementAt(index); + } + + /** + * @private + * IList implementation of setItemAt removes the old + * child and adds the new + */ + public function setItemAt(item:Object, index:int):Object + { + var result:Object = removeElementAt(index); + addElementAt(item as IVisualElement,index); + return result; + } + + /** + * @private + * IList implementation of toArray returns array of children + */ + public function toArray():Array + { + var result:Array = []; + for (var i:int = 0; i < numElements; i++) + { + result.push(getElementAt(i)); + } + return result; + } + + /** + * @private + * + * Apply the destruction policy to the lastSelectedElement. + */ + private function applyDestructionPolicy():void + { + if (lastSelectedIndex == -1 || lastSelectedIndex >= numElements) + return; + + var lastElement:IDeferredContentOwner = getElementAt(lastSelectedIndex) as IDeferredContentOwner; + + if (lastElement && + (lastElement.elementDestructionPolicy == ContainerDestructionPolicy.AUTO || + lastElement.elementDestructionPolicy == ContainerDestructionPolicy.ALWAYS)) + { + lastElement.removeDeferredContent( + lastElement.elementDestructionPolicy == ContainerDestructionPolicy.AUTO); + } + + } + + /** + * @private + */ + private function instantiateSelectedChild():void + { + if (!selectedElement) + return; + + // Performance optimization: don't call createComponents if we know + // that createComponents has already been called. + if ((selectedElement is IDeferredContentOwner) && + IDeferredContentOwner(selectedElement).elementCreationPolicy != "none" && + IDeferredContentOwner(selectedElement).deferredContentCreated == false) + { + if (initialized) // Only listen if the ViewStack has already been initialized. + selectedElement.addEventListener(FlexEvent.CREATION_COMPLETE,childCreationCompleteHandler); + IDeferredContentOwner(selectedElement).createDeferredContent(); + } + + // Do the initial measurement/layout pass for the + // newly-instantiated descendants. + + if (selectedElement is IInvalidating) + IInvalidating(selectedElement).invalidateSize(); + + invalidateDisplayList(); + } + + /** + * @private + */ + private function dispatchChangeEvent(oldIndex:int, newIndex:int):void + { + var event:IndexChangeEvent = + new IndexChangeEvent(IndexChangeEvent.CHANGE); + event.oldIndex = oldIndex; + event.newIndex = newIndex; + + dispatchEvent(event); + } + + //-------------------------------------------------------------------------- + // + // Event handlers + // + //-------------------------------------------------------------------------- + + /** + * @private + * Called when we are running a Dissolve effect + * and the initialize event has been dispatched + * or the children already exist + */ + private function initializeHandler(event:FlexEvent):void + { + effectOverlayChild.removeEventListener(FlexEvent.INITIALIZE, + initializeHandler); + + UIComponent(effectOverlayChild).addOverlay(effectOverlayColor, effectOverlayTargetArea); + } + + /** + * @private + * Handles when the new selectedElement has finished being created. + */ + private function childCreationCompleteHandler(event:FlexEvent):void + { + event.target.removeEventListener(FlexEvent.CREATION_COMPLETE,childCreationCompleteHandler); + event.target.dispatchEvent(new FlexEvent(FlexEvent.SHOW)); + + } + + /** + * @private + */ + private function elementAddHandler(event:ElementExistenceEvent):void + { + addingChildren = true; + internalDispatchEvent(CollectionEventKind.ADD, event.element, event.index); + childAddHandler(event.element); + addingChildren = false; + } + + /** + * @private + */ + private function elementRemoveHandler(event:ElementExistenceEvent):void + { + internalDispatchEvent(CollectionEventKind.REMOVE, event.element, event.index); + childRemoveHandler(event.element, event.index); + } + + /** + * @private + */ + private function childAddHandler(child:IVisualElement):void + { + var index:int = getElementIndex(child); + + // ViewStack creates all of its children initially invisible. + // They are made visible as they become selected. + child.visible = false; + + if (child is INavigatorContent) + { + child.addEventListener("labelChanged", navigatorChildChangedHandler); + child.addEventListener("iconChanged", navigatorChildChangedHandler); + } + + // If we just created the first child and no selected index has + // been proposed, then propose this child to be selected. + if (_selectedIndex == -1 && proposedSelectedIndex == -1) + { + proposedSelectedIndex = 0; + dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); + needToInstantiateSelectedChild = true; + invalidateProperties(); + } + else if (index <= selectedIndex && numElements > 1 && proposedSelectedIndex == -1) + { + proposedSelectedIndex++; + dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); + } + + if (child is IAutomationObject) + IAutomationObject(child).showInAutomationHierarchy = true; + + } + + /** + * @private + * When a child is removed, adjust the selectedIndex such that the current + * child remains selected; or if the current child was removed, then the + * next (or previous) child gets automatically selected; when the last + * remaining child is removed, the selectedIndex is set to -1. + */ + private function childRemoveHandler(child:IVisualElement, index:int):void + { + if (child is INavigatorContent) + { + child.removeEventListener("labelChanged", navigatorChildChangedHandler); + child.removeEventListener("iconChanged", navigatorChildChangedHandler); + } + + // Handle the simple case. + if (index > selectedIndex) + return; + + var currentSelectedIndex:int = selectedIndex; + + // This matches one of the two conditions: + // 1. a view before the current was deleted, or + // 2. the current view was deleted and it was also + // at the end of the stack. + // In both cases, we need to decrement selectedIndex. + if (index < currentSelectedIndex || + currentSelectedIndex == numElements) + { + // If the selectedIndex was already 0, it should go to -1. + // -1 is a special value; in order to avoid runtime errors + // in various methods, we need to skip the range checking in + // commitSelectedIndex() and set _selectedIndex explicitly here. + if (currentSelectedIndex == 0) + { + _selectedIndex = -1; + dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); + } + else + { + _selectedIndex--; + dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); + } + } + else if (index == currentSelectedIndex) + { + // If we're deleting the currentSelectedIndex and there is another + // child after it, it will become the new selected child so we + // need to make sure it is instantiated and shown. + needToInstantiateSelectedChild = true; + invalidateProperties(); + + showSelectedIndex = true; + invalidateDisplayList(); + } + } + +} + +} + Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.as ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.as ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.png URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.png?rev=1370028&view=auto ============================================================================== Binary file - no diff available. Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/ViewStack.png ------------------------------------------------------------------------------ svn:mime-type = image/png Added: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/calendarClasses/DateChooserSelectionMode.as URL: http://svn.apache.org/viewvc/incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/calendarClasses/DateChooserSelectionMode.as?rev=1370028&view=auto ============================================================================== --- incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/calendarClasses/DateChooserSelectionMode.as (added) +++ incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/calendarClasses/DateChooserSelectionMode.as Mon Aug 6 21:25:54 2012 @@ -0,0 +1,101 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.calendarClasses +{ + +/** + * The DateChooserSelectionMode class defines the valid constant values for the + * selectionMode property of the Spark DateChooser controls. + * + *

Use the constants in ActionsScript, as the following example shows:

+ *
+ *    myDateChooser.selectionMode = DateChooserSelectionMode.MULTIPLE_RANGES;
+ *  
+ * + *

In MXML, use the String value of the constants, + * as the following example shows:

+ *
+ *    <s:DateChooser id="myDateChooser" 
+ *        selectionMode="multipleRanges"> 
+ *        ...
+ *    </s:DateChooser> 
+ *  
+ * + * @see spark.components.DateChooser#selectionMode + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ +public final class DateChooserSelectionMode +{ + + /** + * Constructor. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public function DateChooserSelectionMode() + { + super(); + } + + //-------------------------------------------------------------------------- + // + // Class constants + // + //-------------------------------------------------------------------------- + + /** + * Specifies that one date can be selected. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public static const SINGLE_DATE:String = "singleDate"; + + /** + * Specifies that a single range of contiguous dates can be selected. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public static const SINGLE_RANGE:String = "singleRange"; + + /** + * Specifies that multiple ranges of dates can be selected. + * A range can be one or more days. + * + * @langversion 3.0 + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @productversion Flex 5.0 + */ + public static const MULTIPLE_RANGES:String = "multipleRanges"; +} +} \ No newline at end of file Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/calendarClasses/DateChooserSelectionMode.as ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/flex/whiteboard/cframpton/adobe.next/frameworks/projects/spark/src/spark/components/calendarClasses/DateChooserSelectionMode.as ------------------------------------------------------------------------------ svn:mime-type = text/plain