Wednesday, March 30, 2011

Adding a button (or whatever) to a Panel header

The other day I had the need to add an Image control to the header area of a Panel. Since the Panel component does not support adding things to its header I had to find my own solution. My first simple approach was to just add the Image to the Panel content and then tweak the paddingTop style of the Panel to make the Image appear in the header. This worked for appearance but any mouse interaction on the Image was blocked. So I looked around a bit and found several solutions for extending the Panel component to add a single button to the Panel header. Since, in my case, I needed to add an Image and I figured in other use cases I might want to add several Buttons or a ButtonBar or whatever I decided to extend the Panel class to create a generic Panel component that would accept and place any kind of UIComponent in its header.
Here is the code. Feel free to re-use it in any way you deem fit.

package com.flexceptional.components
{
   import mx.containers.Panel;
   import mx.core.UIComponent;

   public class ExtendedPanel extends Panel
   {
       public var headerPanel:UIComponent;

       override protected function createChildren():void
       {
           super.createChildren();

           // Add the title panel
           if (headerPanel)
           {
               titleBar.addChild(headerPanel);
           }
       }

       override protected function updateDisplayList
(unscaledWidth:Number, unscaledHeight:Number):void
       {
           super.updateDisplayList(unscaledWidth, unscaledHeight);

           // Position the title panel
           if (headerPanel)
           {
               var y:int = (titleBar.height - headerPanel.height) / 2;
               var x:int = this.width - headerPanel.width - 5;
               headerPanel.move(x, y);
           }
       }
   }
}

Now, thanks to the convenience of MXML and the way it is compiled, we can specify our additions to the Panel header in MXML when defining the Panel.
Example:

<comp:ExtendedPanel width="100%" height="100%" title="Properties">
   <comp:headerPanel>
       <mx:Image source="{helpIcon}"
                 width="16"
                 height="16"
                 toolTip="Open help documentation in new window"
                 useHandCursor="true"
                 buttonMode="true"
                 mouseChildren="false"
                 click="propertyHelpIcon_clickHandler(event)" />
   </comp:headerPanel>
   <!-- Panel content -->
   <comp:PropertiesGrid />
</comp:ExtendedPanel>

2 comments:

  1. You dont need a custom Panel.
    In a normal Panel's creation complete event handler, just call this.titleBar.addChild( component );
    where component is some component you declared in the mxml - and set the x, y for the child in the resize event or similar

    Line 17 should have tipped you off to this...

    Also should be ??

    ReplyDelete
  2. titlePanel should be headerPanel in the example

    ReplyDelete