Blog

  • Flex Chronicles #22: Embedding Fonts in a Button

    There are a few dark little secrets to the Button control in Flex 2 that can trip a designer up. It took me 2 1/2 hours to figure this shiz out so I just HAVE to blog it. I’m running on fumes, and this is the 3rd blog entry in the past 30 minutes, but my fingers never tire; they’re always willing to move furiously. They know I have words I need to get out, and fast because there is so much to do and so little time. My head feels like lead… it keeps swaying… wtf, am I at sea?

    The mx.controls.Button class utilizes a mx.core.UITextField for it’s text label. This class basically wraps TextField, and add some CSS & measurement support so it’s easier to work with. By default, a Button’s label is bold.

    This may seem minor, but if you try to embed a font, and apply the style to the button, it won’t work. You’ll apply the same style to Label’s, and see it work just fine, and go, ‘WTF?“. You can use a horrible hack, and utilize the mx_internal namespace, call getTextField on the Button, and call embedFonts on it to true. You can then apply this to every event a Button emits, and duct tape that mofo into submission. This looks & works horrible.

    The problem stems from the fact that when you are embedding a font, you aren’t always embedding the bold version of it. Some fonts don’t have bold equivalents, and some are specifically to be made bold, but aren’t seen as bold by some tools. Lame.

    The fix? 3 lines of CSS.

    Let me stop and just say right quick that Flex 2’s implementation of CSS is off the hook! It’s come a long way from Flex 1.5. I spent 4 hours the other day in CSS. That’s right… 4 hours in Firefox & CSS skinning & incorporating a design. Not MXML, not ActionScript, but CSS! Insanity. It feels so much like web design, but… something’s different… oh yeah, I know! My design actually, you know, works the same in every browser and looks like I intended with no compromises!

    Anyway, you overwrite the Button’s main style attributes. You ensure he’s embedding fonts, you set his font weight to normal, and you set his default font, like so:

    Button
    {
    	embedFonts: true;	
    	fontWeight: normal;
    	fontFamily: oldSkool;
    }
    
    @font-face
    {
    	src:url("PAPYRUS.TTF");
    	fontFamily: oldSkool;
    }

    This is a big deal because a lot of components use Button. You’ll have the same font problems with them as well, such as TabBar/TabNavigator, and LinkButton/LinkBar to name a few. Doing the above vs. using a custom style ensures that all LinkButtons and Tab’s will now use your font. w00t!

    :: collapses ::

  • Porting Flashcom Applications to ActionScript 3

    Regardless if you Flex or Flash, I ran into a porting issue with a Flashcom app I wrote in Flex 1.5 & ActionScript 2. A lot of the server-side code, which is written in case sensitive JavaScript 1, utilizes the Flashcom Component Framework. This framework utilizes a namespace scheme to allow clients to identify server components, and server components to identify client components. This allows them to send messages to each other, and works really well…

    …except in Flash Player 9. For some reason, the namespace mechanism doesn’t work for ActionScript 3 classes. This isn’t a big deal for playing existing content. All of my existing Flashcom apps I wrote in Flash MX 2004 & Flex 1.5 (Flash Player 7) still run just fine in Flash Player 9 in both Firefox & IE.

    It’s when you have a server-side script do a NetConnection.call on an Flash Player 9 created SWF that things don’t work. You CAN call a method that your class has defined as public assuming you point the NetConnection’s client property to your class; protected and private don’t work. However, the namespace mechanism commonly used in ActionScript 2 doesn’t work with the server; it constantly reports method not found. You’d typically decorate the client side NetConnection object reference that you’re component got passed in via it’s loose interface “connect” method. This decoration with the namespaces pointing to your component allowed the server-side to find it. The server-side Flashcom Component Framework already has a built-in namespace mechanism that still works just fine.

    You can emulate this by extending NetConnection, and making the class dynamic. Still, you’ll get the method not found error.

    My only guess at the problem is I think it has to do with the lack of support of “slash syntax”. I’m not sure the new ActionScript Virtual Machine supports it. I know AVM does; it’s how Flash Player 4 SWF’s will work the same as they always have. However, it seems the FCS Component Framework utilizes this behind the scenes somehow. When you do this on the server-side:

    nc.call ( this.callPrefix + "method" );

    You’re basically going:

    nc.call ( "YourComponent/InstanceName/method" );

    …I guess. I gave up after 3 nights of trying to get it to work. I didn’t mind porting client code, but I didn’t want to port server-side code. Anyway, fix for me is to pass in the callPrefix as the first parameter to the method, and have the client side Observer class just parse out “who this message goes to”.

    If you get it to work on your end, drop a note in the comments. I’m using Flex 2 & FCS 1.5 on Windows via Flash Player 9 in Firefox 1.5.

  • NetConnection, SharedObject, & NetStream’s client Property in ActionScript 3

    Past two weeks, I’ve been porting over some Flashcom & Flex 1.5 code to Flex 2 (still using FCS 1.5 vs. FMS 2). One nice addition I found in the ActionScript 3 SharedObject class is the client property. This little gem allows you have events that are called by SharedObject.send to be called on a proxy class instead. What this means is, if someone in a Flashcom application causes the remote SharedObject to be updated, and it fires a “onChatMessageUpdate” method, it’ll actually get called on the client object if you set it to something. Since a lot of intrinsic classes are now “final”, meaning you can’t futz with ‘em as easily as you could in AS2, this is a great way to incorporate it via Composition.

    var my_rso:SharedObject = SharedObject.getRemote("chat", nc.uri, false);
    my_rso.owner = this;
    my_rso.onChat = function(str)
    {
            this.owner.onChatMessage(str);
    };
    
    function onChatMessage(str)
    {
            textArea.text += str;
    }
    
    

    In the past, you’d use something like the above; proxying the message yourself, or even putting the logic inside the method closure if you were in a hurry.

    Now, you can forward it to an anonymous object, yourself, or even a class instance.

    var my_rso:SharedObject = SharedObject.getRemote("chat", nc.uri, false);
    my_rso.client = this; // onChatMessage needs to be a public function in this class
    my_rso.client = {onChatMessage: function(str){ // }}; // anonymous function
                    my_rso.client = new ProxyClass(); // you can make a class specifically to handle events
    

    David Simmons from Adobe told me it was on NetConnection as well. Just checked, and she’s on NetStream too. In my tests, for classes, it only works on methods in the public namespace; protected & private don’t work. I didn’t test custom namespaces, nor do I know how to make it “see” them.

    Handy! Thanks Adobe.

  • Flex 2 WebService & Cairngorm 2 Example

    *** Update: 8.14.2007: The code in this article is out of date. Please refer to the new entry instead. ***

    ws_icon.jpgThis example utilizes Amazon’s search webservice in the Cairngorm 2 application framework. You can go to Amazon.com and register for a free API key. Once you do, you just plug into this example’s constant file, and she’ll work for you too if you when you compile. This example application allows you to search for books on Amazon.com by keywords.

    The events are debatable in their place in the package structure. They extend CairngormEvent, thus implying they fire commands, but you could reuse events. Also, I am not very good at E4X so please do not use that as an example of E4X usage.

    Here’s basically how she works:

    1. App boots up, shows first state
    2. user types in some keywords, clicks the Search button
    3. this fires the doSearch event handler
    4. the doSearch handler creates a CairngormEvent, and dispatches it
    5. the Controller has mapped that type of event to a Command, and thus it runs the command, passing it the event
    6. the Command looks at the event type in the execute function and decides what to run, in this case, searchBooks, passing the event’s data to the function
    7. search books creates the Business Delegate, and calls its method
    8. the Delegate gets the WebService from the ServiceLocator, fires off the WebService, and waits for a response
    9. if the response is successful, it parses the E4X XML via a Factory to a list of Book ValueObjects
    10. finally, it calls the responder’s onResult function
    11. Since the Command is the Responder, he gets the data, and sets it to the ModelLocator and updates the applications state
    12. The View’s are bound to the state variable and book list in the ModelLocator, so they immediately have their bindings fire
    13. This causes the main app to change state, and show the results DataGrid
    14. The results DataGrid is bound to the books list in the ModelLocator, and shows the results.

    * Note: I haven’t got my serial for Flex Builder 2 yet, so the App & View Source will time out after a day. The source, however, is good forever.

    Flex 2 WebService & Cairngorm 2 Example – App | View Source | Source ZIP

    BTW, I fixed my Atom feeds, thanks to those who let me know they were busted. If I don’t know it’s broke, I can’t fix it.