TabNavigator Update: Draggable Tabs

Of course I had to do this but this was much easier. Now you can drag the tabs to reorder them. Works pretty well. The one thing that seems lacking is instant notification where the new tab is going (on MouseMove), like FireFox brings up a purple arrow at the point where the tab is going. I dont know if I have the time for that, especially since it doesn’t seem like I will be using this container for my project, but the implementation should be simple.

Check the swf out here, and right click to view source.

If you are using this in a commercial app or something make sure you catch history management errors since removing tabs screws up history before that event (there isnt a tab-add undo when you click back 😉 ), and brings up the error stack trace if you are running the debug player.

Hope this helps someone :).

[Update] Responding to a query from someone, this code is released under the MIT license. You can download/fork the code from the GitHub Repository

TabNavigator with Close Icon: WORKS :)

Okay so this took me more than a day but there is a certain level of satisfaction when things do work. The goal was to create a TabNavigator with a close icon so that tabs could be closed (pretty much like FireFox or Eclipse). First of all, check out the final version here. The source for the project is here

Whats already out there
Darron Schall has had a working codebase for a while but he hasnt released the source code yet since the project was for some client. The other implementation I saw online was by Keun Lee, but I wasnt too happy with that implementation since it was using x,y position calculation for the implementation and that completely breaks the logic encapsulation. Anyway, so I just gave up and decided to just implement it from scratch myself.

Implementation
The TabNavigator class basically extends the ViewStack and adds a tabBar as one of its rawChildren. The tabBar’s dataProvider is set to ‘this’, ie the TabNavigator’s ViewStack data.
The TabBar uses a ClassFactory to instantiate Tab instances when the user adds controllable content to it. The Tab itself is an instance of the mx.controls.tabBarClasses.Tab class and extend the Button class.

The first step was to create a Button instance that on rollover showed the close icon. That is the ViewTab class. The only important part here is that when the user rolls over the button, the Button creates the rollover skin and attaches itself on top of the basic (rollout) skin. So I just remove and add the close Icon just to keep it on top (uhm..Adobe, Can we please have our numbered depths back ? I would just love to attach the icon at 1000 at the createChildren() method and forget about it, assuming skins were added on lower depths). The other thing was to update the measure method so that the icon’s width is added implicitly to the measured values.

Now I needed the ViewBar, my extension to the TabBar class, to use instances of the ViewTab class. That was done my modifying the ClassFactory that generates the Tabs. The ViewBar also adds itself as a listener to the TAB_CLOSE event. On tab-close, the dataProvider is modified based on which tab is clicked. Finally my ViewNavigator just forces the TabNavigator to use the ViewBar instead of the TabBar.

Not bad for a day’s work :). As I update this component, I’ll keep updating the source as well.

Feedback is always welcome.

Blogging from Flash Forward, Austin

Am at the Flash Forward Conference at Austin. Has been fun so far even though I am really tired. I attended a few useful sessions so far one of which I am not allowed to speak about ;). I think the most educational session has been the one on the Flex component life-cycle by Chafic Kazoun. I have been reading about it but its different when someone walks you through the code of a custom component. Quick notes from the talk:

1) Lifecycle: constructor -> createChildren -> commitProperties ->measure -> updateDisplaylist.
2) The constructor and the createChildren is called only once.
3) Invalidation: invalidateProperties, invalidateSize, invalidateDisplaylist each calls a corresponding commit event to be fired from Flex.
4) Embedding swfs and ripping symbols from the library: [Embed(source=”/assets/source.swf” symbol=”[symbol_linkage]”]
5) I have never used the BitmapAsset class. Need to look at what that is.
6) In the updateDisplayList call [instance].move(x,y) rather than [instance].x = [value] since move fires additional functions that let flex layout stuff correctly.
7) Measure doesnt get called if width,height are declared explicitly.
8) You can access unscaledwidth, unscaledHeight in the updateDisplaylist functions to layout your stuff. Call the children’s setActualSize function accordingly.

Another tip from a different talk:
[Flash8] CacheAsBitmap your masker and maskee to get smooth 8bit alphas.

Thats it so far. More stuff as it happens.

Obligatory Flickr post

Had a few hours (well actually I didnt but I couldn’t but I needed a break from ‘work’ 😉 ), so I decided to refactor some of the code from Flexamp and create a few ‘widgets’ (I am beginning to hate that term by the way). Anyway, I had the basic application out in like 20 minutes but I wanted to see if I could do something a little more fun. So I tried to create a tsunami kind of Flickr photoshow when the images expaned when you rolled over them. So the logic was simple:

  • Load the Flickr Images
  • Populate a Tilelist with the data with a custom itemRenderer
  • In the itemRenderer, on rollover set the Image component’s source to the large image url
  • invalidate the tilelist so that the new image can be drawn larger than irs neighbours

Unfortunately that didnt work and here is why that seems to be:

According to the Flex docs for TileList:

You can set the size of the tiles by using the 
rowHeight  or columnWidth properties. 
Alternatively, Flex measures the item renderer 
for the first item in the dataProvider 
and uses that size for all tiles.

So looks like you cant have a custom tile with different dimensions than the rest of the tiles.
So after two hours I was back where I started from. I’ll try to play around more with it and see if I can do something about it.

The only thing i did learn was that to get to the _root of the application you need to reference it as Application.application

[SWF] /blog/swf/flickr.swf, 450, 475 [/SWF]

PS: The Search Button seems to require clicking twice. Not sure why.

Flickr changes bust Flexamp and other Flash apps

Flickr changed the crossdomain file on their servers a few days back breaking Flash applications across the www. The flickr crossdomain file at http://www.flickr.com has been removed and Flash developers have been asked to point their applications to api.flickr.com. Unfortunately I missed the news and so far the last few days, related media has not been working. Hopefully I’ll get down to recompiling it soon. I looked around the many Flex apps using Flickr and most havent updated their apps.
In other news I have also started a new page to point to Flex links I have found on the web. I keep jumping from computer to computer and am not completely in love with del.icio.us (mostly because of the UI …. I wish it looked more like popurls basically one big page of links) so it seemed like a good idea.
I still havent had too much time to put up source code for tutorials and stuff but hopefully that’ll come soon.

Blogging from FlexSeminar, NY

Well, here I am, or rather have been for the last 5 hours, at the Roosevelt hotel, attending the Real World Flex Seminar.. Whats it been like? demos….loooots of demos. And thats exactly what I came for. Seeing some of the apps that adobe has developed has been pretty interesting. Some interesting apps I have seen are a complete CMS system (ShadoCMS) and a ColdFusion Framework for writing Flex apps based on CF backends. Not that many other application vendors although there are a bunch of consulting houses out here.

Got a few doubts cleared for FlexAmp v2 ;).

Links for the day:

Loading skins at Runtime

Static methods vs. Singletons

For the last 2 years, I have been working on a number of very intense projects that involved a truckload of AS2 code (I cant imagine ever doing it in AS1). As of today, the framework is pretty extensive with enough functionality to make the day-to-day stuff a breeze. However, there is always room for improvement so I keep flipping things around trying to make the most agile and adaptable system I can.

Some of the designs I recieved for an upcoming project looked like they could benefit from a little reorganization on the framework end. The situation was this: The designs for the user-controls (scrollbars, buttons, text inputs, etc) seemed to reuse the same drawing elements. For example the input areas for checkboxes, text inputs, etc looked exactly the same. So I figured, it would be neat if the controls in the framework could instantiate an application level graphics toolkit and pass MovieClips to it. The toolkit would then draw on the MovieClip to conform to the look and feel of the application. This made the controls in the framework fairly agnostic to the application look and feel.

The system works perfectly only if all the application-level graphics toolkits implement the same methods. For example, all toolkits would need a method to draw a text-input background or a button state etc. The whole idea of polymorphism fits wonderfully here: define an interface and let each implementation implement the functions that you mandate. Unfortunately in my case there was a snag: The simplest way I implemented the first toolkit was by making it have a series of static functions. So, for example, my text-input control code looks like:

class TextInput extends BaseControl{
private var _toolkit:IUIToolkit;
private var background:MovieClip;

/* init code */

public function set toolkit(t:String{
this._toolkit = eval(t);
}

public function build():Void{
if(this._toolkit==undefined){
throw new ToolkitUndefinedError();
return;
}
_toolkit.drawTextInputBg(this.background);
}
}

A point to note above is that toolkit name is being sent in as a string. This ensures that you are not compiling any application level toolkit when you compile the framework. When you do the eval, the class name sent is evaluated and a class object is returned. This is the Flash equivalent of Java’s Class.forName().

Unfortunately, since all the functions in the toolkit class were static methods and Interfaces cannot define static methods, there was no way for me to ensure application toolkits would define the methods mentioned. The only solution was to have a singleton implementation for the toolkit so that you always instantiate ONE instance of a toolkit and use that.

Although that does seem like the best scenario, I am still not completely convinced especially in light of the AS3’s discontinuation of private constructors (sigh !). Anyways lets see how this works out.

I can always refactor later ;).

p.s : I found a rather interesting discussion on singletons here

Off to NY for the Real World Flex Seminar

Whew. The approval came just in time. I am off to the Real World Flex Seminar in NY on the 14th. While I have attended enough Adobe pitches on Flex 2 , I am more interested in how other industries are percieving it. Probably the most interesting session would be the one that talks about integrating Java and Flex 2. Coming from a Java background myself, hopefully I will have a better understanding of how Adobe imagines the workflow to be for a Java developer writing Flex apps.

Flex 2 growing pains

As I continue to poke my way around with Flex2 in the few hours I get a week, once in a while I keep hitting walls that I dont really expect. And with any new technology, my skills with google search yield few results to ease the pain. Take today for example…

So there I was trying to write this real easy app that would take this not too convoluted XML file and render it in a list with the node-names as the entries. Nothing simpler, you say?…not quite. For the longest time after putzing with the HTTPService class, I was still not able to read the stupid document. I looked at some of the examples couldnt quite find out what I was doing wrong…..until 5 minutes ago.

Turns out HTTPService returns the data as an object by default. To get an XML document back make sure you have resultFormat=”xml” in the HTTPService.

Oh, and remember to keep XML.ignoreWhitespace = “true”.

…source code coming soon.