Flex 3: Setting List component itemRenderer

In MXML you can easily set the itemRenderer to the string of your class, including dot syntax classpath, but in ActionScript it is different.

_list = new List();
_list.itemRenderer = new ClassFactory(IndexRenderer);
addChild(_list);

As you see the ClassFactory class is used because itemRenderer expects an IFactory implementation.

Just a quick tip.

GTween: Quick Review

One of the easy things to do in Flash is tween but it never hurts to make an easy thing easier and that’s exactly what Grant Skin…errr…my bad…gSkinner (hehe) has done. So, maybe it doesn’t suit you, heck…might not suit me all the time, but I would say it is at least worth a look.

(more…)

AIR Deleted My Desktop!!

Ok…this isn’t a “spoof” post or anything like that. AIR literally deleted everything on my desktop as well as screwed something up on my OS (Vista). How did this happen? I’m glad you asked.

First off…I didn’t tell it to delete ANYTHING. I’m adding features to an app and one of the features is to save a file to a network share so I was testing it against my desktop directory. Since this is AIR I figured a simple file copy was sufficient.

Do you remember that old joke where someone sent you a spam email and opening the attachment showed your My Computer window deleting every file on your system? That’s how I felt watching my desktop directory contents leave.

I’m on Windows…just right click on Recyle Bin and restore, right? NOPE. AIR DELETED ALL OF MY FILES PERMANENTLY!!!!! Every file…gone. I open Computer and and it tells me “C:\Users\John C. Bland II\Desktop refers to a location that is unavailable. …” which is great because now I literally do not have a desktop (beyond a background image).

So, again…how did this happen? Ok…don’t get testy. I had to vent through sidebars real quick.

//Copy JSON file to web server
var file:File = File.createTempFile();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeUTF(“some content”);
stream.close();

var jsonFile:File = new File(_filePath);
jsonFile.resolvePath(“live” + _Index + “.json”);
file.copyTo(jsonFile, true);

So, this all works up to the last line. Odd right? I don’t have any delete lines. _copyTo(…)_ is the culprit. Yep, copy really should be: copyAndDeleteAllContentsInTheDirectoryThenMoveFile(….). 🙁

What’s worse is the desktop directory is gone so I have NO idea if it even worked. Now I have to try it again. 🙁 This time I’m setting _filePath to _File.desktopDirectory.nativePath+”/myapp”_ so it will only delete that directory vs everything.

copyTo(…)’s overwrite explanation:
“If false, the copy will fail if the file specified by the target parameter already exists. If true, the operation will first delete any existing file or directory of the same name (however, you cannot copy a file or folder to its original path). (Note: If you set this parameter to true and the source and destination File objects point to the same path, calling this method deletes the file or directory.) ”

So…whatever it was…AIR DELETED MY DESKTOP! 🙁 Boo FLIPPIN’ hoo! 🙁

UPDATE:
The bug is in my _resolvePath_. It should be _jsonFile = jsonFile.resolvePath(“live” + _Index + “.json”);_. So, AIR tried to copy a file to a directory which caused the directory to get nixed since it was an overwrite. The time you want Vista’s UAC to kick in…it is MIA! 🙂

James Ward – Flex Videos

This is just a redirect to James’ site. He has posted two videos which are both pretty good.

Last night I decided to not work but found myself on the computer. So while I was messing around I had the videos play in the background and he covered the very basic to the good stuff. I thought it was well done and organized.

“Video: Flex Best Practices”:http://www.jamesward.com/wordpress/2008/07/22/video-flex-best-practices/

“Video: Flex and Java”:http://www.jamesward.com/wordpress/2008/07/21/video-flex-and-java/

Good work James.

LCDS 2.6 Released

I probably haven’t stated it publicly but LCDS is my favorite way of getting data into Flex. Even though I’m solid in CF I tend to enjoy setting a Java backend using Spring. Call me crazy but I dig Flex+Java(via)LCDS.

Anyways…”LCDS 2.6 is out”:http://www.adobe.com/products/livecycle/upgrade/dataservices.html and in the wild.
(Source: http://www.forta.com/blog/index.cfm/2008/7/21/LCDS-26-Released)

As I stated previously, here are my favorite features/updates in 2.6:
* **Data Management offline improvements** – Using the SQL database contained in Adobe AIR, you can use the offline support introduced in LiveCycle Data Services ES 2.5.1 to persist data directly to a SQL database. With little additional code, you can use an application written to use data management offline with complete access to any data and queries you executed online. To do so, specify a cache id and either use the auto-save option or explicitly save queries or items you want to persist offline for retrieval later.
* **Alignment with Adobe Flex 3** – LiveCycle Data Services ES 2.6 supports the releases of Adobe Flex 3 and Adobe Flex Builder 3.
* **Scalable HTTP based channel** – Supports thousands of connections for each Java process. You can use the RTMP channel if you are able to make these connections from your clients directly to the LiveCycle Data Services ES process. You can use the scalable HTTP based channel infrastructure if your clients can only connect to your servers using the HTTP protocol. Using the flexible ChannelSet mechanism of LiveCycle Data Services ES, it is easy to support a list of channels so your clients can connect using the implementation which provides the most efficient implementation.

Read the full “release notes here”:http://help.adobe.com/en_US/livecycle/8.2/lcds_releasenotes.html.

Enjoy!

Flex 3: Two-way Form Databinding

I saw this "trick" in someone’s code and have been using it lately so I thought I’d share. The idea is to create an object, bind it to the form elements, and bind the form elements to the object. In this example, I’m using a simple form from an app I’m working at the moment.

 

Userform.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:dto="com.katapultmedia.mystreamer.dto.*">
    <mx:Script>
        <![CDATA[
            private function save():void{
            }
        ]]>
    </mx:Script>
    <dto:User id="user" />
    <mx:Binding source="firstNameField.text" destination="user.firstName" />
    <mx:Binding source="lastNameField.text" destination="user.lastName" />
    <mx:Binding source="emailAddressField.text" destination="user.emailAddress" />
    <mx:Binding source="passwordField.text" destination="user.password" />
    <mx:Binding source="isActiveCheck.text" destination="user.isActive" />
    <mx:Form>
        <mx:FormItem label="First Name">
            <mx:TextInput id="firstNameField" text="{user.firstName}" />
        </mx:FormItem>
        <mx:FormItem label="Last Name">
            <mx:TextInput id="lastNameField" text="{user.lastName}" />
        </mx:FormItem>
        <mx:FormItem label="Email Address">
            <mx:TextInput id="emailAddressField" text="{user.emailAddress}" />
        </mx:FormItem>
        <mx:FormItem label="Password">
            <mx:TextInput id="passwordField" text="{user.password}" />
        </mx:FormItem>
        <mx:FormItem>
            <mx:CheckBox id="isActiveCheck" selected="{user.isActive}" />
        </mx:FormItem>
        <mx:FormItem>
            <mx:Button label="Save" click="save()" />
        </mx:FormItem>
    </mx:Form>
</mx:VBox>

 

So, I’m not going to go line but line since it is pretty straight forward but here’s a brief outline.

Form Items

  • Each TextInput is bound to the user objects respective property (ex – firstNameField.text is bound to {user.firstName}).
  • The isActiveCheck is bound to {user.isActive}

Binding Tags

  • Each Binding tags source property is bound to one of the form items.
  • Each Binding tags destination property is bound to the respective user property.

That’s it. What happens is when I create an instance of this component I will set myUserForm.user = someUser; and when the user edits one of the form items the respective value of the user object will be updated instantly. This way, when the user clicks the Save button I can easily pull myUserForm.user and pass that dto (data transfer object) to the backend.

Kinda cool, huh? Well, I think so. Saves a good bit of Actionscript writing.

Enjoy.

Update: I should test code before posting. 🙂 I’ve removed the brackets around the source/destination properties on the Binding tags. They aren’t needed.

AIR+OpenAIM: Buddy List Viewer

I’m researching OpenAIM for an upcoming article and thought I’d share a few quick tidbits about connecting to OpenAIM. Let me first say…I didn’t do anything special here. AOL has provided a pretty quality developer center and they have written the ActionScript 3 code necessary for connecting to the AIM service. As a test I thought I’d try to grab my buddy list and show it in an mx:Tree component.

Disclaimer: This is purely a sample app so the code does not use any best practices or anything…just showing how to use the OpenAIM code.

Sample AIR app:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:wim="com.aol.api.wim.*"
                        layout="absolute"
                        applicationComplete="init()">
    <mx:Script>
        <![CDATA[
            import com.aol.api.wim.data.types.SessionState;
            import com.aol.api.wim.data.User;
            import com.aol.api.wim.data.Group;
            import com.aol.api.wim.Session;
            import com.aol.api.wim.data.BuddyList;
            import com.aol.api.wim.events.BuddyListEvent;
            import com.aol.api.wim.events.SessionEvent;
            private var aolSession:Session = new Session(stage, "your developer key", "Your Test Client", ".1");
            private var aolBuddyList:BuddyList;
            private function init():void{
                aolSession.addEventListener(SessionEvent.SESSION_STARTING, handleSessionStarting);
                aolSession.addEventListener(BuddyListEvent.LIST_RECEIVED, handleBuddyListLoad);
                aolSession.signOn("your username", "your password");
            }
            private function handleSessionStarting(event:SessionEvent):void{
                aolSession.requestBuddyList();
            }
            private function handleBuddyListLoad(event:BuddyListEvent):void{
                aolBuddyList = event.buddyList;
                updateBuddyList();
            }
            private function updateBuddyList():void{
                var buddyList:XML = <node label="AOL Buddy List" />
                var group:XML;
                var user:XML;
                for each(var item:Group in aolBuddyList.groups){
                    group = <node />
                    group.@label = item.label;
                    for each(var userItem:User in item.users){
                        if(userItem.state == SessionState.OFFLINE) continue;
                        user = <node />
                        user.@label = userItem.aimId;
                        group.appendChild(user);
                    }
                    buddyList.appendChild(group);
                }
                buddies.dataProvider = buddyList;
            }
        ]]>
    </mx:Script>
    <mx:Tree id="buddies" width="100%" height="100%" showRoot="false" labelField="@label" />
</mx:WindowedApplication>

So, briefly I’ll cover the code (gotta cook dinner in a sec; lol). On Line 4, above, we set the applicationComplete event to call our init() function, lines 19 to 23. In there we add a couple event listeners then call the signOn(..) function of the WIM api. Before we can successfully do this the aolSession variable must be created, which we do on line 15.

Note: You HAVE to get a developer key from AOL in order to test this code.

Once the sign on request is complete we call requestBuddyList(), line 26. When the buddy list is returned we set the aolBuddlyList variable then call updateBuddyList(), line 32. The updateBuddyList() function merely loops over the groups (your buddy groups) and users in each group, updates the buddyList XML local variable, then assigns it to the dataProvider of the buddies Tree component.

For the UI we mer
ely create an instance of mx:Tree and set the labelField to @label, which is what we created in the updateBuddyList() function.

That’s it. Run the app and you’ll see your buddy list in a window like below:

MyBuddyList

They have some work to do on the source code but I went from from 0 knowledge to this sample app in 20 or so minutes. Grab the code and check it out.

AS3: FLVPlayback SMIL Support

This is just a little piece of code for using a SMIL file as the source of the FLVPlayback component in Flash. This is AS3 code but it is pretty much the same for AS2.

bq. import fl.video.FLVPlayback;

var player:FLVPlayback = new FLVPlayback();
addChild(player);

player.source = “my.smil”;

“For more information on SMIL read LiveDocs”:http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000588.html.

I don’t like frameworks but I love Mate!

Some people may want to flame me for not liking frameworks but keep an open mind while I briefly explain.

**Why I don’t like frameworks**
Frameworks are great for getting from 0 to 60 really fast, most of the time. They take care of redundant tasks for you by providing code to manage those tasks. If this is true, and I believe it is, then why don’t I like them?

The majority of the frameworks out there add a bunch of extra junk you don’t need or won’t always use. Sometimes they have weird configurations and approaches. Most times the only thing it provides is a common code-base a new developer can jump in and be productive because they already know the chosen framework. If the latter is the benefit, give me a few days with the new developer and I’ll get them up to speed and productive.

I won’t spend much time here because this isn’t really what my post is about but the truth is I like to home-roll my own “framework”. There is absolutely nothing wrong with you not using a framework…nothing AT ALL. (“Maxim Porges has an entire preso”:http://maximporges.blogspot.com/2008/05/cfobjective-2008-presentation-materials.html he did, and I liked, at cf.Objective()) You choose what design patterns you want to implement and have at it. This is my preference regardless of language except PHP because “CodeIgniter”:http://www.codeigniter.com makes PHP fun. “Spring”:http://springframework.org makes Java a lot cleaner for me as well but those are about the only two. Well…enter “Mate”:http://mate.asfusion.com.

**Mate** (mah-tay)
I talked about “Laura’s preso at cf.Objective() in another post”:http://www.johncblandii.com/2008/05/cfobjective-2008-review-cf8-ne.html and due to my excitement I instantly wanted to see what it was about. Mate is “presently in an Alpha stage”:http://www.asfusion.com/blog/entry/mate-flex-framework-in-public-alpha but feels like a v1.

The event handling is what I longed for my own custom code-base to include (namely the one I built at “Limelight”:http://www.llnw.com) but never had the time to explore it. Mate is a gem in this area. Simply let your events bubble, setup “EventHandlers”:http://mate.asfusion.com/page/documentation/tags/eventhandlers (to do any number of tasks; ex – call a service, set a value on a class, call a method on a class, dispatch another event, etc) for the event(s), and you’re good to go. You could stop there, I have so far, and be pleased with Mate.

The joy is being able to dispatch an event 20 levels into your UI and without setting a globally available property/calling a globally available method (ie – ModelLocator, etc) you can have another view/component receive an update regardless of the location in your app (direct ancestor or otherwise). It is really nice.

Now, another thing I don’t like about frameworks that Mate solves is the majority of the time your app is 100% geared to **that** framework. Mate doesn’t force you to extend any specific classes, unless you want to, so you could strip Mate from your app and merely have to rework your event handling and maybe a few other things, pending how deep you got with things.

I absolutely have enjoyed using it. Personally I am building an AIR app with it and at “Limelight”:http://www.llnw.com I’m redoing a presently built Flash 8 app in Flex w/ Mate. In 3 days of development (mind you, a little in the morning and at night including learning Mate) I have my personal app in a clickable beta and not with dummy code. It is 100% final app code already at the place to tie in data and be ready for an alpha build. The app at “Limelight”:http://www.llnw.com has only had about 3 hours of work on it and is almost in the same state.

Kudos to “Laura and Nahuel of AsFusion”:http://www.asfusion. You have changed my (Flex dev) life.

Domino’s Pizza Tracker

I saw this online and thought it was pretty clever as well as useful.

Monday I ordered pizza from “Domino’s Pizza”:http://www.dominos.com/ online. I finished my order and it went to the normal confirmation page. I was on another tab while it completed the order and I saw the tab title change to “Order Confirmation” so I ALMOST did a ctrl+tab (to go to the tab) then a ctrl+w (to close it). That was my initial desire but when I went to the tab I saw a lot of color which made me look twice and pause. What I saw was pretty interesting.

DominosPizzaTracker.JPG

The image above shows the current status of my pizza order as well as a message letting me know who is working on my pizza. The FACT-O-MATIC widget slides in different facts here/there to keep me interested while my order is processed.

I thought this was very clever and have been waiting for a long time to see more restaurants integrate their in-store system with their web site.

Go ahead…order some pizza from Domino’s and take a looksy…I’m sure your inner-geek will like it too. 😉

PS – It’s built on the Flash Platform. 😉

LiveCycle Data Services ES 2.6 Beta 2 ROCKS HARD!!

Ok, I’ve been working on an article regarding LCDS + AIR and offline sync. I had everything pretty much done EXCEPT saving offline data back to the server (which I haven’t tested with 2.6 B2 yet but will). Yesterday I installed “LCDS 2.DS ES 2.6”:http://labs.adobe.com/technologies/livecycle_dataservices2_6/ and today I decided to toy with it. I jumped into the “Dev Guide”:http://download.macromedia.com/pub/labs/livecycle_datservices/2.6/docs/lcds26_devguide_040908.pdf and looked at what they said was needed to do online/offline.

So I’m a skeptic at times when I see a little bit of code doing a lot but DANG! This time I was proved wrong.

_airfds.swc_, I’m assuming, handles creating a sqlite database and updating it. I won’t spill the beans on all of the goods (my article will cover it more) but peep how flippin’ simple this is:

bq. contactsDS.saveCache(contacts);

Yep, that’s it. _contactsDS_ is my _DataService_ and _contacts_ is an _ArrayCollection_ loaded from LCDS. There are other things to do for loading data from the cache and your LCDS implementation, as well as saving data back, but for the most part…WOW!

I’m loving it and keep rockin’ Adobe/LCDS/Flex team!!

More to come…