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 ...