Test Post
Posted by Phil Chung on March 21, 2007 3:04 AM | Permalink | Comments (68)

Testing the new blog setup...

Flex 2 is the NEW Flash 3
Posted by Phil Chung on March 21, 2007 3:11 PM | Permalink | Comments (258)

After taking a year away from the Flash world entirely (to reno and flip houses...that's a story for another day), I've returned to experience a sense of excitement and energy that I haven't felt personally since the days of Flash 3. Sure, there were other periods in Flash history that produced moments of near euphoria:

  • ActionScript introduced in Flash 5
  • Flash Video introduced in Flash MX
  • AS2 in Flash MX2004
  • Bitmap effects in Flash 8

However, the era that I look back on with the most warm fuzzies was back in the day when nrg.be and matinee.co.uk made heads spin with their sheer slickness and everyone hung on the edge of their chairs for the new version of Gabocorp. You know...the days when motion tweens were in, and TellTarget was for "real" coders. That was what birthed in me a REAL passion for Flash, and I knew back then it was what I wanted to do. Now it's 10 years later and things have changed substantially in a way that few of us would have predicted. A lot of Flash designers have moved into the role of "developer" and learned a thing or two about programming through this thing called ActionScript. And now we even have our own "developer" IDE in FlexBuilder. Who would've thunk it?

Yet, as I read the blog posts and see the excitement over Flash/Flex/Apollo/etc. I can't help but feel somewhat the same as I did 10 years ago. A sense of buzz over what the future holds for Flash, centred largely around this framework called Flex. A lot of people talk about how Flex has changed the Flash ecosystem (some wonder where designers are left in all of this). I can't help but think of the possibilities the future holds for us. At what point in the past have we had:

I think it's a great time to be a Flash/Flex developer. Even though we're far removed from the days of Flash 3, I anticipate looking back on these days 10 years from now with the same fondness as I do those days 10 years ago, knowing that we were on the verge of going somewhere bigger than we were (at least if I'm not off flipping houses... :)

I look forward to posting useful tidbits on anything Flash related in the coming days and weeks...

[Flexcerpts 201] - Understanding the Flex 2 Framework
Posted by Phil Chung on March 21, 2007 10:36 PM | Permalink | Comments (3)

In Flex 2, it's pretty safe to say that we are presented with the largest framework ever developed for the Flash platform. What that means for us as developers is that we have more power at our fingertips than ever before to build larger, more robust applications. At the same time, it means that in order to use the framework at more than a surface level, we need to learn a lot about the framework API, as well as how to use the framework to build the custom bits and pieces that every project requires (i.e., components). If you've looked at the number of components and classes in the Flex framework, this appears to be a daunting task.

Adobe has done a great job of documenting the framework (my new best friend is the Flex Language Reference), but sometimes you need to muck around a bit to make the framework do what you need it to do in any given situation.

[Flexcerpts 201] is a series of posts that aims to break down the framework into bits (excerpts) and try to understand these bits better. If we can understand enough of these bits, hopefully we'll have gained a stronger understanding of the framework as a whole and how we can do things like extend components or maximize the use of existing ones.

Watch this space for posts in the coming days and weeks...

[Flexcerpts 201] - Accessing Embedded Assets from Flex
Posted by Phil Chung on March 22, 2007 11:13 AM | Permalink | Comments (8)

Not really an official Flexcerpt, but something that might be useful when embedding assets...

One thing that's been discussed a lot is the hassle of embedding assets in Flex and then adding them to the stage. At the core of the issue is that everything in the Flex world IS a UIComponent. This is necessary so that the framework can "talk" to components within it through a known API (particularly with respect to Containers). So if you try to create a custom class that extends, say flash.display.Sprite, and try to add it to the stage, you get a runtime error called something like "Type Coercion Failed". This is due to line 3301 in mx.core.Container (in the addingChild method):

// Throw an RTE if child is not an IUIComponent
var uiChild:IUIComponent = IUIComponent(child);

As you can see, a check is made to see if the child being added implements IUIComponent, and if it fails that check, then the error occurs. The sole purpose of that line of code is to throw a runtime error (uiChild isn't actually used elsewhere in that method). Grant has a very simple and effective solution to this called DisplayObjectWrapper. Head on over there and grab it, but basically, the premise is that since ALL Container based components in the framework require children to implement IUIComponent (ie., extend UIComponent), you can first wrap the asset in a UIComponent before adding it to the stage. Note that NON-Container based components don't have that same requirement for its children, which is why this works.

In Grant's example, he uses a DisplayObjectWrapper mxml tag to draw the asset to the stage. Works great. Then I tought, ok, let's use ActionScript instead of mxml to add it to the stage. Problem is that for some reason which I couldn't figure out, I couldn't access my asset's class from AS (to be honest, I haven't really done this as I generally use mxml to add assets). Then I stumbled upon this...

It appears that when the asset is embedded into the swf, it gets assigned a classname that looks like "ProjectName_AssetClass". So for example, let's say you have a project called "PhilterBlog", and you embed the following asset:

[Embed(source="assets.swf#Logo")]
public var Logo:Class;

Then you would do something like this:

import com.gskinner.ui.DisplayObjectWrapper;
var wrapper:DisplayObjectWrapper = new DisplayObjectWrapper(PhilterBlog_Logo);
addChild(wrapper);

Note the class name of the asset I used (PhilterBlog_Logo). Also note that you don't need to create an instance of your asset because DisplayObjectWrapper does it for you :)

Anyway, this is as much for my own reference as it is for others as I hadn't seen this elsewhere, but feel free to point me to other urls if this is widely known about embedding assets.

[Flexcerpts 201] - Observations on UIComponent Drawing
Posted by Phil Chung on March 26, 2007 2:45 PM | Permalink | Comments (342)

Since everything in the Flex framework essentially must be a UIComponent, we'll start with examining some of the inner workings of this class. In this Flexcerpt, we discuss how invalidation is implemented in UIComponent and why it is important when extending existing components or creating your own.

Invalidation is based on the premise that all displayable objects (anything that is a DisplayObject) are only drawn to the stage once every frame (since Flash is timeline based). In a nutshell, invalidation refers to delaying the drawing of a component until the next frame, so that we save processor cycles by only running that draw code once. "Drawing" can refer to things such as sizing (including measuring), displaying text, updating a skin, or changing any visible property of a component.

For example, what if the height value of a component was set 3 times during the same frame? If the component were to "redraw" itself immediately every time the height value was changed, it would be drawing 3 times, when it really only needs to draw itself once based on the last value that was set in that code block. This is a simple example, but when you consider that within the framework, there may be hundreds of lines of code executing when components are drawn (depending upon the complexity of your app), obviously, we want to prevent unnecessary redraws whenever we can. Enter invalidation...

There are 3 invalidation methods implemented in the framework:

  • invalidateProperties (commits properties)
  • invalidateSize (does measuring)
  • invalidateDisplayList (does layout)

These methods are called interally within Flex components when the component has something done to it that requires it to be redrawn. Often, more than one of these will be called within the same method. Here is an overview of the code execution that occurs with each of the invalidation methods (not all called methods are shown here to simplify things a bit):

> UIComponent.invalidateProperties() > LayoutManager.invalidateProperties() > enterFrame/render > LayoutManager.validateProperties() > UIComponent.validateProperties() > UIComponent.commitProperties()
>UIComponent.invalidateSize() > LayoutManager.invalidateSize() > enterFrame/render > LayoutManager.validateSize() > UIComponent.validateSize() > UIComponent.measureSizes() > UIComponent.measure()
>UIComponent.invalidateDisplayList() > LayoutManager.invalidateDisplayList() > enterFrame/render > LayoutManager.validateDisplayList() > UIComponent.validateDisplayList() > UIComponent.updateDisplayList()

As you can see, the flow is very similar among these methods. So why does this really matter? Well, here are a few things I took from this:

  • When extending components, the methods that you want to override if you want to draw things to your custom components are the ones at the END of the execution order, so specifically, "measure", "updateDisplayList" and "commitProperties". You can be assured that these methods will be called when needed to redraw the component. Don't forget to call the super's overriden method.
  • When creating methods/properties in your component that will result in needing to redraw the component, make sure you call one of the invalidation methods. If the size is changing, call invalidateSize. If you want to update a text label, call invalidateProperties (and possibly invalidateSize and invalidateDisplayList if your label could have an impact on how your component is sized).
  • Its important to note that if more than 1 of these invalidation methods gets called before the next frame, they will execute in the order above (ie., commit properties, then measure, then layout).
  • Layout management plays a big role in all of this and is definitely worthy of a set of posts on its own. However, gist of it appears to be that measurement occurs "inside-out" and layout occurs "outside-in". So when measuring components for resize, the framework starts with the deepest nested child component and works up the parent chain, and once that's complete, it starts with the topmost parent and lays out its children, who then lay out their children, etc.
  • Container based components also call Container.layoutChrome() from within updateDisplayList(). This is the method that draws any appropriate chrome around the container. Override this method when creating a container with custom graphics.
  • Skins are generally drawn in the updateDisplayList method.
  • Delaying drawing until the next frame is fine, but delaying properties (for example, TextInput.maxChars) could pose a problem because there will often be times when you need to set the value of a property then access that property's value before the next frame. So the solution is to store the value as a private variable that the getter will return, so if you need to retrieve the value, you're getting the correct value back. Once the next frame rolls around, then the value is actually set on the component (for example, maxChars gets set on the TextField contained within the TextInput).
  • Related to the previous, when commitProperties is run, we need to know WHICH properties have been updated so that we don't do a wholesale property update on the component, and again use unnecessary cycles. The solution used in the framework is to set a flag within the component telling it which property has been updated (in the above example, "maxCharsChanged" is the flag), and then put your property commit code inside of an "if" statement that only runs if the flag is set to true. Could result in some longwinded code if you have a lot of properties, but it works.
  • To follow are more tidbits on UIComponent and examples of how to utilize these bits.

    Please feel free to add your thoughts in the comments.

Adobe myFeedz Tag Viewer
Posted by Phil Chung on March 26, 2007 6:11 PM | Permalink | Comments (6)

After seeing myFeedz and looking through the API, I figured I'd build something visual out of it, and this Tag Viewer is what came out of it. Some of the features include:

  • Tag cloud and related post visualization
  • Favorite tag list
  • Tag search function that continually updates with tags
  • Drag scroll UI

For me, the most interesting aspect was the drag scrolling and experimenting with different ways to scroll things horizontally and vertically. I've started to port it over to Flex, however, the one big obstacle I ran across was trying to get drag scrolling to work with existing containers (unfortunately, when you turn off the scrollbars, you also lose the ability to set V and H scrollPosition).

I noticed that the api urls tend to be quite slow in returning data (not sure exactly of the reason), so it's not as zippy as it could be. Also, the api really is currently limited to fetching tag clouds and posts, so it doesn't do everything that you can do through the myFeedz site.

Give it a try!

[Flexcerpts 201] - Other Relevant UIComponent Bits
Posted by Phil Chung on March 27, 2007 10:10 PM | Permalink | Comments (2)

Previously, i discussed observations on UIComponent drawing. Before I follow with a simple example of how to apply that knowledge into extending a component, let's look at some of the other bits in UIComponent that might help you as you extend or build your own components (and that are used in the example I'll give):

  • If your component contains other components or displayable classes that only need to get added once, you should set them up in the createChildren() method. This method gets run once, when the component is initializing.
  • One of the things I love about Flex 2 is that it allows the creation of custom component styles with minimal effort. Basically, all you need to know is this:

    To create a new style, you use the "Style" metadata tag as follows in your component:

    [Style(name="myCustomStyle", type="uint", format="Color", inherit="no")]

    I won't go into details regarding all of the values for each of these tag attributes, but essentially, inserting this tag into your component automatically generates the style for you as well as events associated with style changes. The only thing left for you to do is capture the event and draw your component based on the value of the style. In order to do that, you use the styleChanged() method which looks as follows:
    UIComponent.styleChanged(styleProp:String):void

    When a style changes, this method is fired and gets passed the name of the style that has been changed (as you set in your metadata tag). Within this method you can use the new style value to draw the component. To access the value of your style, use:
    UIComponent.getStyle(styleProp:String):*

    This returns the value for your style.

  • Unlike AS2, AS3 allows you to override internal player methods and getter/setters. UIComponent does this on many occasions (for example, x, y, width, height, addChild, removeChild, ...) so that it can capture changes in value and dispatch events or add additional functionality where needed. This is cool, but there are times when extending UIComponent or any Flex component that you want to directly access those overridden methods/properties. The Flex framework exposes those within UIComponent in the mx_internal namespace using the "$" prefix. If you extend a component, you can access those by doing something like:
    mx_internal::$height = value;

    For example, your component might draw a simple box that you just want to size using width and height rather than redrawing the graphics every time. In that case you can use $width and $height. Not often used, but still handy to know.


Now that we're equipped with these additional bits, we're prepared to tackle a simple example...