13 Replies Latest reply on Dec 1, 2009 4:04 PM by dgeurts11

    hostComponent scope

    TomDelorenzi Level 1

      When is hostComponent guaranteed to be defined for a skin. I have seen during the creationComplete event, hostComponent being null. In my current project I had some code that was working fine. It had a creation code block that used hostComponent to check some values and adjust its display. Later I changed around some stuff on its parent etc and then started getting null pointers in that previously working block in the creationComplete.

       

      I saw this same behaviour before but it sort of went away on its own from other changes. What I was trying to acomplish is having a 2 component group adjust its orientation(which of its 2 was on the left side or right) based on a property in its hostComponent.

       

      Here is a trace on the null pointer if you want it

      TypeError: Error #1009: Cannot access a property or method of a null object reference.
          at com.ericsson.components.skins::IconLabelSkin/created()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\skins\IconLabelSkin.mxml:19]
          at com.ericsson.components.skins::IconLabelSkin/___IconLabelSkin_SparkSkin1_creationComplete ()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\skins\IconLabelSkin.mxml:5]
          at flash.events::EventDispatcher/dispatchEventFunction()
          at flash.events::EventDispatcher/dispatchEvent()
          at mx.core::UIComponent/dispatchEvent()[E:\dev\trunk\frameworks\projects\framework\src\mx\co re\UIComponent.as:11982]
          at mx.core::UIComponent/set initialized()[E:\dev\trunk\frameworks\projects\framework\src\mx\core\UIComponent.as:1540]
          at mx.managers::LayoutManager/validateClient()[E:\dev\trunk\frameworks\projects\framework\sr c\mx\managers\LayoutManager.as:988]
          at mx.core::UIComponent/validateNow()[E:\dev\trunk\frameworks\projects\framework\src\mx\core \UIComponent.as:7452]
          at com.ericsson.components.inmc::ApplicationBrowser/showImage()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\inmc\ApplicationBrowser.mxml:87]
          at com.ericsson.components.inmc::ApplicationBrowser/created()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\inmc\ApplicationBrowser.mxml:24]
          at com.ericsson.components.inmc::ApplicationBrowser/___ApplicationBrowser_Group1_creationCom plete()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\inmc\ApplicationBrowser.mxml:8]
          at flash.events::EventDispatcher/dispatchEventFunction()
          at flash.events::EventDispatcher/dispatchEvent()
          at mx.core::UIComponent/dispatchEvent()[E:\dev\trunk\frameworks\projects\framework\src\mx\co re\UIComponent.as:11982]
          at mx.core::UIComponent/set initialized()[E:\dev\trunk\frameworks\projects\framework\src\mx\core\UIComponent.as:1540]
          at mx.managers::LayoutManager/validateClient()[E:\dev\trunk\frameworks\projects\framework\sr c\mx\managers\LayoutManager.as:988]
          at mx.core::UIComponent/validateNow()[E:\dev\trunk\frameworks\projects\framework\src\mx\core \UIComponent.as:7452]
          at Monitor/showChild()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\Monitor.mxml:42]
          at Monitor/doLogin()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\Monitor.mxml:19]
          at Monitor/__loginComponent_loginSuccess()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\Monitor.mxml:56]
          at flash.events::EventDispatcher/dispatchEventFunction()
          at flash.events::EventDispatcher/dispatchEvent()
          at mx.core::UIComponent/dispatchEvent()[E:\dev\trunk\frameworks\projects\framework\src\mx\co re\UIComponent.as:11982]
          at com.ericsson.components.inmc::LoginPanel/fadeFinished()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\inmc\LoginPanel.mxml:55]
          at com.ericsson.components.inmc::LoginPanel/__fade_effectEnd()[C:\Users\edeltom\Adobe Flash Builder Beta\Monitor\src\com\ericsson\components\inmc\LoginPanel.mxml:82]
          at flash.events::EventDispatcher/dispatchEventFunction()
          at flash.events::EventDispatcher/dispatchEvent()
          at mx.effects::Effect/effectEndHandler()[E:\dev\trunk\frameworks\projects\framework\src\mx\e ffects\Effect.as:1818]
          at flash.events::EventDispatcher/dispatchEventFunction()
          at flash.events::EventDispatcher/dispatchEvent()
          at mx.effects::EffectInstance/finishEffect()[E:\dev\trunk\frameworks\projects\framework\src\ mx\effects\EffectInstance.as:805]
          at spark.effects.supportClasses::AnimateInstance/finishEffect()[E:\dev\trunk\frameworks\proj ects\spark\src\spark\effects\supportClasses\AnimateInstance.as:792]
          at spark.effects.supportClasses::FadeInstance/finishEffect()[E:\dev\trunk\frameworks\project s\spark\src\spark\effects\supportClasses\FadeInstance.as:185]
          at spark.effects.supportClasses::AnimateInstance/animationEnd()[E:\dev\trunk\frameworks\proj ects\spark\src\spark\effects\supportClasses\AnimateInstance.as:731]
          at spark.effects.animation::Animation/sendAnimationEvent()[E:\dev\trunk\frameworks\projects\ spark\src\spark\effects\animation\Animation.as:829]
          at spark.effects.animation::Animation/end()[E:\dev\trunk\frameworks\projects\spark\src\spark \effects\animation\Animation.as:925]
          at spark.effects.animation::Animation/doInterval()[E:\dev\trunk\frameworks\projects\spark\sr c\spark\effects\animation\Animation.as:782]
          at spark.effects.animation::Animation$/timerHandler()[E:\dev\trunk\frameworks\projects\spark \src\spark\effects\animation\Animation.as:686]
          at flash.utils::Timer/_timerDispatch()
          at flash.utils::Timer/tick()

        • 1. Re: hostComponent scope
          Glenn Ruehle Adobe Employee

          The hostComponent property is set immediatly after the skin constructor is called, and before the skin is added to the display list. Look at SkinnableComponent.attachSkin() for details. It should definitely be set before creationComplete is called.

           

          Can you recreate the problem in a simple test case? If so, please file a bug.

           

          Glenn

          • 2. Re: hostComponent scope
            TomDelorenzi Level 1

            It looks like this was being caused by an incorrect host component class, ie one that did not match the

            [

            HostComponent("x.y.z")]  listed in the skin. Should this result in a more meaningful error then a null pointer? Either way it was my bug.

            • 3. Re: hostComponent scope
              Glenn Ruehle Adobe Employee

              Glad you found the problem. Yeah, it should give a better error. Would you mind filing a bug for this?

               

              Thanks,

              Glenn

              • 4. Re: hostComponent scope
                TomDelorenzi Level 1

                By the way can anyone confirm the way I am doing something here with skins. I wanted to add a new skin state of selected. I was thinking I would have the host component also have that state and then I can set selected, and it would fire the event down and the skin would update. So this is how I did it. The object of this is to have a custom icon+text label component

                 

                <?xml version="1.0" encoding="utf-8"?>
                <s:SkinnableComponent
                    xmlns:fx="http://ns.adobe.com/mxml/2009"
                    xmlns:s="library://ns.adobe.com/flex/spark"
                    xmlns:mx="library://ns.adobe.com/flex/halo" width="400" height="300"
                    skinClass="com.ericsson.components.skins.IconLabelSkin"
                    creationComplete="created()">
                   
                    <fx:Script>
                        <![CDATA[
                            import spark.components.Group;
                            [Bindable]
                            public var text:String;
                            [Bindable]
                            public var textAlignment:String;
                            [Bindable]
                            public var icon:Class;
                           
                           
                            private function created():void
                            {
                                textAlignment="top";
                                icon=null;
                                text=null;
                            }
                           
                            public function get selected():Boolean
                            {
                                return currentState=="selected";
                            }
                           
                            public function set selected(val:Boolean):void
                            {
                                currentState=val?"selected":"normal";
                            }

                        ]]>
                    </fx:Script>
                   
                    <fx:Metadata>
                        [SkinState("normal")]
                        [SkinState("disabled")]
                        [SkinState("selected")]
                    </fx:Metadata>
                    <s:states>
                        <s:State name="normal" enterState="invalidateSkinState()" />
                        <s:State name="disabled" enterState="invalidateSkinState()" />
                        <s:State name="selected" enterState="invalidateSkinState()" />
                    </s:states>

                 

                </s:SkinnableComponent>

                 

                And skin

                 

                <?xml version="1.0" encoding="utf-8"?>
                <s:SparkSkin
                    xmlns:fx="http://ns.adobe.com/mxml/2009"
                    xmlns:s="library://ns.adobe.com/flex/spark" 
                    alpha.disabled="0.5" creationComplete="created()">
                   
                    <fx:Metadata>
                        [HostComponent("com.ericsson.components.controls.IconLabel")]
                    </fx:Metadata>
                   
                    <fx:Script>
                        <![CDATA[
                           
                            import spark.layouts.HorizontalLayout;
                            import spark.layouts.VerticalLayout;
                            private function created():void
                            {
                                var labelAlign:String=hostComponent.textAlignment;
                                if(labelAlign=="top")
                                {
                                    //make the text first in the child list and make it vertical
                                    group.setElementIndex(labelText,0);
                                    var l0:VerticalLayout=new VerticalLayout();
                                    l0.horizontalAlign="center";
                                    l0.paddingBottom=3;
                                    l0.paddingTop=3;
                                    l0.paddingLeft=3;
                                    l0.paddingRight=3;
                                    group.layout=l0;
                                }
                                else if(labelAlign=="left")
                                {
                                    //make the text first in the child list and make it horizontal
                                    group.setElementIndex(labelText,0);
                                    var l1:HorizontalLayout=new HorizontalLayout();
                                    l1.verticalAlign="middle";
                                    l1.paddingBottom=3;
                                    l1.paddingTop=3;
                                    l1.paddingLeft=3;
                                    l1.paddingRight=3;
                                    group.layout=l1;
                                   
                                }
                                else if(labelAlign=="bottom")
                                {
                                    //make the text first in the child list and make it vertical
                                    group.setElementIndex(labelText,1);
                                    var l2:VerticalLayout=new VerticalLayout();
                                    l2.horizontalAlign="center";
                                    l2.paddingBottom=3;
                                    l2.paddingTop=3;
                                    l2.paddingLeft=3;
                                    l2.paddingRight=3;
                                    group.layout=l2;
                                }
                                else if(labelAlign=="right")
                                {
                                    //make the text second in the child list and make it horizontal
                                    group.setElementIndex(labelText,1);
                                    var l3:HorizontalLayout=new HorizontalLayout();
                                    l3.verticalAlign="middle";
                                    l3.paddingBottom=3;
                                    l3.paddingTop=3;
                                    l3.paddingLeft=3;
                                    l3.paddingRight=3;
                                    group.layout=l3;
                                }
                            }
                           
                        ]]>
                    </fx:Script>
                   
                    <s:states>
                        <s:State name="normal" />
                        <s:State name="disabled" />
                        <s:State name="selected"/>
                    </s:states> 
                   
                    <s:Rect width="100%" height="100%" radiusX="5" radiusY="5" includeIn="selected">
                        <s:fill>
                            <s:SolidColor color="0xBBBBFF"/>
                        </s:fill>
                    </s:Rect>
                   
                    <s:Group id="group" verticalCenter="0" horizontalCenter="0">
                        <s:layout>
                            <s:VerticalLayout horizontalAlign="center" paddingBottom="3" paddingLeft="3" paddingRight="3" paddingTop="3"/>
                        </s:layout>
                        <s:Label id="labelText" text="{hostComponent.text}"/>
                        <s:Group id="labelIcon">
                            <s:BitmapImage source="{hostComponent.icon}"/>
                        </s:Group>
                       
                    </s:Group>
                   
                </s:SparkSkin>

                • 5. Re: hostComponent scope
                  TomDelorenzi Level 1

                  Issue created. I didn't know if it technically qualified as a bug but since I hit it twice I figure other people will too and it can be difficulty to track down.

                  https://bugs.adobe.com/jira/browse/FB-23979

                  • 6. Re: hostComponent scope
                    TomDelorenzi Level 1

                    I have another situation here where hostComponent is getting set to null without any warning. I will update the bug if I can figure out what is causing it in this situation.

                    • 7. Re: hostComponent scope
                      TomDelorenzi Level 1

                      Another thing I just noticed. It may have always been this way but... Its not required to have a ; at the end of the line?

                      It doesn't give any errors if you omit them from what I can see.

                      • 8. Re: hostComponent scope
                        Flex harUI Adobe Employee

                        In Actionscript/EcmaScript, the ';' is optional.  Not sure why, but that's the way the committee wants it.

                         

                        Alex Harui

                        Flex SDK Developer

                        Adobe Systems Inc.

                        Blog: http://blogs.adobe.com/aharui

                        • 9. Re: hostComponent scope
                          Glenn Ruehle Adobe Employee

                          I don't see a getCurrentSkinState() method in your component. You'll need this to push the state into the skin.

                           

                          Are you using the component state for any other reason besides selection? If not, it would be simpler to just keep a selected flag and return the appropriate state name in getCurrentSkinState().

                           

                          Glenn

                          1 person found this helpful
                          • 10. Re: hostComponent scope
                            TomDelorenzi Level 1

                            Thanks. I ended up doing what you suggested with the boolean as well. This leads me to my next issue but I will post it in a new thread since its unrelated and might be helpfull to others.

                            • 11. Re: hostComponent scope
                              dgeurts11 Level 1

                              I kept getting hostComponent as null when trying to associate it with a custom class in my creationComplete handler.  This doesnt seem like the best work around but it works!  I ended up with a work around by accessing the component that is using (this.parent as CustomComponent)

                               

                               

                              <?xml version="1.0" encoding="utf-8"?>
                              <!-- http://blog.flexexamples.com/2009/07/02/setting-a-header-background-image-skin-on-a-halo-d atagrid-control-in-flex-4/ -->
                              <s:SparkSkin name="CustomBackgroundImageSkin"
                                           xmlns:fx="http://ns.adobe.com/mxml/2009"
                                           xmlns:s="library://ns.adobe.com/flex/spark"
                                           minWidth="21" minHeight="19" creationComplete="init()">
                                  <fx:Metadata>
                                      <![CDATA[
                                          [HostComponent("mx.containers.Canvas")]
                                      ]]>
                                  </fx:Metadata>
                                 
                                  <fx:Script>
                                      <![CDATA[
                                          import arthropod.Debug;
                                         
                                          import Modules.Components.CustomComponent;
                                         
                                          private function init():void
                                          {
                                              if((this.parent as CustomComponent).bgImage)
                                              {
                                                  bgRect.alpha = (this.parent as CustomComponent).bgAlpha;
                                                  bFill.source = (this.parent as CustomComponent).bgImage;
                                              }
                                              else
                                              {
                                                  Debug.warning("Warning: CustomBackgroundImageSkin.bgImage value was null !");
                                              }
                                          }

                               

                                      ]]>
                                  </fx:Script>
                                 
                                  <!-- layer 1: fill -->
                                  <s:Rect id="bgRect" left="0" right="0" top="0" bottom="0" alpha="1">
                                      <s:fill>
                                          <s:BitmapFill id="bFill"/>
                                      </s:fill>
                                  </s:Rect>   
                              </s:SparkSkin>

                              • 12. Re: hostComponent scope
                                Glenn Ruehle Adobe Employee

                                Does your HostComponent metadata specify the correct type for the component? If not, the hostComponent property will be null.

                                 

                                Glenn

                                • 13. Re: hostComponent scope
                                  dgeurts11 Level 1

                                  update,.....  the hostComponent is only null when I try to set the skin like:

                                   

                                         setStyle("borderSkin",Core.common.skins.CustomBackgroundImageSkin); 

                                   

                                   

                                  but If I set the skin in the mxml through a style the hostComponent is not null.

                                   

                                  <components:CustomComponent styleName="topBarBG">

                                   

                                  <mx:Style>
                                          .topBarBG
                                          {
                                                  borderSkin: ClassReference("Core.common.skins.CustomBackgroundImageSkin");
                                            }

                                  </mx:Style>

                                   

                                  Im using sdk nighlty build 4.0.0.12222    also if you were wondering why I am using Halo and mx:  its because I am porting a very large app and the only component that I am porting to spark are text primitves so that I can use the TLF.

                                   

                                  -Dave Geurts