When You Hit a Design Brick Wall in Flex…

…code it your bloody self. But first, weigh the consequences. I’m referring specifically to when you have a design that you are trying desperately to shoe-horn into the Flex components. Key phrase here being “shoe-horn”, meaning it doesn’t fit quite right.

A lot of designs can have specific elements that can be extremely challenging to implement into Flex. Challenging in this case means taking a LOT of time. If you are getting paid to learn on your employer’s dime, as you were. If, however, you just want to get stuff done, you can extend the appropriate Flex framework base class and code it yourself. There comes a turning point when the time spent trying to successfully integrate a design is more than the time it would of taken you to whip up a workable solution by coding a similar component yourself. The con is that your agile approach (least amount of work to hit the goal) may not scale and you’ll be constantly “upgrading features” on your custom component. The challenge here is to weigh the risks of both.

Preface

I’ve been using Flex 3 Beta for awhile and only recently got to dig into the new designer friendly features they’ve added. Frankly, the faster mxmlc it has now would of kept me happy for at least 8 months, hehe. Seriously, though, the new CSS previews, the faster and slightly more accurate Design View are really great.

The Flex SDK itself, however, still is relatively the same in API and design integration. They’ve made massive improvements under the covers, but nothing drastic in work flow. While we’d all love low-level generated MXML that Thermo makes, or the uber-abstraction Flex 4 might give, what we have now is what we have now. Bottom line, if you’re doing ANY design in Flex right now, you’ll want to be using Flex 3 instead of 2.

I’d say 90% of the apps out there for Flex, the current Flex 2 and Flex 3 SDK component set is spot on for. More than half of those probably need little to no tweaking to the default styling. This is based on my consulting experience, as well studying what existing .NET and J2EE implementations look like, and thus set expectations for.

The consumer applications you see blogged by Ryan Stewart and on Techcrunch are dope looking, but I’d still argue a lot of consumer facing Flash Player content right now is still created in Flash, mainly because of the designer’s heavier role in consumer oriented content. That’ll change as time goes on, specifically in the application realm, never for the branded website.

Examples of Brick Walls

Let me point out some examples.

Did you know that the TabBar & TabNavigator don’t support negative padding? They do, but not to the desired effect. The default horizontalGap property is actually -1 so the borders overlap. However, any more than that, and the 3D effect is lost.

Tab’s give the illusion of depth to indicate which one is currently selected. They sometimes also have a bottom that has the same color of the form below it, making it even more apparent that is the state you are currently viewing. They do this by appearing “in front of” the others.

tabs.gif

You’ll notice some interfaces have tighter spacing on the tabs making them scrunched together. This effect gives you a lot more room for more tabs. It also accentuates the fact that the tabs have depth. The Firefox web browser’s tabs are nice and snug next to each other with only a 2 pixel gap.

tabs_02.gif

IE 7 takes this a step further and changes both size and height of the selected tab to show prominence.

tabs_03.gif

If, however, you want to show negative depth like this comp shows:

tabs_04.gif

…it won’t work. In Flex, it looks like this with a horizontalGap of -4:

tabs_05.gif

Whoops, the “Tres” is up-staging “Dos”! He IS on top of “Uno” however.

Why does the TabNavigator, and thus TabBar work this way? You have to dig into the code of their base classes to find out. There are a couple reasons why this is, but the quick answer is that selectedIndex is hard-coded to depth. That means that it uses the index of the child keeping track of depth. If ToggleButtonBar kept an internal reference to the child instead of using depth and selectedIndex as a 1 to 1 relationship, you could change the depths of things to be “in front of other things” irrespective of selectedIndex’ value.

No, you can’t hi-jack the depth; that REALLY screws things up and confuses the heck out of the poor thing… visually anyway.

// TabBar's itemClick handler
protected function onItemClick(event:ItemClickEvent):void
{
        var tab:UIComponent = event.relatedObject as UIComponent;
        var index:int = tabs.getChildIndex(tab);
        tabs.setChildIndex(tab, 0); // nope
        tabs.setChildIndex(tab, tabs.numChildren - 1); // nice try...
}

Maybe this’ll be a footnote in Doug’s book, hopefully with more curse words at things that blow.

So, you’re condemned to greater than or equal to -1 horizontal-gap style for TabBar & TabNavigator… or ARE you? This is Flash Player, ladies and gents, and you’re a coder (or hybrid). In 4 hours (tell the client 12 just in case) one could whip together a wrapper class that instantiates mx.controls.tabBarClasses.Tab, keeps track of a selectedIndex, and positions them to the design.

Cons? Tons. This still won’t fix TabNavigator, just TabBar. Furthermore, you’ll have toggle a ViewStack’s selectedIndex manually, thus spilling out un-ecapsulated code into the Mediator that hosts both controls. Those AND all the other things that you’re giving up with layout and events that the Flex TabBar already provides. Worth the cost? For a prototype, hell yes. For a production app, no way. Ask the designer to give you a re-designed TabBar without a negative depth. Most designers I know will be totally cool with that and save you days of coding & debugging, ecspecially when they see the look of desperation on your face. I find rubbing your hand through your hair, a big sigh, and a general look of desperate exasperation really help put on a good show. Acting like the designer is Obi Wan, and you’re Leia generally ALWAYS works.

Example 2, Icon and Label Placement in a Button

The Button control in Flex has 2 properties that allow you to decorate it with internal design funk. One is called “label”; it allows you to set dynamic text on top of the button. The other is called “icon”; it allows you to set an image for the Button. By default, the icon sits to the left side of the Button, and the label sits to the right of the icon. The problem, however, is that the icon that “follows” the text by 2 pixels. This value can be adjusted by setting the horizontal-gap style. However, if you want to implement this design:

tools_01.gif

It’ll instead look like this:

tools_02.gif

This one isn’t so bad. You can actually just export the up, over, down, and selected states as flattened bitmaps from Fireworks and you’re good to go. Cons? If you’re font changes from anything but Black Arial 12, you’ll have to re-export your images from Fireworks, and re-compile your Flex app (loading at runtime is a cool optimization later, but you need to embed to quickly build your app). Furthermore, all the styles in Flex for your Button are pretty much worthless; this includes if someone uses the Button selector in CSS; your Button will ignore most.

…or you could create your own Button. One that handles it’s own selection states, creates an image where you want, and a label where you want. Coding the styles, though, OVER, is a lot of work.

Example 3, Custom Panel

The Panel and TitleWindow components in Flex are really great to work with. They provide a nice, visual container with highly defined borders that gives the user something to focus on; functionality within the Panel is implied to be grouped and thus related. Since it’s a Flex container, you can just put whatever you want into it, and it’ll handle where it goes based on the layout property.

A lot of Flex devs will relegate these things into some MDI interface. They’ll make the Panels draggable, add custom buttons to the title bar’s, and make them re-sizable. All are really dope.

The problem, though, is that getting your custom border to be seemless and yet still retain all the functionality of the Panel is a LOT of work. You have basically 2 options.

The first is to extend it. The Panel has 2 main features you need to know about to make the most of your new class. The first is the rawChildren that a lot of Containers have. This is where the internal stuff goes. The regular children that developers add go in the regular content sprite, “contentPane”. You may want to add stuff to rawChildren; where all the things that make up some of the Panel’s chrome. The rawChildren is not acessed by DisplayObject methods like getChildAt, and addChild; they proxy usually to contentPane. The rawChildren is where the fun stuff happens.

You can also add stuff to it as well. For adding custom buttons to the Panel, for example, you’d add them to the “titleBar”. The titleBar is a UIComponent added to the Panel’s rawChildren. That is the “thing” up top that houses the close button, title, and status text amongst other things. This is the easy part. Even the border metrics, the measurement one does to ensure that your border fits around the contents, are challenging but definately do-able in 12 lines of code.

…the title background, however, is where things start to go downhill. Chrome in the rawChildren is ABOVE all content. This really really sucks. If you’re doing programmatic skinning, this creates chrome on top of your controls; aka the close button and others. You don’t have to, could use scale 9 images, but you’d still have the same problem. This means no clicks get through to the buttons and stuff appears “on top of” it/them.

Solution? Override the mx_internal namespace function called “createContentPane”. The one that is in Flex 2’s Container class on line 4608 (4632 in Flex 3 Beta … um… beta something) clearly states the location of your chrome. You’re screwed unless you override it. You can follow my original foray into this horrible, malaria infested jungle, originally forged by Michael Schmalle.

What’s wrong with overriding it? Well, let’s get a quick eduction on what Adobe officially supports in the Flex SDK, and what they don’t. First, if it’s public or protected, you’re good to go. If it’s in the mx_internal namespace, or it’s private, they do not. Their reasons for this is that they can change the functionality under the hood, yet still expose the same API in future fixes/updates/verions of Flex that won’t break your app. Additionally, there could be other things released in the future that use the Flex SDK’s API but wouldn’t work with your stuff if you used those unsupported namespaces.

That attitude is one of the main reasons why apps opened in Flex 3 that were created in Flex 2 have extremely little to change; we’re talking less than an hour for Enterprise apps.

…the attitude still sucks, though. The Flex team gets bashed by people on this issue at every convention I’ve been to. There is some seriously good shit in mx_internal and private that causes monkey patched Flex frameworks to be floating around in some projects. For those uber-purists who refuse to touch the sacred internals, they either put in lame work-arounds that don’t work well, or just drop the idea. Both are seriously jacked… although, I definately support the former, hehe!

My guess is, they perceive us as the loud minority mostly consisting of Flash malcontents. Whatever. Here’s my added 20 decibels.

SO, back to my original point. To get custom chrome to work, I have to override an un-supported method, adding my custom skins to a supported, yet never fully working for antiAliasing exception reasons I never figured out to get the Panel to have custom chrome. I solved the text problem by making it an image; that was fun every time the text changed (in all fairness, wasn’t often) updating the PNG and refreshing. Doesn’t seem like a bad thing, but remember, Flex 2 was SLOOOOOOOWWWWW… then again, Flex 1 was worse; must be appreciative and all.

…OR, you can create a custom container in Flash using the Flex Component Kit for Flash. I’m pretty sure this came out like 2 weeks after my project. Even if I had used it, there’s one problem: Container, while bad ass, is NOT Panel.

When you are creating components for Flex, you need to leverage the Flex framework. To not do so wastes the effort what 15+ bad ass developers from all the other world spent over a year on. Re-writing things yourself may feel cool, but it’s probably already done, and done well, in the Flex SDK. Furthermore, you need to play nice with others. For smaller service level projects, you can get away with it. For larger endeavors where other developers will be using your code “as they’d expect Flex to work”, you’re custom versions just won’t fly for maintainability reasons. You increase the cost of maintainece by using non-standard Flex components.

Naturally, writing that paragraph pisses me off, because while I agree, I grew up in Flash where this shiz is EASY. Making the 2 come together is extremely frustrating. While examples 1 and 2 are resolvable, #3 was a hack job. It looked and worked damn good, but I feel sorry for the poor bastard to dug into my BluePanel.as (remember, extending containers in MXML is lamesauce; even Flex 3 acts happier when you use AS to extend containers). If I were to do it over again, I probably wouldn’t change a thing; I learned a TON about the internals of Panel and Container. However, if it were a major client project ( I was working for friends at the time on a prototype project ), I’d just code the bastard myself in ActionScript 3, extending UIComponent, and only support an extremely small sub-set of styles. I would of been done in 1/10th the time, and we only used like 20% of the features of Panel; aka, putting controls in it… whoop-pu-dee-frikin-doo.

Conclusions

Anytime I run into a design challenge in Flex, my first reaction in the past was to just “figure out how to make it work”. My gut today is, “screw it… just code it myself”. I then remember back to the days of Flash MX when I’d go, “You know… this Scrollbar component sux. I could code this myself!” Laughingly, every version was missing a MAJOR feature. Version 1 had no arrows. Version 2, you couldn’t click on the scroll track. Version 3, didn’t have the scrollbar’s thumb grow and shrink to accomodate content. None of them even did scrolling right because my math was pathetic. After 2 weeks of re-inventing the wheel 3 times, I had a MAJOR respect for the component writers.

That, and other experiences like it, combined with the implied maintaince costs vs. speed to market agile-is-t3h-buzzword… basically cause insane internal debates. Balancing pragmatism with your duty to strive for OOP Purism in these scenarios, EVEN AFTER you’ve asked the Designer for help, is really hard. “I can code this functionality faster myself… but at what cost down the road?”

So far, the ratio has been hack/abandon crazy ideas 60%, do it yourself in a conservative way, 40%. That’s for the big Flex jobs. The rest, 90% do it yourself. This doesn’t always come up, mind you in every Flex project; it’s not a constant thorn. It IS a thorn, though, when you get a bad ass designer, specially one of those with Flash experience who’s already been spoiled by good Flash Developers, and the design just won’t fit. Save me Thermo, you’re my only hope… just don’t generate crap code, please!

4 Replies to “When You Hit a Design Brick Wall in Flex…”

  1. Great post. I hit a big design wall. I already built several Flex projects with lots lots of screens(no less than 50), skinned with some sort of CSS & images, without designer. My team members already feel it good enough. But one day then there came the designer, showed his design made with Flash IDE. Then my boss asked me, I need this, how long you need. Where’s the hell!

  2. We ran into exactly that problem with the TabBar . It seems pretty crazy that they relied on the depth to order the tabs in the x plane rather than creating a separate protected property… I can’t really explain why they took that approach…

    We did, however, manage to subclass TabBar and get the behaviour we wanted. It involved overriding getChildAt, getChildIndex, removeChildAt, createNavItem and hiliteSelectedNavItem and storing the tabs in our own array. Basically as far as the underlying flex framework was concerned it was still dealing with the depth of the tabs but actually we managed the depth ourselves and allowed it to use what it thought was the depth for it’s horizontal layout purposes…

    Nasty solution to a nasty problem!

  3. Amen!

    I have run into this problem in almost every project i have done. The solution depends on how close you can get to the comp with Flex alone… you know you can nail it in Flash but you know you are asking for trouble.

    I lay a good amount of blame on the Flash and Flex teams not thinking enough about how these two platforms can work well together. It’s most evident when you take a look at the list of Flash components and the list of Flex components and wonder why there are so many that do exactly the same thing but yet don’t share any code.

    And sure, Thermo looks great. But Flash should have been Thermo from the beginning of Flex. Instead it’s yet another development environment to learn.

  4. Jesse,

    You are a hella funny writer just like in person. I have been in the teo.labs for about 5 months ignoring about everything that moves dealing with Flex (flexcoders..blogs).

    This is where eventually people will see value in rock solid 3rd party components that ‘extend’ the flex framework and add all those benies you talk about.

    Thanks for mentioning me in your malaria infested jungle. Most of the time I just like to think of it as life (judah informed me of your colorful blog post).

    Your title should have been…

    When You Hit a Design Brick Wall in Flex… Find a bad ass Flex component developer and stick with them. ;-)

    haha oh… wait flex component developers are considered white trash, useless money grubbing bastards that are considered the Application developers illegitimate child!

    Times will change… BTW, components will find there niche in Flex 4(or companies will get smart enough to find those that truly save them huge amounts of development time and money).

    Peace, Mike

    PS Oh yeah, I’m not talking about another revamped color picker or scroll bar here, I’m talking monolithic components that we will be offering in 2008-2009.

Comments are closed.