1 Reply Latest reply on Jan 1, 2011 2:28 PM by Shongrunden

    Architecture design question: layers of components

    Wrataxas Level 2

      I am sooo confused about how to combine components, and when I should inherit, and when stuff goes in skins. I have a custom component Tile that looks like this:

      plaintile.jpg

       

      Source (simplified) looks like this:

      <s:SkinnableContainer skinClass="skins.TileSkin">

           <fx:Script>

                <![CDATA[

                     [Bindable] public var tileColor:uint = 0xFF0000;     // Base color of the tile.  The center area will be this color.

                     [Bindable] public var tileThickness:uint = 4;          // How high the tile appears to have its center part raised.

                ]]>

           </fx:Script>

      </s:SkinnableContainer>

       

      All the drawing happens in the skin.  I subclassed this component to have a LabeledTile:

       

      goldtilex.jpg

      Source (simplified) looks like this:

       

      <components:Tile>

           <fx:Script>

                <![CDATA[

                     protected static const PADDING:int = 3;

                     public function get text1():String { return Label1.text; }

                     public function set text1( str:String ):void { Label1.text = str; }

                ]]>

           </fx:Script>

           <s:Label id="Label1" x="{tileThickness}" y="{tileThickness}"

                height="{height - 2 * tileThickness}" width="{width - 2 * tileThickness}"

                maxDisplayedLines="1" textAlign="center" verticalAlign="middle"

                paddingLeft="{PADDING}" paddingTop="{PADDING}" paddingRight="{PADDING}" paddingBottom="{PADDING}"/>

      </components:Tile>

      I want to have a subclass of LabeledTile called LabeledTileWithGizmo that looks like this:

      goldtile.jpg

       

      I thought this would work:

       

      <components:LabeledTile width="130" height="32" tileColor="0x0077EE"

                          contentCreationComplete="ContentCreated()">

           <fx:Script>

                <![CDATA[

                     private function ContentCreated():void

                     {

                          Label1.setStyle( "fontSize", 14 );

                          Label1.setStyle( "color", 0xFFFFFF );

                          Label1.setStyle( "fontFamily", "Trebuchet MS Bold, Arial, Helvetica, _sans" );

                     }

                ]]>

           </fx:Script>

           <components:Gizmo x="100" y="4" height="24"/>

      </components:LabeledTile>

       

      The gizmo shows up on the tile, but the label disappears.  If I put the Gizmo component right next to the Label component in the LabeldedTile, they both get drawn.  But I want to have labeled tiles that don't have gizmos, as well as ones that do.  I also want to have different types of gizmos.

       

      So, should I have one subclass of Tile with optional subcomponents?  And how would I do that?

       

      Should I be putting more of this in TileSkin?  And have the alternate components be states in the skin?

       

      Should I have a different skin for each of Tile, LabeledTile, and LabeledTileWithGizmo?  Should the second skin inherit from the first skin, and the third from the second?

       

      Can I have a skin for a component set styles on a subcomponent (e.g. having a LabeledTile set the fontSize, etc. on the Label subcomponent)?  Or is that even possible.

       

      I am sooo confused on how all these pieces should fit together.  Any insight would be appreciated.

        • 1. Re: Architecture design question: layers of components
          Shongrunden Adobe Employee

          Your MXML for LabeledTile has Label1 as a child element in MXML.  When you subclass that class using MXML (<components:LabeledTile ...) then whatever child elements you put in that subclass will replace what you had declared in the LabeledTile.

           

          Sounds like what you want to do is subclass SkinnableContainer to have a label skin part and move your label into the skin.  That way when you add child elements to your container it won't replace the label with your child elements.

           

          This article is a good start to learn about spark skinning: http://www.adobe.com/devnet/flex/articles/flex4_skinning.html

           

          If you follow the approach above then here are some answers to your specific questions:

           

          So, should I have one subclass of Tile with optional subcomponents?  And how would I do that?

           

          >> You could make the Label an optional skin part so if someone didnt want the Label to show up then they would create a custom skin that didn't include it.  Another approach would be to consider exposing a showLabel property on your component that would control the visibility of the Label skin part.

           

          Should I be putting more of this in TileSkin?  And have the alternate components be states in the skin?

           

          >> Yes move the Label to the skin.  You could use states or expose a showLabel property as I mentioned above.

           

          Should I have a different skin for each of Tile, LabeledTile, and LabeledTileWithGizmo?  Should the second skin inherit from the first skin, and the third from the second?

           

          >> Sounds like you could do this all with one component and one skin by adding another custom skin part for the gizmo. Inheritance via MXML skins is not trivial to implement.

           

          Can I have a skin for a component set styles on a subcomponent (e.g. having a LabeledTile set the fontSize, etc. on the Label subcomponent)?  Or is that even possible.

           

          >> Yes you should be able to do that, just call setStyle on the skin part