November 20, 2011

AS3 and Zeo Again

Recently got around to checking a couple of items off of my todo list that had been on there way too long. In summary:

Sometimes the simple things take the longest time.

Tags: as3 csv flex zeo

December 1, 2010

Code Coverage Comparison

Having spent some time using the new ActionScript Code Coverage Plug-in for Flash Builder, I thought I'd compare it to the existing Flexcover tool.

Below are the major reasons why I'd chose one tool over the other.

Why Flexcover is the better choice:


  • Support for continuous integration systems (generate a report from the command line in common code coverage syntaxes)

  • Partial line coverage (does every part of a boolean expression get exercised to both true and false)

Why ActionScript Code Coverage is the better choice:


  • No special compilation step (just run your project with the collector enabled)

  • Ease of use (no need to load CVM files and switch out of Eclipse to view coverage)

Personally I see using the two tools complimenting each other. I see using the ActionScript Code Coverage during my development and unit testing to get quick feedback and Flexcover as part of integration and nightly builds to track coverage over time and get more detailed coverage statistics.

Tags: as3 flex tools

November 17, 2010

Beyond IoC: Advanced Experiments with Swiz (RIA Unleashed: Boston 2010)

Beyond IoC: Advanced Experiments with Swiz by Ben Clinkinbeard

Swiz is all about custom meta-data parsing as returned from describeType(). Recent changes have exposed that meta-data processing to anyone. General switch from autowire to inject.

Swiz is all about defining a list of beans that it knows about. Swiz watches for views to be added and then manages them (i.e. set beans on the view).

In general most of what you can do with a meta-data tag you could also do with an interface, but it isn't as cool.

IProcessor (root of it all)
init() - reference to Swiz instance one is operating in
priority - determine what order processors are run in

IBeanProcessor (extensions) any object that Swiz manages
setUpBean() and tearDownBean()

SwizInterfaceProcessor: checks for common interface types (backwards compatibility)

Bean is wrapper that Swiz puts around your object. It has source property and type descriptors that handles meta-data. Support for class, property, and method meta-data.

IMetadataProcessor (parse custom metadata tags)
metadataNames() - associate with more than one metadata tag
setUpMetadataTags() - metadata tags found and the bean
tearDownMetadataTags()

PostConstruct run after all injections satisfied
MetadataTag allow additional properties like "order"

var f:Function = bean.source[metadataTag.host.name];

Bad things might happen if two register the same meta-data tag. Might be good to add a mapping report to let you know what was injected where.

Unit testing custom meta-data tags is possible.

When an event is dispatched, to check permissions or security constraints, may prevent method from running.

Growing collection of third party custom meta-data processors.

New feature is event chains and command chains. Determine flow by returning AsyncToken or AsynchronousIOOperation.

Tags: as3 flex riaunleashedboston2010 swiz

November 17, 2010

litl Lab (RIA Unleashed: Boston 2010)

litl Lab by Ryan Canulla and Kathryn Rotondo

Not nearly enough hands on coding, especially since half of the session was devoted to their upcoming set-top box product but for which they didn't have a hardware demo.

Flash based SDK for developing channels. Each channel has three views: card (menu with optional slideshow), focus (mouse, keyboard support), and channel view (passive view, swipe type gestures only).

User can install multiple channel instances with different settings. Think weather widget with different zip codes all displayed at once.

Card view should have minimal animation but can reflect live data.

Focus view is the most details. Put ability to change channel options in this view and things like capturing username and passwords for remote data. Can configure a website and links that will launch in the litl chrome based browser.

Channel view should be designed for distance viewing. Think of it like a screen saver, very passive, but should be used for video and games since it provides the most screen real estate. For gestures in the view put most common in the middle (least likely, somewhat likely, most likely, somewhat likely, least likely).

Keep in mind the user can switch between the three views at any time. Be smart about what you do. Remember that data should update regularly but handle the fact that the network will come and go.

A channel can store properties in either shared properties (part of the channel, consider them public) (example same channel in marketplace with different defaults), device properties (specific to the device the channel is running on, consider them private) (example font size for webbook versus TV STB), or account properties (tied to your account, consider them protected) (example Facebook username and password).

New set-top box offering will have trackpad with slide out keyboard. Will offer gestures, accelerometers, microphone, and possibly webcam. For STB you need to worry about overscan, but the litl SDK will tell you usable dimensions when switching which view is active. Important to liquify your layout as STB dimensions will vary like crazy.

Tags: api as3 flex litl riaunleashedboston2010

November 17, 2010

Keynote (RIA Unleashed: Boston 2010)

Keynote by Ryan Stewart and Terry Ryan

Flash has seen a rise in competition: Silverlight, Java FX, JS/HTML

Flash adoption is getting faster. To get penetration from 0 - 80%


  • Flash Player 8 = 12 months

  • Flash Player 9 = 11 months

  • Flash Player 10 = 6 months

  • Flash Player 10.1 = 74% in 3 months


Flash is showing up on more and different devices every day. Truly becoming a multiscreen platform. All walks of technology want Flash.

Flash is responding with device centric features like: accelerometers, GPS, multi-touch, and virtual keyboards.

Adobe is enabling you to use your Flash skills while tailoring the experience to use each devices unique capabilities.

Flash focusing on performance enhancements like: optimized garbage collection, JIT improvements, audio/video hardware acceleration, and AS2 optimizations.

Important to remember that content written for desktop won't run out of the box on the TV or mobile. Currently can target mobile using Flash in the browser or writing native applications.

Flash showcase for mobile at http://m.flash.com/.

Flash 10.1 is currently on 2 million devices and should be on 10 million by the end of the year.

Juniper Research says the mobile application market will be worth $25 billion in 5 years.

Blackberry is a whole new idea because native development is done in AIR, default applications are all AIR, and AIR runs the UI.

For multiscreen development, write once run anywhere isn't the case. Need to make changes based on UI and device.

Flash CS5 has added templates and packages for Android and iOS.

Flash Builder Burrito includes templates for Android, Flex mobile components, deployment and package tools, and on device debugging (deployments are over USB and debugging is over Wifi).

For front end development, Flex SDK "Hero" adds a mobile framework with views and view navigator and mobile optimized components, while Flex Builder "Burrito" adds mobile projects, debugging for mobile, publishing for mobile, and multiscreen testing.

For back end development, ColdFusion 9 gives you ORM, CFScript, and Flash Remoting, while ColdFusion Builder has extensions, and an IDE that works great.

ColdFusion Builder Storm gives you: code editing with better code folding, better code assist, better code formatting (with customizable preferences), better search, and better find and replace, while the new extensions offers more server data, extensions in views (instead of modal boxes), extensions code assist, and extensions custom keys.

Flash is making is easier to create games with native game controller support and new 3D APIs (code name Molehill) that can target DirectX and OpenGL to fully render on the GPU.

Multimedia improvements for Flash include StageVideo which is a new way to display video that offloads entirely to GPU which cuts down on CPU usage and battery drain.

Message of the day: It is a great time to be a Flash Developer!

Tags: adobe flash flex riaunleashedboston2010

November 17, 2010

Real Component Development on the Flex 4 Architecture (RIA Unleashed: Boston 2010)

Real Component Development on the Flex 4 Architecture by Michael Labriola

This was a hands on lab so these notes just capture general concepts discussed.

Think of Flex 4 components as the atoms of the system.


  • highly reusable

  • no external dependencies

  • everything is passed into them

  • participate in Flex lifecycle (defined by UIComponent)

  • know how big they are and should lay out nicely



Reusable components should be written in AS3 as MXML components with children can't be extended. MXML components should really be considered leaf nodes.

In Flex 3 you used UIComponent while for Flex 4 use SkinnableComponent (which separates out its visuals). In Flex 3 you used addChild() while for Flex 4 use addElement.

Parent's size children in Flex, this is what you get. The measure() method is concerned with setting measuredHeight, measuredWidth, measuredMinHeight, and measuredMinWidth.

In updateDisplayList(unscaledWidth, unscaledHeight), maybe you add scrolling if your contents won't fit in the size give, tell children via setActualSize(width, height).

In commitProperties(), continue to follow the check flag and component exists before making changes.

SkinnableComponent delegates to skin. Define SkinPart through meta-data. When the skin is set Flex adds parts to the class and calls partAdded. Typically use interfaces like IGraphicElement and IVisualElement to ensure the skin can really do whatever it wants.

Tags: flex riaunleashedboston2010 skinning

October 26, 2010

Initial Zeo Data Explorer Released

I'm pleased to announce the first release of Zeo Data Explorer. For anyone that uses a Zeo to track their sleep, I've been playing with different ways to visual my sleep data, which some of you may have heard me talk about at BarCamp Boston 5. To that end I put together a generic library for parsing the CSV file you can export from the myZeo site. Along with the generic parsing library I've started exploring different ways to visual my sleep, beyond what you can do on myZeo, in an application called the Zeo Data Display. All of the source code is available on bitbucket at Zeo Data Explorer. This includes a pure AS3 library for parsing the data and a sample Flex application for visualizing it. For those that don't have a Zeo I've included a sample of my own data to get an idea of what it tracks. As time permits I hope to add additional visualizations to the tool now that the overall framework is in place. Enjoy and let me know what you think.

Tags: as3 flex zeo

September 21, 2010

Sanitize String for Regular Expression

I recently came across a need to use a user supplied input in a regular expression. To prevent any special characters in the user's string from being treated as a regular expression control character I stumbled upon this solution. Alas I can't remember where I found it but wanted to share.

/**
* Convert a random string into a format that will make sure it doesn't
* impact a regular expression when inserted into it.
* @param string String to sanitize.
* @return Sanitized string
*/
public function sanitizeForRegExp(string:String):String
{
    if (string == null)
    {
        return null;
    }
    return string.replace(new RegExp("([{}\(\)\^{{content}}amp;.\*\?\/\+\|\[\\\\]|\]|\-)","g"), "\\$1");
}

Tags: as3 flex regexp

September 21, 2010

Urban Warfare Game

A former co-worker of mine just announced an awesome new Facebook game that they built with Flex, Swiz, and AS3Signals. It's called Urban Warfare, plays like Civilization, and can be found at http://apps.facebook.com/urbanwarfaregame/.

Tags: flex game

August 24, 2010

Optional int

I've recently run across the need to have a optional int field. That is a property on a class that is of type int but can be left unset (or null). AS3 doesn't provide the Java equivalent of the Integer class so I was curious what my options are. Below are four options that I played with. If you know of others leave a comment.

Option 1: type it as Number

public class Temp {
    public var value:Number;
}

Pro: Test if value has been set using isNaN(temp.value). No compiler warnings for assignment to another int and mathematical operations.
Con: Doesn't convey that the value is of type int. Allows user to set non integer values.

Tweak: Provide a get/set that downcasts the incoming Number to an int and possible throw ArgumentError if a non int value is passed.

Option 2: type it as *

public class Temp {
    public var value:*;
}

Pro: Test if value has been set using temp.value == null or temp.value == undefined. No compiler warnings for assignment to another int and mathematical operations.
Con: Doesn't convey that the value is of type int. Allows user to set anything.

Option 3: get/set/isSet

public class Temp {
    private var _value:Number;
    public function set value(value:int):void { _value = value; }
    public function get value():int { return _value; }
    public function isValueSet():Boolean { return !isNaN(_value); }
}

Pro: Test if value has been set using temp.isValueSet(). Clear that value is of type int.
Con: Bunch of code. Not a common AS3 paradigm

Option 4: Integer class

public class Integer {
    private var _value:int;
    public function Integer(value:int) { _value = value; }
    public function valueOf():int {return _value; }
}
public class Temp {
    public value:Integer;
}

Pro: Test if value has been set using temp.value == null. Clear that value is of type int and is optional. Safe to use in mathematical operations.
Con: No direct assignment to another int. Bigger memory footprint.

Note: The use of the valueOf() function makes the Integer class do the right thing in most contexts such as var sum:int = 12 + temp.value. You do need to use valueOf() when doing direct assignment var value:int = temp.value.valueOf();.

Conclusions

I can see each of these options working based on the situation. Out of all of them Option 1 is the most appealing from a minimal code perspective and is a typical AS3 paradigm. Wrapping the setting with a conversion of the Number to int improves correctness.

Tags: as3 flex

May 23, 2010

Static Const of the reference not the content

In the middle of helping a co-worker debug a unit test, we had a test method that ran fine by itself but failed when run with the rest of the tests in the same class. Looking over the code there was no obvious reasons why when both test methods were run the second one failed.

Turned out to be a duh moment. At the top of the unit test there were a bunch of XML fragments declared with private static const. Problem was one of the two test methods was modifying the children of the XML. XML is a complex Object, unlike an int or a String, so the constant keyword doesn't prevent changes to the structure within the XML, it just prevents the reference from changing. A couple of simple fixes:

  1. Make the XML fragments be class instance variables, since each unit test creates a new instance of the test class
  2. Before using the XML use its xml.copy() function

Tags: e4x flex testing xml

April 18, 2010

BarCamp Boston 5

Had a blast at BarCamp Boston 5. Learned about some new technologies and topics that I'd love to play with and learn more about. Some of my favorites Cooking for Geeks, OpenFrameworks, Wolfram Alpha, and Introduction to jQuery.

I threw some slides together and gave a talk about Agile Programming Methods since there looked to be a bunch of interest. Kind of hard to compress everything cool about agile into 25 minutes, but hopefully I got a couple of points across.

What I was more excited to talk about was my continued sleep tracking with Zeo. I'm not quite ready to release a version of the software (still in prototype phase) but I've got an updated set of slides and screenshots. Thanks to those that attended and gave great suggestions on data that I could pull in and plot against.

Tags: barcamp boston flex graph sleep zeo

January 31, 2010

AIR 2.0 and Presentation Nightmares

Tonight I spoke at the Boston Flex User Group about AIR 2.0 with a focus on the new Native Process API and Networking APIs. Alas the talk didn't go as planned since I forgot my bag of video output adapters at home and didn't notice until I was setting up. The meeting was only a few blocks away from the Allurent offices so I ran (more like a sprint) back to find suitable replacements. Alas in my rush to borrow an adapter (only being able to find a mini display port to HDMI) I ran afoul of the old Mac VGA/HDMI mechanical virus issue. However, it wasn't until after sprinting back to the meeting and futzing with projectors for 15 minutes that I realized this issue. Thankfully a fellow attendee loaned me his computer and using the USB drive I did have on me, I managed to gave a modified version of the talk sans running demo code. I'd like to thank those in attendance for their patience, apologize for my forgetfulness, and hope that at least a little information was conveyed. A copy of the presentation is available in PDF format. The most import code snippets are below:

Define a Native Process Startup Information instance:

// _mxmlc, _cssFile, _brandFile, and _kitDir are of type File
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = _mxmlc;
var mxmlcArguments:Vector.<String> = new Vector.<String>();
mxmlcArguments.push(_cssFile.nativePath);
mxmlcArguments.push("-output");
mxmlcArguments.push(_brandFile.nativePath);
nativeProcessStartupInfo.arguments = mxmlcArguments;
nativeProcessStartupInfo.workingDirectory = _kitDir;

Create and attach listeners to a Native Process:

// _nativeProcess is of type NativeProcess
_nativeProcess = new NativeProcess();

_nativeProcess.addEventListener(Event.STANDARD_ERROR_CLOSE, handleStandardErrorClose);
_nativeProcess.addEventListener(Event.STANDARD_INPUT_CLOSE, handleStandardInputClose);
_nativeProcess.addEventListener(Event.STANDARD_OUTPUT_CLOSE, handleStandardOutputClose);

_nativeProcess.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, handleStandardErrorError);
_nativeProcess.addEventListener(IOErrorEvent.STANDARD_INPUT_IO_ERROR, handleStandardInputError);
_nativeProcess.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, handleStandardOutputError);

_nativeProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, handleStandardErrorData);
_nativeProcess.addEventListener(ProgressEvent.STANDARD_INPUT_PROGRESS, handleStandardInputProgress);
_nativeProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, handleStandardOutputData);

_nativeProcess.addEventListener(NativeProcessExitEvent.EXIT, handleNativeProcessExit);

Typical event handling code:

private function handleStandardOutputData(progressEvent:ProgressEvent):void {
    trace(_nativeProcess.standardOutput.readUTFBytes(_nativeProcess.standardOutput.bytesAvailable));
}

private function handleNativeProcessExit(nativeProcessExitEvent:NativeProcessExitEvent):void {
    trace(nativeProcessExitEvent.exitCode);
}

Create a new server socket that listens on an OS selected available port:

// _serverSocket is of type ServerSocket
_serverSocket = new ServerSocket();
_serverSocket.addEventListener(Event.CLOSE, handleServerClose);
_serverSocket.addEventListener(Event.CONNECT, handleServerConnect);
_serverSocket.bind();
_serverSocket.listen();

Handle a new incoming connection:

private function handleServerConnect(serverSocketConnectEvent:ServerSocketConnectEvent):void {
    var socket:Socket = serverSocketConnectEvent.socket;
    socket.addEventListener(ProgressEvent.SOCKET_DATA, handleSocketData);
    socket.addEventListener(Event.CLOSE, handleSocketClose);
    socket.addEventListener(IOErrorEvent.IO_ERROR, handleSocketIOError);
}

Handling socket data:

private function handleSocketData(progressEvent:ProgressEvent):void {
    var socket:Socket = Socket(progressEvent.target);
    var byteArray:ByteArray = new ByteArray();
    socket.readBytes(byteArray, 0, socket.bytesAvailable);

    socket.writeUTFBytes("HTTP/1.1 404 Not Found" + CRLF);
    socket.writeUTFBytes("Connection: close" + CRLF);
    socket.writeUTFBytes(CRLF);
    socket.flush();
    socket.close();
}

Tags: air flex

December 26, 2009

AASFSHNR Kiva Team Statistics

For most of this year I've been collecting frequent data snapshots of the Atheists, Agnostics, Skeptics, Freethinkers, Secular Humanists and the Non-Religious Kiva Team. I've been a member of Kiva for some time and thought it would be neat to track the success of the group leading up to our one million dollar goal. A few months ago I started playing with the Flex Charting Components to see what I could do with the data I'd been collecting. I don't have the graphical touch (as anyone who has looked at this website can attest to) but working with the charting components made it easy to throw together some basic visualizations of the data.

The code for the application is ugly, so unlike most of my other sample applications, I didn't view source enable it. Given the plethora of other sites talking about the same material this isn't a loss, trust me :) One thing that I'd like to experiment with is other ways to visual the data. Any recommendations are welcome.

Tags: charting flex kiva

November 22, 2009

Custom Components in Flex 3 and 4 (RIA Unleashed: Boston 2009)

Jesse Warden

Custom components are important
* Flex based application instead of just Flash
* Designers don't know flex
* Memory constrained
* Isolated and encapsulated for code reuse and testing

Types of components
* Visual
* Non-visual (data/service manipulations)
* Either Facades or Proxies

Base class versus component
* Shape (best for drawing), Bitmap (rastering), Sprite (Flex), MovieClip (Sprite with Animation)
* De-coupling through composition

Component Libraries (Take care of low level Flash player stuff for you, when to draw, event handling, etc.)
* Flash CS3 (Build quickly, small file size)
* Minimal (Keith Paters, up and running quickly, RAD)
* Flex (Enterprise quality stuff)

Custom Components
* UIComponent
* Model, View, and Controller
* Invalidation
* Embedded Content
* Styles

Place custom components in a library project so that you can see them in design view.

For complex processing use green threads.

Testing
* fluint
* FlexUnit4
* visual test harnesses (Application that just shows the component you care about)

Monkey Patching
* When the framework doesn't do what you need (like making a private variable public)
* Makes it hard to follow Flex SDK updates (copy and edit the file along with version file)

Conclusions
* Components are building blocks of Flex apps
* Extend UIComponent
* static children in createChildren()
* draw stuff in updateDisplayList()
* data setter sets internal value, and flags to redraw and call invalidate methods

Tags: flex riaunleashedboston2009

November 22, 2009

How Not to Code Flex Applications (RIA Unleashed: Boston 2009)

Jeff Tapper

What is bad code
* Doesn't meet needs of the project: efficiency, maintainability, time to develop
* Code which doesn't make sense

Why do we write bad code
* Lack of time
* Lack of knowledge
* Lack of caring

What bad code leads to
* Delays
* Project failure
* Job loss
* Death

Bad code samples

If you are doing something wrong note it, add comments about why so you know you need to fix it later

Bad Code Sample 1

<mx:VBox styleName="doubleLine"/>
.doubleLine {
    background-image: Embed("/assets/images/doubleLine.png");
}

* Bad use of container (don't use if it won't have children)
* Better to replace with mx:Image

Bad Code Sample 2

<mx:List itemRenderer="see below" selectable="false">
<!-- item renderer -->
<mx:VBox>
<mx:Image/>
<mx:Label/>
</mx:VBox>

* Use of list when you don't need it's features: virtualization, selectability
* Better to replace with mx:Repeater

Bad Code Sample 3

public function setDate(u:String, p:String):void {
    username.text = u;
    password.text = p;
}
<mx:TextInput id="username"/>
<mx:TextInput id="password"/>

* Properties set on controls instead of a model (race conditions, control names, additional fields)
* Modify the model let the view follow using Bindings

Bad Code Sample 4

<mx:Form currentState="{ModelLocator.getInstance().loginState}"/>
new CarignromEvent("changeState");

* View events handled in top level component
* Local property changing local state is best unless other people need to know about it

Bad Code Sample 5

<mx:VBox borderStyle="solid" backgroundColor="" otherCSSStyles>
<mx:Text/>
</mx:VBox>

* Inappropriate container nesting (mostly for styling, not child layout, i.e. container with only one child)
* Exception is mx:ViewStack and mx:TabNavigator require children be containers
* Better to use mx:TextArea as that supports background and border styles

Bad Code Sample 6

<comp:Comp1 id="menuChooser"/>
<comp:Comp2 menuForDisplay="{menuChoose.menuGroup.selection.label}"/>

* Bad coupling (two dots and you are out)
* Better to dispatch event that others can listen for

Bad Code Sample 7

<mx:Button enabled="foo &amp;&amp; (bar != ''  || bar == '') // etc."/>

* Being too clever (hard to maintain and debug)
* Move the logic into a function

Tags: design flex riaunleashedboston2009

November 22, 2009

Social Applications with Adobe Flash Collaboration Services (RIA Unleashed: Boston 2009)

Kevin Hoyt

Flash Collaboration Services: Collaboration in the cloud
afcs.acrobat.com for an account

SDK includes samples and an AIR application with lots of goodies in it: room console, local server (for easier testing/data only).

API
* Session and authentication (0 = nothing, 100 = owner, # = application assigned)
* Shared model components
* Shared managers
* Collaboration components (whiteboard, chat, are built in)

Room Concepts
* Users and roles
* Audio/video streams (including peer-to-peer via RTMP)
* Content from collections and nodes

Authenticator
ConnectionSession (Synchronization change events used for both connected and disconnected)
ConnectSessionContainer (show hides children based on connectedness)
SharedObject (RTC specific, different than standard Flex one) Used to share data into the cloud

Build in WebCamera wrapper that broadcasts video feed.

GPS Tracker Demo using Flex for web, AIR for data acquisition, and CS4 mobile application all talking to same room.

Golden rule: Do not take action until data arrives (including echo back)

Website Watcher Demo

Technology being used for education (RosettaStone), customer service call center, anywhere where you need real-time capabilities.

Audio echo is a big issue.

Tags: cloud flex ria riaunleashedboston2009

November 22, 2009

Building Flex Applications with the Swiz Framework (RIA Unleashed: Boston 2009)

Chris Scott

What is Swiz:
* Simple IoC for Flex / AS Development
* MVC Architecture
* Simple tools for common tasks: remote methods, event handling, modules

What Swiz is not:
* Excessive JEE patterns
* Boilerplate code
* Verbose XML configuration
* Overly prescriptive

Swiz uses dependency injection to satisfy component requirements.

Common dependencies:
* Remote services
* Data
* Logic
* Views

Other approaches:
* Wire ourselves
* Use Service Locators
* Verbose XML configuration

Swiz application:
* Define application it needs to use: remote objects, controllers, presentation models
* SwizConfig component in top level application
* [Autowire] metadata for dependency injection, two flavors (type reflection) or by bean name
* [Mediate(event="", properties="")]
* Swiz class called AbstractBaseController: executeServiceCall(async token, result, fault, arguments)
* Immediate run-time checking of event names
* Swiz:Prototype using class reference or name
* Module specific scope for Swiz config

Tags: flex framework riaunleashedboston2009 swiz

November 22, 2009

Keynote (RIA Unleashed: Boston 2009)

Ryan Steward

Three trends being focused on right now:
Rich Internet Application which Adobe have been doing for a long time.
Cloud Computing is coming to the forefront. Have your data available anywhere. SoA is becoming the norm. Clean separation between front-end and back-end.
Desktop and Devices making the experience available everywhere.

All rolled into contextual applications. Applications where and how your users want them.

finetune.com example of contextual applications. Explore with the traditional browser, then use desktop specific application, iPhone version, and Wii specific version.

Take advantage of device specific features.
Move data and state between contexts.

New runtime support:

Flash Player 10.1 geared for smart phones. Approximate 60% memory reduction with no code changes. Better battery performance.

AIR 2.0 extending ability to leverage native code. Native installer and application support.

Code an application in Flash CS5 and run it natively on iPhone.

New tooling support:

Flash Catalyst is all about designer having more control over UI without touching Flex.

Flex 4 is all about separating logic and look. Components based on states and skinParts.

Demo of Flash Catalyst.

Adam Lehman

New IDE for ColdFusion development called ColdFusion Builder also Eclipse based. CFML support for: code assist, insight, debugging, and ORM insight. Also have code assist for: HTML, DOM, CSS, JavaScript, AJAX (jQuery, ExtJS, etc.), and SQL. Code snippets, log viewer, AIR 2.0 Support. IDE can be extended through CFML extensions. CFScript allows tag-less components. Additional ORM support for CFCs based on Hibernate with CFML languages but still have access to low level settings. Expanded access to ColdFusion services for PDF, charting, document services, etc. all exposed through a SOAP & AMF interface with granular security control.

New CF SWC that will give AS3 / MXML libraries for accessing these functions like: , , , etc. Flash Remoting is 9 times faster in the latest versions. Now has full BlazeDS integration.

ColdFusion 9 has many PDF enhancements. Headers, footers, optimize, extract text and images, and converting Word to PDF. Has support for working with spreadsheets.

Demo of ColdFusion.

Ryan Steward

New Flash Builder adds data centric design features, better refactoring, performance optimizations, network monitor, and many others.

Demo of Flash Builder.

For people at the conference you have access to AIR 2.0 bits.

Tags: air coldfusion flash flex iphone riaunleashedboston2009

September 23, 2009

RIA Unleashed Boston November 13, 2009

I just wanted to recommend to anyone who will be in the Boston area on November 13, 2009 that you should head to RIA Unleashed. Formerly called Flex Camp Boston this is one the lowest cost highest content conferences I've attended. Tickets for this year are going for $60 or less depending on how early you register. Not being above a little self promotion, when you register let them know I (Daniel Rinehart) sent you :) For those that weren't able to attend the last couple of years, a list of talks is below.

2008:

2007:

Tags: flex riaunleashed2009

July 19, 2009

Image Rotation with Pixel Bender

Unlike my previous experiments with Pixel Bender, today I set out to implement a basic image manipulation routine, image rotation. While Flash natively provides the ability to rotate a DisplayObject that doesn't help if you want to combine multiple Pixel Bender filters that should use the rotated image as the source image. Turns out rotating an image in Pixel Bender was a little harder than I thought, but I ended up with a nice solution.

Rotation is a simple image manipulation that can take advantage of transformation matrixes like you can create in Flash. The normal 2D rotation transformation matrix looks like this, given d is the angle of rotation, x and y are the original pixel location, and x' and y' are the new pixel location:

 cos(d)-sin(d)  *  x  =  x' 
sin(d)cos(d) y y'

The problem with this rotation (and the standard DisplayObject.rotation property) is that the rotation is performed relative to the origin. In this case it is (0, 0) or the upper left corner of the image. To address this problem we switch to 3x3 transformation matrixes and first translate the image to define a new origin (like changing the registration point on a MovieClip) before performing the rotation. By combining a translation, rotation, and reverse translation we can rotate the image around an arbitrary point but still have the result appear anchored in the upper left. The full matrix transform then looks like this, given a and b are the translation in x and y respectively:

 10a  *  cos(d)-sin(d)0  *  10-a  *  x  =  x' 
01b sin(d)cos(d)0 01-b y y'
001 001 001 1 1

Now we are getting somewhere. The next problem is that we don't know what x and y are. We do know x' and y' as that is what outCoord() gives us. In order to use this transformation matrix in Pixel Bender we need to solve for x and y. It turns out the matrixes reduce to a linear system of equations. Thankfully I have an old symbolic solver kicking around that did the dirty work. First simplify the transform matrixes:

 (x - a)*cos(d) + (b - y)*sin(d) + a  =  x' 
(y - b)*cos(d) + (x - a)*sin(d) + b y'
1 1

That leaves us with two equations and two unknowns. Using a linear equation solver, we end up with:

x = (x' - a)*cos(d) + (y' - b)*sin(d) + a
y = (y' - b)*cos(d) + (a - x')*sin(d) + b

The translation into a Pixel Bender kernel is straight forward from here. Using a parameter called origin I've replaced a and b, outCoord() replaced x' and y', and a parameter called rotation (specified in degrees) is used for d.

float2 dstCoord = outCoord();
float angle = radians(rotation);
float cosAngle = cos(angle);
float sinAngle = sin(angle);
float x = (dstCoord.x - origin.x) * cosAngle + (dstCoord.y - origin.y) * sinAngle + origin.x;
float y = (dstCoord.y - origin.y) * cosAngle + (origin.x - dstCoord.x) * sinAngle + origin.y;
dst = sampleNearest(src, float2(x, y));

After the kernel was created and exported for use in Flash I slapped together a simple test application to play with it (view source enabled). Note: if you use the kernel in the Pixel Bender toolkit you will want to setup a minValue and maxValue for the origin parameter based on your test image size, otherwise you can't meaningfully adjust it.

If you played with the application you probably noticed the extension slider. By default a shader filter in Flash will map the source image to an equally sized output image. Increasing the various extension properties of ShaderFilter you can create an output image larger than the input which avoids any output image clipping.

I suspect if Pixel Bender graphs were supported in Flash you could easily setup a series of filters that do the image translation and rotation separately instead of combining them all into a single matrix. It might even be easy enough to do that with an array of filters but this isn't something I've played with much.

Tags: flex graphics image pixelbender

May 12, 2009

Be wary of micro-benchmarks baring speed improvements

I've seen some links recently to the Round up of ActionScript 3.0 and Flex optimization techniques and practices and I'm afraid. I'm afraid that entries on that list are going to become gospel and code that doesn't use the tricks listed will be labeled bad. Knuth said it best, "We should forget about small efficiencies say about 97% of the time: premature optimization is the root of all evil." While the author frames the discussion correctly stating "You have to learn when to use some techniques and when to leave some out." I don't think he does enough to call out the type of optimization each entry is, or more importantly, how these techniques were derived.

One of the key tenants of any performance reporting is carefully detailing the environment and method used to construct the test. I'll focus first on the environment. With any ActionScript 3.0 and in particular Flex optimization techniques there are factors beyond the code that impact the effectiveness of a possible performance tweak. Depending on your target audience (e.g. intranet, internet, etc.) some of these techniques may work against you (i.e. your tweak makes your code run slower in certain cases).

The first is the Flex compiler. The same code compiled with different versions of the compiler will produce different performing SWFs. The Flex SDK is continually improving the optimizations applied to the generated SWF. That means that in some cases a performance tweak you made for the Flex 3.0 SDK may end up fighting the compiler and producing slower code with 3.2. As such keep track of any performance tweaks you make and be sure to test them whenever you change the tools you use to produce your SWFs. #19 is a classic example of a code pattern that in many cases the compiler could optimize automatically.

If we assume that the compilation tools are consistent the next big factor that will affect your performance is the Flash player itself. Remember one of the big advances that Adobe did with Flash 9 was introduce a virtual machine into the player that has just it time (JIT) compilation support. Each version of the Player makes tweaks to the JIT that can impact how your code runs. That might mean code which ran one way in a previous version of the player now behaves differently possibly even running slower. #13 and #15 on the list are examples of how the player may impact performance.

Of course the other half of runtime in the machine that the Flash player is running on. While Adobe does a fantastic job of providing a consistent cross platform runtime, they don't have any hard guarantees about the performance across platforms or hardware. Maybe memory management on one machine makes your code page fault more frequently which will slow it down. Maybe hyper threading or hardware acceleration of Pixel Bender filters helps the code run faster. The wide variability in hardware and software that the Flash player can run on means that there are many performance optimizations that could easily backfire in certain situations if you are really trying to eek out every millisecond of performance.

The other area I'd like to touch on beyond the environment is the testing methodology. The article gives almost no information about how each of the performance techniques was measured. While references are listed at the bottom the hints and tips are not cited well enough to easily track down the source. To take #1 "Array instantiation" as an example: Did someone write a single function that created X arrays using each technique and measure the total time taken? Were they two methods in the same SWF or were they different SWFs? Did they vary the order that the methods were called? How many times did they run the loop? Did they examine what happened when garbage collection started happening? Did they create these Arrays within the scope of a method, a class, as a static? What compiler did they use? What Flash Player was it tested on? What were the specifications of the machine that the tests were run on? That's just a sampling of questions that come to mind when I see a sample optimization technique. The answer to anyone of them could impact how helpful it might be to your code or even if it does anything in real code versus some micro-benchmark.

With all of that said my intent is not to dissuade you from thinking about performance optimizations but instead focus the discussion not at the micro-benchmark level but at the algorithmic level. What I mean is that for a given problem, I don't care how you initialize your Arrays, the fact that you are using bubble sort instead of heap sort means that for any reasonable implementation and application usage it will always be slower. That is the 97% that Knuth is referring to. Real world performance problems are almost always going to be inefficient algorithms long before your Array initialization technique starts taking up the majority of your time.

Scanning the list of techniques, I consider these to be more algorithmic focused and worth thinking about first:

  • 26: given that the Flex documentation continues to say this I'm inclined to agree with this one
  • 27: more objects to layout, more objects to keep in memory, etc. make this a good thing to keep in mind
  • 37: it's much better to not even need to think about needing to draw something, I'd add that includeInLayout is another important setting

A couple other observations:

  • 2: I'd say any object that you don't need is expensive so don't create what you don't need
  • 12: ideally you're using polymorphism so you don't even need to do branching but if not the axiom of Keeping the Common Case Fast applies here keeping in mind there is still a chance that the compiler or JIT can impact performance

I'm know my observations about items from the original list could be debated. I still think it is a great list of things to try, but in general don't treat it as gospel. Overall I want to emphasize that minor tweaks will not impact performance as much as algorithmic inefficiencies. Keep that in mind next time you need to speed up some code.

Tags: flash flex performance

March 24, 2009

HP SWF Decompiling and Security Analysis Tool

HP has released a tool called SWF Scan for decompiling and looking at SWFs for security issues. Available from http://www.hp.com/go/swfscan.

Tags: flex swf tools

March 24, 2009

Building Muscular Graphical Editors in Flex (BFUG March 2009)

Joe Berkovitz is speaking about Building Muscular Graphical Editors in Flex.

Focus on how people build and edit visual documents. Amazed at the problems that come up building visual editors like that.


Ran into lots of issues while building Noteflight. Ended up creating Moccasin framework for working with visual editors. Moccasin is also being used in InfraRed5's new RedLine site editing tool.

He gave a quick demo of Noteflight. Tool for creating and sharing musical scores with a little social interaction thrown in. Selection has different modes: individual object, group of objects (sequence or collection), and a passage. Undo and redo are built in to almost everything.

Uses MVC with a few tweaks. Views emit events that are fed to Mediators which perform actions on a Controller which edits the Model. Models are abstract and non visual. Layouts are visual grouping of model but not drawn.

Undo History <- Document <- Layout Context <- View Context
           ^       ^            ^                ^
            \-> Model    <- Layouts        <- Views

Model, Layouts, and Views are collection of objects that are cooperating, but all belong to a single object, the context or document they are operation in.

Sometimes when you need to print you need to make visual tweaks so that it looks better, in this case just have a separate view context.

Don't like using events for what should be a function call.

Standard undo/redo wisdom is to use a command pattern. ICommand, execute(), undo(), and redo(). Commands are stateful, need to create them.

Instead constrain the model to only allow, property change, child add, or child remove. Bindable properties will dispatch events for you. For collections and change events you need to bubble them up in your model. Then you only need to listen to the root.

UndoHistory needs to open group/close group. Makes many micro modifications that are recorded. Undo or redo called on undo history controller.

How do you track dirty versus clean? Bookkeeping in undo history.

He gave a demo of InfraRed5's RedLine site builder which is also using Moccasin.

Moccasin is on Google Code. MVCS framework, XML based model, "smart wrappers", object selection management, group based undo/redo, mouse gesture/object handle support, scalable document views.

Moccasin wraps a model object to handle events. Moccasin includes simple world which is an application to show how the framework is used. Uses a feedback layer sitting in front of objects. Ran through an example of changing the Square object to have a width and height instead of just a size.

View registers mediators that it wants to use.

How to persist state of views? Have separate model that hte views manage.

Likes domain specific frameworks instead of monolithic frameworks.

Moccasin more focused on UI design and layout versus client/server work that Cairngorm uses.

Tags: flex framework moccasin

January 31, 2009

Flex Automation Framework (BFUG Jan 2009)

Eric Hilfer from Tom Synder Productions is speaking about Flex Automation Framework and automated testing.

Automation Framework: records and playbacks UI events (mouse and keyboard), identifies controls by context to make them less brittle, can read object properties, delegate objects separate automation logic from core component (allows runtime and compile time inclusion).

How it works: Flex includes SWC libraries, compiled as [Mixin] (during compilation the code gets pulled in), Agent then interacts with AutomationManager (can be 3rd party), testing tool communicates with Agent, tests, suites, etc. QA uses tool developer has to expose to Agent.

Good: Smart UI element identification, decouple automation from code, no bloat.
Bad: Not fully AIR-aware (no good support for multiple top-level windows), assumes everything is a UIComponent.
Can programtically detect presence of AutomationManager and behave differently, but not recommended.

Using it: HP QuickTest Pro (expensive, must run in IE browser), RIATest (inexpensive agent) (will be demoing), build your own. Flex Monkey is another alternative.

When you compile your project, include all of the automation SWCs. Alternative is if your application can be loaded just as a SWF, load it into a wrapper that has the automation libraries.

Anything derived from UIComponent will just work. For custom extensions, register with an XML file. Automation name, real classname, events to watch, properties to expose. Delegates register themselves with the AutomationManager for which class they handle.

Making automation easier: Give each button a unique name so that automation can find it even if it is moved. Don't use UIDs.

RIATest demo. Can be run interactively to record tests and setup verifications. Windows native application but can have instances running on other machines reporting to it. Has command line run mode. Scripts supports loops, limited external data file reading.

Customization of "get automationName()". Names can be context unique, doesn't need to be application unique. Need to wrap custom events with automation events (should be placed in delegate object). Need special handling for native window.

XRay Tool very useful for debugging.

Tags: automation flex testing ui

January 31, 2009

Server Side Sojourn

I'll been a little quite on the blogging front as of late, besides the occasional user group post. The main reason for that has been the last couple of months I've been heads down doing server side Java development for a cloud computing infrastructure using Amazon's Web Services for S3, EC2, SimpleDB, and CloudFront. All that is the back end for some amazing Flex based applications that Allurent has in the works.

Being back heavy on the server side is a mixed blessing. Its an area I've done a lot of work in, in fact many of my first technically oriented posts on this blog where about Java. As a result I'm not playing with that many new things. The flip side is that I've been able to crank out a bunch of high quality code which feels good. Using Eclipse for Java development has unfortunately made me realize how far Flex Builder has to go to be a truly productive editor. Top three things I'm missing when working on ActionScript and MXML code: code formatting , MXML organize imports, and right-click run as FlexUnit test.

Allurent practices peer review before check in and automated unit testing. In order to make reviews effective we've established a coding standard so that anyone looking at someone else's code won't be distracted by funky formatting. Consistent formatting also makes looking at file differences much easier, eliminating the angry fruit salad only the whitespace changed difference report. Alas, without automated formatting support time gets wasted tabbing and spacing files to keep them readable. Likewise the need to launch an external program and occasionally tweak files to run a single TestCase or method increases the barrier to writing unit tests, which is never a good thing. Thankfully, Flexcover helps us keep tabs on areas we are lacking.

Java does has a big head start on Flex/AS3 for getting the tooling in there. Progress is being made, but for someone coming from the Java/Eclipse world, it's frustrating at times.

Tags: aws eclipse flex ide java tdd

December 28, 2008

Unit Testing Flex Application with Fluint (Flex Camp Boston 2008)

Unit Testing Flex Application with Fluint
Mike Nimer, Digital Primates (presented for Jeff Tapper who was unable to make it)

Testing is like source control. You don't know how much you need until you start using it.

Cold Fusion started out without much testing.

Ever bug has to have a unit test that exercises the bug before fixing it. Regression bugs discovered as part of testing are show stoppers.

Testing methods
Manual testing: humans create and run, low cost to start high cost to maintain, testing happens less often
Automated testing: humans create and computers run, higher cost to develop but lower to run, more often

Testing as part of development
Code until the red goes away
Developers create code and write tests, focus on test driven development
Automated build checkout, build, and test running, various tools to do that

Test types
Unit tests: individual method testing
integration tests: combination of test components

Tools for testing
FlexUnit: Original testing framework, based on JUnit
Flunit: Better asynchronous testing, better UI testing support, and sequences

Integartion testing is hard: Visual Flex Unit does bitmap comparison,
Fluint checks sequences and events

Test methods , test cases, test suites, and test runner. Various types of assertions. Comes with runner and has file watcher to pickup modules and run tests on change.

Asynchronous Testing
Events can occur at any time so you need to handle it sometime later. Uses asyncHandler which is a function that you pass as the event listener. Also want to pass data through to handler. Second argument to event handler. Can have asyncHandler as part of setup step.

UIComponent Testing
TestCase is a UIComponent so it can have components added to it as a child. Still need to what events to listen for.

Sequences
String together many sets and event waiting.

Test meta-data flag
Meta-data is copied over and available in the reports. Also produces XML like file in a JUnit like format.

Test filter and sorting
Only run certain tests, headless test runner

Configuring Fluint and test setup: Writing libraries can have another test application. Flex projects can't link so

Migrating from Flex Unit to Fluint? Best to ask on the forumns.

Mocking data? Nothing tied into Flinut, framework can support it.

Code coverage: using Flex Cover.

AIR test runner: looks for directory changes and runs it.

Tags: flex flexcampboston2008 flexunit fluint testing

December 28, 2008

How to use Flex 3 & Cairngorm with LiveCycle Data Services 2.6 (Flex Camp Boston 2008)

How to use Flex 3 & Cairngorm with LiveCycle Data Services 2.6
Brian O'Connor, Universal Mind

Material is on his website. Going to cover what it takes to develop with these technologies today, versus the brave new world that the other Adobe folk presented earlier.

Only a couple of people have used LCDS. About half the audience have used Cairngorm. Really looking to remove a lot code that you have to write.

BlazeDS versus LCDS: Data management only in LCDS and has better Service Adapters.

What is data management: Need paging, collaboration, automated CRUD, offline capabilities. Client has data service that connects to destination on server that uses an adapter.

Fill method gets all data from data source and caches it in middle tier and paged to client. Have the ability to control auto commit of changes to the data. Page fill gets only a subset of data at once. Can configure the fill type to use. How you program your adapter to execute it is a hot topic of performance consideration. refreshFill() can be a performance bottleneck. Is determined by the return value of method calls. For example 4000 clients shouldn't all refresh their data at once.

Data grid and data service cooperate to only request new data when needed (i.e. when user scrolls down).

Dispatch event, front controller, service locator, response populates data or view. Get garbage collected which isn't what you want. One class per data service with a manager. Have Singleton for getting access to the method.

Data Service Transactions handle multiple different access methods. Can start transactions on destinations with either commit or rollback after a bunch of changes. Can hookup with JTA. External updates to database aren't reflected to clients. Better to code in middle tier so that it can participate in refreshing clients.

Can also use data services to persist it to AIR SQLite database. Data service has saveToCache method (which is asynchronous). Don't have autoSaveToCache set to true. With a 4 level deep object hierarchy and 4000 rows it takes about 10 seconds to save. Hard to tell when your data is finished loading (fill is problematic). Have to daisy chain clearCache calls when working with multiple data managers. Client sometimes see managed object proxy instead of strongly typed wrappers. need to add properties.

Data manager handles sending back conflict events. Can determine how it gets resolved.

No built in locking support.

Tags: cairngorm flex flexcampboston2008 lcds

December 28, 2008

Flex for ColdFusion Developers (Flex Camp Boston 2008)

Flex for ColdFusion Developers
Mike Nimer, Digital Primates

What is Flex, presentation is CF application stack. CF connects to everything. Flex Data Services ship with Cold Fusion (BlazeDS RPC and Messaging wrapped with LCDS' Data Management).

How to connect a Flex application: RPC using HTTP, AMF, RTMP (no server required). Flash remoting requires server side piece like CF that translates protocol to CFC. Flex messaging can push message to all clients through an event gateway.

Need: CF 7.0.2 or 8. CFEclipse as an IDE. Flex Builder IDE. CF plug-ins for Flex Buidler (optional but you really want them) many wizards. Can also have separate LCDS but not needed as it is already part of CF.

Hybrid application, HTML and Flash. Full application, takes over entire page. Desktop application, using AIR with CF server.

Break out of page model and switch to event model. Small self contained components. Application around widget decides what to do with events. Properties in events out (rule of thumb for components).

Only writing CFC no need for CFMs. Binding to data grid the call service.method.lastResult. Can also use bindings if needed.

Any data type in CF can be set back. Can use either array, structs, queries or strongly types entities like User, Products, and other CFCs. CFC instance on server and AS class in Flex. Public only properties. Easy if you get it right. CF case insensitive and not typed. AS is case sensitive and typed. CFProperty used for WSDL generation and Documentation generation. Also used to specify contract between CFC and AS (uses case defined in CFC and property type). CFC also specifies alias (optional but really required for Flex). AS object uses RemoteAlias meta-data. Have to mark a cffunction method with access="remote" to be called by Flex.

CF by default runs as a service. Turn that off and run it from the command line. cfdump is a handy tag and you can see the output in the CF console. Can also turn on Flex logging to see the traffic. Very handy for debugging. ServiceCapture is a network tool or Charles. For a Flex debugging on server, primarily look at body property for requests and responses.

With the CF administrator you can turn on very detailed debugging that is returned to the client. Flex supports browser cookies. Need to specify services config when you compile the Flex application. With server config you can control what the client is allowed to do. Flex can only request CFCs under web root. Flex remoting adapter configuration can change how CFCs and methods are found, secure by default but you can open them up, force certain casing type.

Session and client variables are supposed in Flex. Can't persistent CFC to Flex Session.

Tour de Flex (Released at MAX)

Tags: coldfusion flex flexcampboston2008 lcds

December 28, 2008

Keynote: Flex 4 Preview (Flex Camp Boston 2008)

Introducing Flash Catalyst ("Thermo") and Flex Builder Gumbo (Flex 4)
Tim Buntel, Adobe

Overview of the Flash platform.
Design and Develop: Flash CS4 Professional, Flash Catalyst, Flex Builder
Framework: Flex
Clients: AIR, Flash Player and Servers, but not the focus of today's talk

Two different drivers for application, coming at it from the design side versus the data side. Independent of starting point you end up with code.

Focus Areas for the Flash Platform
Design tools focused on: Flash Catalyst, Flash Pro CS4, FXG
Data: Data-Centirc Development
Code: Developer Productivity
Flex Framework: Next-gen components, declarative states and behaviors
Tight integration across teams

"Thermo" introduced at MAX 2007 have been laying the foundation since then, FXG, component model, CS4 FXG support, argue with marketing

Flex 3 had baked in presentation: can only replace individual components, non-boxy designs are hard.
Next-gen components separate presentation from controller: layout almost all controlled by the skin,.

Next-gen: graphics and text as first-class citizens, revised component architecture, declarative states and behaviors

FXG: Graphics format based on MXML, supported in key CS4 applications, just another file format for the CS4 suite, needed a portable notion of states and transitions that could be more declarative.

Flash Catalyst
Why? Harder for one person to do everything design to development. Web applications are getting bigger, "Developer-Designers" are harder to find.
Today: limited roles, designer creates visual design and developers adds interactivity, linear process making it hard to incorporate visual updates, interactivity is hard for designer to add.
Pre-alpha released at Max 2008, public beta early next year

Flex Builder 4
Designer/developer workflow improvements: introduces FXP, launch Flash Professional from Flex Builder
Data centric applications: making visual connectivity easy, end-to-end development with BlazeDS and LiveCycle Data Services, common application templates, code generation for common tasks
Feature improvements: Refactoring, code generation (get/set) debugger, profiler, improved compiler speed, bi-directional text, automated unit testing, network monitor

Demo of Flex Builder 4
Data Centric Application
AMF is now part of the Zend framework, project explorer now has package views instead of folder based,
Data and services tab, new cold fusion IDE called Bolt built on Eclipse, does introspection of the service and builds internal data model, can drag and drop data type into design and generate data grid that can call backend. Can manage a data type and map client side operations like update to the server side calls. New generate event handler from either design view or within code assist. Strongly typed wrapper of data returned can call something like "actorService.comit()", where actor is the manager data type. Network monitor will let you see the traffic between the client and server. Can setup data type to support paging, will call backend as needed. Service also adds support for easy revert of changes.

Flash Catalyst and Flex Builder 4 have pages on labs where you can keep track of the progress of the tools.

Does client side data management work with LCDS? Preview release has some issues that will be fixed by first public.
Network monitor support RTMP? Not yet.
Will real-time protocols be supported? Not implemented at this time, but will expand in the future, no firm timeline. Right now only HTTP and AMF, maybe .NET in the near future.
Flex Builder on Linux? Only a few people raised their hands for using Flex Builder on Linux. Some supporting tools not on Linux yet so the support is lagging. It is a stated goal.
Workflow flow such as Catalyst, Builder, Catalyst. Yes the two projects will work well together. FXP is a way to move between the two with tools to manage it. Difference view for merging FXP projects.
How much data access will be available in Catalyst? Know designer needs data access within Catalyst, sample data available now, trying to figure out the best approach. No live connection but most likely representative data.

Tags: catalyst flex flexcampboston2008 gumbo thermo

December 28, 2008

Model Driven Development Using Flex Builder and LCDS "Next" (Flex Camp Boston 2008)

Model Driven Development Using Flex Builder and LCDS "Next"
Christophe Coenraets, Adobe

Only three people in audience are using LCDS, but that is part of the problem. Hard to use, hampering adoption.

Showing demo with data grid editing. Refreshing page shows changes were not lost. Two different clients against same data are synchronized. Showing multiple views of the same data. Two different companies and a search results window. Multiple view synchronization. LCDS is all about data management.

Why aren't people using it: Price shouldn't be the issue, it's all too difficult. Not focusing on server.

Currently: must create destinations (XML), create assemblers (Java), create DAO (Java), VDO (Java, AS), keep everything in sync. Don't have code completion, binding is difficult, no service introspection.

Accessing data is first hurdle. Configure server through Flex Builder wizard. Normal server properties (server name, port, context root). Can now explore data exposed by server. New "Adobe Data Model" wizard as part of project. Select server and tables you want to work with. Right now it produces XML but many have GUI later on. Including associations. Deploying data model generates code. Includes base class and subclass generation so that the base class can be regenerated without disturbing your extensions. We didn't build "demo ware" code can be used for simple to complex applications.

Dropped company list that show up as data grid. Dropping detail table in prompts for needed data based on dropped table from data model. Do have to manually write handler to connect the two data grids.

Why a custom data model? Wanted to do more than just describe data structure also wanted to define behaviors. You may have more than one data model.
Manually editing generated model to include a derived property. I.e. full name which is a combination of first and last name with some formatting. Change to data model synchronizes to other generated code.

Adding constraint to data model. Boolean variable showing valid state was added. Constraint also added to server side data model checking. Need to cast the data object in client code in order to get compile time checking that all properties are valid.

Business logic location? Can specify where a validation rule gets run. Constraint automatically would reject edit.

How it happens on the standards can't talk about how it happens yet. Is standards based, currently using Hiberante but that is subject to change.

Do you care how your data is updated in database? Will have hook before persistence but really shouldn't care about how is is saved.

Now have Flex and Spring integration. With remoting have SpringFactory that determines what method to call buts has lots of configuration today. Not really Spring like (connections are too loosely correlated as part is Sping and part is LCDS). New model is all Spring based with LCDS, easier to maintain.

Changes to schema will require refreshing the client's data model.

Tags: flex flexcampboston2008 gumbo lcds

December 28, 2008

Merapi (Flex Camp Boston 2008)

Merapi
Andrew Powell, Universal Mind

Only a couple people have used it.

Grew out of old Apollo project. Named after volcano on Java. What AIR to talk to Java.

AIR does what it does well, but we want it to do more. How do you extend AIR? Have it talk to GPS. Make mashups that just aren't components but also bring hardware into the mix. Anything that has Java library or JNI will work. Main component is called a Bridge because it is all about moving data back and forth between AIR and Java.

Need to create a connection, could be local or remote. AIR/Flex runs on OS. Bridge runs on OS. Hardware and applications also running on OS. AIR and Bridge are connected via AMF using BlazeDS serialization/deserialization techniques. Bridge then talks to applications and hardware.

var message:Message = new Message();
message.data = "Hello World";
message.type= " Reply";
Bridge.instance.sendMessage(message);

BridgeInstance has result event that you can handle.

Bridge API is easy, complexity is all in external APIs Merapi talks to.

It's alpha so security, reliability, installer, etc. are still being worked on.

merapiproject.net (where to get)
infoaccelerator.net (Andrew's site)

All applications have a Java piece and a Flex piece.

Demo of AIR application controlling bluetooth connected robot. Lego Mindstorm.
Demo of Google translator and text to speech.
Demo of Growl for the Mac. This also works from the browser.

Demo showing data grid in Flex exported to Excel. Data updates in Excel when saved update the data grid. Can create and send email message, update contacts, meetings, etc. If you can do it in Java you can do it with Merapi.

If within the browser, can it be an applet or if it is an application. Right now it needs to be a Java application, possibly a service.

Remote Java objects and competing with BlazeDS. Some overlap, but Merapi is more about hardware connections.

It is all Flex based. Next beta will also include Flash support.

Excel formula values are sent back. Word formatting probably comes back over RTF.

Public beta in the next couple of months.

Is it open source? It is open source, value is in derivative work.

How would the browser and desktop piece work? Still TBD.

Only limit is your imagination. Anything Java can do you can send it back and forth.

Data access size and transfer rate limits are not known, probably limited to hardware.

Tags: air flex flexcampboston2008 java merapi

December 28, 2008

Building Mashups with Flex and AIR (Flex Camp Boston 2008)

Building Mashups with Flex and AIR
Oscar Cortes, BrightCove

What is a mashup? Borrowed from music. Could be a dish (with potatoes). Web application that defines data from different sources. Not only about pulling together APIs, the sum should be better than the parts. Like the love song from Moulin Rouge, it combines many to make a more interesting whole.

Mashup sources: database, web services, media, xml, are some of the key ones.

Protocols: REST (64%), Soap (22%), JavaScript (7%), XML-RPC (3%), Atom (2%).

Who: Used to be only flickr, now also enterprises like Google, salesforce.com, and Yahoo. But developers are key player.

Flex maps strongly to APIs and models these services supply. Advantage of web services are that other people are providing data and maintaing it. The barrier to entry is low so you can experiment quickly. Build your own portfolio and try out new stuff.

Typical REST call: URL, API Key, API version, method to call, parameters, maybe digest or checksum. Can also use Web Libraries, JavaScript, and SWC libraries.

Typical result: XML or JSON, CVS or Text, Docs or PDFs, media (growing trend).

Can use native flex classes for REST (HttpService) and Web Services (WebService).

Demo using NYTimes community API (comments by URL). http://developer.nytimes.com/, Ribbit API http://developer.ribbit.com/, Google Maps (http://code.google.com/apis/maps), Google translator (http://code.google.com/apis/ajax/language/), Proxy (simple JSP Proxy)

Translates comment to Spanish. Visualizes locations of where people making the comments are from.

Tools and Techniques: Cairngorm (organized codes and ideas), AS3CoreLib (JSON parsing), E4X (XML parsing).

Durango: Mashup creator available from Adobe Labs.

Tags: air flex flexcampboston2008 mashup

December 28, 2008

An Introduction to AIR Development, Security, and Deployment (Flex Camp Boston 2008)

An Introduction to AIR Development, Security, and Deployment
J. Philip Camp, IBM Interactive - Boston

Moving from Flex to AIR isn't that big of a deal. AIR is as easy as Flex. Coding is the same, just the top level application changes, additional styling options for the chrome.

Use external style sheet to help style the application (could be done by the designer and just included by the developer with an mx:style tag).

How to get rid of the Native OS look and field. Set application chrome to none. All pieces of the Flex chrome are standard Flex components. Those can also be styled using CSS.

Using code behind can further reduce the coupling between the MXML and the ActionScript code. Programmatic setting of UI component properties.

Now we want to add data persistence. With code behind we can add in persistence as needed instead of always using HTTPService to request the data on demand. SQLiteAdmin is simple tool to look at a SQLite DB.

Security:
All apps use the same engine, one app can read another application. Possible to use encrypted database.

Deployment:
Need certificate to sign it (available from most certificate provides) can create temporary certificate. Bundle with AIR Badge to create a nice installer that can be run from the web.

Tags: air flex flexcampboston2008 security

November 17, 2008

Architecting a Shared Codebase from Browser and Desktop

Architecting a Shared Codebase from Browser and Desktop
By David Coletta

Maybe more hacking than Architecting. First time giving the talk so all feedback is welcome.

Goal: Build a browser application and an AIR application from a single shared codebase.

Four areas of concern: UI design (People have different expectations for a desktop based word processor versus a web based word processor), shared code packaging (giant pile of code delivered in two different forms, downloaded modules versus bundled with application), abstracting the AIR APIs (clipboard access is different in the two models), many other things including Singletons.

Primary UI differences: Browser version surrounded by browser chrome with AIR the application looks cleaner. Demo of Buzzword in browser and the AIR desktop version. Native menus in desktop menus versus flex based menus.

UI issues: Installation, automatic updates (Much improved in 1.5), menu bars (browser to native menu translation, native menu model is different between Mac and Windows, AIR APIs insulate from menu accelerators), multiple windows (on Mac you need to manually switch which menu is active based on the window, versus on Windows it is attached to the window), transition between the two (link to Buzzword opening in browser versus desktop if you have it installed, do runtime detection if AIR application is installed, if Application is running can use local connection), opening hyper-links, remember me (skipped talking about this), URL display (command that copies URL of document into clipboard), going to sleep and waking up, modal dialogs (in browser best you can be is window modal in AIR you can block the entire application), language preference.

Shared Code

Two modes: Browser SWFs loaded by AIR version, mostly SWCs linked in by two level application.
Went with loaded SWFs as browser version was already doing that, looser coupling meant faster builds, did require Ant to package it all together for development and production
In browser downloading latest version always happens. AIR application captures static version of modules. AIR does version checking at startup to see if it running the latest.

How much updating of an installed application will a user tolerate? Will things still work after the update? Old code running against new version of the server was already handled since people maybe using Buzzword in a browser during an upgrade, but its still an issue.

Abstract AIR APIs

Writing code like "if (isAIR) {} else {}" just won't work. Easy to forget its shared code. Errors when code is loaded and trying to run.
Common approach is to create an interface with two implementations. PlatformBroker with AIRPlatformBroker and FlexPlatformBroker as subclasses. As it for an interface and get that back. IPersistenceSecureToken is the interface with BrowserCookie (using ExternalInterface) and EncryptedLocalStorageCookie (using AIR facilities) implementations. Flex version is okay to live in AIR application, but not vice versa.

Singletons

Convenient but breaks when a single application is running with multiple windows on the desktop versus separate VM instance per window in browser. Solving the singleton issue for AIR required rewriting the browser version since the majority of the code was shared. Singleton was easier to get going but had issues when adding multiple window support.

Rich text support

Major problem for Buzzword. Needed to support copy and paste of rich text. Had to have hacks for browser support with hidden div. Very fragile. AIR has it's own issues since you only get raw HTML, not formatted, normalized, or parsed for validity. Ran it through HTMLLoader.

Other issues

Relaunching (browser errors just reload the page, no real way to do it in AIR, but can hack it with relaunch via air.swf but you have to be online), AIR update framework (much improved with AIR 1.5), Flex menus versus native menus from single model (created XML reader with factory methods), internationalization and localization (Buzzword currently has multiple versions, localized in SWF and loaded based on preference at runtime), Runtime CSS versus compiled CSS, idle tracking (rolled own for browser, AIR has API for idle tracking, used for autosaving and turning off server session).

99% of the code is shared between the browser and desktop applications.

Session is primarily serving XML, co-authoring shared batton is server based, does long polling (server holds client request until it has data to send to it).

Tags: air architecture flex

November 17, 2008

Sorting out Pixels or How I Didn't Plan to Spend My Sunday

I wasted, well maybe wasted is too strong of a word. I used way more time than I should have on Sunday playing with Pixel Bender trying to figure out how to make it sort values. In my trend to make Pixel Bender do stuff besides manipulate pixels I thought a fun mental exercise would be to implement a parallel sort. Now I've not come up with any good use for this yet, considered if this is the best performing parallel sort, yadda, yadda, but it works, which is what I really wanted to get out of this experiment.

While quicksort and mergesort are efficient given their O(n*log(n)) runtimes, they require iteration which isn't what Pixel Bender is good at. I ran across one paper that outlined a parallel sort on a linear array of cellular automata algorithm but its running time was O(2*n-3) cycles. For a reasonably large array I was concerned about exceeding the size of an image that I could feed into Pixel Bender.

As always, Knuth had an answer. On page 111 of his Sorting and Searching tome, he outlines Batcher's sorting scheme which is characterized as a "merge exchange sort". The key piece that makes the algorithm attractive for what I wanted to do is that step "M3. [Loop on i.]" can be done for all relevant i in any order, even simultaneously. [Knuth 111]. It also scales nicely, with worst case steps required to sort being O(1/2*ceil(log_2(n))*(ceil(log_2(n)+1). At 4096 elements 78 steps are needed while at 262,144 elements only 171 steps are needed. I'm going to exceed the width much more quickly than the height.

Doing a rough implementation of the algorithm in ActionScript was straight forward:

/**
* Merge Exchange Sort using Batcher's Method
* Knuth, The Art of Computer Programming,
* Vol 3. Sorting and Searching, Page 111.
* @param data The data to be sorted, will be modified inplace
*/
private function mergeExchangeSort(data:Array):void {
    // Sanity check
    var n:int = data.length;
    if (n < 2) {
        return;
    }
    // M1. [Initialize p.]
    var t:int = Math.ceil(Math.log(n)/Math.log(2));
    var p:int = Math.pow(2, t - 1);
    do {
        // M2. [Initialize q, r, d.]
        var q:int = Math.pow(2, t - 1);
        var r:int = 0;
        var d:int = p;
        var loopOnQ:Boolean = true;

        do {
            // M3. [Loop on i.]
            for (var i:int = 0; i < n - d; i++) {
                if ((i & p) == r) {
                    // M4. [Compare/exchange R_(i+1):R_(i+d+1)]
                    if (data[i] > data[i + d]) {
                        var temp:Object = data[i];
                        data[i] = data[i + d];
                        data[i + d] = temp;
                    }
                }
            }
            // M5. [Loop on q.]
            if (q != p) {
                d = q - p;
                q = q / 2;
                r = p;
            } else {
                loopOnQ = false;
            }
        }
        while (loopOnQ);

        // M6. [Loop on p.]
        p = Math.floor(p / 2);
    }
    while (p > 0);
}

The variables, p, q, r, and d are bookkeeping and my thoughts was that I would pass these in as values for each row in the pipeline. While the M3 and M4 piece would be the actual parallelized sorting piece. I quickly hit my first problem when I discovered that it doesn't look like I can do bitwise operators in Pixel Bender. The ((i & p) == r) line is vital to only testing possible exchanges at specific indexes for a particular step. It is in fact what gives the algorithm its complexity and beauty.

My next thought was to manually calculate the bitwise and using what functions I had available in Pixel Bender. In the back of my mind I think there is some eloquent way to do bitwise operations that I've forgotten since college (and some quick Google searches didn't refresh my memory). Just wanting to get something working I hacked together a quick little routine that used only operations available in Pixel Bender. Thankfully Pixel Bender does support modulus. This is the ActionScript version of the code:

private function bitwiseAnd(a:int, b:int):int {
    var result:int = 0;
    var n:int = 1;
    while ((a > 0) && (b > 0)) {
        if (((a % 2) == 1) && ((b % 2) == 1)) {
            result += n;
        }
        a = a / 2;
        b = b / 2;
        n = n * 2;
    }
    return result;
}

I had forgotten that Pixel Bender, when exporting for Flash, doesn't support loops :( I unrolled the loop for the largest values that I thought I'd test with, yay cut and paste. Then I ran into another subtle aspect of the code that I'd skimmed over. Primarily the fact that when looping over i it is doing a swap of the elements. Given that I'd be running in parallel I really had to calculate not only if i was bigger than i+d but the opposite at the same time. That would mean another unrolled bitwise and operation. This was turning into more of a pain than I had hoped and I was far exceeding whatever playtime limit I'd set aside for this little project.

Alas, for better or worse as Brian has aptly pointed out, I have a tenacious personality. I did take a break to run some errands, eat some more of the yummy chicken stew I made last night, and catch up on some saved TV shows. I came back, didn't have any insight, and figured I'd just write up this blog post. Half way through writing it I had an insight. The p, r, q, d, and i nonsense is just bookkeeping overhead. For a fixed size n, the values of p, r, q, d, and what swaps need to be made can be calculated once and reused as part of the pipeline.

Pixel Bender supports multiple source images. One could be my input data and the other could be the bookkeeping junk. (Insert long pause while I try this out). Success! I've now used way too much time putting this together. I only hope I haven't forgotten something else that I was supposed to be doing...

The couple of changes are before M3 in the algorithm mentioned above, I store the value of d in my bookkeeping bitmap:

// Pass along the value for d
step++;
bitmapData.setPixel(0, step + Y_OFFSET, d);

Then I replace M4 with the following change:

// M4. [Compare/exchange R_(i+1):R_(i+d+1)]
// Store the fact that we need to make this comparison
bitmapData.setPixel(X_OFFSET + i, step + Y_OFFSET, RIGHT);
bitmapData.setPixel(X_OFFSET + i + d, step + Y_OFFSET, LEFT);

This stores either a compare to the right or compare to the left value in the bookkeeping bitmap.

Lastly to get the pipelining working, the Pixel Bender code operates offset by one row. That is when working on row 1 it is pulling source pixels from row 0. This way each time the code runs the source row can be changed but the previous rounds values will continue to work down the sorting steps. This way if you can feed new data into the system every step and then after the minimum number of steps needed start pulling data off the other end that has been sorted. The cheesy UI I put together to test the code demonstrates this pipelining effect.

The Pixel Bender code ended up being straight forward once I introduced the bookkeeping bitmap. The only funky thing is doing the comparisons. Since I'm setting values as pixels, when in Pixel Bender it is chopped up into RGB which means a little special handling. Also, I've had some issues with float versus integer comparisons so don't be surprised if there are some stray oddities in the code. This then is the core of the algorithm on the Pixel Bender side:

// grab the data to figure out what which direction to compare with, if any
pixel4 bookdata = sampleNearest(book, outCoord());
// grab the d value to use, which is always stored at x = 0 for this row
pixel4 dData = sampleNearest(book, float2(0.0, outCoord().y));
// convert it into a real value, only need GB since we would create images too large otherwise
// although I don't know what the size limit is...
float d = dData.g * 65536.0 + dData.b * 256.0;
// grab the previous step's data, doing this makes for easier pipelining
pixel4 me = sampleNearest(src, outCoord() + float2(0.0, -1.0));
// default to doing nothing
dst = me;
// always skip x = 0 as that holds bookkeeping information
// and skip y = 0 as that is the start of the pipeline
// we read the previous row and write in this row
if ((int(outCoord().x) != 0) && (int(outCoord().y) != 0)) {
    // need to compare to the value on our right at me.x + d
    if (bookdata.r == 1.0) {
        pixel4 right = sampleNearest(src, outCoord() + float2(d, -1.0));
        // simplistic way to make the RGB compare like a number, can probably be optimized
        if ((me.r > right.r) || ((me.r == right.r) && ((me.g > right.g) || ((me.g == right.g) && (me.b > right.b))))) {
            dst = right;
        }
        // need compare to the value on our left at me.x - d
    } else if (bookdata.g == 1.0) {
        pixel4 left = sampleNearest(src, outCoord() + float2(-d, -1.0));
        // see note above
        if ((left.r > me.r) || ((left.r == me.r) && ((left.g > me.g) || ((left.g == me.g) && (left.b > me.b))))) {
            dst = left;
        }
    }
}

Give the finished application a try. Flash Player 10 required. It currently limits the values to 0xFFFF and the number of elements to 16 so they fit in the grid. View the full source if you want to play with it some more.

Tags: flex pixelbender sort

October 14, 2008

Using Flex & Cairngorm with LCDS Data Management

Using Flex & Cairngorm with LCDS Data Management from Brian O'Connor, Principal Architect at Universal Mind.
Will focus on Flex 3.0 &LCDS 2.6 and post the slides and sample code on his blog.

Previously with Macromedia consulting and Adobe consulting. Some of the audience have used Cairngorm and a few have used LCDS.

Really looking at Data Management as the focus since it has a lot of power. Lots of problems with how best to model data management and data services this type of application.

BlazeDS versus LCDS. BlazeDS offers RPC Services and messaging with back-end support for JMS and Java with a limited proxy service. No RTMP, no data management, AMF support, and non-NIO (aka blocking) HTTP streaming. LCDS adds Data Management, many more back-end adapters (ColdFusion, Hibernate, SQL, etc.) and NIO (aka non-blocking) HTTP streaming.

LCDS can't be opened to the internet due to denial of service and security issues. Still issues with web servers being the block that sits in front of LCDS.

LCDS helps solve lots of data management issues, like paging million row result sets, collaboration, offline capabilities.

Start with a DataService pointed at a Destination that talks to a Java object called an Assembler. Data send to client to populate ArrayCollections. Can be pointed at client side Data Management Controls like a DataGrid. LCDS remembers which client has which data to do intelligent data handling. Default Fill and Page Fill are key methods of an Assembler. DataService.saveCache() handles persisting to local database for offline storage.

Running through a sample application. JBoss running in the background. Cairngorm application with DataGrid for editing data. Uses samples.war that comes with LCDS to make it easier to setup and run yourself. Showing difference between default and page based filles. Page only got first 11 rows.

Data Service calls fill on Assembler. Default Fill got all the data from the database. Assembler then pages it out to the client. Data Service populates ArrayCollection which is bound to DataGrid. More than 100,000 rows and you want to be sure to use Page Fill which will only grab the requested data from the back-end. Must include count() method so that a paged based query knows how much data can be returned. In either case after a data update has occurred Data Service calls CRUD operations on Assembler. Assembler uses refreshFill(). A badly tuned refreshFill() can kill performance. Really need to understand it. If you update the database directly without going through LCDS you need to notify it through the Data Services Transaction mechanism.

In order to sort by a column you need to manually determine the column and direction to sort by (called fill arguments) and then call a data service manager to get the data in the newly sorted manner. DataGrid is good a paging and data presentation but you need to manually add custom sort order or filtering.

With auto commit set to true clicking off a row will send the CRUD operation. RTMP is best to synchronize data. AMF polling is okay but you really want to use HTTP Streaming (can't proxy streams through Apache). Three options to resolve a conflict given to you as an Array of conflicts. 1) accept server, 2) accept client, or 3) custom conflict resolution. You can use these techniques with or without using auto commit.

Handling large data sets can be tricky. ItemPending errors didn't upgrade nicely from Flex 2 to Flex 3. The UI needs the count method to accurately reflect the total length of available data. Trying to lazy load ahead of the user was problematic updating from Flex 2 to Flex 3. Better left to Flex UI component logic unless you are writing something completely custom.

Configuration on a DataService in MXML overrides the base behavior defined in the data-management-config.xml file. Many errors (best to debug with trace log turned on) result from a missing or incorrect metadata identity element.

When using Cairngorm with Data Management the typical Command/Delegate pattern has problems. Best to have DataServiceManager as a Singleton so it sticks around and holds reference to DataService. Have manager create event listeners on DataService that it keeps around all the time. It is a different type of connection.

refreshFill() on an Assembler can be a performance issue. Tied to autoRefreshFill() result. Append to fill is added at end (not sorted or filtered). Don't need to fill when just doing an update, really should do it on an insert. AutoSync will pick that up for you. 4 different status that can be returned. Really want to optimize when and if a fill is ever needed.

DataServiceTransactions allow server side only code to tell the rest of the system that their are data updates that it should synchronize. Different entry points to the database may make it harder to use LCDS. Really depends on frequency and type of updates to the database and its ability to call Data Service Transactions.

AIRs ability to save a local cache lets you access it offline. Must use same parameters (i.e. same filtering and or sorting). Can do a sync that will handle updates and trigger normal conflict resolution mechanism. autoSaveCache may have row limit but has tested up to 16K without issues, stated limit is 2K.

Where to look for data aware components? No good resources yet, best to look at Flex source code and how it does it.

Some of the limitations are with clustering. Hard to do. Destinations and Data Synchronizing is hard. Built on top of JGroups which is very chatty so really can't scale.

100s/CPU with BlazeDS versus 1000s/CPU with LCDS. Really want to use RTPM but non-blocking I/O in LCDS is better. On the Internet polling type cab make a big difference especially with browser being used. A connect and wait system will eat up a browser HTTP channel.

Retrieved data is fed directly to UI as the model. Managed model objects have client and server side pieces which handle the pieces for you. Granularity of updates is per property can control with autoCommit settings.

Tags: cairngorm flex lcds

October 14, 2008

PPE 1: Flex Project Skeleton

The most tedious part of any project I find is getting the skeleton setup. Thankfully Flex Builder's project wizards make this easier. I'll be creating two Flex projects, one called GameOfLife, which will hold the UI application, and one called GameOfLifeTest, which will hold the testing code. Additionally I'll create a Java project called GameOfLifeServer which will hold the back-end code. Both the production and test code will reside in the same Java project since you can easily mix them in Eclipse's Java mode, unlike with Flex. These will all be sibling projects in a top level directory.

Command Line

First a little command line mucking to get the directories setup:

cd source/trunk/danielr/projects/
mkdir PPE
mkdir PPE/GameOfLife
mkdir PPE/GameOfLifeTest
mkdir PPE/GameOfLifeServer

GameOfLife

Run through the Eclipse new Flex Project Wizard using the directory above as the project root and accepting all the defaults.

Now onto the associated test project.

GameOfLifeTest

Run through the Eclipse new Flex Project Wizard using the directory above as the project root and accepting all the defaults.

To GameOfLifeTest I need to add the testing library I'm going to use. For this project I'm planning on sticking with FlexUnit. An alternative that I considered was fluint. Like some of my other decisions I'm sticking with what I know works well and I don't see anything with fluint that I'll be needing that FlexUnit doesn't already cover. After downloading the current release I drop it into the libs folder of the recently created project.

Next I need to put in the FlexUnit test runner scaffolding. Makes me wonder how hard it would be to extend Flex Builder to add a "Create new FlexUnit Project Wizard". In this case I'm just going to cut and paste the code from the recipe I wrote that is up on the Adobe Cookbook. Lastly I want to setup how the test project is going to reference the code from the main project. Since Flex Builder can't efficiently handle compiling multiple projects at once (i.e. a SWC library project and the application that it depends on) I'm setting this up as a source path reference. Be warned that such a setup has it's own set of problems.

Since I'm the only developer on the project I'm doing the quick and dirty "source path" add folder option. Eclipse will store a hard coded path in the project file which means that anyone else importing the project will get an error unless they also happen to store the folder at "/Users/danielr/source/trunk/danielr/projects/PPE/GameOfLife/src". The simple fix is once the project is imported, go to the project properties and update the source path folder reference.

To finish this skeleton code I want to make sure I can create and test something that exists in the referenced source path. At this point I only have the main application, but that's good enough to verify things are working with some trivial test. Note I'm break from the traditional test naming scheme since I'm going to delete this test once I have some real code to work on.

package com.neophi.gol
{
    import flexunit.framework.TestCase;

    import mx.core.Application;

    public class ApplicationTest extends TestCase
    {
        public function testApplication():void
        {
            var gol:GameOfLife = new GameOfLife();
            assertTrue(gol is Application);
        }
    }
}

Next I need to include it in the test suite that gets run. A quick edit to GameOfLifeTest.mxml will do the trick:

private function createTestSuite():TestSuite
{
    var testSuite:TestSuite = new TestSuite();
    testSuite.addTestSuite(ApplicationTest);
    return testSuite;
}

Sweet. That compiles and runs and passes! Next up a small stub of the main application.

GameOfLife

Not much to do here but make sure it compiles and runs. For that I'm just going to stick in a simple label.

<mx:Label text="Game Of Life" horizontalCenter="0" verticalCenter="0"/>

That was easy enough. That is also now compiling and running. For the paranoid, you could run the test suite project again to make sure everything is still working. Remember to refresh the test project otherwise Eclipse might not pick up the fact that we changed a file in a referenced source path. Have I mentioned that source paths are buggy? Now to create a skeleton back-end. Looks like I'll work on that tomorrow as it's later than I thought.

For a snapshot of the project in process grab PPE-1.tar.gz.

Closing Thoughts

The format I used for this post is working well so I'm going to continue using it, not that you can tell all of the thought process behind it. What I've been trying is before I do something I've been writing the step down and then performing it to make sure what I thought I was going to do actually worked. Given how bad I am with tenses when writing most of the time, these posts will probably be worse in that regard so fair warning on that front. As a tongue-in-cheek expression call this approach blog first development, which some might say is a BFD.

For the history of this project see Programming Project Experiment (PPE).

Tags: flex gameoflife ppe

October 14, 2008

Antennae 1.2.2 Released

Antennae 1.2.2 has been released. This is a very minor update that just changed the bundled version of FlexUnit. I'm now bundling the version from the Adobe Open Source Site. I've also created a discussion group for Antennae available at http://groups.google.com/group/antennae-discussion.

Tags: ant antennae flex

September 22, 2008

Making Applications With Degrafa and ObjectHandles

Marc Hughes spoke at the Boston Flex User Group on Making Applications With Degrafa and ObjectHandles.

All of the talk materials are available on his blog.

Degrafa Introduction

Declarative graphics for MXML.. Based on surface that you draw things on. Surface has standard flex styles and placement. Surface is a Flex shape so you can apply filters, etc. Placed on a surface: Strokes, Fills, Geometry (the shapes). Multiple shapes are drawn in the z-index as defined in MXML. Wide variety of shapes (circle, rectangle, arc, etc.). Has repeater for most types of shapes. Can define objects outside of surface and use them anywhere. VectorFill recently added which allows complex shape composition. Since everything is a flash object can use tween on them. TweenMax is one example. Does support style sheet properties for most options and even creating entire surfaces in CSS.

Degrafa has some bases classes for doing skinning. GraphicBorderSkin is one example to define a skin for a component like a button. GeometryComposition allows defining how each state in the skin behaves.

ObjectHandles Introduction

ObjectHandles utility classes for doing real time object manipulation (move, resize, etc.). Background done in Degrafa. Objects to be manipulated extend: ObjectHandles <- BaseShape <- (SquareShape, CircleShape, etc.). CircleShape uses Degrafa to display itself. ObjectHandlesCanvas is a way to group ObjectHandle objects to enable keyboard support and easier z-index ordering. ObjectHandle objects dispatch various events like "Object Moving" and "Object Moved", once for during and once for after. SelectionManager is a singleton and an ObjectHandles class that manges the currently selected object. Rotation maybe added in the future (works in version 13 but not in latest).

ObjectHandles can't be composed into an existing object. Must be the base class.

Able to change the style of the handles through skinning.

ObjectHandles 2.0 is coming in the future that has better handle handling (get around scaling issues).

Tags: degrafa flex objecthandles

September 22, 2008

Pixel Bender and Conway's Game of Life

When I started reading about Pixel Bender and realized at its core it was a cellular automaton engine I immediately thought of Conway's Game of Life. I started looking into how to use Pixel Bender to render generations in the game of life.

Given that pixel bender is boundless (i.e. defined over an infinite plane of discrete pixel coordinates) I had to introduce the notion of a border pixel to make handling edge cases easier. Since most of the area in a generation is dead I decided to use white for a pixel that is dead (easier on the eyes) and black for a pixel that was alive. My initial attempt at the algorithm ran into a bug with the kernel export for Flash Player feature. After some rewriting I had a working pixel bender kernel that implemented the logic (albeit unoptimized):

<languageVersion : 1.0;>
// $Id: GameOfLife.pbk 57 2008-09-16 02:55:33Z danielr $
kernel GameOfLife
<   namespace : "Daniel Rinehart";
vendor : "NeoPhi.com";
version : 1;
description : "Conway's Game of Life";
>
{
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        pixel4 border = pixel4(1.0, 0.0, 0.0, 1.0);
        pixel4 dead = pixel4(1.0, 1.0, 1.0, 1.0);
        pixel4 alive = pixel4(0.0, 0.0, 0.0, 1.0);

        pixel4 me = sampleNearest(src, outCoord());

        // default to no change in pixel
        dst = me;

        // I would like to write "all(equal(border, me))" but that's buggy in Flash
        if (!((border.r == me.r) && (border.g == me.g) && (border.b == me.b)))
        {
            int aliveNeighborCount = 0;
            float2 offset = float2(pixelSize(src).x, pixelSize(src).y);

            // Find out how many of my neighbors are alive
            // left
            pixel4 test = sampleNearest(src, outCoord() + (offset * float2(-1.0, 0.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // upper left
            test = sampleNearest(src, outCoord() + (offset * float2(-1.0, -1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // up
            test = sampleNearest(src, outCoord() + (offset * float2(0.0, -1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // upper right
            test = sampleNearest(src, outCoord() + (offset * float2(1.0, -1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // right
            test = sampleNearest(src, outCoord() + (offset * float2(1.0, 0.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // lower right
            test = sampleNearest(src, outCoord() + (offset * float2(1.0, 1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // down
            test = sampleNearest(src, outCoord() + (offset * float2(0.0, 1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // lower left
            test = sampleNearest(src, outCoord() + (offset * float2(-1.0, 1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }

            // As per: http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
            // 1. Any live cell with fewer than two live neighbours dies, as if by loneliness.
            // 2. Any live cell with more than three live neighbours dies, as if by overcrowding.
            // 3. Any live cell with two or three live neighbours lives, unchanged, to the next generation.
            if (((alive.r == me.r) && (alive.g == me.g) && (alive.b == me.b)) && ((aliveNeighborCount < 2) || (aliveNeighborCount > 3)))
            {
                dst = dead;
            }
            // 4. Any dead cell with exactly three live neighbours comes to life.
            if (((dead.r == me.r) && (dead.g == me.g) && (dead.b == me.b)) && (aliveNeighborCount == 3))
            {
                dst = alive;
            }
        }
    }
}

Now with a working filter I used some of the recent posts by Mike Chambers on how to embed a pixel bender kernel into MXML. However, since I wasn't using it as a filter and wanted more control over the flow I leveraged the ShaderJob class.

var shader:Shader = new Shader(new gameOfLife() as ByteArray);
shader.data.src.input = current;
var result:BitmapData = new BitmapData(current.width, current.height);
var shaderJob:ShaderJob = new ShaderJob(shader, result, current.width, current.height);
shaderJob.addEventListener(ShaderEvent.COMPLETE, handleShaderDone);
shaderJob.start();

Slap a minimal UI around it and you have (click to launch, view-source enabled, Flash Player 10 required):

Tags: flex gameoflife pixelbender

July 30, 2008

Advanced CSS Techniques and Programmatic Skinning

At the start of this month I attended the Boston Flex User Group Meeting where TR Coffey, Design Lead at Allurent (where I also work) gave a talk about Advanced CSS Techniques and Programmatic Skinning. Below are some rough notes I took during his talk.


TR comes to Flex from a visual design background, not coding. Has approached design as a picture to code process. Not only has he created the visual design but has also been involved in coding the styling to make it work.

Flex provides a great framework to start off from using Halo and CSS. Try to use it before going into any of the more labor intense methods. If CSS doesn't work the other options are: graphic skins, states, and programmatic skins.

Using graphic skins in a program like Flash (also available in Photoshop and Illistrator) lets you use scale 9, nested movie clips to provide global control, and work with percentage sized components.

State based skinning can be done with MXML components or on the Flash timeline. State skinning allows transitions between states (color fading, resizing, animations, etc.). For Flash the timeline has labels for each state. Component utility plug-in for Flash exists to help with the creation and exporting for use in Flex. Work to maintain timelines skins is very high.

When creating custom programmatic skins look at Halo border. It does a lot of heavy lifting.Are required to do things like set the border style to solid to get it to show up. Makes heavy use of theme color but doesn't provide that much subtle control over how colors get used.

If creating a custom border skin extend RectangularBorder, Border, or as a last resort ProgrammaticSkin. RectangularBorder gives edge metrics and other utility functions that shorten the development time. All of the border skin drawing will take place in updateDisplayList(). If style properties change call invalidateDisplayList() to trigger a redraw.

He demonstrated an issue with the default Halo border with thick borders and rounded corners. Should be logging a bug about that.

Have your skin pickup custom CSS properties from the style manager to offer control not found in the standard Halo skins. Always use hyphens in the CSS file for property names and camel case in code. The utility function drawRoundRect() gives you control to make almost any kind of border you want.

When creating a CSS file, define type selectors for defaults then cascade down to class selectors for overrides. Handy to make a CSS skin reference ClassReference(null) to turn it off for something like an up-down button. Components should have default values baked in that can then be overridden by CSS.

When to use inline MXML vs. style sheets: Designers don't really want to muck with MXML to style the application so providing style sheet properties that the skin picks up makes life easier.

Trade off between making a single mega-skin like Halo border, versus multiple smaller skins each with a single purpose. Mega skins allow more layers of effects but are harder to maintain.

Allurent tends to push more skin configuration to the style sheet since we are making products and having a single configuration point makes it easier. Having it in a style sheet instead of inline MXML also allows for external style sheet loading, compiled independent of the rest of the application. Since styling is cross component having everything in one place is best.

Tags: css flex styling

July 30, 2008

Antennae 1.2.1 Released

Antennae version 1.2.1 has been released. Grab it from http://code.google.com/p/antennae/. Highlights of this release include:

  • Support for AIR based FlexUnit testing, including a project template
  • Other minor bug fixes

For anyone not familiar with Antennae here is a brief description:

Antennae is an open-source project designed to automate the building and testing of Flex applications. It uses Ant and Java to provide cross platform utilities to compile Flex libraries, Flex applications, generate FlexUnit TestSuites, and run FlexUnit tests in an automated manner. Antennae also defines a framework for building complex projects with multiple dependencies and intelligently handling recompilation.

Tags: ant antennae flex

July 30, 2008

For Loop Foolishness

I spent way too long yesterday debugging a stupid typo all the while thinking maybe I'd stumbled across a compiler bug. The code in question:

for (var name:String in _data);
{
    trace(name, _data[name]);
}

In the debugger I could clearly see that my _data object had multiple dynamic properties but I only ever saw one value printed out. In retrospect it was code blindness that comes from working with too many languages that use semicolons at the end of lines. While semicolons are optional in ActionScript, I always put them on, so my eyes just kept skimming over the fact that at the end of the for loop I had a stray one kicking around. Removing it magically made everything work again.

Tags: bug code flex

May 28, 2008

Adobe's David Coletta on Buzzword's Automated Testing Framework

This past Tuesday the Boston Flex User Group held its second meeting. David Coletta from Adobe's Buzzword team spoke about Automated Testing Framework. This was a deeper dive into the topic he presented at Flex Camp Boston 2007. I counted about 50 people at the meeting. It was a very interactive session with a bunch of good questions coming from the audience. Below are my rough notes from the presentation.

David's has a long background in development but hasn't programmed in Flash. Sees work done in Flash and wonders how that was possible, gets same reaction for work he's done in Flex.

Rough Buzzword time line: Jan 2006, started coding; Oct 2006, First public demo; Fall 2007, opened up for real use.

He gave a quick demo of Buzzword. On startup that an issues with new unsupported browsers. They have support for latest Safari but it isn't released yet. Big advantage of online word processor is like Google Docs you can get at it from anywhere. Better than Google Docs because you aren't confined to email only like editing capabilities.

Document browser with support for sorting by last changed, last viewed, role on document, date, number of pages.
Google can't do pagination. Showing picture import, resize, and text wrapping around it. Layout is all done on the fly. Has a nice ruler that no one knows about.

Three models (in the MVC sense used):
document (persistent user content, hierarchical, moving text is just a tree operation), layout (transient position of content, updated after every keystroke), and display (flash/flex objects on the display list, mostly tracking what is part of the flash player).

Primary loop is: hit a character, inserts into document, fires events, triggers layout, visuals, and redraw.

Document internals: Containment (document) versus Inheritance (run).

Buzzword has a built-in inspector. View and set properties manually. Exposes raw data structure.
Typically when using a tree component you can hook it up to XML. With ITreeDataDescriptor you can plug directly into your own custom data structures. Your application should have debugging tools built into it. Flex's easy to use out of the box components without much styling are a good enough interface to create these tools quickly.

Question about why should someone trust Buzzword for documents?: Basically just need to "trust us". SWFs are not over SSL but all documents are. Adobe practices good data security. Need to ask "how bad would a security breach be for Adobe?" and understand they don't want that to happen.

Created a way to test the real application through a system called "LiveTest". Needed to test correctness of document model after every command. Not a replacement for QTP as it is focused on state of internal models. Internally everything is done via command pattern.

To test some feature it records document model after changes to create known good state. Windows/IE used as platform using ActiveX control to write out state into files. These can later be rerun to compare that the same results are produced each time.

Question about how much effort it took to build the test harness? Not sure, maybe 10% of total time.

Comment made about inability to type in full screen mode. It's a security concern which is why its disallowed.

Commands run during a live test know how to output an ActionScript version of themselves that can be pasted into a .as file to create the test file. Could send to server and compile and send back a SWF, but wanted a light-weight solution. Pieces of test are broken into anonymous function, one for each part. Done to work around issue that if ActionScript runs for too long Flash player freezes. Cooperative multiple tasking. Separate functions can run and return control back to UI.

Question about generating ActionScript code versus interrupting XML? Going through API on top of Buzzword to make testing possible. Built this way to ensure you have a good API. Being bale to set breakpoints in code versus XML is very handy.

New code needs to be referenced so they have a file that pulls in all of the tests so they are compiled in.

Manual training of the test. Took XML snapshots of document and layout and wrote them to disk. XML documents have representations of model objects. Has green thumbs up or red thumbs down. Good discipline about running all test before doing a check in.

Test success based on final XML matching checked in XML. On test failure outputs error files and do text compare of expected and actual. Almost no test is visually analyzed, mostly look at raw XML.

Question about sharing the tests? Yes, every developer has all tests, checked into source control.

Question about if you started over today would you change anything? Wouldn't use IE to write files, probably use AIR instead. Might consider an XML representation for capturing test steps. Do use FlexUnit for lower level API testing.

Question about why not QTP? Why doesn't Adobe provide more testing frameworks? Testing tool capturing at a much lower level than QTP. Could refactor testing tool to be more generic.

Question about how something gets retrained? New kind of break, causes document model to change. May cause new XML to be written out and tests will fail. Now need to generate new XML.

Question about how much of the code is covered by the tests? Look to FlexCover.

Question about handling documents from older versions? Can upgrade documents when opened. Have tests that exercise that process. May have fringe cases that cause problems but hasn't been an issue, yet.

Document organizer testing is harder, need to get into correct state, initialize test user with known set of documents.

Browser tests are only running in IE. Haven't really looked at memory profile under multiple browsers.

Tags: buzzword flex testing

April 27, 2008

Flex 4

Some of the first hints about Flex 4 have been posted to the Adobe Open Source site. Great to see the future development of the Flex platform starting off this open.

Tags: flex oss

April 27, 2008

Debugging Bindings with BindingManager

At last night's BFUG meeting Peter Farland demonstrated an undocumented class called BindingManager that is handy for debugging bindings in Flex. This class exists in both Flex 2 and Flex 3. Below is a quick example of how it is used:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" preinitialize="handlePreInitialize();">
<mx:Script>
<![CDATA[
private var _counter:int = 0;

private function changeText():void
{
    text1.text = "Changed Text " + _counter++;
}

private function handlePreInitialize():void
{
    BindingManager.debugBinding("text2.text");
}
]]>
</mx:Script>
<mx:Text id="text1" text="Initial Text"/>
<mx:Text id="text2" text="{text1.text}"/>
<mx:Button label="Update Text 1" click="changeText();"/>
</mx:Application>

The magic is the call to BindingManager.debugBinding(). The argument is the destination of the binding. The translation syntax is a little clearer if you aren't using an inline binding. For example the text2 binding above could also be written like this:

<mx:Text id="text2"/>
<mx:Binding source="text1.text" destination="text2.text"/>

Using either syntax, when the program is run I get the following output:

Binding: destString = text2.text, srcFunc result = Initial Text
Binding: destString = text2.text, error = TypeError: Error #1009: Cannot access a property or method of a null object reference.
Binding: destString = text2.text, srcFunc result = Initial Text
Binding: destString = text2.text, srcFunc result = Changed Text 0
Binding: destString = text2.text, srcFunc result = Changed Text 1
Binding: destString = text2.text, srcFunc result = Changed Text 2

The most interesting part of this output is the "TypeError" message. Normally errors like this are hidden from you on purpose by the binding mechanism. Now instead of having to set breakpoints in the framework it's possible to easily see just what is going on when a binding fires.

Tags: bindings flex

March 31, 2008

Antennae 1.2.0 Released

Antennae version 1.2.0 has been released. Grab it from http://code.google.com/p/antennae/. Highlights of this release include:

  • Changed to standard naming conventions for properties, targets, tasks, and directories
  • Updated support for AIR 1.0

For anyone not familiar with Antennae here is a brief description:

Antennae is an open-source project designed to automate the building and testing of Flex applications. It uses Ant and Java to provide cross platform utilities to compile Flex libraries, Flex applications, generate FlexUnit TestSuites, and run FlexUnit tests in an automated manner. Antennae also defines a framework for building complex projects with multiple dependencies and intelligently handling recompilation.

Tags: ant antennae flex

March 31, 2008

User experience considerations with SQLite operations

An article I wrote for the Adobe Developer Connection entitled "User experience considerations with SQLite operations" has been published. Its focus is on issues Allurent uncovered while working with a SQLite database on the Allurent Desktop Connection application for Anthropologie that was demoed at Adobe MAX 2007 in Chicago.

Tags: adc air article flex

February 25, 2008

Flex 3, AIR 1, and OpenSource

Wow, it's amazing to think about all of the wonderful work that Adobe put into getting Flex 3 and AIR 1 out the door. My congratulations to everyone involved. Lastly the source for the Flex compilers is open source, I've already thought of some things I want to try with that. Download, play, enjoy.

As a side note, I've updated my simple Window Explorer application to run on the released version of AIR.

Tags: air flex oss

February 25, 2008

Puzzling Proxy Problem: Solved

The short version is what AS3 operator triggers a call to the isAttribute() method of a Proxy? The answer, none. isAttribute() is a utility function provided by Proxy that can be called to determine if the name passed to a function was specified as an attribute. A couple of Proxy's methods can't be called in an attribute context, as noted below. I've created a sample Proxy class called MyProxy to help show what's going on:

package com.neophi.test {
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;

    public dynamic class MyProxy extends Proxy {
        override flash_proxy function callProperty(name:*, ... rest):* {
            trace("callProperty", name, rest);
            flash_proxy::isAttribute(name);
            return null;
        }

        override flash_proxy function deleteProperty(name:*):Boolean {
            trace("deleteProperty", name);
            flash_proxy::isAttribute(name);
            return false;
        }

        override flash_proxy function getDescendants(name:*):* {
            trace("getDescendants", name);
            flash_proxy::isAttribute(name);
            return null;
        }

        override flash_proxy function getProperty(name:*):* {
            trace("getProperty", name);
            flash_proxy::isAttribute(name);
            return null;
        }

        override flash_proxy function hasProperty(name:*):Boolean {
            trace("hasProperty", name);
            flash_proxy::isAttribute(name);
            return false;
        }

        // Don't override isAttribute(), it is a utility function
        // used by methods that specify a name:* parameter
        // to determine if the name argument was specified as an
        // attribute. It doesn't look like there is any other
        // way to determine if a name was specified as an
        // attribute besides calling Proxy's isAttribute()
        // implementation. 
        override flash_proxy function isAttribute(name:*):Boolean {
            var result:Boolean = super.flash_proxy::isAttribute(name);
            trace("isAttribute", name, result);
            return result;
        }

        override flash_proxy function nextName(index:int):String {
            trace("nextName", index);
            return null;
        }

        override flash_proxy function nextNameIndex(index:int):int {
            trace("nextNameIndex", index);
            return (1 - index);
        }

        override flash_proxy function nextValue(index:int):* {
            trace("nextValue", index);
            return null;
        }

        override flash_proxy function setProperty(name:*, value:*):void {
            trace("setProperty", name, value);
            flash_proxy::isAttribute(name);
        }
    }
}

I then exercise all of the methods (with and without namespaces) on MyProxy with this code:

private function go():void
{
    namespace myNamespace = "com.neophi.test";
    var myProxy:MyProxy = new MyProxy();

    // callProperty()
    myProxy.foo();
    // Compiler error: 1041: Attributes are not callable.
    // myProxy.@foo();
    myProxy.myNamespace::foo();
    // Compiler error: 1041: Attributes are not callable.
    // myProxy.@myNamespace::foo();

    // deleteProperty(): uses isAttribute()
    delete myProxy.foo;
    delete myProxy.@foo;
    delete myProxy.myNamespace::foo;
    delete myProxy.@myNamespace::foo;

    // getDescendents(): uses isAttribute()
    myProxy..foo;
    myProxy..@foo;
    myProxy..myNamespace::foo;
    myProxy..@myNamespace::foo;

    // getProperty(): uses isAttribute()
    myProxy.foo;
    myProxy.@foo;
    myProxy.myNamespace::foo;
    myProxy.@myNamespace::foo;

    // hasProperty()
    "foo" in myProxy;
    // Compiler error: 1084: Syntax error: expecting identifier before foo.
    // @"foo" in myProxy;
    new QName(myNamespace, "foo") in myProxy;
    // Compiler error: 1084: Syntax error: expecting identifier before new.
    // @new QName(myNamespace, "foo") in myProxy;

    // nextName(): uses nextNameIndex() 
    for (var string:String in myProxy) {
        trace(string);
    }

    // nextValue(): uses nextNameIndex() 
    for each (var object:Object in myProxy) {
        trace(object);
    }

    // setProperty(): uses isAttribute()
    myProxy.foo = "bar";
    myProxy.@foo = "bar";
    myProxy.myNamespace::foo = "bar";
    myProxy.@myNamespace::foo = "bar";
}

The output of running is below (whitespace added to match up with blocks above):

callProperty foo
isAttribute foo false
callProperty com.neophi.test::foo
isAttribute com.neophi.test::foo false

deleteProperty foo
isAttribute foo false
deleteProperty foo
isAttribute foo true
deleteProperty com.neophi.test::foo
isAttribute com.neophi.test::foo false
deleteProperty com.neophi.test::foo
isAttribute com.neophi.test::foo true

getDescendants foo
isAttribute foo false
getDescendants foo
isAttribute foo true
getDescendants com.neophi.test::foo
isAttribute com.neophi.test::foo false
getDescendants com.neophi.test::foo
isAttribute com.neophi.test::foo true

getProperty foo
isAttribute foo false
getProperty foo
isAttribute foo true
getProperty com.neophi.test::foo
isAttribute com.neophi.test::foo false
getProperty com.neophi.test::foo
isAttribute com.neophi.test::foo true

hasProperty foo
isAttribute foo false
hasProperty com.neophi.test::foo
isAttribute com.neophi.test::foo false

nextNameIndex 0
nextName 1
null
nextNameIndex 1

nextNameIndex 0
nextValue 1
null
nextNameIndex 1

setProperty foo bar
isAttribute foo false
setProperty foo bar
isAttribute foo true
setProperty com.neophi.test::foo bar
isAttribute com.neophi.test::foo false
setProperty com.neophi.test::foo bar
isAttribute com.neophi.test::foo true

That then is a complete run down of all the Proxy methods and how to use them. I'd like to thank Jacob Wright for the pointer on how isAttribute() is used.

Tags: as3 flex proxy

January 9, 2008

Truncating labels that use a percentage width

When an mx:Label is created, truncateToFit is true, and a percentage is specified for its width the label will show all of its content even if placed inside a fixed width container. The following example shows this scenario:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:HBox width="100" horizontalScrollPolicy="off">
<mx:Label text="This is a really long label" width="100%" truncateToFit="true"/>
<mx:Button label="X"/>
</mx:HBox>
</mx:Application>

The result is which is not what I had hoped would happen.

The fix is to specify a minWidth for the label. If another HBox is added as shown below the label behaves correctly.

<mx:HBox width="100" horizontalScrollPolicy="off">
<mx:Label text="This is a really long label" width="100%" minWidth="0" truncateToFit="true"/>
<mx:Button label="X"/>
</mx:HBox>

The new result is which is just what I wanted.

Tags: flex label percentage width

December 31, 2007

Flex Camp Boston 2007: Using the Flex Profiler

Rough draft notes

Paul Reilly is speaking about Using the Flex Profiler

Memory profiling lets you look at objects being created, take snapshots and compare them. Performance profiling allows snapshots for looking at cumulative and internal time.

Memory profiling is light-weight compared to performance profiling when configuring the settings.

Profiler runs at the end of the frame which is why there maybe delays in getting updates to the profiler in Flex Builder.

Memory leak detection work flow: select app and take memory snapshot, switch to application and perform an operation, then take a second memory snapshot. Select both snapshots and view loitering objects. Can look at back references to determine who is holding onto something. Most common memory issue is strong references with event listeners. Can either remove the listeners manually or in most cases it is possible to use weak references. Best to reset profile information at the start unless you want to focus on initialization phase.

Can profile any external SWF, in general this is done with the standalone Flash player. Filtering of artificial functions isn't there yet (such as reaping, mouse handling, etc.) but you can change what gets shown such as removing the mx.* filter.

With performance profiling you can look at callers and callees to see how a function is being used. Important to remove filters so that mx.* abd flash.* are included in the list unless you want to focus only on your code.

Profiler supports debugging capabilities. mm.cfg file can be used to control settings. flashlog.txt doesn't get created if using a release version, good way to test that you are using a debug version of the player.

ErrorReportingEnable=1
TraceOutputFileEnable=1
PreloadSwf=ProfilerAgent.swf?debug=true

Additional information outputted into flashlog.txt that shows what the profiler is doing.

mm.cfg is only read once so if you are using multiple tabs in a browser it is only read the first time.
Runtime exceptions or infinite loops will cause the profiler to not work very well.
Taking a memory snapshot implicitly makes a garbage collection call.

Internally the player is using a stack trace (once every millisecond) for performance timing, new object samples (every time an object is create), and delete object samples (every time the GC collects an object). flash.sampling package includes way to get at the same information if you want to roll your own profiler.

DisplayObjectContainer and EventDispatcher are classes that are hard to get the internals of and there are back door methods to get access to data useful for profiling.

Profiler is sample based (not trace based), provides quicker profiling but not as detailed.

When is the best time to take snapshots? Look at overall memory chart to see where the issue might be. Try to narrow down operation in application that causes memory increase. Then start taking snapshots before and after performing that application.

Can you programmatically trigger a snapshot? Not at this time but create an enhancement bug and vote for it.

It is possible to profile AIR applications.

Tags: flex flexcampboston2007 profiler

December 31, 2007

Flex Camp Boston 2007: Using ColdFusion with LCDS

Rough draft notes

Tom Jordahl is talking about Using ColdFusion with LifeCycle Data Services.

Why Data Services?

Powerful back end. Talk to ColdFusion. CFML to manage complex data.

LCDS with CF 8 installed by default.

Messaging: Publish & Subscribe, asynchronous communication, message header and body (can contain complex types CF components or ActionScript types), CF can both produce and consume.

Why messaging?
Real-time notification to your Flex application.
Triger long running server side processes
Notify multiple clients at once

messaging-config.xml contains the data along with reasonable defaults.

Easy to have CF both handle and publish messages that will be broadcast to all clients that are listening.

Client can do HTTP pooling to get around RTMP firewall restrictions.

Data Management

Distributed data management, data replication and synchronization, able to manage large data, nested data one-to-one or one-to-many, has some occasionally connected clients.

All clients that are looking at data will get notifications based on updates that are made. The changes are batched up.

Why Data Management?
Easily synchronization data between clients with conflict detection, data replication, and performance optimization (such as data paging and lazy loading).

Assemblers manage the data. Can be written as ColdFusion Components or Java, leverage Hibernate. Four main mehtods: Fill, Get, Sync, Count.

CF 8 extension for Eclipse are freely available. Gives you RDS (Remote Development Service). Includes query builder. Automated creation of ColdFusion Components and ActionScript classes related to database object management including the Assembler.

Special CF channels: cf-polling-amf (work around firewalls), cf-rtmp (off by default).

Possible to have existing Java or CF applications notify clients of data changes using new Event Gateway.

Able to configure that certain data pieces don't trigger changes being published as a way to optimize changes.

JSP tag to compile MXML applications on the server available on Labs.

All data transmitted via binary AMF3 protocol.

www.adobe.com/go/lcds_devguide
www.adobe.com/go/lcds_javadoc

Tags: coldfusion flex flexcampboston2007 lcds

December 31, 2007

Flex Camp Boston 2007: Keynote

Rough Draft Notes

Christophe Coenraets is giving the Keynote

Talking about Flex 3 Improvements

Advanced DataGrid: hierarchical data, flexible grouping, custom formatting
Charting Enhancements: data-oriented graphical APIs, per-item labels and fills, region selection
New List and Data Effects: choreograph data

Showing iLog charting example
3D bar and data charts
Organizational chart example with grab and pan

Showing code example with the AdvancedDataGrid

<mx:AdvancedDataGrid>
<mx:GroupingCollection>
<mx:Grouping>
<mx:GroupingField name="category"/>
</mx:Grouping>
</mx:GroupingCollection>
</mx:AdvancedDataGrid>

Need to tell grouping collection to refresh itself.

Persistent Framework Caching
Flash player caches Flex framework across projects and sites.
Size of target SWF can now be as small as 50KB.

Base application size 600KB, removing debugging via compiler flag -compiler.debug=false 380KB, Flex Build path/library path/framework linkage, change that to runtime shared library, 200KB. Has fall back capability to support loading SWF instead of using signed SWF caching.

Memory and profiling and code refactoring are two big improvements in Flex Builder 3. Demonstrating sample application called Salesbuilder as a way to show these two new features. Source code is available off of his blog. Application is AIR based and supports desktop drag and drop to save graphs along with offline data synchronization using the SQLite DB and LCDS. Next talk is about profiler so this he isn't talking about it. Showing find references and rename variable support.

Designer and developer workflow is improved through skin asset importing and CS3 Flex component support in Flash. Showing Fireworks example of show to easily skin a button, export the asset and pull it into the Flex CSS file. Once in Flex Builder one can use the new CSS Design view to manipulate the file. Ability to graphically assign Scale 9 parameters that it updates the CSS file with. Can also export style information from Flash.

Flex Builder 3 now supports wizards for working with data and web services. Will generate both client side and server side code in PHP and some other languages for data access. Can introspect a web service through a wizard, select desired methods, and generate stub code on the fly that is strongly typed.

Flex 3 has enhanced JavaScript/AJAX wrappers and improves the deep linking support from Flex 2. Showing deep linking support in Buzzword. All about anchor management. Can leverage the existing URLKit.

Showing new Flex pricing and packaging. Flex 3 SDK, free, Flex Builder 3 standard is $249, there is other pricing.

bugs.adobe.com/flex
www.flex.org/community


Tags: flex flexcampboston2007

December 31, 2007

Flex Camp Boston 2007: FlexUnit Testing with Cairngorm

Rough draft notes

Thomas Burleson is talking about FlexUnit Testing with Cairngorm

Looking at StormWatch and TestStorm used to test that information.

Showing demonstration of StormWatch. Loading XML data of stock market information.

Unit Testing: Test all the functionality of a single unit.
Continuous Testing: Test all units each cycle (each commit). Locally.
Continuous Integration: Test all units created by other developers.

Test API server exposed, transformations in Flex, business logic, event processing, and model updates. Not testing UI (hard to do).

Custom extensions to FlexUnit and Cairngorm to aid testing. Should be live on Google code early next year. Universal Mind (UM) Cairngorm.

Traditional testing approach requires extracting stuff. Bad because: Tests performed outside MVC, requires many test shells, and boundary conditions are not tested well. Focus on human issue (functional test) versus tool issue (unit test).

Uses parallel but different base package naming com..commands.* versus tests..commands.*. 1-to-1 for package, classes, functions.

UM Cairngorm adds: view responders, command event dispatching, delegate queues, batch events, command logic aggregation, and FlexUnit support.

Different unit testing frameworks include: ASUnit, FlexUnit, dpUInt, and UM Wrappers (builds on FlexUnit).

Cairgorm Explorer is a handy application.

Showing how the unit tests are constructed and run. Importance of testing with events to mimic what the UI is doing as much as possible.

Have Synchronizer that watches for code changes and creates stubs automatically. May not be opened sourced but good to think about the ideas.

Tags: cairngorm flex flexcampboston2007 flexunit

December 31, 2007

Flex Camp Boston 2007: Flex and ColdFusion: Mysteries Revealed!

Rough draft notes

Matt Woodward is talking about Flex and ColdFusion: Mysteries Revealed!

mattwoodward.com/blog

For ColdFusion people why use Flex: Very powerful. Simple. Big wow factor. Fun new technology. Don't limit yourself.

Sample photo gallery application, uses custom Flex components, ActionScript, and Events. ColdFusion back end that with RemoteFacade and DB layer.

Flex Builder needs to see ColdFusion's WEB-INF/flex directory.

Forget about request/response when dealing with Flex development. It's all event-driven and much more stateless. Events can be announced at any time. Request to server can be made but the response will come back at some undetermined time.

Business logic should not care who is talking to it. Can get input from anyone. Allows either ColdFusion or Flex to act as front-end. Facade isolates what Flex is talking about.

ColdFusion Components (CFC) and ActionScript (AS) can be translated between if done right. Must have mirrored properties. Have AS define "[RemoteClass(alias="path.to.cfc")]" and CFC define "<cfcomponent alias="path.to.cfc"/>". To return a collection use "<cffunction returntype="path.to.cfc[]"/>". Has good performance for most applications with reasonably sized collections.

Custom Events let you include your own custom data in the Event.

Accessibility questions about Flex? Doesn't have to worry about them. Member of the audience finds Flex easier to make accessible then HTML sites.

Will be posting sample code to his blog.

Where to do error handling? Has person making the call handle what to do if there is an error. Flex can handle ColdFusion error since it gets the error back.

Tags: coldfusion flex flexcampboston2007

December 31, 2007

Flex Camp Boston 2007: Building Buzzword

Rough draft of notes

David Coletta is talking about Building Buzzword.

Jan 2006, started coding in an attic. Oct 2006, public demo at MAX and funding from Adobe. Nov 2006, more people and real offices. May-Aug 2007, monthly preview releases. Fall 2007, open for real use.

Show documents by alphabetically, author, role, last viewed, last modified, # of pages. Custom scroll bar with numbers in it. Able to click on scrollbar to jump to location. Leave comments in document. Also supports tables and advanced formatting capability.

Text on page. Three main pieces: document (content being saved to server), layout (transient position of the content, relay out after every character), and display (Flex/Flash objects on display list). Flow: document to layout. Tries to optimize what changed and handle as few things as possible.

Document internals: Body with one Section has multiple Paragraphs each with multiple Runs. Run has AnchoRun and FontyRun as subclasses. FontyRun has BreakRun, FieldRun, and TextRun and subclasses.

Use custom Tree ITreeDataDescriptor to provide custom tree data providers that can manage any custom data type. Not just XML.

Screen metric - print metrics = micro-spacing to get consistent layout between screen and printing. Very expensive to calculate but vital to getting consistent layout between the two.

Cache of display elements so that only certain objects are shown at once. Buzzword controls what is rendered on screen since the number of text fields for a document would overwhelm the Flash player.

Buzzword back end is .NET and uses low level HTTPService for back end communication. Backend does comment notification, document locking, and other raw CMS features. Login over SSL. Parking HTTP request on the server which then responds when it has data to send to the client.

Testing was vital primarily used FlexUnit. Spent a lot of time developing custom test framework called LiveTest. Focused on document command validity not focused on UI (like QTP). Able to record, debug, train, and playback a test. Generated ActionScript code can be copied back into the platform. Wrote custom framework instead of something like QTP required more constant feeding of unit tests.

Custom skinning scroll bar in Flex 2 was difficult. Hard to get skin to draw text (much improved in Flex 3 with UIComponent skinning model).

Has modular loading. Caches editors, styles, fonts, but if not there is displaying a progress loading bar. Pro: Improves build times, background loading, and good design through information hiding. Con: Can increase overall download, slow overall build, and increased complexity. Debugging across modules is hard, need runtime switching of loading debug versus production. Centralized control of what gets loaded when based on startup mode to prioritize based on startup mode.

Merge user dictionary on a collaborative document into a document dictionary to provide consistent spell checking. Look at gskinner.com for spell checking libraries.

Rich Text Copying is not supported by Flash. Hidden IFRAME or DIV render content from HTML control to allow clipboard content to be rich content. Push focus back to browser so that it picks up copy/paste events.

Off the shelf Flex isn't used much (more for debugging components), leveraging low level components (UITextField). 90% custom AS versus 10% MXML.

David's blog: TheJoyOfFlex.com

Tags: buzzword flex flexcampboston2007

December 31, 2007

Flex Camp Boston 2007: Ask the Experts

Rough draft notes

Panel: Dave Gruber, Tim Buntel, Phil Costa, Jeffry Houser, Todd Prekaski, and Paul Reilly

Q: When can Flash be multi-threaded?
A: Not for awhile. Tricky to do. Not in 10.

Q: What more will be in Flex for designer work flow?
A: Thermo is a new designer tool for converting wire frame into an interactive application. Also giving them tools to handle behavior. Improving skinning models and more declarative. Ely gave talk about this, should be up on MAX website.

Q: Best resource for a designer to get up to speed on Flex?
A: The Adobe Developer center. Grouped by background. Flex Cookbook. And watch for Thermo. Programming Flex is a great for an understanding of Flex in general.

Q: Any plans for different LiveCycle polling options?
A: Server side polling channel configuration (requires thread per socket). LCDS 2.5.1 should have examples about how to mimic real time latency. RTMP is best for non-blocking IO.

Q: Any ability to expand HTTP components to support additional REST capabilities beyond GET and POST?
A: Short answer yes. Flash player is limited by Flash and plug-in APIs. Workaround is to use the LCDS proxy.

Q: How best to handle authenticated remoting?
A: Use a session token. Usually rely on cookies with HTTP.

Q: Why use J2EE session ID as opposed to CF token ids?
A: J2EE session ID are superior to CF token ids.

Q: Any plans to include component that can display web pages in Flex?
A: Support is there for AIR. Can use frames to overlay SWF to get the behavior. No current plans since it requires Flash changes. Look at Drumbeat.

Q: Any plans to have .NET AMF tier?
A: No plans for .NET version of LCDS. Adobe is using a 3rd party Midnight Coders to provide similar services.

Q: Updated version of Cairngorm?
A: Run by Adobe Consulting. Best way to find out more is use their mailing list. Announced at MAX a data driven site version.

Q: ColdFusion application with CFCs for Remoting, what needs to change for AIR?
A: Hopefully nothing! Compiling against the services config does require a little tweaking when using AIR since config isn't parameterized in AIR. Pier (one of the sponsors) gave a talk on that behavior.

Q: Any mechanism to provide synchronous event handling?
A: AIR provides both synchronous and asynchronous. Log enhancement request against Player.

Q: Better Flash and Flex component integration?
A: On the radar to make it better. Flash to Flex is there. Flex to Flash isn't there yet. The component model conversion is a problem.

Q: Flex Builder 4?
A: Looking to users for ideas. Broadening audience that uses it. Let them know if you want to be involved in product planning. Put feature requests into open Flex bug system.

Q: How to synchronize SQLite to MySQL?
A: LCDS may do something in the future. ColdFusion at MAX showed some of the online/offline connection data management.

Q: Additional SQLite support for full SQL syntax?
A: Frozen for AIR 1.0.

Q: Status of code coverage tools?
A: Adobe consulting was looking to build an open source project but don't know the status. Plumbing has been added to player. Should be available soon.

Q: Ted Patrick commented about AMF being released?
A: No.

Q: Issues with profiler on 64-bit.
A: Player doesn't work on 64-bit machines, everything runs in 32-bit mode. Does work on Vista and Leopard.

Q: Linux support for Flex Builder?
A: Alpha of Flex Builder for Linux announced and released at MAX. Development ongoing.

Tags: flex flexcampboston2007

December 31, 2007

Error creating AIR file: 103: ERROR, application.name

Last night I started playing with the public beta 3 drops for Flex 3 and AIR. Using the project creation wizard I created a new Flex based AIR application. After looking at the new application descriptor format which has changed a lot since beta 2 I started to customize it so that I could use it as a template for sample applications I was updating to beta 3. When running the Export Release Build... wizard it got through most of the .air creation process but then erred out at the end with the following message:

Error creating AIR file: 103: ERROR, application.name

A 0 byte .air file existed and a randomly named .tmp file was created.

Turns out the default application descriptor created by the project wizard has a small bug in it. It inserts a commented out <name> element below <filename> at the top of the file. Right before the closing <application> element it inserts an uncommented <name> element. When I uncommented the <name> at the top of the file I was accidentally defining <name> twice and hence causing an error. I would have liked the error message to be more descriptive, but now that I know what it was trying to say (error with <name> in the application descriptor) I should be able to deduce other issues.

Tags: air error flex

December 31, 2007

Flex Camp Boston 2007: Rich Commerce on the Desktop with AIR

Rough draft notes

Joe Berkovitz and Tim Walling are speaking about Bringing Rich Commerce to the Desktop with AIR.

Case study and development notebook presentation.

Wanted to provide rich vibrant shopping experience online and/or offline. Utilize local persistence mechanisms for shopper customization. Business users can author experience. Fast local database. Online conduit for checkout.

Showing a demo of the demo application developed with Anthropologie, a canned demo online. System tray notification, scrolling of primary view, continuity of experience with zooming into product details, ability to locally tag items, search by color, with drag and drop image support, and the ability to have the merchant modify the content shown in the application.

Architecture for final product: web server provides updates and AIR application with an existing commerce server and analytics engine. Update manager supplies catalog meta data, media and markup. Content integration merges local files with web server supplied content to provide a uniform interface to the rest of the client. Personalized data persisted locally in the SQLite data.

Demo made everything local, minimal fixed product catalog, and tweaks to make the data work for the demo.

WindowedApplication is the primary application instead of Application. Chromeless window to get complete control over the look and feel. Different application modes are accomplished by command line arguments. These alternative modes much be manually created. Able to have application startup in system tray only mode.

The AIR application descriptor defines how the application startups. Key values are systemChrome, visible, and transparency are used to control the look and feel. Controlling window is through simple calls like minimize() and startMove().

System tray notifications are custom coded. Need to make sure you take into account screen size and multiple monitors.

Able to use "like" query against SQLite for simple text based searches.

Color search requires custom cursor management to provide custom color widget overlay. Color wheel itself was an image versus dragged in image handled the same way. When using drag managers in AIR there is a NativeDragManager that gives you access to the Clipboard format. Different applications supply drag data differently, such as IE giving a URL for an image versus Firefox giving the raw bitmap data. BitmapData.getPixel(x,y) can be used to color sample images.

The navigation strip navigation is about content. Uses goal based animation to provide smooth scrolling to handle rapid changes in what the user wants to see. Setup want you want to change and how it should change over time. Just supply the value you want and the engine maps to that goal.

Database populated for SQLite by using existing database file. Custom AIR application was created that could read in and populate the SQLite database. Some SQLite tools are available on labs to make working with the files easier (run queries, create tables). Rewrote integration to pull form SQLite database instead of a web service.

SQLite usage internals. DAO to isolate database gunk from the rest of the application getProduct(uri:String, handler:Function). Translator handles SQLResult translation into ActionScript objects.

Asynchronous API to keep event loop alive. ConnectoinPool and StatementPool to manage connections and statements to improve performance. Caching statements saves the need to reparse the statement.

Color match requires looking at color wheel. A given RGB value wasn't matched exactly by anything in the database. How to get close. Instead used HSV (hue, saturation, luminescent). See wikipedia for more details. Used color swatches to extract data for every product. Extract all HSV values and then do a linear search. Not that much data to pull into memory. Animate product results by looking at intersection of two result sets. Fade out what went away, fade in what is new, and move anything to its new position.

Goal based animation is about providing seamless animation experience. All about getting to some state. Doesn't use easing or tweans to apply real-time updating of what the goal is. Can work on multiple properties at once (alpha, position, size). Takes the most direct path to get to the target goal.

To get to the pilot: need to have the application download more content, update mechanism to see the new edition, enable offline cart, and additional personalization capabilities.

Tags: air flex flexcampboston2007

December 31, 2007

Window Explorer Updated for Beta 3

I've updated Window Explorer to work with AIR beta 3. I think I've also got the new badge install for 9.0.115 working. I don't have my PC with Flash Switcher handy so I'm not 100% sure, will have to double check tomorrow. A quick recap of what Window Explorer is: Utility designed to allow easy exploration of the various Flex Window and Native Window options available in AIR. Code generation for selected options is included.

Updating to beta 3 was mostly painless, primarily I just had to remove stuff from the UI which Adobe took out.

Tags: air flex

December 31, 2007

Flex Camp Boston 2007: Config, Debug, Deploy LCDS

Rough draft of notes

Peter Farland is talking about Configuring, Debugging and Deploying LiveCycle Data Services.

Notes from the talk will also be posted to his blog.

Version issues with LCDS

A LCDS version is best used with the version of the Flex SDK that comes with it, in most

Flex 2.0.1/FDS 2.0.1
Flex 2.0.1 HF2/LCDS 2.5
Flex 2.0.1 HF3/LCDS 2.5.1
Flex 3/LCDS 2.5.1

Client side: rpc.swc and fds.swc and services-config.xml are the key pieces to keep synchronized. Don't forget fds_rb.swc.

If you find a bug open up the swc and look in catalog.xml to report the version you are using. The jar file has a similar version in the manifest.

Performance very tied to java version. 1.5.0_07 is very bad for performance. Avoid 1.4.2_02 to 1.4.2_05 and 1.4.2_10. 1.5.0_13 is recommended.

Configuration

Flex compiler knows about services-config.xml. -services compiler flag generates needed AS3 code. -services isn't needed if you want to roll your own ChannelSet management code.

Multiple Channels in a ChannelSet provides failover.
Use a single ChannelSet for all services in the client.
Only authenticate once per client ChannelSet.setCredentials().
Allows runtime determination of secure channel selection.

Programmatically create the ChannelSet to provide a poor man's load balancing. Randomize the order that the Channels are defined is. Still give you fail-over but the random list gives some load balancing (Math.random()).

LCDS messages brokers can create MessageDestinations on start programmatically instead of having to specify everything in a services-config.xml.
Important to optimize your configuration file and get rid of sample pieces and channels that are not used. Can improve compiler performance since it is less data to parse and manipulate. Be sure to remove debugging and redployer watchers from a production configuration file.
Sun's JDK XML parser should be replaced by xalan.jar.

Flex Builder only supports one project in memory at a time. Only the last edited project is retained in memory for incremental builds.

When debugging make sure you have references to data types retrieved from runtime otherwise they won't be linked in. Missing flash.utils.IExternalizable leads to "one of the parameters is incorrect" error which can be solved by referencing the class.

Client side debugging: will dump additional information to flashlog.txt. Paros Proxy, Charles, ServiceCapture are great client side traffic sniffers.

Server side debugging: Can configure debugging levels in services-config.xml. LCDS includes a server side tool sniffer.exe.

Common browser issue is non 200 HTTP status codes.

When doing deployment compile your SWF and simplify your web.xml file. LCDS 2.5.1 allows configuring client point to be secure while server uses HTTP to allow using SSL accelerators. RTMP can use the bind-address and bind-port to allow hooking it up to a load balancer. Resource availability can be problematic on hosted web servers since most are tuned for short lived connections on persistent connections that LCDS uses.

With LCDS express (limited to 1 CPU) 1000 plus users with RTMP should be possible since it is multiple threaded. Other techniques like servlets would block too many threads.

Tags: flex flexcampboston2007 lcds

December 31, 2007

Headless Linux Automated FlexUnit Testing Idea

When using Antennae or some other tool to run automated FlexUnit tests to Linux, it should be possible to use xvfb to create the display that the standalone Flash needs to run. With this approach you avoid the need to have a full X instance running while still being able to use the standalone Flash player to run the test SWF. I won't claim that this is any great insight, but I found a piece of paper on my desk with xvfb scribbled on it and I figured this was as good a place as any to record it :)

Tags: flex flxunit linux

December 31, 2007

Frankenstart: User Startup Experience

I've been thinking about the startup experience a user sees when launching applications. In particular I've been using a bunch of AJAX and Flex based RIAs recently. This observation is still gestating so I've not compiled a well defined list. It's one of those thoughts that I'm pretty sure is there and I'm just looking for additional evidence.

When browsing the web many HTML pages haphazardly form into the final view. Some of this is due to the order that the images, CSS, and other content pieces are loaded by the browser and some of it is the rendering speed of the browser, which has mostly become a non-issue. This experience is something that I think has fallen into the background consciousness of most people browsing the web. The thinking has become, that's just how HTML sites and web browsing work. Contrast that with how most desktop applications launch. There is still some waiting but aspects of the interface only appear when they are ready to be shown, instead of the half rendered state many a web page is briefly shown in.

Since AJAX RIAs rely on the same raw HTML rendering and loading of content by the browser, complex applications can take time to render and in the process look pretty freaky. I've nicknamed this raw startup experience a Frankenstart. One AJAX example of a Frankenstart experience is meebo.com. If you are a frequent user the problem isn't as pronounced but for first time users (try clearing your browser cache) they are presented with a half rendered interface for a few seconds on speedy cable modem. The effects are much worse on slower connections. A picture of my meebo startup experience is shown below (click for a larger image):

It doesn't take much to provide a cleaner startup experience. Buzzword is a Flex based RIA that provides a nice startup experience. A simple progress bar that fades in the fully rendered interface when loading it complete. A picture of my Buzzword startup experience is shown below (click for a larger image):

While the startup experience is only a brief view into your application, first impressions do count, even if only subconsciously. Many AJAX and Flex RIAs do get it right, but there are plenty that need help. Users may still be used to the HTML browser rendering world, but when RIAs start to look and act more like desktop applications, I can see user expectations changing. Don't make a Frankenstart be the first look someone gets at your application.

Tags: ajax flex frankenstart ria

November 30, 2007

Styles, Fonts, and Compile Time

There has been some recent conversation about the impact of styles and fonts on compilation time in Flex Builder 3. I figured I'd take the project I'm currently working on and see what the numbers came out as.

Some more details about the test: About 700KB of raw .as and .mxml code. 2 separate CSS files are imported. 120KB of TTF fonts. 650KB of SWF fonts. Compiling using Flex 2.0.1 Hotfix 3 SDK. Each tests was run 3 times with the average time reported. Each test was run by changing text in the top level MXML component, saving it, and timing a manual build. Timing was from time of click until the progress view reported the build was finished. Copy non-embedded and generate HTML template were disabled.

As with all measurements these should be taken with a grain of salt and are meant to be representative. Your project will vary, yadda, yadda, yadda.

Compile State Compile Time (in seconds)
All styles, 11 SWF fonts, and 2 TTF fonts 11.3
No styles or fonts 4.8
All styles and no fonts 6.9
All styles and 8 SWF fonts 9.1
All styles and 2 TTF fonts 9.1
All styles and 3 SWF fonts 8.1

Clearly using TTF encoded fonts has a higher overhead than SWF encoded fonts. More fonts take more time. The next item to explore is using Flex Builder 3's compile CSS to SWF option. Doing that would require looking at application startup time since the styles would no longer be compiled in but instead loaded during startup.

Tags: as3 css flex

November 30, 2007

AIR support added to Antennae build template system

I'm pleased to announce Antennae release 1.0001 has now been posted. The full release notes are available online. Please leave me any feedback if you run into issues or have feature requests. Below is a summary of the key updates:

Flex based AIR application support

New targets and tasks have been added to support the building, running, and packaging of Flex based AIR applications.

A sample project has been put together that demonstrates the use of these new targets.

A key concept used in AIR application support is the concept of an "assets" directory. Since the AIR ADT application packager requires you to specify each file that should be bundled into the application, Antennae has instead chosen to specify a single directory. The goal being that by default all files under "assets" will be packaged with the application and there is no need to include these files in the source tree.

Simplified importing

All template applications have been updated to use the new single build-common-imports.xml file to pull in all standard Antennae build files.

Source code included

The source code for the ARC-FlexUnit pieces are now bundled with Antennae. This is for reference purposes. To rebuild the platform please grab the latest source code from the SVN repository for Antennae. http://antennae.googlecode.com/svn/

Linux fixes

Fixed bug about not being able to run automated unit tests on Linux.

Tags: ant antennae flex

November 30, 2007

Flex Cookbook Code License?

The growing Flex Cookbook is great for finding answers for a wide range of problems. The problem is the site doesn't make it clear what license everything is under. For a developer creating a product that uses some of the cookbook code what might it mean? Your guess is as good as mine. For an entry I posted I cited the license the code fell under. While other examples are not as clear. What does that "@author" mean?

I think for the Flex Cookbook to be a general purpose reference it really needs to clearly state the license all code falls under. Ideally it should establish a blanket public domain license. If I'm missing something please let me know.

Tags: cookbook flex license

October 24, 2007

MAX 2007: Case Study: ESRI Geospatial Application Using Adobe Flex

Rough Draft Notes

Mansour Raad

ArcWeb Services, APIs for adding GIS data to applications.

Data Visualization: GeoRSS includes lattitude, longitude, point, line. Looking to create 2D/3D map interaction. Vector data is much faster to work with (Poly 9). gwx:Map and poly9:Globe are a couple of components that make it easy to work with the data.

Mashups: Edge 305 to gather data. Created a GPX feed. Combined with photos and leveraged ESRI map data to show route and tag with photos. gpx:GPXLayer and awx:BubbleMarker were some of the components used.

Framework in general. User has full control over draw methods. Supports client side spatial searches. Showed example of circling section on map and highlighting those points within it. Uses client side RTree. Using the server select a point and call utility.getDriveTime returns geometry object with real-time 5 minute drive time radius. Has server side natural language processing to determine location. Example was "Let's get a Chicago deep dish pizza at the corner of main and elm in Boston." Determines that Chicago isn't a location.

Mentioned MIT Simile AJAX project to combine GIS data with time line visualization.

SHP file format. There is a Google code library that can read it.

Modify display with things like Graphics.curveTo with a control point.

ERS demo application. Placed barricades on map and allowed people to determine how to route around them. Used to help Minneapolis public after bridge collapsed.

Beta of APIs and services available at www.esri.com/flex

Other URLs of interest
www.arcwebservices.com
thunderheadxpler.blogspot.com

Tags: flex gis max2007chicago

October 24, 2007

Adobe Offers Flex Builder 2 to Students and Faculty at No Cost

Adobe announced today that beginning in November qualified education end-users will be able to get Adobe Flex Builder 2 for free. I think this is another good move on Adobe's part to help open up and promote the platform.

Full details here.

Tags: flex

October 24, 2007

AIR Window Explorer

I spent most of today putting the finishing touches on a utility AIR application. The application is geared towards making it easy to explore what kind of custom Flex Window and Native Window objects you can create and how they look. It includes some debugging features and the ability to generate AS3 and MXML (Window only) code that matches the selected options.

I played around with the latest SWFObject and the badge install so that grabbing the application should be painless. Window Explorer Download Information.

Let me know if you run into any issues or have ideas for improvement :)

Tags: air flex

October 24, 2007

MAX 2007: Keynote 2

Rough Draft Notes

Kevin Lynch

adobe.mtv.com Adobe AIR contest now open

Bruce Chizen

Financial community is like tooth drilling without novocaine. Press is fascinating. Print the words he says but surrounding it with other stuff, which isn't what I meant. As as CEO privacy is an issue. How much he makes is public. Now as a CEO there is legal risk, signing his life away.

Saturday. Dave Mathews Band concert. Back-stage pases. Talking about Adobe products.

In Keynote, sneak peaks, what developers/designers do with tools Adobe provides.

Kevin

Server, Services, and Tools

Back common server side patterns into server code and reuse there.

Steven Webster

Experience matters, that happens on the glass. Experience behind the glass. LiveCycle ES, back-end to rich experience front-end.

Mitch Fried (mfg.com) online marketplace, geographically diverse, RFQ lots of data. Real-time back end matching., 3D PDFs with policy settings.

Steven

LiveCycle on top of Java SOA. Data services (what was FDS) is one piece of LiveCycle.
LiveCycle workbench (Eclipse based). Form guide builder. Getting to scan a piece of paper and turn it into an RIA.
Rights Management and Digital Signatures. Prevent printing or emailing. Assure return of confidential information.
Process Management. Workspace ships with LiveCycle to define and work with processes.
LiveCycle is available free on devnet.

Kevin: Adobe looking to create hosted services.

Scene7 Imaging, Share, Pacifica, CoCoMo

Doug Mack: Scene7, Rich media service and automation. Single master image. Many parameters to control flow. Demo of online uniform creation. Take content for granted and just design the experience. Delivered as SaaS. Scene7 image portal. QVC demo with AIR, Scene7, and Video. Looking to be as strong with print and online.

Andrew Shebanow: SHARE, file sharing in and outside firewall. 1GB of storage. Uploaded file from desktop, virus scanned, emailed person data was shared with, thumbnailed document. Viewer is Flash Paper on steroids. Embed file into HTML page through custom control. REST APIs (upload, share, retrieve). Also have AS3 libraries. In the future more improvements with file formats and organizations.

adobe.com/go/share/ beta available now.

Danielle Deibler: Pacifica, high quality voice, messaging, and presence. Almost like HD voice. Video preview sharing. Point-to-point connection on top of Pacifica service. High quality voice, text messaging, presence, NAT and F/W traversal. Roadmap: video, p2p, air, pstn access.

Private Beta starting this month, looking for people with applications that would fit the platform, also they are hiring.

Nigel Pegg: CoCoMo, Adobe Connect, been working on new client-server platform. Client UI now in Flex, now UI component framework, have access to lower level APIs. Opening up hosting infrastructure, real-time data messaging, av streaming. , , ,

Kevin: Thermo (Designers to create RIA)

Mark Anders, Stephen Heintz: Thermo, RIA Design Tool. Creating Flex applications. Own design. In context (x, y, width, height) display. Flex framework extensions (mx:Graphic, mx:Rect). Import PSD. Options to treat layers. (mx:BitmapGraphic, mx:TextGraphic). "Convert Artwork To". List management (auto random data). State management and automatic transition creation. Visual bind of controls. Automatically repeat sample data. Thermo and Flex Builder share project definitions.

Start to be available next year.

Kevin: XD

Mike Sundermeyer: What makes a great experience. Adobe inspire experience design site.

xd.adobe.com (alpha) Case studies, design patterns, hot topics.

Kevin: Biggest Flash Device. Susan B Yacht, Captain Kirk. InteliSea.

Tags: flex max2007chicago

October 24, 2007

MAX 2007: On AIR Security

Rough Draft Notes

Lucas Adamski

AIR Threat Model
Installation
Runtime managed dialog, application signed by CA, self-signed = unsigned
Line between guaranteed harmless/automatic execution to full privilege/explicit install.
Only time user makes a decision is on the security dialog
AIR updates must be signed by the same publisher

Elevation Attacks
Remote content should not be able to discover anything about local system.
Should not be able to cross sandboxes.

Injection Attacks
JSON isn't a problem, JSON by eval() is the issue.
Smallest sandbox is a frame.
Injection Vectors: Code importing, DOM manipulation, URI schemes, Code generating functions.
Focused on protecting the user, not the developer.
Mitigations: Escaping or stripping (requires diligence). Clearly separate code and data (SQL prepared statements are a good example).

Typical Desktop Application Threats
Writable files
Credentials stored insecurely
Default passwords
Buffer and stack overflow
Upgrade/downgrade attacks (manually uninstall to downgrade)
Applications should not update without explicit user permission, no runtime importing to application content from remote servers.

AIR Security Model
Scripting languages have greater access than browser
Dynamically loading shouldn't have access
Provide loading mechanism that puts loaded data in its own sandbox
Explicit communication mechanisms
Safer cross domain data

AIR Does Not
Can't run untrustworthy applications
Prevents security mistakes
Has sandbox to guarantees security

AIR Does Provide
Full system access
Explicit installation
Signed applications

Guiding Principles
Local and remote data is like running in a browser
AIR shouldn't be natively more dangerous than other platforms
AIR shouldn't be a vehicle for attacking machines
AIR shouldn't require security guru
Develop paradigm during beta process

Flash in AIR
app-resource vs. app-storage
Application content: no asfunction, loader.loadbytes(),
Non-application content: no direct AIR API
No one: no write to app-resource, sandboxBridge

HTML Security Model
Application (desktop model) vs. Classic Sandbox (Browser like)
Application: direct air access, set innerHTML but script ignored, dynamic allowed only during load
Classic: dynamic always permitted, script for JSON are fine, no direct AIR API

Have to wait for parent Sandbox bridge before you can do anything

Cookies can be turned on/off.
SSL supported
Secure local store API, generic secure key storage (app ID and user Key)

Q: If I download a SWF into application-storage will that have fewer privileges than a SWF loaded from application-resource? Yes. Looking in the long term to provide plug-in API (not 1.0). Bridging will get you there. In general it's not prevented just discouraged.

Tags: air flex max2007chicago security

October 24, 2007

MAX 2007: Best Practices for Developing with ActionScript 3.0

Rough Draft Notes

David Hassoun

Talk will focus on resources and guides, this isn't a how to.

Three main pieces: Analysis (what to do), Design (how to do it), and Implementation (creating code)

Saffron AIR UML Tool, Enterprise Architect, UML and a focus on class diagrams
Unit testing frameworks include FlexUnit and ASUnit

Coding Guidelines: Doesn't matter what you pick, but consistency is key.
Areas to consider: object creation policy, variables typing and scoping, package structure, class structure, naming conventions, code commenting, and curly braces

Not confirmed but mentioned something about declaring multiple variables on a single line as being more efficient. (ala. private var foo:String = "", bar:String = "";)

Program to interfaces.

Memory and performance. Areas to consider include: deferred instantiation, paging in data, don't load assets until needed, remove references, remove trace statements, use the mxmlc optimize flag (on by default I believe), use int as type of loop counter.
Unconfirmed but mentioned accessing static member variable in a loop is more expensive then copy value to local variable and referencing that instead.

Architecture: Create and use frameworks (reusable code blocks).: provide proven and targeted solutions and the expense of code size and potential bugs. Design patterns are repeatable solutions and should be used as needed. RSLs and modules great for sharing code and leveraging testing effort (once tested can be used again with higher confidence). Look at using -link-report and -load-externs command line options. Flex 3 is adding cached framework library. Flex Builder 3 has UI for setting up and using modules.

Best practices: code management and version control. Create code integrity, do unit testing, and continuous integration.

Tags: as3 flex max2007chicago

October 24, 2007

Continuous Integration with Flex, FlexUnit, and Ant

I've posted a version of my slides (0.5MB PDF) that were used for my Flashforward talk and MAX talk under the titles "Automation of Flex Building and Unit Testing" and "Continuous Integration with Flex, FlexUnit, and Ant" respectively.

The demonstration files used in the talk are mostly equivalent to the tutorial and template directories that are included in Antennae.

The resources mentioned in the talk are listed below:

Tags: ant flashforward2007boston flex flexunit max2007chicago

September 26, 2007

Flashforward Boston Talk Time Change: Automation of Flex Building and Unit Testing

Due to a scheduling conflict the time of my talk has been moved up a slot. The new details: Grand Ballroom, Salon E: Friday, September 21, 2007 1:30 PM-2:45 PM.

Tags: ant antennae flashforward2007boston flex flexunit

September 26, 2007

Flashforward Boston: What's this button do?

Rough Draft Notes
robert hoekman, jr.

Need to get user up to speed, help to get through your application.

What's this button do?
I'm feeling lucky?

suffer from a lack of explanation, or lack of context, don't install confidence

Talking about instructive text:
Using senduit as an example. (upload file and get temporary URL for that file)
Need to communicate: purpose, benefit, usage
need to keep it short

using default value in field to prompt user
show default zip code value (5, 9, 5+4)

Squidoo (create pages to market things)
inline help balloons for instructive text

command line (something that triggers action) "call to action" verb-noun pair
people don't like object based actions "page organization"

people have gotten used to dragging, almost expect it on the web. People that have been on the web a long time might not expect drag and drop may not work. Be explicit.

once over drag, cursor changes. when dragging move other modules around to show them the change.

"I'm done editing" sense of closure

Old Version of WordPress.com page doesn't have clear way to sign-up. Links hidden in text. Redesigned to big green button (contrasting color, different background) "sign up now". Jumped up 10-12%. Instructive piece more obvious.

RSS. Most web users still don't know what RSS is. Why would a user click a button that says RSS if I have no idea what this means. "Subscribe to this blog" is a better way to approach it.

Feedburner has a good approach. Creates a stylized version of your feed. "Syndication" and "content" are stuffy words. XML is a scary word.

Addthis.com has a different approach. Easy one click subscription, but doesn't help inform a user if they don't know what RSS is.

commoncraft.com/ Screencasts are a great way to explain a concept or a new idea.

BaseCamp.com: Disposable constructive element. New page has text that goes away when user performs the action.

GoogleReader for a new user has a screencast that talks about what it does with screen shots. Put a personal face on the experience.

Software for making screencasts.
Windows: Jing, TechSmith Camtasia Studio.
Mac: Jing, SnapzProX.

Flickr and most popular tag page. Size reflects popularity. No one gets tag clouds. No real life methaphor. Big doesn't mean more popular.

LibraryThing.com "What are tags" link. Very scary tag cloud page. Information overload.

NYTimes.com has explanation of tag cloud above cloud. Still a horrible interface...

miva.org
miskeeto.com (new design firm)
updownrepeat.com (The art and science of web forms)

Q: How to capture the content scrolled off the web.
Snagit (handle captures all scrolling of the web page)

Tags: design flashforward2007boston flex

September 26, 2007

Flashfoward Boston: Designers vs. Developers: How To Avoid Fights on the Playground

Rough Draft Notes

Marc Leuchner, Almighty
Matt Wright, ROKKAN

Everyone is working together to make projects happen. Most common sense but people aren't really calling it out.

Industry overview: Best area related to Internet. Unique people, extremely creative, lots of technologies continually expanding. FWA tracking latest and greatest. newstoday.com, Communication Arts Magazine.

Subcultures: code fiends, design junkies, framework freaks, application addicts, game gurus, usability nuts.

In larger companies: role strictly defined, objective, performance, but hard to communicate. While in a small company: roles loosely defined, absorb responsibilities, easier communication.

Can people work together? Yes if we talk and compromise.

Look at current workflow. If it is working, maybe you don't need to change anything. Some areas could be improved, need to really pinpoint weaknesses and admit your faults. Focus on opportunities to collaborate.

Education is key to working together. Need to educate each other about what you do and why it matters.

Some people don't want to change (don't force it), start with something fun. You will probably fail a few times but learn from your mistakes.

Designers: should ask for help with programming tasks to get into it more.
Developers need help with: UI design, typography, color theory, photoshop.

Brainstorming: invite everyone, technology can drive ideas, PM as moderators, open mind (no egos).

Creative Development: narrow ideas, define technologies. Need to be as clear as possible and justify. Talk about why a technology is good/bad, don't throw around buzzwords, stay open minded. Last time to argue.

Information Architecture: Don't work in a vacuum, avoid nonobjective views, run ideas by developers, keep yourself in check.

Art Direction & Design: Need prototypes, solicit developer feedback, might need to sell your idea, may require longer design.

Production and Development: After hand-off check in frequently, nit-picking is okay, way to get back to idea since translation to code may have lost something. Pixel perfect isn't always possible. Motion comps are helpful and remember that some compromise maybe needed.

Testing & QA: Not just for developers, learning experience, help prevent future issues

Project Review: discuss positives and what went wrong.

Workflow: Layer comps, motion samples, functional specs, Flex skins, separate style information, consistent folder structure.

Ted Patrick has some good articles on skinning Flex components.

Breaking communication barrier: active early communication helps build trust, respect and learn about everyone's role, don't be afraid to ask questions. Keep an open mind. Don't build barriers creates clicks and makes it hard to cross the bridge.

Middle Man: Hard to find but good for bridging the gap.

Deadlines = stress = fights. It is unavoidable but strive to work together.

nobien.net

Tags: flash flashforward2007boston flex

September 26, 2007

Flashforward Boston: Stylizing Flex Applications

Rough Draft of Notes

Joey Lott The Morphic Group

Main application to be styled is just using standard components. VBox, List,

Inline attribute on List: backgroundColor
This isn't preferred since you have no centralized location of what your style information is.

Adding . Type selector and Class selector.

<mx:Style>
List {
    backgroundColor: #0000FF;
}
</mx:Style>

Applies to all components. Another List in the program would also get it. To have more control you can use a style selector. Need to set it via styleName on a target component.

.exampleStyleSelector {
    backgroundColor: #0000FF;
}

Why do this. Can reuse selector on any other component while keeping the style information centralized. Camel case for style names or hyphenation. Inline styles must use camel case but CSS information can use either.

Moving selector into external styles.css file via:

<mx:Style source="styles.css"/>

Application {
    background-color: #000000;
}

Precedence of style application: Type selector applied first, then class selector, lastly inline style attribute.

What to style items in the List. Going to use an item renderer. Like Cell renderer in Flash. Using another MXML component to show the list item. Gets passed a data property which contains the list item.

<mx:HBox>
<mx:Image source="{data.image}"/>
<mx:Text text="{data.title}"/>
</mx:HBox>

Add itemRenderer="com.example.DataRenderer" to List we want to render items of. Always need to use full class name can't use class name only even if imported.

Style scrollbars with a type selector. It is using custom images for arrows.

ScrollBar {
    up-arrow-up-skin: Embed('images/scrollArrowUp.png');
}

Embedding fonts can use url or local directive can be used to reference font file.

@font-face {
    src: url("Verdana.ttf");
    font-family: Morphic;
}

Styling some of the other components. Some type selectors can reference other class selector names.

TabNavigator {
    tab-style-name: tabButtons
}
.tabButtons {}

VBox with nested image. Using scale 9 to control embedded image.

.framedImage {
    background-image: Embed('image.png', scaleGridTop=30, scaleGridBottom=59, scaleGridLeft=30, scaleGridRight=59);
}

Programmatic skinning. Consider a general style that you want to have many variations of. Graphic assets would require unique file for each variation and increase file size. A programmatic skin let's you do it in code instead.

public class ButtonSkin extends ProgrammaticSkin {
    // key method to override
    override protected function updateDisplayList(...);
    if (getStyle("backgroundColor") != null) {
        //pikcup value
    }
    // name property of programmatic skin
    if (name == "upSkin") {
        //skin specific style
    }
}

// in css
Button {
    upSkin: ClassReference("com.example.ButtonSkin");
}

Customizing the preloader. Make sure you only use ActionScript stuff, nothing from Flex framework since they won't be available yet.

public class CustomDownloadProgress extends DownloadProgressBar {
    override public function set preloader(value:Sprite):void {
        // progress and init_complete events
    }
    // dispatch complete event when done and application should start
}

<mx:Application preloader="com.example.CustomDownloadProgress"/>

scale9.com for premade styles

Tags: css flashforward2007boston flex styling

September 26, 2007

Flashforward Boston: Keynote

Rough draft of notes

Flickr tag with flashforward


Kevin Lynch from Adobe

Pushing Flash forward with AS3. Complimentary copies of Essential ActionScript 3.0.

With FP9 and AS3: E4X, regular expressions, strong and lose typing.

Inside Tamarin is the Virtual Machine within FP9. Core of VM has been opened sourced to Mozilla. 10 times speedup in FP9. Also have this is as the scripting language for the web. FireFox and Flash Player 9. ECMAScript standard. Includes Just-in-Time compiler.

Showing RSS XML data and E4X possibilities:

feed.channel.title.text()
feed..title.text()
feed..item[1].text()
feed..item.(@id =="82").title.text()

Power of regular expression.

Showing comparison of AS3 and JavaScript 1.7. In general 10 times faster.

Flash Player adoption. Fp7 70% in 1 year, FP 8, almost 90% in one year, FP 9 90% in one year.

Picnik. Online photo editing. Zoom, rotate, alignment, color editing (saturation, temperature), sharpness, real-time editing.


Joshua Hirsch from Big Shapeship (Digital Creative Agency) talking about HBO.

8 apartments single building, like no walls. Projected onto side of building. Watch on-demand on digital cable. Also put the web.

HBO Voyeur. Using papervision for 3d effects. Full video.


Kevin: Adobe is focusing on digital technologies. Video workflow from creation to distribution. Adobe media player to view video on desktop.

H.264, multi-core cpu, full screen hardware scaling, bitmap downscaling, secured delivery of streaming video. IPv6, ISO video standard video camera, personal media players, set-top boxes, tvs. FP9 being updated to include H.264 code named Moviestar.

HD Video Demo. Releasing soon, new component for CS3 to use H.264 right in Flash. CSI HD video example. 70% of web video is in Flash.

Papervision example with multi-core speedup.


Adrian Ludwig talking about Flex. Already two versions of Flex. Currently working on Moxie. Language intelligence, profiler, visualization, workflow.

Flex is moving to be open source. bugs.adobe.com. Profiler demonstration. Memory usage. Object creations. Snapshot of application. Application is running faster than he expected (had to muck code). Zoom in on method that is taking a long time. Who was calling.

Showing refactoring example. Method rename. Workflow speedup.Sample application is using charting controls. Advanced data grid, has per column formatting.

Flex perceived as too big. Flex framework cache. Download framework code only once.


Kevin back talking about AIR. Flash, PDF, and HTML. AIR platform overview.

AIR sample applications. AIR Samples.
Showing badge install process. One click to install AIR and your application. PixelPerfect example.

artMusheen. Paint with shapes example. Native chrome.

digimix, mixing audio.

Finetune. Streaming music on your desktop.

Buzzword. Word processor. Edit locally or shared thorugh a cloud. Lists, tables, pictures, graphic editing. No drag'n'drop support out of the box yet.

Flickair searches Flickr for photos, nice chromeless application.

adobe.com/go/air

CS3 extension for Flash to just package application as AIR, should just work.

Tags: air flash flashforward2007boston flex

August 31, 2007

on AIR Bus Tour Boston: AIR and Flash Video in 20 minutes

Thierry Curis from Akami gave a talk about using Flash Video in AIR.

Akami is creating an open source connection class (main site) that is robust, lightweight, and flexible, with credits to Will Law. Pure AS3 code. Setup to handle on demand content and protocol detection.

He gave a demo using the AkamaiConnection class to show streaming content. Some sample code is below. The complete source is available.

public function init():void {
    var ak:AkamaiConnection = new AkamaiConnection();

    // Some of the setup properties
    ak.createStream = true;
    ak.maxBufferLength = 5;
    ak.useFastStartBuffer = true;

    // Some of the events

    // handle connecting to the content
    ak.addEventListener(AkamaiNotificationEvent.CONNECTED, connectedHandler);
    // handle network connection going online/offline
    ak.addEventListener(AkamaiStatusEvent.NETCONNECTION, netStatusHandler);
    // know when the length of the stream becomes available
    // read it through the ak.streamLength property
    ak.addEventListener(AkamaiNotificationEvent.STREAM_LENGTH, streamLengthHandler);

    // where the stream is located
    ak.connect("hostname");
}

public function connectedHandler(event:AkamaiNotificationEvent):void
{
    var video:Video = new Video();
    video.attachNetStream(ak.netStream);
    ak.requestStreamLength("filename");
}

// once enough content has streamed
ak.play("filename");

// methods to control the playback
ak.resume();
ak.pause();
ak.seek(#);

Tags: air flex onair2007boston video

August 31, 2007

Flex Automation Links

If you are interested in using the Flex automation features, this is a collection of links which might be helpful:

Tags: automation flex

August 31, 2007

on AIR Bus Tour Boston: AIR API Overview

Daniel Dura gave an overview of the AIR APIs.

Air provides a rich stack of APIs that is available to both Flash/Flex and HTML and runs on multiple platforms. These APIs cover: network detection, file I/O, custom window chrome, multiple windows, native menus, drag and drop with clipboard, system tray and dock notifications, application signing, application icons, file type registration, background applications, application updates, and network support.

He next drilled into some of the above areas in more detail. AIR specific classes are included in the Flex 3 documentation available on LiveDocs.

Windowing: Multiple window support, transparent windows, different window types (lightweight, utility, and standard), z-index ordering, and always in front.

Pixel Perfect: Alpha window overlay that shows width and height with no standard window chrome.

HTML Control: Integrated into Flash rendering pipeline (can apply effects to it), script bridging, and override default behavior (navigate, history, window, resize).

File I/O: Full read/write access, native file dialogs (save, select, select multiple, directory), and Async and Sync APIs.

Database: SQLite embedded database, zero setup, single file, and based on SQL92.

Drag and Drop/Clipboard: System level drag and drop (AIR to AIR, AIR to OS, OS to AIR, etc.), multiple formats (URL, files, text, serialized AS objects), and modifiers (link, copy, move). Drag and drop is handled through TransferableData objects.

Application Icons: No feed to know about icon format, can just supply PNG images.

Service Monitoring: Monitor network interface changes, monitor services, and extensible (supports multiple service types). URLMonitor class is one example.

Flex Builder: Debugging, code hinting, packaging, and application signing.

Tags: air flex onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Business Class AIR

Charles Freedman gave a couple of demos for Saleforce.com and Ribbit.

Salesforce.com

Salesforce provides a set of AIR specific classes to ease creating RIAs which leverage the data in Salesforce. AIRConnection.as is the main class which provides a layer between Flex and the AIR database which is based on SQLite. Looks like registration is required to get access to the toolkit.

Showed an example of how to use the AIR URLMonitor class to detect online and offline status. When online the sample application pulls data from the online database and caches it locally. Can then run queries against it and queue updates while offline.

Ribbit

Fully functional Flex based phone that allows adding telephony to any web page. Online version allows you to listen and read voice mail (they do some speech recognition). The AIR application downloads your call history to allow displaying it offline. Didn't feel like a convincing use of an offline application since it didn't look like it cached voicemail (even the transcribed version). He gave a live demonstration of calling someone in the audience.

developer.ribbit.com has developer tools.

Tags: air flex onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Keynote

Ryan Stewart gave the keynote as part of the on AIR Bus Tour here in Boston.

Adobe has primarily become a web company. Flash penetration is happening quickly, Flex is gaining ground, and other standards like PDF are being used everywhere.

Adobe has lately been focusing on: Runtime Performance (AVM2 and AS3), Development Model (Flex and Flex Builder), and Desktop Runtime (AIR). I'd also add that the CS3 enhancements for Flash/Flex sharing are another great example of recent improvements.

AIR is focusing on existing standards. Gives the ability to create an AIR application without needing to touch Flash at all, can be entirely HTML and JavaScript. The real advantage of AIR is the tight integration, like having JavaScript call Flash and vice versa. One of the key technologies included in AIR is WebKit, the same HTML rendering engine behind Safari. Better support for PDF will be included in later AIR releases.

AIR enables desktop interaction through AIR specific APIs for accessing the file system, network detection, notifications, application updates, drag and drop (with the host OS), and local databases using SQLite. More details in the AIR API Overview.

AIR support is currently only for Mac and Windows. Linux version should exist after 1.0 release. I think not having Linux out of the gate is sad, but nice to know they do have a road map which includes intended support for it.

Next up were a bunch of demos showing AIR applications. Some of them extended an existing website down to the desktop to make interaction easier and provide capabilities not available in a browser only experience.

finetune.com: Site is a combination of AJAX and Flash. AIR application extends music capabilities onto the desktop. Able to reuse most of the code. Hook into iTunes XML file to drive what music it will play. Shared profile information between website and desktop.

pownce: Micro blogging website. AIR application allows sending data by dragging and dropping it from the host OS. Website is in AJAX but they wrote the AIR application in Flex to provide additional flexible.

simple tasks: Quick AIR application thrown together using HTML and JavaScript.

buzzword: Still in private betas. Originally build in Flex as an online word processor. Created an entire text rendering engine in AS3 (possible because of the speed of AVM2). Document sharing, comments, fully WYSIWYG editing, and online/offline synchronizing.

Adobe Media Player: New way to deliver video content to users through channels.

airapps.pbwiki.com: Registry of publicly available AIR applications. People are encouraged to add links to their application.

At the upcoming MAX conference (more information below) Adobe will release Beta 2 of AIR and announce the winners of AIR Dev Derby contest. There is still time to enter the derby, deadline September 5, 2007.

If you can only make it to one conference, the MAX conference September 30 - October 3, 2007 in Chicago is highly recommended.

Tags: air flex onair2007boston

August 31, 2007

on AIR Bus Tour Boston: ActionScript and JavaScript Integration

Kevin Hoyt is back with a second talk about how to integrate ActionScript with JavaScript within a single AIR application. Currently on the web you have an HTML page and throw in an embed to display some video, but it is a black box. Likewise a Flash application is mostly not interacting with HTML at all. Script bridging is the magic that makes it all possible.

He showed a simple Flex application with a location field that loads and displays an HTML page within AIR. Currently AIR can't display Flash embedded in an HTML page that it is rendering. That should be supported in a later beta.

AIR has a Flex tag called which can render HTML content. Primary use is to set the location property, which will load and display the URL given. He showed an AIR HTML "Browser" in 5 lines of MXML code:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:TextInput id="input" enter="web.location = input.text;"/>
<mx:HTML id="web" width="100%" height="100%"/>
</mx:WindowedApplication>

In ActionScript you have full access to the HTML object and through it access to all JavaScript like functions such as getElementById. To read an HTML value in ActionScript:

// Read an HTML text field
var name:Object = web.javaScriptDocument.getElementById('txtName').value;
// Update an HTML text field
web.javaScriptDocument.getElementById('txtName').value = "text";

Data comes back as a JavaScript String, which doesn't map directly to an ActionScript String. The returned value should be stored as an Object. He didn't mention about gotchas when going in the other direction.

Next he showed how to use native drag and drop. The example took a desktop image and droped it on the Flex application. NativeDragEvent and friends let you handle the drag and drop. Once the Flex application got the image, it introspected the HTML and replaced all images in the rendered web page with the dropped in image.

The next example showed how JavaScript can leverage and manipulate ActionScript. JavaScript developers should consult the Flex 3 SDK documentation to know what is available and what packages the classes are in.

The application's back story is about wanting to display the user's version of an icon for a specific file extension. Showing a sample from the core in the Aptana (source available) that knows how to determine and show the custom icons. OS returns an Array of different icons. The example uses PNGEncoder in ActionScript to render the information. HTML can include ActionScript libraries by specifying the SWF as the script source.

<script src="library.swf"></script>

The last example was showing that HTML rendered in AIR can be manipulated by Flash. It loaded a simple HTML page and then applied Flash filters to various divs. Really cool capability. No source shown.

Tags: air flex html javascript onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Yahoo and Adobe AIR

j r conlin gave a talk about What can Yahoo! Do For You?

Yahoo Developer Network provides lots of tools, largely free to use, with Flash/Flex specific content. These include: Maps, Search, YUI, Flickr, del.icio.us, Upcoming, Pipes, MyBlogLog, BBAuth, YSlow, Astra, etc.

YUI: Lots of widgets that you don't have to build. Calender, grid, etc.

Pipes: RSS type mashup capabilities for non programmers.

AirMail: Drag and drop mail application written in AIR (not public yet).

Astra: YUI for Flex developers, BSD style license.

Tags: air flex onair2007boston yahoo

August 31, 2007

on AIR Bus Tour Boston: Native Windows

Chafic Kzoun gave a talk about how to use Native Windows with AIR.

He showed a bunch of simple examples which demonstrated the native window capabilities in AIR. Best was a screen size tester called PixelPerfect available from Adobe Labs.

NativeWindow is the core of what you will work with. Keep in mind Window is also just a class. Some options need to be setup before the window is created, while others are runtime properties. This is why the AIR application descriptor forces you to specify certain options.

// Create a simple utility window and display it
var options:NativeWindowInitOptions = new NativeWindowInitOptions();
options.type = NativeWindowType.UTILITY;
var nativeWindow:NativeWindow = new NativeWindow(true, options);
nativeWindow.activate();

A more complex example that uses more options.

package com.example {
    import flash.display.NativeWindow;
    import flash.display.NativeWindowInitOptions;
    import flash.display.NativeWindowSystemChrome;

    public class StandardWindow extends NativeWindow {
        public function StandardWindow() {
            var options:NativeWindowInitOptions = new NativeWindowInitOptions();
            options.systemChrome = NativeWindowSystemChrome.STANDARD;
            options.maximizable = true;
            options.minimizable = true;
            super(true, options);

            alwaysInFront = true;
            title = "Custom NativeWindow";
        }
    }
}

Many options available with the NativeWindow API, best to look at the documentation. "bounds" gives you lots of flexibility. Lots of good events (resize, move, moving, etc.)

The Window component is a wrapper around the NativeWindow. Flex provides an out of the box chrome with standard minimize, maximize, and close buttons and adds a status bar. Can be easily used in MXML. Use open() after creating the instance instead of activate() like you would with a NativeWindow. The showFlexChrome Window attribute can turn off the default Flex chrome. The Window class also provides access to the native window through its nativeWindow property.

<?xml version="1.0" encoding="utf-8"?>
<mx:Window xmlns:mx="http://www.adobe.com/2006/mxml"
systemChrome="none" showFlexChrome="true" showStatusBar="false" transparent="true">
</mx:Window>

The Screen singleton gives you access to information about the users' monitors. Has support for multiple displays along with supplying sizes and capabilities. Screen.mainScreen.visibleBounds will return visual area that is available taking into account task bar or dock (doesn't look like this is working in the current AIR beta on the Mac).

The Flash CS3 AIR update allows you to export and run your Flash application as an AIR application.

Tags: air cs3 flex onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Quick Demos

The last session was a collection of quick demos from the speakers and audience members. My apologies in advance if I missed your contact information.

Todd Prekaski (audience): Demoed a photo album builder application. Allows pulling in pictures from the local file system. Has some integration with Flickr and zoomr (wasn't completely clear on what that functionality was). Has random photo placement mode for viewing a collection of pictures. Has ability to email collection to contacts. Hopes to add online synchronization to pull down additional image presentation components (stylized borders, filters, etc.). Tool also supports photo resizing, rotation, and other simple effects.


Daniel Dura: TwitterAIRCamp is a way to do a nice public presentation of Twitter data. If you want to get in on the fun onairbustour is the Twitter name.

Salsa created by Christian Cantrell. Application that does drag and drop file uploading/downloading to Amazon S3.


Johnny Boursiquot (audience) from Pier: Business value calculator being used by companies like HP. Goal is to make sales people mobile and allow offline ROI value calculations. It uses Flex charts, graphs, and HTML output (will switch to PDF when supported). Took approach of what is the business value of AIR. Primary reasons for going with the platform included: way to extend backend service onto the desktop, easy to update, and online integration allows robust security model.


Kevin Hoyt demoed some more applications from Adobe labs. He created an AIR version of MapCache. Allows saving maps, copy to clipboard, and drag and drop. Rendering an HTML version. Mentioned source is on his site.

Geocode allowing geo tagging an image by dragging it onto the map. Still working on this application. Again an HTML/JavaScript application. It handles such activities as copying images, extracting thumbnails, and displaying the images in the UI. Makes heavy use of asynchronous events to do it on the fly without hanging the UI.

Kevin also ported a version of Ted Patrick's AIR Chat to HTML/JavaScript. The application uses Amazon EC2, running Python socket server, to provide simple chat services. The port uses the Ext JS Framework. HTML version is not posted yet.


Mike Chambers: Is a World of Warcraft player and uses Wowhead to track game information. Wrote an AIR wrapper around Wowhead. It is an always on top window that allows typing in a search term and launching the results in a browser window.

Hubble: Geo tagging image uploader for Flickr. Shows where images are located on the map. Nice UI to geo tag and upload. Can drag image onto map to tag it with drop location. He mentioned that the application is fairly buggy right now.

GeoPlotter: Show a Yahoo map and you can plot any latitude longitude pair on the map. Supports ability to drag a data file of way points and plot them all on the map. Most of his code is on Google code.

Ascension: One of the first AIR applications. It is an MP3 player and way to explore your music. Supports importing your music from iTunes, grabbing album art of Amazon, and displaying lyrics from lyricwiki. Has ability to display a slide show of images from Flickr that match the artist's name.

Tags: air flex html javascript onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Summary

On Friday I attended the on AIR bus tour in Boston. It was a free one day conference primarily sponsored by Adobe. The conference focused on getting people introduced to the AIR platform. While I was already familiar with most of AIR's capabilities I thought it would be a good opportunity to network with other Boston developers and meet a bunch of people from Adobe.

Overall Adobe did a good job with the conference. My only complaint was that the building was very warm the entire time. The building is a green facility so it doesn't have A/C. The hundred plus people that were there along with their laptops, combined with a Boston heat wave, overwhelmed what fans the building did have. Adobe did run out to grab some additional fans which helped, but it got uncomfortably hot at times. Thankfully Adobe had a full menu planned with lots of beverages. A continental breakfast, BBQ for lunch, and a beer and Mexican social hour towards the end.

During the conference I decided to blog about each session. I was posting my original rough drafts shortly after the conclusion of each session. Since then I've gone back to fix some typos, add additional links, and expand the content as needed. Below is the full list in presentation order:

I felt the vendor sessions were not that valuable. I understand why they needed to happen and that without them the tour may not have happened or have been free. For people new to the platform seeing some of the vendor applications may have sparked some ideas. Alas in most cases source code for those applications isn't available which made them feel more like a sales pitches.

Unbeknownst to me, Mike Chambers plugged my blog towards the end of the event to let people know it was a resource for anyone that hadn't taken notes but wanted a summary of each session. Even more shocking was during the software raffle I received an honorary copy of CS3 for having blogged the summaries. I'm still in shock about that. Given that receiving the software was an afterthought, I hope you won't accuse me of any bias.

Tags: air flex onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Taking apart the bus

Mike Chambers gave a talk about some of the technology being used on the tour bus. Using AIR applications to help track the location, what is going on, and display the information on the web.

Code for all the applications is available from Google code.

AIRTracker: Application that gets GPS info periodically and posts it to the server. The AIR application is passed the GPS coordinates via command line arguments. Uses a program called GPSBabel to get the GPS information. Command line arguments are handled through an invoke event.

Shell.shell.addEventListener(InvokeEvent.EVENT, handler);

If your application is already running, the handler will get called again with the new arguments. The application queues up GPS point data to handle server up/down and connection online/offline. Stores them in a local file using binary serialization of the AS3 array. It waits for ACK from server before removing data from the array. In order to serialize the custom class in the array you need to add metadata to the class.

[RemoteClass(alias="com.adobe.onair.geo.GeoPoint")]

He pointed out that there is no compile time checking so you could type the class name wrong. Showed an example using SocketMonitor to do a low level check for connectivity. The application demonstrates a common pattern of queuing and saving data locally and pushing the data up to server as connectivity is available. Handles both connectivity issues and application crashes. Shows a good robust application. Application and server interaction is easy since there is a single source of data which removes the need to handle conflict resolution.

He next showed pictures of the hardware on the bus. The hardware for grabbing the GPS coordinates was a Garmin GPS 18, which is a hockey puck sized device that attaches to the top of your vehicle.

AIRSnapshot: Application that every minute takes a picture (JPG format), geo encodes it, and uploads it to Flickr with appropriate tags. Application shows handling bigger data and multiple queues. It has to go to the server twice, first to upload the picture and a second time to add the geo tags.

flump: Application that downloads all of your raw Flickr images. Used this to pull all of the pictures from the bus and put them together into a movie available on The Flex Blog.

Audience asked about using AIR to broadcast a live video stream, which sounded like it was possible.

Tags: air flex onair2007boston

August 31, 2007

on AIR Bus Tour Boston: Introduction to Adobe AIR with Flex

Mike Chambers gave a presentation about building your first Adobe AIR application with Flex.

A quick poll of the audience showed about 60% of the audience develops with Flex/Flash and 40% develops with HTML/ColdFusion/PHP.

For the demonstration he used the Flex Builder 3 Beta to create a sample application. This version has native support for AIR applications. You can extend the beta by using your Flex Builder 2 license key.

There is an included Flex AIR project wizard. Creates an Application.mxml (Flex Code) and Application-app.xml (metadata) file in your project.

The Metadata file is well commented, but he called out certain values:
appId: Used to distinguish each application, only used internally by the installer process. Next beta will using code signing to handle identifying applications.

name: Application name as it is displayed to the user and used by the OS to display the application in the process viewer, etc.

title and description: Name and description shown in the AIR installer.

rootContent: Most important tag. Defines what and how your application gets launched. "systemChrome" is standard or none, it toggles native window chroming. "transparent" determines if the background of the application is rendered or not (use this to create non standard chrome). "visible" determines if your application is visible when it launches. Flex Builder has special syntax for the rootContent text, but in most cases it points at your Application.mxml.

The main application code works like a standard Flex application:
Using design view he quickly threw together the application. In this case it was just a simple button. Primary change for a standard Flex application is that the root MXML tag is WindowedApplication instead of Application. WindowedApplication gives access to native window APIs. With Flex Builder you can easily run and/or debug your AIR application. The work flow is similar to a Flex application.

Packaging your application:
Badge based install process which can install both the runtime and your application all through a single website click. Flex Builder includes the ability to export your code as an AIR application. Dialog lets you select which files get included. Currently there are some cryptic errors when you don't include required files which should be fixed by the next beta.

In descriptor file you can specify application icons:
Give AIR an PNG file for your application and it will handle making it work on all the different platforms. Back in the metadata file uncomment the icon block and set just the 128x128 icon and the others are taken care of. Icons aren't required, but they add polish.

Doubling clicking exported .air file launches the installer. Still tweaking install dialogs. Under the hood it sets up everything needed to run the application. On Mac it gets installed into the user's application directory (this may change). Looks and acts like a native application.

Other Resources:
Apollo for Flex Developers Pocket Guide: Released under Creative Commons License.

Adobe Integrated Runtime (AIR) for JavaScript Developers: Released under Creative Commons License.

adobe.com/go/air/: Best link to get started.

onair.adobe.com: All of the sessions from the tour are online in video format (recorded at various stops along the tour). Code created on the bus is available on Google code including media assets. They are also publishing different data feeds that people can play with.

Tags: air flex onair2007boston

June 28, 2007

Inversion of Control in Flex

At the recent BFPUG Design Patterns Meeting I gave an overview of Inversion of Control. Unfortunately due to time constraints I wasn't able to also put together a compelling example and as such I won't be posting the lame example I did put together. Instead I'll point you to an example that demonstrates the concepts and gives you something more to play with.

The ReviewTube source contains an example of IoC. The main file to look at is "com/joeberkovitz/reviewtube/services/ReviewTubeComponents.mxml" which is pulled in from "ReviewTube.mxml".

The key concept is that by using MXML style bindings, you declare a component once and give it a name through the id property. Now everywhere else that you need to reference that component, standard MXML binding syntax can reference that component. The use of setter dependency injection makes it all work. A couple of points not captured in the slides that should be pointed out.

  1. Make sure the MXML file that defines your components is the first child of your main application. That way the creation of everything gets kicked off as soon as possible.
  2. You will probably want to put a creationComplete handler on the MXML file to indicate that component configuration is done and your main application can start.
  3. Components should not rely on the order that their dependent components are set.

Tags: design flex ioc

June 28, 2007

Antennae: Ant Templates for Flex

I'm pleased to announce the release of Antennae version 1.0000. This is the first release since Antennae was migrated from Joe Berkovitz's blog up to Google Code. You can access the project at http://code.google.com/p/antennae/. This release includes a bunch of tweaks and new functionality. For those that are not familiar with Antennae it covers:

  • Macro tasks for invoking mxmlc and compc
  • Ready made templates for application projects and library projects
  • A robust system for importing and exporting assets from one project to another
  • A solid way to compose projects inside container projects
  • Dependency checking on sources and libraries to avoid unneeded recompilation
  • Handling for HTML page token substitution and web app deployment
  • Automated unit test suite generation and command line integration with Flexunit

This release is primarily aimed at getting the tools out there for public consumption. Future releases will focus on additional documentation and other ways Ant can help automate your Flex builds. Please let us know what other improvements you would like to see.

Tags: ant antennae flex

June 28, 2007

Flashforward Boston Ant Talk

I'm going to be speaking at the upcoming Flashforward Boston about Automated Flex Building and Unit Testing. The description hasn't made it up onto the site yet but is roughly something like:

A talk focusing on tools and techniques needed to get continuous integration running with a Flex project -- that is, ensuring that at any given point in time, your application is buildable and free of errors. I'll cover how to automate the build process with Ant, setting up and running unit tests both interactively from the command line, and integrating the entire process into an automated build system. All tools used are open-source and publicly available.

If there are particular topics that you'd like to see covered let me know.

Tags: ant flex

May 19, 2007

mx_internal

Sometimes you want to change the behavior of a Flex component but its hidden behind a private method or variable so you can't subclass it. Thankfully they provide the source so you can just create your own version. This is heavy handed and in some cases you just need to tweak things a little. Many components within the Flex framework have methods and properties flagged as mx_internal. These you can access without having to do anything too funky.

As an example lets change the restrict set on the input field of a NumericStepper.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.core.mx_internal;
use namespace mx_internal;
private function setupStepper():void
{
    stepper.mx_internal::inputField.restrict = "0-9";
}
]]>
</mx:Script>
<mx:NumericStepper id="stepper" creationComplete="setupStepper();"/>
</mx:Application>

The key things to note are:

  1. import mx.core.mx_internal;
    Import the namespace that is going to be used

  2. use namespace mx_internal;
    Tell Actionscript that is a namespace

  3. mx_internal::inputField
    Prefix the property name with its namespace

That's all there is to it. Happy hacking.

Tags: flex mx_internal namespace

May 19, 2007

Stopping Flash 4 SWF with Sound in Flex 2

I recently had an issue where in Flex 2 I had to load and play a Flash 4 SWF that had embedded sound in it. I'm not a Flash developer so I'm not 100% sure if the sound was encoded as an event or what have you. In any case as soon as the SWF was loaded it would start playing and it would loop. Since Flex 2 uses Flash 9 the Flash 4 SWF shows up as an AVM1Movie when loaded which means you can't do much of anything to the movie once it's loaded. Most annoyingly the sound keeps playing and playing.

Problem 1: How to stop the sound?
The only fix I found was to call SoundMixer.stopAll();. Drastic, but it worked.

Problem 2: How to stop the sound looping?
Great the sound stopped, temporarily, only problem was when the SWF looped the sound started up again. The fix requires using a Loader and a call to unload() when you are done using it:

// create a loader and load the file
var loader:Loader = new Loader();
loader.load(new URLRequest("sound.swf"));

// later when you want to stop it
SoundMixer.stopAll();
loader.unload();

Problem 3: Security issues?
This works if you are requesting the SWF from your own server, but if you are using another site to store the sound files (say a CDN), you'll run into security sandbox issues. To get around this the remote site will need to have an appropriate crossdomain.xml file and you'll need to use a custom loader context:

// create the loader context
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.securityDomain = SecurityDomain.currentDomain;
loaderContext.applicationDomain = ApplicationDomain.currentDomain;
loaderContext.checkPolicyFile = true;

// use it when loading the file
loader.load(new URLRequest("sound.swf"), loaderContext);

Other notes:
You should also setup a listener on loader.contentLoaderInfo to register when the SWF has loaded as unload() only works when the loader has completed, prior to that you need to use close().

Tags: flash flex sound

March 11, 2007

Programmatic Bindings

Recently I found myself refactoring an MXML component into an AS base class to make it easier to provide multiple views of the data. I wanted to factor as much of the code as I could into the base class including some of the bindings. While I've known for some time that Flex has programmatic binding support I'd not had a real use for it until now. The documentation is reasonable but I think I couple more examples would have helped. Below is a sample binding and the corresponding programmatic equivalent along with some gotchas.

Take an example MXML component that has a model Object set on it. The model exposes an enabled flag which the view needs to respond to in a complex fashion, beyond just disabling itself. If you want you can also replace the setter with a variable in these examples and it all works the same. It might look something like this (a bunch of code has been removed to focus just on the binding):

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import com.example.Model;
[Bindable]
public var model:Model;

private function set controlsEnabled(controlsEnabled:Boolean):void {
    // logic to handle change
}
]]></mx:Script>
<mx:Binding source="model.enabled" destination="controlsEnabled"/>
<!-- child components removed -->
</mx:Canvas>

Now I want to turn that into an AS base class and not have every MXML subclass need to repeat the binding. My AS base class then looks like this:

package com.example {
    import mx.binding.utils.BindingUtils;
    import mx.containers.Canvas;

    public class SimpleBase extends Canvas {
        [Bindable]
        public var model:Model;

        public function SimpleBase() {
            super();
            BindingUtils.bindProperty(this, "controlsEnabled", this, ["model", "enabled"]);
        }

        public function set controlsEnabled(controlsEnabled:Boolean):void {
            // logic to handle change
        }
    }
}

While the view has changed to this:

<?xml version="1.0" encoding="utf-8"?>
<SimpleBase xmlns="com.example.*" xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- child components removed -->
</SimpleBase>

The key to this magic is the BindingUtils.bindProperty() call in the base class. That mimics the mx:Binding that was previously in the MXML code. The documentation for BindingUtils uses site and host instead of source and destination which means you need to do a little translation when converting from one to the other. The most important thing to keep in mind when doing a translation like the one above is the use of this for both the site and host, otherwise you won't pick up all the changes.

The reason is that the bindings need to be anchored on some object that is issuing property change events. In the SimpleBase constructor model is null, so we can't really bind to that. Even if it wasn't null, the bindings would only fire off of the model instance that was active when it was setup. By chaining off of this you pick up changes both to model and the enabled flag within the model object.

The other tricky thing to notice is that the access modifier of the controlsEnabled() method changed from private to public. This needs to happen so that the code in BindingUtils can call it. Since this code is being executed outside of the class when in AS, instead of being compiled in (which is the case with MXML) it needs to be able to have standard access to the method. If you forget to make the setter public you'll get an error like this:

ReferenceError: Error #1056: Cannot create property controlsEnabled on SimpleView2.

The BindingUtils.bindSetter() method allows you to call an arbitrary method with the new value instead of just setting a variable (directly or via a setter).

Tags: bindings flex

March 11, 2007

Asynchronous Testing with FlexUnit

When testing components that have asynchronous behavior you need to use FlexUnit's addAsync() method in order to correctly handle the events that fire. The reason for this is that unless you tell FlexUnit that you are expecting an asynchronous event, once your test method finishes FlexUnit will assume that the test is done and there were no errors. This can lead to false positives and annoying popup error dialogs with an assert fails. Below are some examples of how to use addAsync().

I'll start off with what not to do so you can get an idea of why you need addAsync(). Let's write a simple test that verifies that the flash.utils.Timer class fires events the way we think it should. The first attempt might look like this:

package com.example {
    import flexunit.framework.TestCase;
    import flash.utils.Timer;
    import flash.events.TimerEvent;

    public class TimerTest extends TestCase {
        private var _timerCount:int;

        override public function setUp():void {
            _timerCount = 0;
        }

        public function testTimer():void {
            var timer:Timer = new Timer(3000, 1);
            timer.addEventListener(TimerEvent.TIMER, incrementCount);
            // the next line should not be written like this, it can produce false positives
            timer.addEventListener(TimerEvent.TIMER_COMPLETE, verifyCount);
            timer.start();
        }

        private function incrementCount(timerEvent:TimerEvent):void {
            _timerCount++;
        }

        private function verifyCount(timerEvent:TimerEvent):void {
            assertEquals(1, _timerCount);
        }
    }
}

Nothing fancy here, we declare a single test method, create the Timer, and then start it. It should run once and then stop. If you add this test to your test suite and run it, you get a nice green bar. This is a false positive! The assertEquals() in the verifyCount() method didn't really contribute to the test passing. Try changing it to:

assertEquals(2, _timerCount);

When you rerun the test you'll get another green bar. Then a few seconds later an error dialog box pops up with the following message:

Error: expected:<2> but was:<1> at flexunit.framework::Assert$/flexunit.framework:Assert::failWithUserMessage()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\Assert.as:209] at flexunit.framework::Assert$/flexunit.framework:Assert::failNotEquals()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\Assert.as:62] at flexunit.framework::Assert$/assertEquals()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\Assert.as:54] at com.example::TimerTest/com.example:TimerTest::verifyCount()[C:\Work\Eclipse3.2\Fresh\AsyncTest\src\com\example\TimerTest.as:26] at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction() at flash.events::EventDispatcher/dispatchEvent() at flash.utils::Timer/flash.utils:Timer::tick()

But, but, the test bar was green! FlexUnit didn't know you where waiting for an event, as a result when the testTimer() method finished, that test was clean. The error dialog pops up because FlexUnit isn't around to catch the error and turn it into a pretty message. This also shows that even though the test finished our object was still running in the background. We can fix this first issue by adding a tearDown() method and use addAsync() to wrap the function that should be called along with specifying the maximum time to wait for that function to be called. The function returned by addAsync() is used in place of your original function. In the example above, the second listener function passed into the addEventListener() call is where addAsync() will come into play. The changes to TimerTest look like this:

private var _timer:Timer;

override public function tearDown():void {
    _timer.stop();
    _timer = null;
}

public function testTimer():void {
    _timer = new Timer(3000, 1);
    _timer.addEventListener(TimerEvent.TIMER, incrementCount);
    _timer.addEventListener(TimerEvent.TIMER_COMPLETE, addAsync(verifyCount, 3500));
    _timer.start();
}

I've taken the original function and wrapped it in an addAsync() and added the maximum time that the function can take to be called. Since my Timer is set to run in 3000ms I gave myself a little buffer. With this change and the assert testing for a count of 2, I'll get a red bar when the test runs. Additionally I added a tearDown() method so that regardless of what happens in the test the Timer will stop running. When doing asynchronous testing it is important to clean up like this otherwise you can get objects hanging round in memory doing things you don't want. On that note I'd also recommend that the event listeners added to the timer use weak references. That way in the tearDown() function nulls out the Timer that object can be garbage collected. The update code would look like this:

_timer.addEventListener(TimerEvent.TIMER, incrementCount, false, 0, true);
_timer.addEventListener(TimerEvent.TIMER_COMPLETE, addAsync(verifyCount, 1500), false, 0, true);

Now that we added in that timeout to the verifyCount() call, you'll also get a red bar if the function isn't called in the timeout specified. Drop the timeout to 1500ms and rerun the test. You should now get the following error:

Error: Asynchronous function did not fire after 1500 ms at flexunit.framework::Assert$/fail()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\Assert.as:199] at flexunit.framework::AsyncTestHelper/runNext()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\AsyncTestHelper.as:96] at flexunit.framework::TestCase/flexunit.framework:TestCase::runTestOrAsync()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\TestCase.as:271] at flexunit.framework::TestCase/runMiddle()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\TestCase.as:192] at flexunit.framework::ProtectedMiddleTestCase/protect()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\ProtectedMiddleTestCase.as:54] at flexunit.framework::TestResult/flexunit.framework:TestResult::doProtected()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\TestResult.as:237] at flexunit.framework::TestResult/flexunit.framework:TestResult::doContinue()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\TestResult.as:109] at flexunit.framework::TestResult/continueRun()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\TestResult.as:79] at flexunit.framework::AsyncTestHelper/timerHandler()[C:\Documents and Settings\mchamber\My Documents\src\flashplatform\projects\flexunit\trunk\src\actionscript3\flexunit\framework\AsyncTestHelper.as:121] at flash.utils::Timer/flash.utils:Timer::_timerDispatch() at flash.utils::Timer/flash.utils:Timer::tick()

That's the quick introduction to addAsync(). Now onto some of the additional features of addAsync() that can be helpful. Say we wanted to test that a Timer is correctly called twice within a specified period of time. The incrementCount() function can easily be reused but the verifyCount() method has a hard coded assertEquals() in it. The optional 3rd argument to addAsync() is an argument called passThroughData, which can be anything. In this case I'm going to pass what I expect the count to be when the Timer finishes allowing me to reuse the same verify function. With these changes the functions now looks like this:

public function testTimer():void {
    _timer = new Timer(1000, 1);
    _timer.addEventListener(TimerEvent.TIMER, incrementCount, false, 0, true);
    _timer.addEventListener(TimerEvent.TIMER_COMPLETE, addAsync(verifyCount, 1500, 1), false, 0, true);
    _timer.start();
}

public function testTimer2():void {
    _timer = new Timer(500, 2);
    _timer.addEventListener(TimerEvent.TIMER, incrementCount, false, 0, true);
    _timer.addEventListener(TimerEvent.TIMER_COMPLETE, addAsync(verifyCount, 1500, 2), false, 0, true);
    _timer.start();
}

private function verifyCount(timerEvent:TimerEvent, expectedCount:int):void {
    assertEquals(expectedCount, _timerCount);
}

In both cases I'm passing along the expected count and have created a generic verify method. The object that you pass can be anything which makes it a very powerful way to write generic asynchronous event verifiers. But wait there's more!

The last optional argument to addAsync() is a way to verify that the event didn't happen. Instead of getting a red bar and the "Error: Asynchronous function did not fire after 1500 ms", you can verify that based on the event not firing, everything is as it should be. For example I could verify that after 1500ms a 1000ms Timer only fired one event and the complete event never fired. This last version of the test class does that. I also modified things a little since if you include passThroughData, it gets passed to both the regular function and the failFunction. This isn't a bad thing as it provides a way to write a generic failFunction handler like the way the generic verify handler was written. Note that the failFunction handler doesn't need to worry about getting an event passed in like the normal listener function since the event didn't fire.

package com.example {
    import flexunit.framework.TestCase;
    import flash.utils.Timer;
    import flash.events.TimerEvent;

    public class TimerTest extends TestCase {
        private var _timerCount:int;
        private var _timer:Timer;

        override public function setUp():void {
            _timerCount = 0;
        }

        override public function tearDown():void {
            // cleanup to make sure the Timer doesn't keep running
            _timer.stop();
            _timer = null;
        }

        public function testTimer():void {
            runTimer(1000, 1, 1500, 1);
        }

        public function testTimer2():void {
            runTimer(500, 2, 1500, 2);
        }

        public function testNotDone():void {
            runTimer(1000, 2, 1500, -1, 1);
        }

        private function runTimer(delay:int, count:int, timeout:int, goodCount:int, badCount:int = -1):void {
            _timer = new Timer(delay, count);
            // use weak references to make sure the Timer gets GC when we are done
            _timer.addEventListener(TimerEvent.TIMER, incrementCount, false, 0, true);
            // pass both a good an bad handler along with counts so the verify methods
            // can detect what happened
            _timer.addEventListener(TimerEvent.TIMER_COMPLETE, addAsync(verifyGoodCount, timeout, {goodCount: goodCount, badCount: badCount}, verifyBadCount), false, 0, true);
            _timer.start();
        }

        private function incrementCount(timerEvent:TimerEvent):void {
            _timerCount++;
        }

        private function verifyGoodCount(timerEvent:TimerEvent, extraData:Object):void {
            if (extraData.goodCount == -1)
            {
                fail("Should have failed");
            }
            assertEquals(extraData.goodCount, _timerCount);
        }

        private function verifyBadCount(extraData:Object):void {
            if (extraData.badCount == -1)
            {
                fail("Should not have failed");
            }
            assertEquals(extraData.badCount, _timerCount);
        }
    }
}

Feel free to play with this final version to test how different asynchronous scenarios are handled in FlexUnit.

Some additional notes:
Make sure the listener function name doesn't start with test, otherwise FlexUnit will think that it is a test method and try to run it.

I've noticed some odd behavior with multiple addAsync()s set at the same time. In general you only want to have one outstanding addAsync() at a time.

If you specify passThroughData and a failFunction, the passThroughData will get passed to both the function and the failFunction.

Make sure that you cleanup any objects that could still fire events in your tearDown() method and either remove event listeners or make them weak. There is more to this topic but I'll cover that in another post.

Tags: as3 flex flexunit testing

February 26, 2007

RegExp Constructor Issue

The Flex documentation is a a little misleading in regards to the RegExp Constructor. Livedocs has this to say:

public function RegExp(re:String, flags:String)

Lets you construct a regular expression from two strings. One string defines the pattern of the regular expression, and the other defines the flags used in the regular expression.

Notice the lack of a default value for the flags argument? One would think that would mean you should get a compilation error if you don't supply both arguments to the constructor. However, both of these compile without error:

var regExpA:RegExp = new RegExp("^http://www.google.com/(.*)$");
var regExpB:RegExp = new RegExp("^http://www.google.com/(.*)$", "");

I would expect the first one to cause this error:

1136: Incorrect number of arguments. Expected 2.

It would be nice if the documentation was just wrong and you didn't need to supply the second argument to the constructor. The problem is the two regular expressions behave differently! The missing flags argument causes the regular expression to do funky stuff, which is not the same as passing in the empty string. For example look at the output of this little example:

trace(regExpA.test("http://www.google.com/"));
trace(regExpA.test("http://www.google.com/webhp?hl=en"));
trace(regExpB.test("http://www.google.com/"));
trace(regExpB.test("http://www.google.com/webhp?hl=en"));
// Output
// true
// false
// true
// true

That false shouldn't be there! The funky stuff that is going on behind the scenes is that without the second argument to the constructor it is looking at the regular expression string itself to set the flags. In this case g appears after a //, which is the way you specify the global flag in a RegExp literal. To confirm this, look at the string version of each RegExp:

trace(regExpA);
trace(regExpB);
// Output
// /^http://www.google.com/(.*)$/gm
// /^http://www.google.com/(.*)$/

Cool, we also picked up the multiline flag since m also appears! The problem only occurs if you have more than one / followed by one of the regular expression flags. The two slahses don't need to be next to each other just having two anywhere in the string followed by other text can cause the problem. In general you are probably better using RegExp literals, but if you do use the RegExp constructor be sure to supply both arguments, even if the second one is just the empty string.

Tags: error flex regexp

December 31, 2006

Removing Anonymous Event Listeners

One of the features that I really like about AS3 is its support of closures. There are many instances when you want to do something to an argument but don't really need or want a full blown class to encapsulate the logic. Lately I've been trying to apply this approach to event listeners and in general it just works. My problem can up when I wanted to have the event listener run only once or stop listening after some point in time. Since the removeEventListener method requires a reference to the listener that you want to remove and the listener in this case is a closure I need a way to get a reference to it. Thankfully closures provide a way to do that but it requires introducing another variable into the mix. Thankfully ActionScript provides another way to get access to the same information arguments.callee.

Arguments is a variable available in every function that is automatically supplied by the system. It is the older style of getting access to the arguments of a function that takes in an arbitrary number. In this case though the callee also gives you access to yourself. In the case of an anonymous event listener, this is all that is needed to remove it as an event listener. Now for the example:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="handleCreationComplete();">
    <mx:Script>
        <![CDATA[
            private function handleCreationComplete():void {
                sampleButton.addEventListener(MouseEvent.CLICK, createClickListener(1));
                sampleButton.addEventListener(MouseEvent.CLICK, createClickListener(2));
            }

            private function createClickListener(clickLimit:int):Function {
                var clickCount:int = 0;
                return function(mouseEvent:MouseEvent):void {
                    clickCount++;
                    trace("Click limit", clickLimit, "registering click", clickCount);
                    if (clickCount >= clickLimit) {
                        trace("Click limit", clickLimit, "no longer listening");
                        mouseEvent.target.removeEventListener(MouseEvent.CLICK, arguments.callee);
                    }
                }
            }
        ]]>
    </mx:Script>
    <mx:Button id="sampleButton" label="Go"/>
</mx:Application>

That gives this output:

Click limit 1 registering click 1
Click limit 1 no longer listening
Click limit 2 registering click 1
Click limit 2 registering click 2
Click limit 2 no longer listening

In this example I'm programmatically adding two anonymous event listeners to my button class. They are anonymous in the fact that the function being executed isn't named. Unlike the creationComplete listener that is attached to the Application, you can only pass around the reference to the function, instead of naming it directly. As I mentioned above, since I want to remove the event listener I can't name it directly. Also since I'm creating multiple instances of it, I can't easily pass the reference to the function around. By instead using arguments.calee I avoid the need to name the function and the need to pass the function reference around.

I'll admit that this is not the most compelling example usage of this technique, but I'm sure you can extrapolate from this.

Tags: as3 event flex

December 31, 2006

AS3 Casting Issues

In most object oriented languages you can cast an object to something more specific in order to be able to call methods particular to the type it was cast as. This frequently comes up when you have a rich class hierarchy and for some reason can't use polymorphism to separate out behavior or more commonly have a factory like method that needs to take in a bunch of different object types but always return the same type. Since AS3 doesn't support method overloading you can't easily separate out the different object types into specialized methods and instead end up with a big if then else block.

My issue with AS3 comes in with the fact that in such as if then else block you can't easily cast primitive objects without getting some funky behavior or without needing to wrap your cast in order to detect errors. I'm sure that there are some techniques out there to avoid this issue entirely, but having now seen it come up more than once I figured I'd jot down my observations on the issue.

AS3 defines a number of top-level or global functions that mirror primitive AS3 objects types. These include String(), Array(), and Date() (currently undocumented) among others. Because these top-level functions exist, they take precedence over a cast. Consider this method.

public function asString(random:Object):String {
    return String(random);
}

public function asCustom(random:Object):Custom {
    return Custom(random);
}

While the two methods look like they would do the same thing, asString is actually calling a function, while asCustom is doing a cast. AS3 provides the as operator as a way to get around this behavior. The problem is that as won't throw casting errors, instead it just silently returns null. Maybe that's fine for what you need, but it just rubs me the wrong way.

I don't want to always have to check for null because in some cases I know that shouldn't be the case, but I also don't want null introduced because of a bug in the calling code. In my mind tracking down a bug from a class cast error is very different then trying to track down a null pointer error especially since the null could percolate further along in the code compared to the class cast error which would happen at the exact spot the cast was attempted.

The other annoying thing about the difference between cast and as is the trick it can play on you in the debugger especially if you are casting something to a String.

public function testCast():void {
    var a:String;
    a = String(null);
    trace(a);
    trace(a is String);
    a = null as String;
    trace(a);
    trace(a is String);
}
// Output:
// null
// true
// null
// false

In both cases the trace of the variable prints out null, but in the first case it is the actual string null, while in the second it is a null value. As I said before my main issue with as is that it doesn't behave like a true cast.

public function testCastError():void {
    var a:Object = new Object();
    var b:String;
    b = String(a);
    trace(b);
    trace(b is String);
    b = a as String;
    trace(b);
    trace(b is String);
    var c:UIComponent;
    c = UIComponent(a);
}
// Output:
// [object Object]
// true
// null
// false
// TypeError: Error #1034: Type Coercion failed: cannot convert Object@ef409c1 to mx.core.UIComponent.

In all three cases above the Object can't be successfully cast to the target type String and UIComponent. In the first case String() doesn't do a cast, instead we get a string representation of the object. In the second case since the types aren't compatibly as silently returns null. In the third we get what I consider the correct behavior which is a class cast error. Since as has this silent behavior you need to check for null both before and after if you want to distinguish between a null value and an incompatible cast.

In general avoid situations where you need to cast primitive objects or cast things at all, but if you do know that casting isn't always casting in AS3.

Tags: as3 casting flex

December 31, 2006

Architectural Blueprint for Flex Applications (MVCS)

If you didn't catch Joe Berkovitz's talk at MAX 2006 about an architectural blueprint for Flex applications, it is now posted on Adobe's Flex Developer Center. Joe is the Chief Architect of Allurent, where I work. It is a great read and introduces the concept of Model, View, Controller, and Service (MVCS). Best of all it comes with a sample application that embodies all of the principles outlined in the article.

Tags: architecture flex links

December 31, 2006

Static Initializers in AS3

I couldn't find much official documentation (if you have links please pass them along) about static initializers in ActionScript 3 so I thought I'd put together a little quick reference. A static initializer is run once when a class is first loaded by the AVM. The typical user of such a block is the compiler, which uses it to assign values to static variables of the class. You also can use it to do more complex static object initialization. The example that I needed it for was to create a lookup object based on constants defined in the class. Consider a class that defines some handy constants:

package com.example {
    public class MIME {
        public static const GIF_MIME_TYPE:String = "image/gif";
        public static const JPG_MIME_TYPE:String = "image/jpeg";
        public static const PNG_MIME_TYPE:String = "image/png";
        public static const SWF_MIME_TYPE:String = "application/x-shockwave-flash";
    }
}

If you wanted to create a lookup table to quickly check if a random string matched one of these you can't use the standard object literal initialization syntax. Consider if this code is added to the MIME class:

// Don't use this, it doesn't do what you think, see below
private static const IMAGE_TYPES:Object = {GIF_MIME_TYPE:true,
    JPG_MIME_TYPE:true,
    PNG_MIME_TYPE:true,
    SWF_MIME_TYPE:true};

public static function isImage(mimeType:String):Boolean {
    return (IMAGE_TYPES[mimeType] == true);
}

If you run this test code, you don't get what you want:

trace(MIME.isImage(MIME.GIF_MIME_TYPE));
// Output: false

False? What's going on is that the text before the : in the object literal is treated as a literal string, not as a variable. What ended up happening was the literal string "GIF_MIME_TYPE" was stored in the associative array. This can be demonstrated by this little test:

trace(MIME.isImage("GIF_MIME_TYPE"));
// Output: true

Obviously not what I wanted. This is where the static initializer comes in. I only want to have to setup the lookup table once and avoid having to track if it is setup, so I put the initialization code in a block at the class level.

package com.example {
    public class MIME {
        private static const IMAGE_TYPES:Object = new Object();
        // This block is run once when the class is first accessed
        {
            IMAGE_TYPES[GIF_MIME_TYPE] = true;
            IMAGE_TYPES[JPG_MIME_TYPE] = true;
            IMAGE_TYPES[PNG_MIME_TYPE] = true;
            IMAGE_TYPES[SWF_MIME_TYPE] = true;
        }
    }
}

Yes those lines are just hanging out in the class itself and not within some method. Truth be told the {} are optional. I like to put them in a block to offset the code and make it more readable. With this updated version of IMAGE_TYPES our two tests from above now do the right thing:

trace(MIME.isImage(MIME.GIF_MIME_TYPE));
// Output: true
trace(MIME.isImage("GIF_MIME_TYPE"));
// Output: false

I should point out that the use of const in the static variable declaration is also a preference thing. Even though the IMAGE_TYPES lookup table is defined as a static constant, the contents of the object can still change at runtime. The only thing that's can't change is the object reference that IMAGE_TYPES points at. For example the following code is invalid:

package com.example {
    public class BAD {
        private static const IMAGE_TYPES:Object = new Object();
        {
            // This is a compile time error
            IMAGE_TYPES = new Object();
        }
    }
}

Trying to compile that will give you the error:

1049: Illegal assignment to a variable specified as constant.

The completed MIME class now looks like this:

package com.example {
    public class MIME {
        public static const GIF_MIME_TYPE:String = "image/gif";
        public static const JPG_MIME_TYPE:String = "image/jpeg";
        public static const PNG_MIME_TYPE:String = "image/png";
        public static const SWF_MIME_TYPE:String = "application/x-shockwave-flash";

        private static const IMAGE_TYPES:Object = new Object()
        // This block is run once when the class is first accessed
        {
            IMAGE_TYPES[GIF_MIME_TYPE] = true;
            IMAGE_TYPES[JPG_MIME_TYPE] = true;
            IMAGE_TYPES[PNG_MIME_TYPE] = true;
            IMAGE_TYPES[SWF_MIME_TYPE] = true;
        }

        public static function isImage(mimeType:String):Boolean {
            return (IMAGE_TYPES[mimeType] == true);
        }
    }
}

I get a handy lookup table populated by constants instead of strings, my test function is short and simple instead of some long if then block, and I don't need to worry about checking each time if my lookup table has been initialized. I'm happy.

Tags: as3 flex initializer static

December 31, 2006

Is Operator and Type Safe Lists

In some recent coding I was playing with a custom type system and needed to add some type checking to it. What this means is that at some point I need to verify that some object is really the type I think it should be. Normally when you are coding in AS3 and need to check a type you do something like:

public function testType(object:Object):void {
    if (object is String) {
        trace("It is a String");
    } else if (object is Array) {
        trace("It is an Array");
    } else {
        trace("Its type is ?");
    }
}

testType(new String());
testType(new Array());
testType(new Object());
// Output:
// It is a String
// It is an Array
// Its type is ?

Nothing out of the ordinary there. The important thing to examine though is that the right hand side of the is operator is really an expression. Typically you just type in the class you are testing against, since you are likely to cast it on the next line, but why not try something else like:

public function returnClass(type:String):Class {
    if (type == "String") {
        return String;
    }
    if (type == "Array") {
        return Array;
    }
    throw TypeError("Unknown type " + type);
}
public function testType2(object:Object):void {
    if (object is returnClass("String")) {
        trace("It is a String");
    } else if (object is returnClass("Array")) {
        trace("It is an Array");
    } else {
        trace("Its type is ?");
    }
}

testType2(new String());
testType2(new Array());
testType2(new Object());
// Output:
// It is a String
// It is an Array
// Its type is ?

Why would you want to do such a thing? ActionScript 3 doesn't have support for generics, but by using this expression based format of the is operator you can simulate them. You don't get compile time type checking but runtime checking is better than nothing. Let's consider an application where you want to have type safe lists (you can only add items of a certain type to the list). Instead of having to create a separate list wrapper for every type you might need to support, create a standard type safe list class that knows what type each item should be. There are many different approaches to creating such a class, one possibility that uses composition is this:

package com.example {
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.utils.getQualifiedClassName;

    import mx.collections.ArrayCollection;
    import mx.collections.IList;
    import mx.events.CollectionEvent;

    // Please note this code is illustrative and has not been fully tested!
    public class TypeSafeList implements IList {
        private var _itemType:Class;
        private var _arrayCollection:ArrayCollection;
        private var _eventDispatcher:EventDispatcher;

        public function TypeSafeList(itemType:Class) {
            _itemType = itemType;
            _arrayCollection = new ArrayCollection(new Array());
            _eventDispatcher = new EventDispatcher(this);
            _arrayCollection.addEventListener(CollectionEvent.COLLECTION_CHANGE, relayEvent);
        }

        private function relayEvent(event:Event):void {
            dispatchEvent(event);
        }

        private function checkItemType(object:Object):void {
            if ((object != null) && !(object is _itemType)) {
                throw new TypeError("Item is not correct type. Wanted " + _itemType + " got " + getQualifiedClassName(object) + ".");
            }
        }

        public function addItemAt(item:Object, index:int):void {
            checkItemType(item);
            _arrayCollection.addItemAt(item, index);
        }

        public function get length():int {
            return _arrayCollection.length;
        }

        public function toArray():Array {
            return _arrayCollection.toArray();
        }

        public function getItemAt(index:int, prefetch:int = 0.0):Object {
            return _arrayCollection.getItemAt(index, prefetch);
        }

        public function itemUpdated(item:Object, property:Object = null, oldValue:Object = null, newValue:Object = null):void {
            _arrayCollection.itemUpdated(item, property, oldValue, newValue);
        }

        public function removeAll():void {
            _arrayCollection.removeAll();
        }

        public function getItemIndex(item:Object):int {
            return _arrayCollection.getItemIndex(item);
        }

        public function setItemAt(item:Object, index:int):Object {
            checkItemType(item);
            return _arrayCollection.setItemAt(item, index);
        }

        public function removeItemAt(index:int):Object {
            return _arrayCollection.removeItemAt(index);
        }

        public function addItem(item:Object):void {
            checkItemType(item);
            _arrayCollection.addItem(item);
        }

        public function hasEventListener(type:String):Boolean {
            return _eventDispatcher.hasEventListener(type);
        }

        public function willTrigger(type:String):Boolean {
            return _eventDispatcher.willTrigger(type);
        }

        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0.0, useWeakReference:Boolean = false):void {
            return _eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }

        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
            return _eventDispatcher.removeEventListener(type, listener, useCapture);
        }

        public function dispatchEvent(event:Event):Boolean {
            return _eventDispatcher.dispatchEvent(event);
        }
    }
}

Notice how the addItemAt, setItemAt, and addItem methods call checkItemType before passing the call onto the ArrayCollection which is doing all the dirty work. By checking every place that a user can add new information to the IList we can insure that only objects matching the desired type are added. You may wonder why I'm choosing to implement IList instead of just extending ArrayCollection. In this case I don't want the extra baggage that extending ArrayCollection would bring along (support for ICollectionView and the Proxy access methods). If you did want to extend ArrayCollection you would only need to override methods that add data to the object and not create pass through methods for the other interface methods.

Now with this new TypeSafeList what does using it look like? Just like any other IList object, but with the added benefit of runtime type checking. This is some sample code that creates a TypeSafeList that can only have String items added to it:

var list:IList = new TypeSafeList(String);
trace(list.length);
var text:String = "An Item";
list.addItem(text);
trace(list.getItemAt(0));
list.addItemAt("Before An Item", 0);
trace(list.getItemIndex(text));
try {
    list.addItem(12);
} catch (typeError:TypeError) {
    trace(typeError);
}
try {
    list.addItem(new Array());
} catch (typeError:TypeError) {
    trace(typeError);
}

// Output:
// 0
// An Item
// 1
// TypeError: Item is not correct type. Wanted [class String] got int.
// TypeError: Item is not correct type. Wanted [class String] got Array.

The nice thing with the is operator is that you can also check against interfaces. Consider wanting to create a TypeSafeList that can only contain IUIComponent objects. Not only could this list contain classes that subclass UIComponent but also custom classes that implement the IUIComponent interface (not that you would really want to do such a thing). Some sample code that uses an interface with the TypeSafeList class:

var list:IList = new TypeSafeList(IUIComponent);
list.addItem(new Button());
trace(list.length);
list.addItem(new Canvas());
trace(list.length);
try {
    list.addItem("I'm not valid");
} catch (typeError:TypeError) {
    trace(typeError);
}

// Output:
// 1
// 2
// TypeError: Item is not correct type. Wanted [class IUIComponent] got String.

This entry became a little more than what I had originally planned to write about. I originally planned to stop at explaining the use of an expression for the right hand side of the is operator, but somehow ended up with this TypeSafeList class. I hope that you can see the benefit of the simple is operator and maybe someone will find that sample TypeSafeList class useful, please test it first though.

Tags: as3 flex list type

October 21, 2006

Singleton Pattern in AS3

AS3 does not support private or protected constructors which makes it harder to implement the singleton pattern. Below are some approaches I've run across on the Internet, problems with them, and what I hope (please tell me if I'm wrong) corrections to get a real singleton pattern working.

First up is an entry by Andrew Trice about Singletons in AS3. His code was:

// faulty example
package {
    public class Singleton {
        private static var singleton : Singleton;
		
        public static function getInstance() : Singleton {
            if ( singleton == null )
                singleton = new Singleton( arguments.callee );
            return singleton;
        }
	
        //NOTE: AS3 does not allow for private or protected constructors
        public function Singleton( caller : Function = null ) {	
            if( caller != Singleton.getInstance )
                throw new Error ("Singleton is a singleton class, use getInstance() instead");
            if ( Singleton.singleton != null )
                throw new Error( "Only one Singleton instance should be instantiated" );	
            //put instantiation code here
        }
    }
}

You can defeat this approach with:

var a:Singleton = new Singleton(Singleton.getInstance);
var b:Singleton = new Singleton(Singleton.getInstance);
// a !== b

The constructor is doing a function reference comparison, but the function being compared to is available to the caller which is why it can be passed in to defeat the test.

I was also pointed at an approach created by Matt Chotin and posted to Flex Coders. This is a direct cut'n'paste so there are some syntax errors.

// faulty example
package whatever {
  public class MySingleton {
    public function MySingleton(singletonEnforcer:MySingletonEnforcer) { }

private static var instance:MySingleton;

pubic function getInstance():MySingleton {
if (instance == null)
instance = new MySingleton(new MySingletonEnforcer());
return instance;
}
}
}

//this is in MySingleton.as but is outside the package block
class MySingletonEnforcer {}

You can defeat this approach with:

var a:MySingleton = new MySingleton(null);
var b:MySingleton = new MySingleton(null);
// a !== b

If you don't know about private classes I wrote up some information. This is just a missing null check in the constructor to make sure that a valid reference was passed in. I like this approach better overall since it has more compile time support. Trying to call "new MySingleton()" gives an "expected 1 argument" compile time error and trying to call "new MySingleton(XXX)" with anything but null will give you a class cast exception. But that is my personal preference.

I'd also recommend that you add final to the class definition. While I'm pretty sure you can't get access to stuff that easily in AS3, it is probably best to guard against subclassing.

If you want to use the first approach, it can be fixed with the introduction of a private method:

package {
    public final class Singleton {
        private static var singleton : Singleton;
		
        public static function getInstance() : Singleton {
            if ( singleton == null )
                singleton = new Singleton( hidden );
            return singleton;
        }
        private static function hidden():void {}	
        //NOTE: AS3 does not allow for private or protected constructors
        public function Singleton( caller : Function = null ) {	
            if( caller != hidden )
                throw new Error ("Singleton is a singleton class, use getInstance() instead");
            if ( Singleton.singleton != null )
                throw new Error( "Only one Singleton instance should be instantiated" );	
            //put instantiation code here
        }
    }
}

The second approach can be fixed with the introduction of a null check:

package whatever {
  public final class MySingleton {
    public function MySingleton(singletonEnforcer:MySingletonEnforcer) {
        if (singletonEnforcer == null) {
            throw new Error ("MySingleton is a singleton class, use getInstance() instead");
        }
    }

private static var instance:MySingleton;

public static function getInstance():MySingleton {
if (instance == null)
instance = new MySingleton(new MySingletonEnforcer());
return instance;
}
}
}

//this is in MySingleton.as but is outside the package block
class MySingletonEnforcer {}

This final example, which I think is best, comes from Daniel Hai via Ted Patrick's JAM. The entry is "Singleton Take 2":


package {
public final class Singleton {
private static var instance:Singleton = new Singleton();

public function Singleton() {
if( instance ) throw new Error( "Singleton and can only be accessed through Singleton.getInstance()" );
}
public static function getInstance():Singleton {
return instance;
}
}
}

I've updated Wikipedia with this last example. Please change it if you notice any problems.

Tags: as3 flex pattern singleton

September 28, 2006

Template Method

I lead the discussion at tonight's BFPUG Pattern Meeting on the topic of the Template Method. For the discussion I put together some overview and simple examples. You can find the Flex 2 project, source, and raw Eclipse files all online.

Tags: bfpug flex pattern

August 31, 2006

Binding Warning

While working on an AS3 class today I had the following message appear in the debug console:

warning: unconverted Bindable metadata in class 'com.example::SampleData'

Everything still seemed to work correctly, but the fact that the message was getting reported concerned me. Unfortunately, this message doesn't appear in the run-time error documentation, which makes some sense since there was no error number associated with the problem and it just a warning. Doing a little more digging I found that the message is coming from the class mx.binding.BindabilityInfo.as. Thank you Adobe for including sources with the framework!

It seems that when the binding is being resolved the class metadata is bad. In this case the metadata was:

<metadata name="Bindable"/>
<metadata name="Bindable">
<arg key="event" value="propertyChange"/>
</metadata>

The message results from the fact that the first Bindable metadata entry doesn't include an event name. The more important thing was what was causing the event not to exist? Turns out it was a combination of the ordering of my get/set methods and the fact that I was casting my object as an Object instead of as SampleData. A little code will help explain what was going on. First this is the simple application that uses the SampleData instance.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:example="com.example.*">
<mx:Script>
<![CDATA[
import com.example.SampleData;
[Bindable]
private var _data:Object = new SampleData();
]]>
</mx:Script>
<mx:Label text="{_data.data}"/>
<mx:TextInput id="textInput"/>
<mx:Binding source="textInput.text" destination="_data.data"/>
</mx:Application>

The reason that _data is cast as an object is that in real code (unlike this simplified example) any one of a number of different types of objects could be fed in as the data to use. Next up is the implementation of SampleData that generates the "unconverted Bindable" error from above.

package com.example {
public class SampleData {
private var _data:Object;
[Bindable]
public function get data():Object {
return _data;
}
public function set data(data:Object):void {
_data = data;
}
}
}

This is where I get really confused about what the compiler and runtime are doing under the scenes. I've not looked at the "-keep" output to see if there is a good explanation. For the time being there are two solutions to the problem. The first one is to switch the order of the getter and setter in SampleData. The following change fixes the Bindable metadata and as such the error goes away:

package com.example {
public class SampleData {
private var _data:Object;
[Bindable]
public function set data(data:Object):void {
_data = data;
}
public function get data():Object {
return _data;
}

}
}

Subtle isn't it :) The [Bindable] documentation shows an example of the setter before the getter, it doesn't seem to emphasize that it can make a difference, which is why I suspect something else funky maybe going on. The other fix is to use more a strongly typed object reference. Using the SampleData class from above with the get before the set, this modified application will also cause the warning to disappear.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:example="com.example.*">
<mx:Script>
<![CDATA[
import com.example.SampleData;

[Bindable]
private var _data:SampleData = new SampleData();
]]>
</mx:Script>
<mx:Label text="{_data.data}"/>
<mx:TextInput id="textInput"/>
<mx:Binding source="textInput.text" destination="_data.data"/>
</mx:Application>

Again nice and subtle. If anyone has thoughts on why the order of the getter and setter might contribute to this warning, I'd love to hear them.

Tags: actionscript3 as3 bindable flex warning

August 31, 2006

CSS and Runtime Modules

Another strange problem has popped up with the use of runtime modules. CSS type selectors don't work correctly. The compiler optimizes the CSS such that it only includes information for types that are actually used, based on the class dependency hierarchy. Since with a runtime module you are indirectly using classes, the dependency isn't found and the CSS information is excluded. Consider the following type selector:

SampleClass {
    backgroundColor: #FFFFFF;
    backgroundAlpha: .5;
    borderColor: #000000;
    borderThickness: 2;
    borderStyle: solid;
    paddingTop: 4;
    paddingBottom: 4;
    paddingLeft: 4;
    paddingRight: 4;
}

If you don't have a dependency on SampleClass in the main application you will end up with the following compiler warning:

"The type selector 'SampleClass' was not processed, because the type was not used in the application."

Right now I don't have a good solution for this. The simple work around is to not use a type selector but instead just make it a style selector (i.e. .sampleClass instead of SampleClass), but that requires you to set the styleName attribute on every instance you create. I'm open to other ideas.

Update
There are a couple of compiler options that help with this issue. If you are getting the warnings and don't care about them you can turn them off like this:

-show-unused-type-selector-warnings=false

This can be either a command line parameter, stuffed into a flex-config.xml file, or setup as an additional compiler argument in Flex Builder. If instead you want to include every CSS type selector, without having to do the static reference nonsense, you can do this:

-keep-all-type-selectors=true

Again that can be setup as either a command line parameter, part of a config, or enabled in Flex Builder. For additional information on the two options see LiveDocs.

Tags: css flex

July 30, 2006

Flex 2 Runtime Error 1009 and Runtime Modules

While the following error is most often encountered when trying to access a property or function through a null object reference, it can also rear its head when working with runtime modules.

TypeError: Error #1009: Cannot access a property or method of a null object reference.
	at mx.containers::Panel/mx.containers:Panel::layoutChrome()
	at mx.core::Container/mx.core:Container::updateDisplayList()[C:\dev\GMC\sdk\frameworks\mx\core\Container.as:2910]
	at mx.containers::Panel/mx.containers:Panel::updateDisplayList()
	at mx.core::UIComponent/validateDisplayList()[C:\dev\GMC\sdk\frameworks\mx\core\UIComponent.as:5672]
	at mx.core::Container/validateDisplayList()[C:\dev\GMC\sdk\frameworks\mx\core\Container.as:2731]
	at mx.managers::LayoutManager/mx.managers:LayoutManager::validateDisplayList()[C:\dev\GMC\sdk\frameworks\mx\managers\LayoutManager.as:594]
	at mx.managers::LayoutManager/mx.managers:LayoutManager::doPhasedInstantiation()[C:\dev\GMC\sdk\frameworks\mx\managers\LayoutManager.as:646]
	at Function/http://adobe.com/AS3/2006/builtin::apply()
	at mx.core::UIComponent/mx.core:UIComponent::callLaterDispatcher2()[C:\dev\GMC\sdk\frameworks\mx\core\UIComponent.as:7789]
	at mx.core::UIComponent/mx.core:UIComponent::callLaterDispatcher()[C:\dev\GMC\sdk\frameworks\mx\core\UIComponent.as:7732]

The problem seems to be that if the runtime module makes a side-effect reference to a component, which is not included in the main application, it never really gets included in the SWF and as such causes problems when accessed. That's a jumble of words so I think an example is needed.

Create a Flex Application with two files in it. The first one is called com.example.PanelComp.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="400" height="300">
    <mx:Text text="Hi"/>
</mx:Panel>

The second one is the main application, call it LoadTest.as:

package {
    import com.example.PanelComp;
    import mx.core.SimpleApplication;

    public class LoadTest extends SimpleApplication {
        private static var panelComp:PanelComp;
    }
}

For more information on that SimpleApplication business check out Roger Gonzalez's blog.

Now in a different Flex Application we want to load the first application and then create an instance of PanelComp.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
    <mx:Script>
        <![CDATA[
            import mx.containers.Panel;
            import flash.utils.getDefinitionByName;

            // must uncomment for "Add Panel" to work
            // TypeError: Error #1009:
            // private static const panel:Panel = null;

            private var _loader:Loader;

            private function loadSwf(location:String):void {
                _loader = new Loader();
                var ctx:LoaderContext = new LoaderContext();
            	ctx.applicationDomain = ApplicationDomain.currentDomain;
            	_loader.contentLoaderInfo.addEventListener(Event.INIT, swfInit);
                _loader.load(new URLRequest(location), ctx);
            }

            private function swfInit(e:Event):void {
                _loader.content.addEventListener("ready", swfLoaded);
            }

            private function swfLoaded(e:Event):void {
                trace("Loaded");
            }

            private function createPanel():void {
                var clazz:Class = Class(getDefinitionByName("com.example.PanelComp"));
                // see note above about TypeError: Error #1009:
                addChild(new clazz());
            }
        ]]>
    </mx:Script>
    <mx:Button label="Load" click="loadSwf('../../LoadTest/bin/LoadTest.swf');"/>
    <mx:Button label="Add Panel" click="createPanel();"/>
</mx:Application>

As noted in the comments, until you uncomment the static reference to Panel in the wrapper application, you will get the stack trace. Something to keep in mind if you are using runtime modules.

Tags: actionscript as3 flex programming

July 30, 2006

Flex 2 Runtime Error 1065

Today while working on some code I started getting this error and stack trace:

ReferenceError: Error #1065: Variable LoadTest is not defined.
	at global/flash.utils::getDefinitionByName()
        at ... (rest of stack trace deleted)

Looking the error up in the documentation didn't help point the way to what might be going on since this had nothing to do with a "variable":

1065 Variable _ is not defined. You are using an undefined lexical reference. For example, in the following statements, the statement trace(x) generates an error because x is undefined. However, the statement trace(y) doesn't generate an error because y is defined: trace("hello world") trace(x) // x is undefined var y trace(y) // No error, y is defined.

In this case I was trying to dynamically instantiate a class by first finding the definition of that class and then newing it. Something like this:

public function createInstance(className:String):Object {
    var instance:Class = Class(getDefinitionByName(className));
    new instance();
}

It turns out the reason why the error was being thrown was that in my Flex Application I didn't have anything which "used" the class. In other words the compiler thought that the class was left over junk and didn't include it in the compiled swf. By adding in a use of it, everything started working. As example use would be something like:

private static const loadTestRef:LoadTest = null;

If there is another way to get this same behavior, please let me know.

Tags: actionscript as3 flex programming

June 30, 2006

AS3 Code Coverage

Note A code coverage tool is now available at http://code.google.com/p/flexcover/.

This maybe a little crazy but I'm going to throw it out there. I've been thinking about a way to get code coverage reports for Actionscript 3. We make heavy use of FlexUnit at work, but I'm always curious just how much of our code is really covered with the tests. I've not found anything about code coverage tools with the few Google searches that I've run hence my search for other solutions.

My current idea is to leverage the Flex debugger. Something along the lines of creating a break point on every line in ever file that you want to check coverage of. As the break points get hit, remove them. Once all of the test code is done running, see if there are any break points that haven't been hit.

This isn't elegant by any means but it should be possible to test the theory with a few hours work. If someone knows of a tool that already does this I'd love to hear about it. Otherwise I'll see how my hacking goes.

Tags: as3 fdb flex testing

June 30, 2006

Flex 2 / Flash 9 Released

Adobe is now shipping Flex 2 and Flash 9. Get them now!

The best part is that the Flex 2 SDK is FREE.

Check out the new Flex.org site for everything about Flex.

Tags: flex links

June 30, 2006

Regular Expression Tester Updated

With the public release of Flash player 9, I've updated the regular expression tester to use the latest version.

I also fixed a bug with the display of optional groups.

NOTE: If the screen is blank, that probably means that you don't have the correct Flash version. Stop by the Flash version page and make sure you have at least 9.0.15.0 installed. If you don't you can easily download it.

Launch RegExp Tester!

Tags: flex regexp

June 30, 2006

Dynamic Interface

I would like a way in AS3 to define an interface as being dynamic. In some cases I want all classes that implement an interface to also have to be dynamic. Why might this be useful? I find the chained property accessors much nicer to deal with. I'm not as concerned about adding new methods to the interface and some of the other stuff that you can do with a dynamic class, I just want easy access to unspecified attributes. The fact that you can still use the associative array style lookup on an interface to get the same result only strengthens my belief that you should be able to mark an interface as dynamic.

Since you can't apply the dynamic keyword to an interface and there doesn't seem to be a system interface that endows dynamicness on an interface, you are forced to either use looser typing or use the alternative syntax. I think this calls for an example.

Say I have this interface defined:


package com.example {
public interface ISample {}
}

In another class I have a method that uses that interface:


package com.example {
public class UseSample {
public function displayProp(sample:ISample):void {
trace(sample.prop);
}
}
}

That generates the lovely compiler error:
1119: Access of possibly undefined property prop through a reference with static type com.example:ISample.

If you change the code to use array syntax it will compile:


package com.example {
public class UseSample {
public function displayProp(sample:ISample):void {
trace(sample["prop"]);
}
}
}

In my mind the array syntax is much more obtuse. Oh well, I can always hope :)

Tags: actionscript as3 flex programming

June 30, 2006

Events in Flex 2

Today I got a familiar error while working with some event code:

TypeError: Error #1034: Type Coercion failed: cannot convert flash.events::Event@35f04c1 to com.neophi.events.CustomEvent.

The short answer is that this error results from failing to implement a clone() method on a custom event class. The long answer is that most of the time not implementing a clone() method won't hurt you, based on how you use your custom events, but you really should create one. In fact the Actionscript 3 (AS3) documentation is pretty clear about this:

When creating your own custom Event class, you must override the inherited Event.clone() method in order for it to duplicate the properties of your custom class.

This is a time that I wish AS3 had abstract methods.

Why I say you don't really need a clone() method is that it only becomes an issue if you relay an event. The follow code is an example of event relaying:

private function relay(customEvent:CustomEvent):void
{
    dispatchEvent(customEvent);
}

In this case an event listener redispatches the event that it got. When this happens the event framework behind the scenes calls the clone() method to create a new instance of the event. If you don't have a clone() method and the next listener in the chain is expecting an instance of CustomEvent, the error from above happens. If instead that same listener was only expecting an instance of the Event class, it would work, but any additional information contained in CustomEvent class would be lost, including the ability to cast it to an instance of CustomEvent.

In most cases the clone() method is simple to implement; just transfer any constructor arguments to a new instance of the class. Something like:

override public function clone():Event
{
    return new CustomEvent(_message);
}

Based on the type of event you will probably have more arguments including the all important type and often the other standard event variables for bubbling and cancelability.

While I'm on the subject of events I'll also talk about Event metadata or annotations that you can apply to classes. Often if you have an AS3 class that can emit custom events you will add metadata like this at the top:

package com.neophi {
    import com.neophi.events.CustomEvent;

    import flash.events.EventDispatcher;

    [Event(name="customChange", type="com.neophi.events.CustomEvent")]

    public class EventSource extends EventDispatcher {
        // class code removed 
    }
}

The thing to keep in mind is that depending on how this class will be used you probably don't need that metadata. If this AS3 class isn't used in MXML you can skip the metadata. The metadata is only used to inform the compiler how to translate an MXML event attribute into the appropriate code.

For example with the above class and metadata you could use it in MXML like this:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:neophi="com.neophi.*">
<mx:Script>
<![CDATA[
import com.neophi.events.CustomEvent;

private function customChanged(customEvent:CustomEvent):void
{
    output.text += "EventTest: " + customEvent + "\n";
}
]]>
</mx:Script>
<neophi:EventSource id="eventSource" customChange="customChanged(event);" />
<mx:Button label="Go" click="eventSource.source();"/>
<mx:TextArea id="output" width="100%" height="400"/>
</mx:Application>

Because cutomChange is defined in the metadata for the EventSource class, in MXML you can now assign a handler to that event. In this case the method customChanged will be called whenever our instance of EventSource dispatches that event.

The method the button is calling to cause eventSource to fire the event is:

public function source():void
{
    var customEvent:CustomEvent = new CustomEvent("Event Message");
    dispatchEvent(customEvent);
}

This code is part of the EventSource class listed above. A new instance of CustomEvent is created and then dispatched. At this point all listeners will get called.

If you tried instead to assign the customChange handler in MXML without the metadata in EventSource you would get a compile error like this:

Cannot resolve attribute 'customChange' for component type com.neophi.events.EventSource.

For events then the two rules of thumb are:

  1. always create a clone() method in any custom event class
  2. add event metadata if you will need to setup handlers for that event in MXML

Tags: actionscript3 as3 events flex programming

June 30, 2006

Interface Constants

Since it has come up a couple of times these past two days, I'm a little disappointed that AS3 interfaces don't support constants. I guess I'm too used to Java's interfaces and really wish AS3 interfaces were as versatile. I've ended up using a class which just has static constants in it to simulate the constants that I would normally have applied to the interface.

If I'm missing some syntax or a better way around this issue, please let me know.

Tags: actionscript as3 flex interfaces

May 31, 2006

Flex Beta 3

For anyone following Flex, beta 3 is now available.
From my experience, Flex Builder is much improved but there are still many quirks with it. There were quite a few Actionscript 3 language changes, but the documentation on them is good. My biggest complaint so far is that many MXML files in a Flex library project are not being handled properly by the MXML Editor which results in a complete lack of code assist. The same MXML file in a Flex Application works fine. I've not completely figured out why some of the files are so broken, especially when they seem to work fine on another user's system.

Tags: actionscript as3 flex programming

April 30, 2006

Flex 2, Actionscript 3, and E4X

I've found a feature of Actionscript 3 (AS3) that I've not seen in other languages that I think is pretty cool. It's taken me awhile to come to terms with it, but now that I've getting more comfortable with it I'm really starting to appreciate it. That feature is what is known as E4X or more officially Standard ECMA-357 ECMAScript for XML (E4X) Specification. At its core is the ability to work with and manipulate XML data in AS3 using standard language syntax instead of having to do everything through an API.

For example to create a variable that contains some hard coded XML you could just write:


var xml:XML =
<componentPackage>
<component id="MyButton" class="package1.MyButton"/>
<component id="MyOtherButton" class="package2.MyOtherButton"/>
</componentPackage>;

Notice the lack of any "new XML("")" or other traditional methods one might use to create an XML document. Pretty cool stuff. You can also do variable substitution when creating XML:


var attributeName:String = "class";
var xml:XML =
<componentPackage>
<component id="MyButton" {attributeName}="package1.MyButton"/>
<component id="MyOtherButton" {attributeName}="package2.MyOtherButton"/>
</componentPackage>;

That creates an XML document that looks exactly like the first XML example. Not the most convincing example, but you get the idea. You can substitute element names, attribute names, or whole attribute values. Besides being able to do inline XML document creation you can also do DOM style navigation to get at elements and attributes within the XML (these return XML or XMLList objects). Going back to the first XML example:


xml.component[0]; // <component id="MyButton" class="com.example.ui.MyButton"/>
xml.component[0].@id; // MyButton

Where things get really cool is the XPath like operations, technically called filters since it isn't as expressive as XPath:


xml.component.(@id == "MyButton"); // <component id="MyButton" class="com.example.ui.MyButton"/>

That searches for all component elements under the root that have an id of MyButton. There are a bunch more. In fact the Working with XML (doc link subject to change) section of the Flex 2 documentation has many good examples. It's at this point that I want to offer a hard learned lesson about what doesn't work with E4X (at present anyway, I can only hope that it will be solved in a future Flex 2 release).

The following line of code doesn't compile (again using the first XML example from above):


xml.component[0].@class; // Error: Expecting identifier before class

The reason is that "class" is a reserved keyword. Thankfully E4X provides alternative attribute access syntax, an example is:


xml.component[0].@["class"]; // package1.MyButton

A little clunky, but still reasonable. What I haven't been able to get working is any of the alternative syntaxes when trying to do a filter using the same attribute:


xml.component[0].(@class == "package1.MyButton"); // Error: Expecting identifier before class

I've tried all four listed variations: element.@attrName, element.attribute("attrName"), element["@attrName"], and element.@["attrName"]. None of them work in the above example, adjusted of course to account for the () filtering operation. This afternoon I finally stumbled upon a solution. This is even more clunky then the alternative attribute accessors, but it does eliminate the need to write custom loops to handle filters like the one above:


xml.component.(@\u0063lass == "package1.MyButton"); // <component id="MyButton" class="com.example.ui.MyButton"/>

In this case I'm using the Unicode value for the letter c (0063) which to my surprise worked. As I said earlier I hope this keyword issue is just a beta issue and it will be resolved. If not, consider using this approach to construct E4X filters that might reference AS3 keywords.

Tags: actionscript as3 e4x flex programmin xml