How do you combine renderers in flex?

I am trying to make a generic list control that has x buttons in it so that users can remove items from the list by clicking the x button. However, this list control needs to support item renderers while still standardizing the layout of items placed next to x buttons.

So I figure the best approach would be to extend the list control and use a renderer that draws the x button and combines that with what ever renderer the user supplies. Unfortunately I cannot figure out how to do that.

I tried overriding newInstance method from the IFactory interface and used that to create an HBox that contains my button and inserts the newInstance result from a user supplied renderer, however it wasn't complete. It displayed as I expected, but the mouse over effect only worked on the user supplied renderer portion and not the entire HBox that my custom renderer made.

There seems to be a lot of missing details in the Flex documentation on this subject.

I am making all of this in Action Script 3.

Answers


I don't think the way to do this is by extending the List control. Instead I would try to create my custom itemRenderer and then extend it as needed. One approach to achive this can be:

  • Create you own SkinnableComponent which implements IItemRenderer or IDataRenderer.
  • Add the component a required part (the Delete button) and the behaviour you need (eg: deleteButton click handler)
  • Extend the component you have created to create concrete renderers.

EDIT: Added example

This is a simple example of how you can create an itemRenderer extending SkinnableComponent and implementing IDataRenderer. It supports 2 states, normal and hovered. Note that ItemRenderers are very expensive to create in Flex, so always try to keep them as lightweight as possible.

package 
{
    import flash.events.MouseEvent; 
    import mx.core.IDataRenderer;   
    import spark.components.supportClasses.ButtonBase;
    import spark.components.supportClasses.SkinnableComponent;

    [SkinState("normal")]
    [SkinState("hovered")]
    public class LearningRenderer extends SkinnableComponent implements IDataRenderer
    {

        /** Define the skin parts. */
        [SkinPart(required="true")]
        public var deleteButton:ButtonBase;

        public function LearningRenderer()
        {
            super();
            // Set the skin class.
            setStyle("skinClass", LearningRendererSkin);
            // Add event listeners to support HOVERED.
            addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
            addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
        }       

        /** Implement the partAdded() method. */
        override protected function partAdded(partName:String, instance:Object):void 
        {
            super.partAdded(partName, instance);
            if(instance == deleteButton){
                instance.addEventListener(MouseEvent.CLICK, button_clickHandler);
            }
        }

        /** Implement the partRemoved() method. */
        override protected function partRemoved(partName:String, instance:Object):void
        {
            if(instance == deleteButton){
                instance.removeEventListener(MouseEvent.CLICK, button_clickHandler);
            }
        }

        /** Implement the getCurrentSkinState() method. */
        override protected function getCurrentSkinState():String 
        {   
            var returnState:String = "normal";
            if (bRollOver)
                returnState = "hovered";
            return returnState;
        }

        public function get data():Object
        {
            return _data;
        }

        public function set data(value:Object):void
        {
            _data = value;
        }

        /** Add methods, properties, and metadata. */
        private var _data:Object;
        private var bRollOver:Boolean = false;

        /**
         * Handlers
         */         
        protected function button_clickHandler(eventObj:MouseEvent):void {
            //Handle click
        }

        protected function rollOverHandler(eventObj:MouseEvent):void{
            bRollOver = true;
            invalidateSkinState();
        }

        protected function rollOutHandler(eventObj:MouseEvent):void{
            bRollOver = false;
            invalidateSkinState();
        }       

    }
}

And this is the skin with the required deleteButton:

<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx">
    <!-- host component -->
    <fx:Metadata>
        [HostComponent("LearningRenderer")]
    </fx:Metadata>
    <!-- states -->
    <s:states>
        <s:State name="normal" />
        <s:State name="hovered" />
    </s:states>
    <s:Button id="deleteButton" label="Delete"/>        
</s:Skin>

Need Your Help

How to identify using a regular expression a specific string written over two lines within a text?

regex string vbscript

Please, how would I identify using a vbs regular expression a specific string within a text knowing that the first part of the searched string is on a line and the second on the following line?

Smart design of a math parser?

math parsing calculator

What is the smartest way to design a math parser? what i mean is a function that takes a math string (like: "2 + 3 / 2 + (2 * 5)") and returns the calculated value? I did write one in VB6 ages ago ...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.