Screenshot of WordWeb Application

Style system bug in Flash CS3 UIComponents

The following bug requires a bit of explanation. I'll start by describing how Flash CS3's UIComponent framework handles styles. The style system is pretty complex, so it helps to review this functionality first. Then I will describe what's wrong with the implementation and how it leads to a particularly annoying bug that affects custom component developers. Finally, I'll include a specific use-case for why this bug needs to be fixed.

I'm posting this to my blog so that other developers can find it. I spent a couple hours trying to figure out why I couldn't redefine the textFormat style in my custom component. Hopefully this will help anyone facing the same problem. For the record, I've also submitted this bug to Adobe.

Flash CS3's UIComponent framework defines styles using three levels of importance:

The order of importance for these style levels is as follows:

  1. Instance styles are the most important. If a component has an instance style defined, it will take precedence over both shared styles and global styles.

  2. Global styles are less important than instance styles, but more important than shared styles.

  3. Shared styles are the least important.

You can see how this works by looking at the getSharedStyle() method of StyleManager. It first checks to see if an instance style is defined and uses that value if it isn't null. Next, it checks for a global style. Finally, it checks for a shared style.

Actionscript:
  1. private static function getSharedStyle(instance:UIComponent,name:String):Object {
  2.     var classDef:Class = getClassDef(instance);
  3.     var inst:StyleManager = getInstance();
  4.     // first check component styles:
  5.     var style:Object = inst.classToStylesDict[classDef][name];
  6.     if (style != null) { return style; }
  7.     // then check global styles:
  8.     style = inst.globalStyles[name];
  9.            
  10.     if (style != null) { return style; }
  11.     // finally return the default component style:
  12.     return inst.classToDefaultStylesDict[classDef][name];
  13. }

Overall, this makes sense. It allows each component class to include default style values through shared styles. If a developer wants to universally change a style that is defined by many components, such as changing the font used by all controls in an application, a global style may be set. This will override the defaults set in shared styles. Finally, a single instance of a component can be made to look slightly different than everything by setting an instance style.

The Bug

Notice the very last line of the constructor defined for StyleManager. Some global styles are defined immediately when StyleManager is initialized.

Actionscript:
  1. public function StyleManager() {
  2.     styleToClassesHash = {};
  3.     classToInstancesDict = new Dictionary(true);
  4.     classToStylesDict = new Dictionary(true);
  5.     classToDefaultStylesDict = new Dictionary(true)
  6.     globalStyles = UIComponent.getStyleDefinition();
  7. }

Remember the order of style precendence?

  1. Instance

  2. Global

  3. Shared

These global styles will always take precedence over shared styles. To review, shared styles are the mechanism for setting default style values. As a custom component developer, when I want a different default value than one of these forced global styles, I'm can't do it properly.

There are actually three workarounds. The very last one is probably best because it doesn't change the existing behavior.

The fix is simple. In the StyleManager constructor, just set global styles to an empty object.

Actionscript:
  1. globalStyles = {};

There's simply no reason to have any global values pre-defined in the framework. They should all be shared styles so that developers have more flexibility. Technically, they already are shared! All implementations of getStyleDefinition() use the inheritance chain to set up their default styles values. Button adds to LabelButton's shared styles, which adds to BaseButton's shared styles, and finally to UIComponent's shared styles. In other words, most component implementations already access UIComponent.getStyleDefinition() to define defaults, so these styles will be shared from the start.

A quick, and obvious, use case

One of the global styles created by this bug is textFormat, which defines the default TextFormat object to be applied to text that appears in a control. I cannot override the default formatting of text in my custom components. If I want my component's defaults to define a text format with a larger font size (or make it bold, italic, or even a different color!), I can't do it without one of the workarounds I mentioned above.

Adobe's own Flex framework actually has this same use case and implements it as well. The Button component in Flex has bold text by default. Most other components (TextInput, for example) do not use bold text. It's an important customization option that the core Flash CS3 components don't use, which is why the developers probably didn't notice it. However, a look at the other major AS3 component architecture shows that it's a valid need.

by Josh Tynjala | 6 comments

Open Source Flex Component: TreeMap 2.0 (Beta)

After quite a bit of work, I'm relieved to present a beta release for the next version of my TreeMap component for Flex. It took me a while, but I reworked much of the core item renderer code to optimize performance, improve maintenance tasks, and generally make it a better component for everyone to use. For full details, visit the TreeMap project page and grab the new build from the downloads section. The package is marked 2.0.0 BETA.

One of the features I'd like to highlight is the new header renderer. The most obvious change is the new zoom button. Because the headers may be selected (when the branchesSelectable property is set to true), a separate zoom button is needed to differentiate these actions. Additionally, you might notice another interesting change in the example linked below. Choose the "Slice-and-Dice" layout, and you'll see that some of the headers have a little arrow after any text that gets truncated. Roll the mouse over the header, and it will grow with animation to its optimal size, revealing the full text and the zoom button. A drop shadow makes it pop out a bit to help differentiate the header from the surrounding component. With particularly complex data providers, this feature helps usability enormously because the headers often become very small, which hides parts of the text and the icons on the zoom buttons too.

As with all beta software, a word of warning. This component is not completely tested, the documentation is obviously incomplete, and you should use this in production apps at your own risk. I did my best to get everything stable, but obviously, this is the very first release of some new code, so I know there will be bugs. If you're feeling adventurous, though, I hope it works well for you. Should you see any strange behavior, please file a bug report so that I can make the next release better! If you have any questions, send them to the new flextreemap discussion group I set up recently so that others can learn too.

by Josh Tynjala | 10 comments

Hey Yahoo!, so long and thanks for all the Flash!

Some personal news for you all. Today's my last day at Yahoo!. I've had an awesome time building cool Flash and Flex components and I'm honored to have been able to shape the best practices and directions taken with ActionScript here under the purple banner. Contributing to the Astra and YUI libraries and helping to expand and improve the Flash Developer Center has been a lot of fun. I'm excited to continue watching what new and interesting open source projects come out of the talented minds at Yahoo! long after I'm gone.

Where am I going now? Next week, I'll start working full time with Clint and Ben and all the great folks at ESRIA. Besides coding in the trenches on various projects there, I plan to continue contributing to the open source Flash and Flex community as much as possible. Keep your eyes on my blog for more details as I get settled in. I have some cool ideas for applications, components, libraries, and all sorts of fun stuff. ESRIA digs my community contributions, and I'll definitely have a lot more time to work on a wide range of interesting projects thanks to their support. I'm excited!

by Josh Tynjala | 5 comments

Gratuitous Text Effects Courtesy of Flash Player 10

Now that I've figured out how to compile SWFs for Flash Player 10 beta using the Flex SDK nightly builds, I'm happy. There may not be any proper API documentation yet, but at least I can experiment with just the compiler and a little curiosity to guide me. My first SWF is nothing special, but let me tell you, I've been waiting to do this for a long time:

This content has been removed. It was for an earlier beta for Flash Player 10, and I don't feel like updating it. It was just spinning text fading in and out. The font wasn't embedded. Generally, lame, but I enjoyed having the ability to do it.

That's right, those are device fonts, and they're rotating and changing transparency. No silly font embedding in sight. I no longer feel dirty when I want to rotate my text. Can I start targeting Flash Player 10 today? ;)

Some other interesting stuff:

Actionscript:
  1. var v:Vector.<int> = new Vector.<int>();
  2. v[0] = "STRING!"; //error
  3. v[1] = 12; //okay!

Mmm... new Vector type.

by Josh Tynjala | 9 comments

Pages: Prev 1 2 3 4 5 6 7 8 ...42 43 Next