Category: Flash

  • 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!

  • Smooth All Bitmaps in Flash

    I keep getting emails asking for code I wrote over 4 years ago. Not sure where most of that stuff is now. The most popular, however, is a JSFL script for smoothing all of your bitmaps in Flash. Here it is as text; that way, if my blog changes 4 years from now, at least it’ll be cached somewhere.

    Just copy the text, paste in a new text file, save as “Smooth All Bitmaps.jsfl”.  In Flash open the FLA you want to affect, choose Commands > Run Command, and choose the script file you just saved.  Done.

    You can copy from Pastebin, or from the below:

    /*
    
    Smooth All Bitmaps
    
    Turns all bitmaps in your library to have their smoothing property on.
    
    by JesterXL
    jesterxl@jessewarden.com
    jesse.warden@gmail.com
    http://jessewarden.com
    
    This code is under the MIT License
    
    Copyright (c)  
    
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                                                                    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                                                                    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    
    */
    
    function init()
    {
            fl.outputPanel.clear();
            var item_array = fl.getDocumentDOM().library.items;
            var i = item_array.length;
            while(i--)
            {
                    var item = item_array[i];
                    if(item.itemType == "bitmap")
                    {
                            item.allowSmoothing = true;
                            fl.trace("");
                            fl.trace(item.name + " allowSmoothing is now true.n");
                    }
            }
    }
    
    // start this mug
    init();
  • Loading Random SWFs in a Strongly Typed Way

    In a hurry? Skip to the code.

    ActionScript 3 has given us true strong-typing; both compile time and runtime. This has many benefits from helping ensure code works once you actually compile as well as helping you debug runtime errors. The problem with perfect systems however is when you put in some chaos. The old adage, “garbage in, garbage out” holds true here. There are basically 2 ways to get weird stuff in Flash Player. You either load in external data and parse it, or you load in an external SWF.

    The former is a little easier to deal with. Using E4X, if some XML node doesn’t exist, your code doesn’t throw exceptions. You can test against undefined, and set default values that match your ValueObjects (strongly typed classes that represent your data). In short, you can correctly write an XML parser that shields your app from bad data. Granted, his job is the most important as he’s the guardian against all loose wrenches in the gears. I’d say the majority of the bugs in the software I write in AS3 comes from a Factory letting bad or missing data through without either compensating with default values, or dispatching an appropriate error. In the end, though, if you do it right, you’re good.

    External SWF’s, on the other hand aren’t really parsed. There are some bad asses doing some weird things with SWF’s, like loading them in for asset use only (since even Images are classes now that can be ripped out of externally loaded SWF’s, aka WinAMP skinning) or just Flash native data transfer objects like Aral does with SWX. For the most part, most use cases that call for loading in an external SWF are NOT positive beyond the 2 above. Some common use cases not including the above are:

    • loading in Flash Player 8, or below content
    • loading in Flash content created in the Flash IDE as opposed to Flex
    • loading in assets too big to compile into main SWF and un-linkable to Flex’ RSL work flow (audio, video)
    • 3rd party PRE-generated created SWF’s (even if AS3, still could use different component set)

    This entry will target #2 and #3. For #1, here’s some morphine. For #4, good luck in the politic-infused blame game meetings.

    Flash is damn good at creating creative content. Whether this is created in-house or outsourced to a 3rd party design firm, you can have this content be in Flash Player 9, AS3. While this sounds positive, it just sucks you cannot easily make this a part of your work flow. There are a few ways I’ve talked about in the past using the Flex Component Kit for Flash, which is now part of Flex 3, or simply writing wrapper classes. The Flex Component Kit is really great if you know ahead of time the scope of what the Flash will be, or it won’t be in flux. The same goes for the wrapper classes with those who are in more formalized programming environments.

    However, sometimes you just get this problem that just defies all conventional ways of solving it. For example, a not-too-small widget was created in Flash CS3 using the new components. It may not easily portable to the Flex components in a reasonable time frame. What do you do? Attempt to get the Flash components to compile, with assets in Flex? I’ve tried this myself and wasted a bunch of time on it. I’m sure it’s possible, but I’m past trying, instead getting work done.

    Real world scenario; DoubleClick’s In-Stream for AS3. Apparently you can get the SWC to work in Flex… we couldn’t. Even if we could, you can can’t test the S.O.B. locally, needs a webserver… So, you have no choice but to use Flash in this scenario.

    In those situations, all you can do is load it in at runtime. The silver lining? Both are AS3. AS3 SWF’s can talk to each other. Your Flex SWF can call methods on the loaded Flash SWF. However, to call methods, the Flex SWF must “know” about those methods; hence being strongly-typed. You’d then have to share the same class between SWF’s. While this wouldn’t be too bad, Flash CS3 broke exclude.xml, the ability to compile a SWF, but excluding certain classes from it. You did this so you could prevent compiling the same class into multiple child SWF’s that you knew would have the same class waiting for them in the parent.

    Sanders commented on my past blog entry about this that there is apparently a way to get it to work. I haven’t read into it, but using intrinsics (namespace internal) seems a valid solution. Using JSFL, it’s also tons easier to create code generating and others tools for Flash than it is for Flex and ANT. Then again, I haven’t tried Europa’s (Eclipse 3.2) JavaScript API yet… me? Digressing? No way…

    Dirk originally came up with the idea of using interfaces when loading Flash content into Flex. At the time, Flex was Flash Player 7 only, and Flash was at Flash Player 8. Flash Player 8 had all the new effect filters; Flex did not. Using interfaces, you could utilize BlurFilter for example via a SWF liaison; file uploading too.

    The reason Interfaces are nice in this scenario is firstly because it’s small; it’s just a tincy class, usually less than 1k (micro-small in bytes when compiled to bytecode). Since you will be adding this interface to 2 or more SWF’s, it helps to lessen the damage. Secondly, it’s strongly typed, even in AS3. You cast things to Interfaces and even test if something implements an interface the same way you test to see if an instance is a class via:

    trace ( cow is IBigPimpin ); // true
    
    trace ( cow is ISpendinGeez ); // true
    
    var rad : IUberYum = cow as IUberYum;

    The steps for loading in a strongly-typed SWF are as follows:

    1. Create an Interface that both Flex and Flash will utilize.
    2. In Flash CS3, have your Document class implement that Interface.
    3. Compile your SWF (aka Test Movie).
    4. In Flex, load in the SWF.
    5. In the Event.COMPLETE handler, cast the result to the interface, and store it as a class member variable.

    Here’s a sample interface that we use at work to handle a loaded Dart.swf. It loads pre-roll videos and ads (animated GIF’s or SWF’s). Notice the events… they give you code hinting in FlexBuilder for loaded SWF’s (Flex 3 only suckaz), woo WOO!

    package com.multicastmedia.doubleclick.core
    
    {
    
            import com.multicastmedia.doubleclick.events.DartEvent;        import flash.events.IEventDispatcher;
    
            [Event(name="gotCompanionAd", type="com.multicastmedia.doubleclick.events.DartEvent")]
    
            [Event(name="prerollDone", type="com.multicastmedia.doubleclick.events.DartEvent")]
    
            [Event(name="error", type="com.multicastmedia.doubleclick.events.DartEvent")]
    
            public interface IAdModule extends IEventDispatcher
    
            {
    
                    function loadPreroll(adx:String,sz:String):void;
    
                    function getCompanionAdURL():String;
    
                    function getCompanionAdClickThrough():String;
    
                    function setVolume(val:Number):void;
    
            }
    
    }

    …yes, I know the DartEvent is compiled into both SWF’s, HOWEVER, it is tincy, and in this case worth it since it’s needed.

    Here’s some psuedo code to load the SWF into Flex:

    // reference to the SWF so you can call methods on it later
    
    var dartSWF:IAdModule;// this can be a SWFLoader in Flex instead, doesn't have to be Loader
    
    var loader:Loader;
    
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
    
    function onComplete ( event : Event )
    
    {
    
            // once loaded, cast t3h SWF as an IAdModule
    
            dartSWF = loader.content as IAdModule;
    
    }

    The caveat to this, which I haven’t tested, is if you load your classes into a different ApplicationDomain. The only person on the planet I know who does this is me, so you don’t have to worry about it.

  • Silverlight on TV and in Startups

    I get exposed to a lot of girly TV shows. The reason is, my wife is one of those people who can leave the TV on for background noise, but not actually watch it. I’m the opposite. If a TV is on, I tune out everything else and get enraptured. During the working day when I’m at home, I’ll get up to get coffee or some food from the kitchen, and then return to my office to continue working. This path takes me past the living room where the Tivo has selected some weird show about modeling or some other celebrity thing.

    One particular show was Entertainment Tonight. Walking back to my office, I saw the Microsoft Silverlight logo. Naturally I slammed on the breaks, and stood there staring. This guy, one of the ET hosts, talking in all announcer voice went “Go to ET online where you can view other video content powered EXCLUSIVELY by Microsoft Silverlight”. Wow. I think I’d convulse on the ground like a 1980’s break dancer if they said that about Flash Player. If Ice-T wasn’t enough, now we have TV shows marketing it. Holy fish.

    Miles away from Adobe. Granted, both companies I think do a great job at engaging developers, but while the Adobe community makes their own banners, Microsoft fronts the bling for a media blitz.

    In other news, I got my first Silverlight 2 startup email. All through 2006, bit smaller amount in 2007, I’d get a least 3 new emails a week from startups looking to create some web app using X back-end with a Flex or Flash front end. It was really weird timing. I just told my CTO last week that we should hold off on any huge Silverlight endeavors that are greater than video players until at least Q1 2009. The reasons were Silverlight 2 is still in alpha, there are no official components yet, and we’re still at an early stage. For all of my positivity about Microsoft’s toolsets, Silverlight the plugin still needs to become ubiquitous in reality. Everyone can talk about how Microsoft can use Windows update, installation CD’s, etc., but it’s all talk and no action. Until I see numbers of successful installations and I can duplicate the ease of install on multiple computers, it’s not viable.

    Hopefully by Q3 of 2008, we’ll have all the toys ready to play with. At that point, we can start doing some serious investigation into the realities of porting some of our existing Windows Media content into a more Flash based realm; where video is dynamic and multimedia centric. Granted, we can do this now with all the alpha bits. Tons of people and companies did this with Adobe’s Flex 2 Alphas and Betas, building real-world projects, just waiting for the final release. They are doing the same thing now with Adobe AIR; in beta 3 and people are chomping at the bit to release on a final version with their already built products. I just mean actual development that isn’t considered skunk works and done off the company clock to make real progress with investigations.

    I can see how a company could perceive on how they could effectively build a product on alpha bits given both public videos such as Top Banana, and Adobe’s track record with usable beta’s. However, Silverlight doesn’t have a component framework out yet. If I’m wrong and it has an alpha version, then you’re good to go; if not, there is no point. Spending your time creating a List component vs. using a List component to build your product is a waste of time unless you plan on somehow monetizing your component work.

    Anyway, the tone of the email was the same as the rest I’ve seen in the past. Meaning, there will be more emails like this one. The Silverlight marketing is working.