Blog

  • I have a hard time writing slow ActionScript 3

    I have a problem going backwards. When I learned attachMovie in Flash 5, that function was the death knell for my Director career. “Create something from nothing!?!?” :: queue Quake sound :: “GODLIKE!!! (nsfw)“.

    In Director, everything you wanted to be on a depth had to have had something there originally, put there on the “score” (Director’s timeline). If you didn’t do this at author-time, you couldn’t swap things out on that depth. The attachMovie function in Flash was great because this didn’t matter; I had thousands of depths to play with; the sky was the limit!

    I later learned the sky on _root had a limit; it was called the Settings Panel. Lakitu wouldn’t even go near that elevation. It didn’t matter though; creating new MovieClip’s allowed millions of depths that designers & coders never used; it was wonderful.

    To be fair, you could abstract this stuff in Director. The crew over at Director-Online had at least 2 sprite engines that emulated what Flash did, with extra features. Furthermore, I couldn’t really appreciate this stuff back then anyway; I couldn’t even return values from functions. I just had functions set global variables. Class? Que? n00b.

    I tried going back after I learned some things, but I just couldn’t do it. Flash offered too much. It was soo fast. So much more effective. ActionScript just seemed more organized than Lingo.

    After getting over my frustration at AS1, I learned that I could create re-usable stuff. While I loved to re-invent the wheel ALL THE FRIKIN’ TIME, it did get tiring after awhile, especially when my 4th generation Scrollbar still lacked track clicking and scroll buttons. Creating re-usable tools was hot.

    After getting over my furious frustration with AS2, and learning enough design patterns to pretend like I knew what I was doing, I slowly developed a loathing for AS1. I then had a hatred for anything not AS1; aka, code puked on frames.

    I remember seeing a lot of creative things done with prototype in ActionScript 1, however, and even some still in AS2. So, I tried to go back, and experiment. I always ended up getting bit in the arse in the end.

    When AS3 came out, the early version, it actually wasn’t that different (for me) from AS2. AddChild vs. createNewMovieClip, aka the new DisplayList was pretty easy. Protected vs. private, and other namespace features made sense pretty quickly too. The only hard thing was learning the immensely large new API. It’s one thing to remember that a CheckBox emits both a click AND a change event in the Flex SDK, and you need to care about the latter… it’s another to remember that navigateToURL is in the flash.utils.* package. Even the built-in stuff is immensely large.

    What is interesting, though, is that I never developed a hatred for AS2. Because of the complete and utter lack of communication between the 2 AVM’s, combined with Flex’ slow rise to power meant a lot of parallel AS2 and AS3 work. If you asked me if I wanted to do an AS2 or AS3 project, I’d probably respond AS3, unless your deadline was a week or less.

    …and that’s my point. Writing AS3 is slow. It’s finally reached a maturity as a programming language; a real language, not a “scripting language” because it now officially compiles to machine code on 3 differentchip sets. As a real language, it has all the features (most, hehe… private constructor what, abstract classes who?) a traditional programmer would expect from a programming language.

    My boss, a professional Java Developer who now does a lot of PHP (and I’m sure has a larger illustrious career I don’t know about yet), said that a strongly-typed language should be making me faster, not slower.

    In shock and anger, I pulled my phone from my pocket, called up “Bullshit”, and requested he leap upon my bosses’ head.

    There is a reason I click the “Flash” icon on my task bar, do File > New, hit F9, and test a new String parsing algorithm there in AS3 instead of going the ActionScript project route in Flex Builder… or even “new ActionScript File” and making it launching it as an Application. Flash is faster. Sure, once you get rolling, you can have some good test bed code combined with test cases even run by ANT in Flex. I’d still argue the instant gratification in Flash beats Flex.

    …but it doesn’t stop there. I mean, after hearing about things such as “int promotion” and “compiler optimizations based on clear, strongly-typed variables”, AS3 can get out of control. Parsing a pipe (|) delimited string, properties separated by commas (,), with name value pairs separated by equal signs (=) has gone from 15 lines in pre AS1 to 40 in AS3 if you ensure every parsed variable is strongly typed. For an algorithm that’s only run one time very rarely, AS3 doesn’t really benefit here.

    Fine? Then why not NOT strongly type so much? Only strongly-type to ensure you don’t get any type casting exceptions, and move on with life?

    …because… I … can’t. It’s hard to stop. I’ve been trained by the fear of the software engineer army to strongly-type everything. To ensure the compiler has a crystal clear understanding of everything, and that my code will run at moch-10. I can have faith that the old AVM will never even need gas, because the key in the ignition for it will never be turned. All the code I write now ensures everything is typed, and all namespaces are correct.

    I’ve tried abandoning namespaces and using *, Object, and even just abandoning type-casting in general for quick tests or prototypes. It’s just as time goes on, I find the code I add to those things starts getting more AS3 like.

    Bottom line, it’s really really hard to break the habit. Every time I go back to AS2 for some random project, I’m reminded how damn fast it is to create things in it. Half the exceptions I get in AS3 I really don’t care about, and don’t need to know about; they don’t impact the project from working if they are small in scope. A lot of my data is either primitives or simply arrays.

    For smaller projects, AS2 is still the bomb. For smaller algorithms, less strong-typing just results in less, more readable code.

    I can see why professional Ruby, JavaScript, and Python developers still exist. I don’t care what anyone says, loosely typed scripting languages still kick ass. While I wish their engines weren’t so damn slow for larger projects, lately, I’ve just been finding that for a lot of smaller scoped projects or areas, I’m glad I have the loosely typed option.

    While I fully believe the majority of the industry will use C# for Silverlight 1.1 going forward, MAN was it refreshing to write it in JavaScript for 1.0. Taking a break from AS3’s strict ways was great. SmartFoxServer has an option similar to later builds of Red5. You can write in the standard Java for performance reasons OR in your scripting language of choice (JavaScript, Python, etc). For a lot of work, scripting languages are good enough, and since they are good enough, you can write less code, faster to get the same result. That last part is debatable, but not by me. After having a career in both, to me they both clearly have their place.

    …what I can’t figure out is how to drop the “good habits” that AS3 teaches you to go back to fast and furious ways of scripting languages.

  • Scale 9 in Silverlight

    Silverlight Scale 9Samples at bottom.

    In creating video players at work in Silverlight, we started getting designs that needed Scale 9. Silverlight, Blend, and/or Design don’t seem to have a Scale 9 option that I can find, so I built one in JavaScript for Silverlight 1.0. Porting to C# for all you Silverlight 1.1 peeps out there should be trivial since it’s not a lot of code.

    What is Scale 9?

    Scale 9 is the ability to have an image scale in a nice, visually appealing way by breaking up the image into 9 sections. It is used primarily with containers such as the windows you use on your OS. For example, if you scale the browser or RSS reader you are reading this in right now, you’ll notice that the top task bar can shrink it’s width, yet still look consistent and nice. If you shrink it vertically, you’ll notice that the sides shrink, yet still keep aligned, and looking nice as well.

    Scale 9 was in my experience done a lot in Flash because as Flash got used more in the application development field, people started creating controls. Those controls were re-usable visual components, and a lot could redraw themselves via code. This code would allow visual layout changes very easily. So, a Button could be as big or as small as you wanted it to be just by calling the Button’s setSize function, and passing in a width and height. The Button would “handle” sizing itself to that size.

    However, a lot of anything in Flash before ActionScript 3 had a lot of overhead in CPU and RAM. So, by implementing Scale 9 natively in the compilers & Flash Player, you reduced the image count from 9 to 1. For 30 buttons, that’s 270 visual objects being moved and sized to 30; 1 to 1. You can see how this is an awesome feature, especially when the runtime does the scaling for you taking the code out of the equation as well.

    RectanglesObviously, for uniform rectangles, you don’t need scale 9. For rounded rectangles, or for anything that has non-uniform edges, if you start scaling it, it’ll stretch and look nasty.

    Here’s a good article by Aral that shows how scale 9 works in Flex (scroll mid-way).

    How does Scale 9 work?

    Image GridScale 9 works by breaking the images into 9 sections. The 4 corners do not scale their width and height, but do reposition themselves to their respective corners. The top left always stays in the top left. The top right always stays in the top right. And so on.

    The top and bottom can scale their width larger or smaller, but not their height. The left and right side can scale their height, but not their width. The center scales normally, and positions himself in the middle of everyone.

    Combining this with custom sliced images, you have 9 pieces that form your image, and can scale to any size, though usually have a minimum width and height.

    How does my implementation differ from Flash & Flex?

    Flash 8 and Flash CS3 do vector only. Additionally, they only require 1 image whereas in this example, you need 9 bitmaps sliced up. Flex can do vector and bitmap, but has the same advantages of Flash; 1 image. Both use the compiler to define the drawing matrix where mine just re-positions things on the fly based on the passed in width and height. Mine’s written in JavaScript which isn’t compiled like C# or ActionScript 3 so runs slower.

    The performance for me, however, is beyond acceptable; for a video player in a browser, it performs very well.

    How do you make an interface capable of being scaled via scale 9?

    A few steps.

    1. Get a designer to create an appropriate comp.
    2. Slice the image up into 9 pieces.
    3. Implement those 9 images into Blend.
    4. Put code to re-position & resize them in your JavaScript.
    5. Tweak.

    Explain to the designer that the border & background, typically a video player, will be scaled to a variety of width’s and height. If you say, “Emulate how Windows XP with the silver theme has those nice, scaleable windows that look good at most any size”, that helps. Things to watch out for are drop-shadows, gradients that go the same direction you are scaling, and lots of textures on the non-corners. Those 3 make it really hard for the design to scale. If the designer can scale it in their image editing program as a bitmap (not vector) and it still looks good, that’s a good acid test for the design. “How would it look with a 4×3 video in it… say, 320×240? How about an HD 16×9 one that’s 420×270?”

    Fireworks RedOnce you get the image, slice the mofo up into pieces. I use Firefox because it’s the shiz for doing quick production work. You could also use Design or Photoshop, for example… I’m just fast at “doing the work the designer doesn’t want to do” in Fireworks. You typically align 4 guides to make your 9 sections. You then make sure the tops can scale width wise, and the sides veritcally. Then you export the slices as PNG’s. You do PNG because it’s lossless comperssion (meaning no image quality loss from compression), and it supports transparency. Then…

    Blend Red…import those bad boys into Blend. Make sure the width and height of the XAML Image tag matches your exported PNG’s so you don’t get any weird scaling. If you see transform matrix tags nested in your image tags for the background pieces, delete that mess; you are using code, not Blend, to position and size your background pieces.

    Use the example scale 9 code below in your JavaScript to scale 9 your interface. Keep in mind CSS has a major impact on this actually working in browsers other than IE. Here’s some example code (at the bottom, 2nd to last thread) on how to get this to work in both browsers.

    Tweak. You may not get it right the first time. Additionally, I swear Silverlight is either scaling my images a tad, or I’m just using Canvas.Left and Canvas.Top wrong. You’ll notice magic numbers in the redraw function; these change EVERY design. For some reason (maybe half-pixel values I’m not seeing) some designs either bleed into another by a pixel, or miss one. The “1”‘s in the redraw function are there to make it, like Goldielocks, just right. Test in both IE, Firefox, and Safari if you gotta Mac or are brave enough to install Safari on your PC.

    Scale 9 JavaScript Code

    Scale9 = function(tl, tc, tr, cl, c, cr, bl, bc, br){
    
    	this.tl = tl;
    
    	this.tc = tc;
    
    	this.tr = tr;
    
    	this.cl = cl;
    
    	this.c  = c;
    
    	this.cr = cr;
    
    	this.bl = bl;
    
    	this.bc = bc;
    
    	this.br = br;
    
    };
    Scale9.prototype.redraw = function(sender, width, height, offsetX, offsetY){
    
    	if(offsetX == null) offsetX = 0;
    
    	if(offsetY == null) offsetY = 0;
    
    	this.move(this.tl, offsetX, offsetY);
    
    	this.move(this.tc, this.getX(this.tl) + this.tl.width, this.getY(this.tl));
    
    	this.move(this.tr, width - this.tr.width, this.getY(this.tc));
    
    	this.tc.width = width - this.getX(this.tc) - this.tr.width;
    
    	this.move(this.cl, this.getX(this.tl), this.getY(this.tl) + this.tl.height);
    
    	this.move(this.c, this.getX(this.cl) + this.cl.width, this.getY(this.cl));
    
    	this.move(this.cr, width - this.cr.width, this.getY(this.cl));
    
    	this.c.width = width - this.getX(this.c) - this.cr.width;
    
    	this.move(this.bl, this.getX(this.cl), height - this.bl.height - 1);
    
    	this.cl.height = height - this.getY(this.cl) - this.bl.height - 1;
    
    	this.c.height = this.cl.height;
    
    	this.cr.height = this.cl.height;
    
    	this.move(this.br, width - this.br.width, height - this.br.height - 1);
    
    	this.move(this.bc, this.getX(this.bl) + this.bl.width, this.getY(this.bl));
    
    	this.bc.width = width - this.getX(this.bc) - this.br.width;
    
    };
    Scale9.prototype.move = function(obj, x, y){
    
    	obj["Canvas.Left"] = x;
    
    	obj["Canvas.Top"] = y;
    
    };
    
    Scale9.prototype.getX = function(obj)
    
    {
    
    	return obj["Canvas.Left"];
    
    };
    
    Scale9.prototype.getY = function(obj)
    
    {
    
    	return obj["Canvas.Top"];
    
    };

    Example Usage

    function onLoaded(sender, args){
    
    	var plugin = sender.getHost();
    
    	plugin.content.onFullScreenChange = onFullScreenChanged;
    
    	plugin.content.onResize = onResized;
    
    }
    
    function onResized(sender, eventArgs)
    {
            var plugin = sender.getHost();
            setSize(sender, plugin.content.actualWidth, plugin.content.actualHeight);
    }
    
    function onFullScreenChanged(sender, eventArgs)
    
    {
    
    	var plugin = sender.getHost();
    
    	setSize(sender, plugin.content.actualWidth, plugin.content.actualHeight);
    
    }
    
    function fullscreenThisMugUpInHere(sender, args)
    
    {
    
    	var plugin = sender.getHost();
    
    	plugin.content.fullScreen = !plugin.content.fullScreen;
    
    }
    function setSize(sender, width, height)
    {
    
    	var scale9 = new Scale9(sender.findName("bg_tl"),
    
    	sender.findName("bg_top"),
    
    	sender.findName("bg_tr"),
    
    	sender.findName("bg_cl"),
    
    	sender.findName("bg_center"),
    
    	sender.findName("bg_cr"),
    
    	sender.findName("bg_bl"),
    
    	sender.findName("bg_bottom"),
    
    	sender.findName("bg_br"));
    
    	scale9.redraw(sender, width, height);
    
    }

    Conclusions

    While vector graphics can be redrawn to get around scale 9 problems with code, not all designs are that simple. Furthermore, as much as Microsoft wants the design community to use Design to create interfaces, they don’t; they use Illustrator, Photoshop, and other 3D and video compositing software NOT made by Microsoft. As such, you’re likely to get a bitmap file that you’re expected to implement into Silverlight instead of an easy, vector design with XAML behind it. Blend is pretty pimp in it’s handling of PNG’s, so if you gotta go raster instead of vector, go with the best.

    Also, keep in mind scale 9 works the same for fullscreen; you just call the scale9.redraw function in the onFullScreen as well as the onResize and it’ll nicely scale to the size of your monitor.

    Thanks for the Gray frame design on such short notice, Charlie!

    Samples

    Red Video Player – Example | Source ZIP

    Gray Video Player – Example | Source ZIP

    Released under a Creative Commons GNU General Public License.

  • No exclude.xml in Flash CS3 for AS3: Solution via Bridge Pattern

    Exclude.xml, functionality in Flash 8 and MX 2004 that allowed you to exclude ActionScript 2 classes compiled into your SWF, does not work in Flash CS3 for ActionScript 3. A similar function is available in Flex 2 via the load-externs option. This is the basis of how Flex modules work. The lack of this functionality just adds another challenge to Flash Developers who have expectations coming from AS2; this actually makes AS3 usage in Flash worse than AS2 when creating Flash sites, or large Flash applications.

    “Great Jesse, no one cares about your vendetta, so how do we fix it?”

    I have no clue, but the server architect I work with, John Howard, had a good idea. We’ll probably implement it in the next 2 weeks after we hit some interim milestones. I’ll explain his idea at the bottom, but first a review. If you want to skip the review, go to the bottom.

    Why Exclude Classes?

    When creating large Flash websites or applications, you’ll tend to have many SWF’s. This was especially true with AS2 driven not just from a media perspective, but also from a performance one. If you go to a visual website, say Flickr, and spend 20 minutes on it, you’ll probably download hundreds of images. Rather than download 20 minutes worth of images initially, you download on the fly and download whats needed. Flash and Flex apps can be built this way; it’s called excluding classes in Flash, and modules in Flex.

    In Flash, the main way to download assets over time is to load external SWF’s into another SWF. You use the loadMovie/loadMovieNum functions or the MovieClipLoader class, or the Loader component to do this pre-AS3. Although you can load images and video externally from a SWF just like a webpage can, the SWF format itself has visual advantages, such as images that can have alpha channels, yet also have JPEG compression applied to those images. JPEG does not have alpha channels, GIF only has a 1 bit alpha, and PNG never got the glorious browser support we all desired and only has lossless compression. When creating visual layouts that have a lot of media such as a multitude of images, audio, and/or video meshed with animations, this can be a stand alone SWF. Typically those types of things would be put into their own symbols such as a Graphic or MovieClip. However, if they got large enough, you should make it an external SWF for 3 reasons.

    The first is because it’s faster for you to make changes to the SWF. When you do a test movie, aka compile a SWF, Flash has to render animations, compress your bitmaps and sounds, as well as integrate your video if any. This can take a lot of time. Sometimes that time isn’t actually that bad, but because of the frequency in which you are re-compiling your SWF’s to check for visual accuracy, and doing this say every 2 minutes, and you end up saving 2 seconds in your compile… well, hey, that’s almost 10 minutes of your day you just saved right there! This is more apparent for larger media, however, like mp3 compressing a bunch of audio, or integrated video that can make your FLA’s take a minute or more to compile.

    The second is you can get help, aka RAD development. Instead of sharing the same FLA, you can have a project broken up into multiple FLA’s that another designer/developer can use so you both can work together on the same project.

    The third is that you only make the user download what they need to download. If you have a site that has 6 sections, you only need to make the user download the first section. You can either load the other section when the user clicks to go there, or download in the background once the first is done.

    The work-flow for visual projects in Flash is dead easy. There are a lot of frameworks, such as Gaia, and methodologies out there for facilitating this kind of work.

    For Flex, you have to be a rocket scientist. Flex 3 has some help in this department, but they are a long way off in how easy this is in Flash.

    For Flash applications, it’s a little different. In the beginning, our first enhancement to this was Remote Shared Libraries. What this allowed you to do was have a “reference MovieClip”, or any other symbol for that matter, in your library. Your symbol would have the SWF that it is stored in stored with the symbol as metadata. You’d go make that Symbol in another FLA, and upload those SWF’s together to your website. When your SWF was played, if a remotely shared symbol appeared on the time line, the Flash Player would automatically go download this for you.

    The bad was you really didn’t have much in the way of code in control or getting events about this. However, that ended up saving you a lot of work since it did it for you. Either way, this worked out pretty good because you could treat the symbols as normal symbols; the FLA would actually keep a local copy. You could update the symbol from the Library in case it changed in another FLA. You could additionally ensure every time you compiled it updated for you, but this was the slowest thing on the planet.

    In the end, Remote Shared Libraries were a management nightmare in Flash. For simple projects where you had a master SWF, they worked damn good. For anything more complicated, it was what I call “Flash Jenga” (Jenga is a game consisting of a tower of stacked wooden blacks the size of your pinky. The challenge was to remove bottom blocks without making the whole thing topple). If you got it to work, you were the shit, but it was very easy to break, and once it did, things came crashing down. The tools never really helped you manage your Remote Shared Libraries.

    Flex Builder has some nice improvements in this realm with regards to tool support.

    The biggest problem, however, with Remote Shared Libraries in regards to application development and code. Like I said, they still work good for assets; anything that isn’t ActionScript classes.

    Since ActionScript 2 and 3 utilize a lot of classes, and thus have dependencies, this makes things challenging when creating your applications for low initial download impact in mind. I’ll rehash my version here, but reading these 3 blog posts by one of the the mxmlc compiler creators, Roger Gonzalez formerly of Adobe, is probably a little more authoritative and better written. (Multi-SWF Applications, Modular Applications (part 1), Modular Applications (part 2)).

    It’s hard enough to architect an application, especially when accounting for a designers needs for dynamic Views. It’s another when you visualize a package of classes, and then have to account on how to reduce dependencies so you only load some classes in some SWF’s, and others in another SWF, but be sure not to use in a master SWF, thus reducing the overall file size. This can lead to code duplication, or a non-efficient use of a RSL, or too much in an RSL that’s not used by 80% of the application. As if software development wasn’t hard enough, you have a designer who keeps changing your MovieClip instance names.

    You could just say fuggit, and just load a bunch of SWF’s as users navigate to those sections. However, your wasting bandwidth by using duplicated code. For example, in the image below, 3 forms are loaded into a master SWF on the fly whenever a user navigates to that section. Each other has it’s own unique set of components; however, each also has it’s own copy of Button, or mx.controls.Button to be exact in AS2. Say that your Button is 14k. You’ve now duplicated that 14k across 3 SWF’s.

    Exclude-01

    …however, why not just load that class once, and have all other SWF’s use that same already loaded class? You can! First, a review on how AS1/AS2 classes work.

    In the old AVM, aka, the one that runs AS2 and A1 (regardless of player version), classes are defined on _global. The _global keyword is like this object that never dies, and is accessible via the _global keyword in ActionScript. It’s also accessible across SWF’s and across _levels (_level is like a loaded SWF basically). This means that SWF’s loaded in can access classes on _global as well as defining their own. They cannot, however, overwrite classes. In AS3, this behavior is controlled via ApplicationDomain; in AS2, it is what it is.

    Since you know you’ll be loading those 3 SWF’s into a SWF that will already have the Button class defined, you can then just not compile those 3 SWF’s with the Button class. The user then only has to download 14k once; any other SWF that uses the Button class can use that already downloaded class. In the example below, the Button class has been moved to the shell.swf, increasing it’s size from 8k to 22k. However, notice that that same 14k is now removed from the login.swf, the amount.swf, and settings.swf.

    Exclude-02

    In this particular example, you’ve ended up saving 24k! Now, imagine a large website or large application consisting of dozens of SWF’s that could potentially use the same class. You can see how this feature saves a ton of bandwidth.

    How Exclude.xml Works

    Exclude.xml works like dis. If you have a FLA called “my.fla”, you create an XML file in the same directory next to the FLA called “my_exclude.xml”. When you compile your FLA, Flash will look for that exclude.xml file. If it finds it, it’ll read it. Any class written in that XML file will NOT be compiled into your SWF. The con to this is the SWF no longer works on it’s own; you have to load it into another SWF to test. The plus is that you’ve now saved file-size since the SWF will get the class it needs to work from another main.swf. Most importantly, your work flow has changed; just your SWF.

    In the past, I wrote some JSFL to automate this. One JSFL script would delete the exclude.xml file, and then do a test movie. You map this JSFL to Control + Enter so your Test Movie works as normal. I then created another JSFL script to create the exclude.xml based off of a set of classes I knew would be shared throughout the site, and then test your movie. I then mapped this JSFL to Control + Alt + Enter, replacing test scene. That way, you can create SWF’s ready for deployment easily.

    Now that Flash CS3 has E4X, writing such scripts is a ton easier, and gives ANT in Eclipse a run for it’s money in automation. Course one could use Rake (Ruby‘s version of Make), but anyway.

    In Flex using mxmlc, this part is actually automated for you; the XML you need is generated via the mxmlc -link-report parameter. You immediately feed that generated XML file to -load-externs, and booya, you have a SWF with those classes removed.

    So, pretty pimp, huh? Guess what; it doesn’t work in Flash CS3 for AS3. I know, right? “Yeah hi, I’ll take some AS3 with a side of lame sauce.”

    Using mxmlc Doesn’t Work

    I tried using mxmlc with -incremental set to true, making sure it doesn’t actually recompile the entire SWF, but just those classes that have changed. If you make sure your FLA has a Document class, this’ll work; mxmlc can use that as the root class. However, in recompiling your classes, it basically ignores the symbols your FLA has created, thus “I’ll take it from here” attitude. Um…mxmlc, dude, f-off, at least we can use pixel fonts…

    You could do this in MTASC for AS2, I guess their bytecode replacement techniques are just different. Either that, or I’m maybe missing a mixture of mxmlc compiler arguments… :: crosses fingers hoping someone says so in comments ::

    Bridge Pattern to the Rescue (sort of)

    So, my boss suggested a proxy technique. Basically, we use the J2EE blah blah blah official blah blah Bridge Pattern. The Bridge Pattern in a nutshell is 2 classes that implement the same interface; one provides the pretty face, whilst the other does all the work. The pretty face is called the Abstraction and the one who does the work is called the Implementation.

    If you were going to create a Button component using the Bridge Pattern, you would do it in 3 steps.

    1. Create the IButton interface
    2. Create the Button class that implements IButton
    3. Create the ButtonImpl class that implements IButton, and does all the work.

    Flex 2 actually uses this in a few places, specifically the ToolTipManager class. ToolTipManager merely proxies everything to ToolTipManagerImpl. He instantiates an Implementation class (ToolTipManagerImpl) via a magic string to ensure there are no dependencies, meaning the compiler doesn’t know to compile it in. To ensure it is compiled in, however, they do do (gross) a dependency variable above that.

    This is how the Bridge pattern will work to save file size. The child SWF’s will only contain the interfaces and abstractions; the implementations will be in the main SWF. First thing to do is create the interface, mainly for typing purposes.

    Now that that’s done, I do the same thing the ToolTipManager does; I instantiate the ButtonImpl class inside of Button via a magic string. This ensures that Flash doesn’t see the usage of the class. If it did that, Flash would compile it in. A magic string, however, cloaks it from the compiler. Using flash.utils.getDefinitionByName, I can instantiate the ButtonImpl class with my magic string:

    var btnImpl:Object = getDefinitionByName("com.multicast.controls.ButtonImpl");
    impl = new btnIpml() as IButton;

    Now, I can just create my sets of components as normal:

    var btn:Button = new Button();
    addChild(btn);

    However, the ButtonImpl class won’t be compiled into the child SWF’s. Instead, he’ll be compiled into the main shell.swf.

    Based on some initial tests, I reckon interface will run about 500 bytes to 2k, and the Button class from 2k to 4k. The Impl will be around 8k. So, being conservative and rounding up, all of my child SWF’s will no longer have 14k in them, but rather 6k. Like exclude, the developer whether using Flex Builder with an ActionScript project, or Flash CS3, can code normally with AS3’s strong-typing, and/or Flash’s time line and symbols. The down-side is I’m still duplicating anywhere from 2k to 6k in any additional child SWF that uses Button.

    It’s not perfect, but it’ll do.

    Unknowns

    What I haven’t figured out yet is the implementation details. Premature optimization is the root of all evil so I hear, but seriously, how much speed does keeping the interface for strong-typing really give me? What if I just remove the interface, and cast impl in the example above as a DisplayObject, or more accurately, a MovieClip? I feel the Interface is for Java people who like a bunch of classes; to me, 2 is too many, let alone 2 and an interface. I’m only doing this because a feature that worked in 2 previous Flash IDE’s now doesn’t; don’t punish me by making me write more classes to compensate for a feature that removed classes in the first place. Convention works for the Ruby guys; why not me? I don’t really want to spend much time on benchmarks, but any dynamic look up will cause the old AVM to be used, and since this component set is created with AS3, it kind of defeats the purpose of using AS3 if you aren’t going to take advantage of the runtime speed.

    Secondly, what is impl, a DisplayObject, or rather a class that uses a DisplayObject via Composition? Traditional programmers who came to Flash in the past would use Composition all the time because the thought of extending a GUI base class freaked them out. So, instead of extending MovieClip or Sprite, they’d instead store a reference to the MovieClip or Sprite passed in the constructor. All methods would then act on that reference, as opposed to the class itself via Inheritance. Would doing Composition be better? Although it may have a tad more code, it’d be redundant, so hopefully zlib SWF compression would see that and I’d still hit my small file size goal. Furthermore, I wouldn’t end up with twice as many DisplayObjects. In AS2 that was bad, but in AS3… not so much. If all Buttons were just a simple shell with the “real” Button inside it as the impl, is that really that bad? My gut says make the Implementation class via Composition to save on the number of DisplayObjects.

    Basically, rather than doing:

    // Button.as
    private var impl:IButton;
    
    public function Button():void
    {
            var btnImplClass:Object = getClassByDefinition("com.multicast.controls.ButtonImpl");
            impl = new btnImplClass() as IButton;
            addChild(impl);
    }
    
    public function setSize(w:Number, h:Number):void
    {
            impl.setSize(w, h);
    }
    
    // ButtonImpl.as
    public function setSize(w:Number, h:Number):void
    {
            this.width         = w;
            this.height     = h;
    }

    I’d instead do:

    // Button.as
    private var impl:IButton;
    
    public function Button():void
    {
            var btnImplClass:Object = getClassByDefinition("com.multicast.controls.ButtonImpl");
            impl = new btnImplClass(this) as IButton;
    }
    
    public function setSize(w:Number, h:Number):void
    {
            impl.setSize(w, h);
    }
    
    // ButtonImpl.as
    private var btn:IButton;
    
    public function ButtonImpl(ref:IButton):void
    {
            btn = ref;
    }
    
    public function setSize(w:Number, h:Number):void
    {
            btn.width         = w;
            btn.height        = h;
    }

    Any other ideas (or corrections), lemme know.

  • How to Show Regular Time in Google Spreadsheets

    I cannot read military time. I can read regular time. Google Spreadsheets at the time of this writing only supports formatting for military time. After digging around, I found this formula works:

    =TEXT ( theCell, “hh:mm a”)

    You can then have the military time column (which will auto-format when you type a time value in) to the left, and then use the above formula for the column to the right. Combined with changing the military time column to a lighter text to lower it’s visual prominence, you get something like this: