Search code examples
apache-flexflex4buttonbarflex-spark

Passing a state to the child button of a Flex4 ButtonBar


I have a Spark ButtonBar that has a custom skin, which defines a custom skin for the "middleButton" requirement. My CustomButtonBarSkin has a custom state, minimized, which I want to pass into my middleButton skin so it can modify its design.

Is it possible to do this? I can see that my button skin could use parentDocument.currentState to get the minimized state, but that's really ugly. Any way to pass a skin from the bar to the child button(s)?


Solution

  • I think you should extend default ButtonBar. Something like this:

    package
    {
    import mx.core.IFactory;
    
    import spark.components.ButtonBar;
    
    [SkinState("minimized")]
    [SkinState("minimizedDisabled")]
    public class MinimizableButtonBar extends ButtonBar
    {
        public function MinimizableButtonBar()
        {
            super();
    
            itemRendererFunction = defaultButtonBarItemRendererFunction;
        }
    
        [SkinPart(required="true", type="mx.core.IVisualElement")]
        public var middleButtonMinimized:IFactory;
    
        private var _minimized:Boolean;
    
        [Bindable]
        public function get minimized():Boolean
        {
            return _minimized;
        }
    
        public function set minimized(value:Boolean):void
        {
            if (_minimized == value)
                return;
    
            _minimized = value;
            invalidateSkinState();
            itemRendererFunction = defaultButtonBarItemRendererFunction;
        }
    
        override protected function getCurrentSkinState():String
        {
            if (_minimized)
                return enabled ? "minimized" : "minimizedDisabled";
            return super.getCurrentSkinState();
        }
    
        private function defaultButtonBarItemRendererFunction(data:Object):IFactory
        {
            var i:int = dataProvider.getItemIndex(data);
            if (i == 0)
                return firstButton ? firstButton : (_minimized ? middleButtonMinimized : middleButton);
    
            var n:int = dataProvider.length - 1;
            if (i == n)
                return lastButton ? lastButton : (_minimized ? middleButtonMinimized : middleButton);
    
            return (_minimized ? middleButtonMinimized : middleButton);
        }
    }
    }
    

    So using this code you can declare your custom skin with the following way:

    <?xml version="1.0" encoding="utf-8"?>
    <s:Skin alpha.disabledGroup="0.5" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
        <fx:Metadata>[HostComponent("MinimizableButtonBar")]</fx:Metadata>
    
        <s:states>
            <s:State name="normal" />
            <s:State name="disabled" stateGroups="disabledGroup" />
            <s:State name="minimized" stateGroups="minimizedGroup" />
            <s:State name="minimizedDisabled" stateGroups="disabledGroup,minimizedGroup" />
        </s:states>
    
        <fx:Declarations>
            <fx:Component id="firstButton">
                <s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarFirstButtonSkin" />
            </fx:Component>
            <fx:Component id="middleButton">
                <s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarMiddleButtonSkin" />
            </fx:Component>
            <fx:Component id="middleButtonMinimized">
                <s:ButtonBarButton skinClass="MinimazedButtonBarMiddleButtonSkin" />
            </fx:Component>
            <fx:Component id="lastButton">
                <s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarLastButtonSkin" />
            </fx:Component>
        </fx:Declarations>
    
        <s:DataGroup height="100%" id="dataGroup" width="100%">
            <s:layout>
                <s:ButtonBarHorizontalLayout gap="-1" />
            </s:layout>
            <s:layout.minimizedGroup>
                <s:VerticalLayout />
            </s:layout.minimizedGroup>
        </s:DataGroup>
    </s:Skin>
    

    Hope this solves your problem.

    And if your minimized state is only about changing middle button skin you can remove all states related code both from custom component and from skin.