explorers' club

explorations in dev, science, sci-fi, games, and other fun stuff!

Extending mx:Panel – a new approach (maybe)

30 Comments

Awhile back I had developed (as many of you may have already) a Panel subclass. Basically I needed a way to add buttons to the titleBar area much like the mx:TitleWindow has the close button. The end result being something very similar to a Window’s Explorer window (not IE). Well if you have tried this, then you know it is not as simple as just saying titleBar.addChild().

A developer’s initial approach may be to override updateDisplayList and createChildren to insert child components inside the titleBar. This was my initial take on it. But this is flawed in that you are…

  1. …unnecessarily overriding methods not generally associated with this area of the Panel. UpdateDisplayList in a nutshell is used to update child components. In terms of mx:Panel, generally child components are what a developer sticks inside the content area. CreateChildren is again something generally associated with child components. Basically these methods are the wrong place to insert items in the titleBar area.
  2. The other flaw in this is that it inefficiently/unnecessarily renders your new titleBr assets. For instance, you want to add 3 buttons to the Panel’s content area. Now let’s assume that the Panel will remain a fixed width and height. So not including calls to these methods during pre-child attachment phases, we are calling these methods 3 times each per button.

I should probably start prefacing my posts with a disclaimer that they are simply guess-timations on the flex framework as I haven’t done any true performance testing and/or benchmarking on my findings. But what testing I have done has yielded positive results. So what I am really trying to say is, correct me if I am wrong.

After doing some peeking into how Panel (not TitleWindow) does the close button logic, I found that it isn’t really tapping the aforementioned methods. The only time it was really calling the createChildren method was to attach the titleBar to its rawChildren and the subsequent children of the titleBar. No layout, sizing, etc was really being handled in this method. More about this later….

Firstly I wanted to be able to make my Panel subclass scalable in that I could have one guy with 3 buttons in the titleBar and then another with one. Also I wanted to be able to attach functionality on the instance’s buttons rather than have a class with hardcoded click listeners. So I just made a simple public method addTitleBarButton (value:Button = null):Button. This method basically takes/creates a button, adds it to an array, then adds it to the titleBar. Lastly it returns the button in case you need to do more to it later on. Just doing this though will not display the items added. You need to resize and reposition them as well. Onto a bit about rawChildren.

Panel’s titleBar is considered a rawChild. So it is not really counted in the displayList (at least directly). This is also true of alot of the skins associated with the container’s borders. When Panel needs to update its borders and titleBar, it does so via LayoutChrome. So this would be an ideal place to add some logic to any new titleBar assets. Now you can get those newly added buttons from that array I mentioned earlier. Then by cycling through the array and getting some x, y, width and height info we can see the new title buttons inside the titlebar area. All without even touching the createChildren or updateDisplayList.

docs – link
source – link

example – link

Advertisements

30 thoughts on “Extending mx:Panel – a new approach (maybe)

  1. Hi There, do you have any example usage… it’s just that I’ve used this code and I just get a normal looking Panel. I’m thinking that there must be a way of adding buttons, but alas I’m too incompetent to work out how (and it is late on a Friday here in New Zealand).

    Thanks,
    Luke.

  2. Oops silly me (lazy me actually). Soon worked it out. Thanks heaps for the post it has saved me lots of time, now just to write all the events I need and it will look sweet!

    Blessings,
    Luke.

  3. Pingback: Source Code for jwo_lib components have been added. « jwopitz - flex/flash exploration

  4. Thanks for the component. Is there any way I can create a controlbar in the panel by modifying this class? I’ve been racking my brain trying to create a controlbar using actionscript. My understanding is that the controlbar needs to be the last component. I’ve tried adding a controlbar last and it still shows up inside the panel. Any advise?

    Thanks
    -Luis

  5. You could probably add a controlBar in the header. Just use:

    var cb:ControlBar = new ControlBar();
    Pod.addTitleBarComponent(cb);

    You might have to do some casting as currently the addTitleBarComponent method does not work as elegantly as I want it to.

  6. Give me an old cool bicycle, and I’ll ride around the city for days.

  7. Hi there,

    Useful component and much trickery needed to get it working. Thanks for figuring it all out.

    Have just migrated from 2.01 to 3B3 and buttons in titlebar no longer appear – any ideas why?

    Cheers, Rich

  8. Thanks for the feedback. I have not tested these guys against FB3. I will take a look into this as soon as I get a chance.

    Probably has something to do with a change to their rendering of the Panel’s border area.

  9. Just put an issue on the project’s home

  10. Hi,

    This is grate. Just the one I was looking for. Thanks

  11. awesome! i was intially overriding the updateDisplayList and createChildren. but your approach makes sense!

    can you please post the MXML of the example too… please?

    power to flex!

  12. @arun
    For some reason the view source is not working. Maybe I accidentally deleted the files. But I have the source here – http://code.google.com/p/jwopitz-lib/source/browse/examples/src/PodApplication.mxml

  13. excellent! thanks!

  14. hey, another question: how do i limit the panel drag boundaries, i mean i would like the panel to be dragged only within a specific area in the screen…

    thanks in advance…

  15. you’d need to say use the bounds parameter of Sprite.startDrag(lockCenter, bounds); – http://livedocs.adobe.com/flex/201/langref/flash/display/Sprite.html#startDrag()

  16. Hooray for this component! I could not initially get it to work in Flex 3 – the added components were being added, but were very, very tiny and located in the upper-left corner of the panel – but was able to fix it with a small change. In the declaration of the defaultStylesInitialized variable, instead of initializing it to setDefaultStyles(), I set it to false (private static var defaultStylesInitialized:Boolean = false; //setDefaultStyles();), and added the following to the end of the titleBar_onCreationComplete event handler (after the line that reads “creationQueue = [];”):

    if(!defaultStylesInitialized) {
    defaultStylesInitialized = setDefaultStyles();
    }

    Thanks for making this available šŸ˜€
    ~greg

  17. @Greg
    Wow. Thanks for posting back. I will update the wiki/issues on the google code project to reflect this. I will probably not implement this fix just yet as I want to be able to do further testing, but thanks again for the lead. Nice find!

  18. @Greg
    Ok I think I fixed that issue. All that is needed is to call the invalidate methods after creationQueue = []; That forces the title bar assets to reposition correctly. Thanks for the find tho. This has been updated in the source as well as the recent swc.

  19. Thanks a ton..!
    made my day….was looking exactly for this.

  20. hey, how do i set an application with this component?

    I get erros like:

    “Could not resolve to a component implementation.”

    i don’t know where to add the Pod.as file and the mxml….which one is the correct folder strucuture? where both mxml and as file should be? and the package and xmlns tag?

  21. @Carlos

    It sounds like you don’t have the Pod.as file in a correct folder structure. Make sure it resides at the com.jwopitz.containers (which means com/jwopitz/containers folder). Your MXML file that would make use of this will reside in the appropriate package of your choice.

  22. i just can’t setup it…but in your example mxml says:
    xmlns:jwolib=”http://www.jwolib.com/2006/mxml”
    that’s actually an unreachable page

    and the as file says “package com.jwopitz.jwolib”

    can’t you send a zip as flex project can be zipped? with all file?

    thanks

  23. yes that page is unreachable as it only serves as a means to identify the components when instantiated within the MXML file. If you are trying to use this component within your project, you can either copy the com.jwopitz package over into your project’s source folder or you can use the compiled SWC and place it in your project’s lib folder and make sure the project properties are pointing to that folder. I don’t have an example project to send to you. But you can certainly do a search on how to use SWC libraries in a Flex project.

  24. hey, thanks. i’m using it correctly now, with the mxml and as files. I needed to copy the as file to my “component” folder and then change the “package component {}” in as file. now it’s working fine.

  25. Hi,
    I am using the Pod.as and have an issue. If I bind a button in the titleBar to a property. It doesn’t update property. I’ve used visible and enabled property of the button but it doesn’t work correctly. If I add another button in the panel the binding works but not if the button is in the titleBar.

    Any idea what could be the problem here?

    Thanks.

  26. @Tahir

    I am starting to think this has to do with the invalidation/updateDisplayList procedure and how those children get notified of their updates.

  27. You are correct but unfortunately I am not yet experience enough in flex to resolve this issue.

    there was a typo in my first post. I meant to say that the binding does not update the button in the titleBar properly so it stays enabled (or visible) even if I change the property it is bound to.

  28. binding to enabled property is working ok but problem is with visible.

    If I toggle the visible property of button in TitleBar directly, the button show/hide properly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s