Tuesday, June 1, 2010

TitledBorderBox (Flex 4/Spark)

I've re-written my original TitledBorderBox class (Flex 3) to use Spark/Flex 4 components. It is slightly simpler, and hopefully more lightweight. It extends the SkinnableContainer class, and uses it's own skin (flex.utils.ui.TitledBorderBoxSkin).

Here are the properties on the component:
  • backgroundAlpha - the background alpha for the box (default: 1)
  • backgroundColor - the background color for the box (default: white)
  • backgroundVisible - if the background should be shown (default: true)
  • borderAlpha - the border alpha for the box (default: 1)
  • borderColor - the border color for the box (default: black)
  • borderWeight - the thickness of the border (default: 1)
  • borderVisible - if the border should be shown (default: true)
  • cornerRadius - the corner radius for rounded corners (default: 0)
  • dropShadowVisible - if a drop shadow is shown (default: false)
  • titleStyleName - the style name for the title label (default "windowStyles")
  • title - the title to show in the border
It also supports most of the layout properties too as styles (paddingLeft/Right/Top/Bottom, gap/horizontalGap/verticalGap, horizontal/verticalAlign, etc) for convenience.

The way the border is drawn is to simply draw a line over top of the border, but underneath the title that is the same color as the background. If you set borderVisible="false", then it will attempt to find the background color of the parent and use that instead.

Here it is in action (view source enabled, right click):

19 comments:

  1. Thanks for the example.

    I did have one issue with embedded fonts though as the mx.core.UIComponent.measureText(text:String) method can't be used with Spark components as stated in the documentation. I used the height and width of the Label component itself to determine the path data.

    ReplyDelete
  2. Very nice! Exactly what I was looking for. Maybe you should get it added to flexlib or some other community set of components.
    I have a question. In Flex3 component, I see a TitleBorderWindow component which has a close button and status feature. Can we have this feature for Flex4?

    ReplyDelete
  3. Hi Vrushali,

    It adds a bit of extra complexity to have the title status label, and a close button, so I left them out.

    I don't have time to do it, but it shouldn't be too difficult by following the same way I did it in Flex 3.

    In the Flex 4 version I made some optimizations, but it should still follow the same logic - it uses a Path this time, and draws the border. So with the status label and/or close button, you'd have to calculate how to draw the top line of the border.

    If I find the time I'll be sure to post it here.
    Chris

    ReplyDelete
  4. Hi Chris.

    Thanks for the flex4 spark version. I have one issue. The border does not leave a big enough gap for the text so I get the text written on top of the line and with a very small gap. Any ideas? Im guessing that it is probably something simple.

    Tks

    Dan

    ReplyDelete
  5. Hi Dan,

    Do you mean that the border doesn't leave enough space for the title text? Or for text that is the content of the window?

    Thanks,
    Chris

    ReplyDelete
  6. Swell component. However, I can't seem to get verticalAlign center to work. Any thoughts?

    ReplyDelete
  7. Hi Intoxopox,

    What are you trying to set the verticalAlign style on?

    Also, usually the verticalAlign style takes one of top, middle, and bottom properties, not center.

    ReplyDelete
  8. My bad, Chris. Was multi-tasking (poorly) when I wrote that. What I meant was using a VerticalLayout, I can't get horizontalAlign="center" to work. I ended up band-aiding this issue by commenting out all the copyLayoutStyle method calls in the skin within updateDisplayList. Any thoughts?

    ReplyDelete
  9. Hi,
    I think what you did is probably best.
    This class is ported from Flex 3 when all the layout properties were available as CSS styles, and I was trying to support that.

    But that isn't really how Spark is supposed to work, so I would either just remove all that styling stuff, or I would add a property to the TitleBorderBox host component called copyLayoutStyles, and in the skin only that value is true then copy the styles.

    ReplyDelete
  10. For what it's worth if you used the VerticalLayout you could also define the horizontalAlign style as well like this:
    <spark:TitledBorderBox horizontalAlign="center"/>

    ReplyDelete
  11. When I dynamically add or remove elements from the TitledBorderBox component its size does not change or at least it does not shrink. I also tried setting the 'includeInLayout' and 'visible' properties of the child elements to 'false' but this didn't work too. :-(
    How can I update the child elements?

    ReplyDelete
  12. Hi Dan,
    I see what you mean. When an element is removed the size of the box doesn't shrink back to the proper measured size.

    Here is a very simple fix that works for me - edit the TitledBorderBoxSkin.mxml file, and edit the measure() function to add the includeInLayout lines around the super call (line 24). This way the border path is not used to determine the measured size of the skin.


    border.includeInLayout = false;
    super.measure();
    border.includeInLayout = true;


    Chris

    ReplyDelete
  13. Cool component:

    i had to change:

    var textWidth:Number = titleLabel.width;

    to

    var textWidth:Number = titleLabel.measuredWidth;

    to make the border update correctly for dynamic title text changes..

    Cheers

    ReplyDelete
  14. Its really Very Usefull.... thank you For u post

    ReplyDelete