Thursday, June 29, 2006

Flex.org

Hello Flex Community,

You've probably already seen that Flex 2 was released yesterday. Did you also know that flex.org was also openend up to the public? It has pretty much everything you need to get started in flex. Be sure to check it out.

Other important links:


Wednesday, June 28, 2006

NewsFlash: Flash player 9 has been released!

Got to www.adobe.com and click on the "Get Adobe Flash Player"... They finally released it, so Flex 2 cannot be far behind. :)

Tuesday, June 27, 2006

Flex 2 Layout: Beyond the Standard Container

This is also posted on my other blog, but I might as well put it here too!

Traditionally, Flex layouts are based upon a hierarchy of containers. For example, Lets take the screen in Figure 1:

Figure 1
Figure 1: Flex 1.5 Style Layout

In the traditional Flex 1.5 container-based layout, this type of screen will require a mx:Panel, a mx:VBox, and a series of mx:HBox elements (each mx:HBox contains a mx:Label and mx:TextInput element). Take a look at the code:


<mx:Panel title="Flex Demo - 1.5 Style Layout"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10">

   <mx:VBox width="100%" height="100%">
      <mx:HBox width="100%" >
         <mx:Label text="Field 1" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 2" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 3" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 4" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 5" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" horizontalAlign="center">
         <mx:Button width="30" label="OK" />
         <mx:Button width="60" label="Cancel" />
      </mx:HBox>

      </mx:VBox>
</mx:Panel>


You will see exactly as I just described. What's wrong with this layout? … absolutely nothing, but there is a better way to do it.

Flex 2 provides us with the capability to position elements relative to their parent containers. Basically, this means that Flex 2 can allow us to build a similar component, but without the nested containers. If you compare Figure 1 and Figure 2, you will see that these screens are nearly identical. On the code level, things are very different.

UIComponent objects now support the "left", "right", "top" and "bottom" properties. These properties allow you to position your component relative to the parent container. So, If I have a mx:Label element that has top="10", that Label will be bound so that it is always 10 pixels away from the top of the parent container.

Lets take a look at Figure 2: You easily see how similar the layout is, but now take a look at the code.

Figure 2
Figure 2: Flex 2.0 Style Layout


<mx:Panel title="Flex Demo - 2 Style Layout"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"
   layout="absolute" height="233">

   <mx:Label text="Field 1" width="50" top="10" left="10"/>
   <mx:TextInput right="10" left="65" top="8"/>

   <mx:Label text="Field 2" width="50" top="40" left="10"/>
   <mx:TextInput right="10" left="65" top="38"/>

   <mx:Label text="Field 3" width="50" top="70" left="10"/>
   <mx:TextInput right="10" left="65" top="68"/>

   <mx:Label text="Field 4" width="50" top="100" left="10"/>
   <mx:TextInput right="10" left="65" top="98"/>

   <mx:Label text="Field 5" width="50" top="130" left="10"/>
   <mx:TextInput right="10" left="65" top="128"/>

   <mx:Button width="30" label="OK" bottom="10" right="80"/>
   <mx:Button width="60" label="Cancel" right="10" bottom="10"/>

</mx:Panel>



You can clearly see that this is much simpler and cleaner code. That's only one of the advantages of Flex 2.0 position bound layouts. Another advantage is that this does not require containers within containers, as the Flex 1.5 style layout does. This is a huge advantage. Each container resolves to be an additional movieclip object when the Flex is compiled into a swf and rendered within your browser. Since there are less components, there are less movie clip objects in the runtime, thus there are less resources being used to render the nearly identical screen! This improves the overall speed, initialization, and rendering time of your entire application. In my example, you won't notice much of a difference, but imagine if you had a huge application with hundreds of different components. There would be an enormous difference.

Another advantage of the Flex 2 style layout is that all of the position binding can be done using Flex's CSS styling engine. Take a look at Figure 3. It looks exactly like Figure 2, doesn't it? Now, take a look at the code.

Figure 3
Figure 3: Flex 2.0 CSS Style Layout


<mx:Style>
   .label1{ width:10; top:10; left:10; }
   .textInput1{ right:10; left:65; top:8; }

   .label2{ width:10; top:40; left:10; }
   .textInput2{ right:10; left:65; top:38; }

   .label3{ width:10; top:70; left:10; }
   .textInput3{ right:10; left:65; top:68; }

   .label4{ width:10; top:100; left:10; }
   .textInput4{ right:10; left:65; top:98; }

   .label5{ width:10; top:130; left:10; }
   .textInput5{ right:10; left:65; top:128; }

   .button1{ width:30; bottom:10; right: 80; }
   .button2{ width:60; bottom:10; right: 10; }

</mx:Style>

<mx:Panel title="Flex Demo - 2 CSS Style Layout"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"
   layout="absolute" height="233">

   <mx:Label text="Field 1" styleName="label1" />
   <mx:TextInput styleName="textInput1" />

   <mx:Label text="Field 2" styleName="label2" />
   <mx:TextInput styleName="textInput2" />

   <mx:Label text="Field 3" styleName="label3" />
   <mx:TextInput styleName="textInput3" />

   <mx:Label text="Field 4" styleName="label4" />
   <mx:TextInput styleName="textInput4" />

   <mx:Label text="Field 5" styleName="label5" />
   <mx:TextInput styleName="textInput5" />

   <mx:Button label="OK" styleName="button1" />
   <mx:Button label="Cancel" styleName="button2" />

</mx:Panel>


Yes, this is more code than Figure 3. Why would you want to do this? … CSS positioning allows you to separate the display/positioning logic from your actual application logic. It enables UI designers to work independently from engineers. Engineers can put an actual application together, while UI designers develop the styles separately. Neither is waiting on the other. When the UI design is ready, the styles can be simply "dropped" into the engineer's code, and now application is fully styled, with little additional work for the engineer.

This is not only beneficial for the separation of designer and engineering roles… An application can be "re-skinned" very easily. Take a look at Figure 4. you will see that the application looks different. The best part is that NONE of the application logic has changed from Figure 3. The only thing that has changed is the CSS style definitions.

Figure 4
Figure 4: Flex 2.0 CSS Style Alternate Layout


<mx:Style>

   .label1{ width:10; top:10; right:10; }
   .textInput1{ left:10; right:65; top:8; }

   .label2{ width:10; top:40; right:10; }
   .textInput2{ left:10; right:65; top:38; }

   .label3{ width:10; top:70; right:10; }
   .textInput3{ left:10; right:65; top:68; }

   .label4{ width:10; top:100; right:10; }
   .textInput4{ left:10; right:65; top:98; }

   .label5{ width:10; top:130; right:10; }
   .textInput5{ left:10; right:65; top:128; }

   .button1{ width:30; bottom:10; left: 80; }
   .button2{ width:60; bottom:10; left: 10; }

</mx:Style>

<mx:Panel title="Flex Demo - 2 CSS Style Layout (alternate)"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"
   layout="absolute" height="233">

   <mx:Label text="Field 1" styleName="label1" />
   <mx:TextInput styleName="textInput1" />

   <mx:Label text="Field 2" styleName="label2" />
   <mx:TextInput styleName="textInput2" />

   <mx:Label text="Field 3" styleName="label3" />
   <mx:TextInput styleName="textInput3" />

   <mx:Label text="Field 4" styleName="label4" />
   <mx:TextInput styleName="textInput4" />

   <mx:Label text="Field 5" styleName="label5" />
   <mx:TextInput styleName="textInput5" />

   <mx:Button label="OK" styleName="button1" />
   <mx:Button label="Cancel" styleName="button2" />

</mx:Panel>


Another key benefit of position binding is that the bindings are relative to the parent container… if the parent container resizes, then so do you child containers. Figure 5 shows an example of this. The only thing that has changed between Figure 4 and Figure 5 is that the width of the mx:Panel container has been increased.

Figure 5
Figure 5: Resizing Elements with Bound Positions

Download All Examples For This Post Here

Monday, June 26, 2006

My Other Blog

I just got a new blog at work. Check it out at http://www.cynergysystems.com/blogs/page/andrewtrice.

There will probably be a few duplicate posts on the two, but I'm still going to maintain both.

Enjoy!

Tuesday, June 20, 2006

ECMA Standards

Here's my post of the week, no code today, but hopefully I can get more posts up soon... I've been ridiculously busy. For anyone interested:

Here is the actual specification for ECMAScript (ActionScript).
AND
Here is the actual specification for E4X (ECMAScript for XML).

I can't say that I've read all of it, but you can learn a lot about the language. More information from ECMA can be found at http://www.ecma-international.org/default.htm.

Enjoy! :)

Monday, June 12, 2006

Capturing Still Images From A Camera Stream in Flex 2 Beta 3

Demo requires Flash Player 9 (available at http://labs.adobe.com)A project that I am working on now requires capturing still images from a camera video stream (from a flash.media.Camera object). Here's a prototype that I put together to demonstrate the concept (requires Flash 9). I started everything with the camera example in the Flex 2.0 API documentation.

I started with my CameraStream class (based off the example) that handles the connection with the camera. I've cut out some other functions for resizing and changing dimensions to keep this example simple. Here's my CameraStream class:

package {
import flash.media.Camera;
import flash.media.Video;
import flash.events.*;
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.display.Bitmap;
import flash.system.Security;
import flash.system.SecurityPanel;

public class CameraStream extends Sprite {

public static const DEFAULT_CAMERA_WIDTH : Number = 320;
public static const DEFAULT_CAMERA_HEIGHT : Number = 240;
public static const DEFAULT_CAMERA_FPS : Number = 30;

private var video:Video;
private var camera:Camera;

private var _cameraWidth : Number;
private var _cameraHeight : Number;

public function CameraStream() {
camera = Camera.getCamera();

_cameraWidth = DEFAULT_CAMERA_WIDTH;
_cameraHeight = DEFAULT_CAMERA_HEIGHT;

if(camera != null) {
camera.setMode(_cameraWidth, _cameraHeight, DEFAULT_CAMERA_FPS)
video = new Video(camera.width, camera.height);
video.attachCamera(camera);
addChild(video);
}
else {
Security.showSettings(SecurityPanel.CAMERA)
trace("Go get a camera.");
}
}

public function getSnapshotBitmapData():BitmapData {
var snapshot:BitmapData = new BitmapData(_cameraWidth, _cameraHeight);
snapshot.draw(video,new Matrix());

return snapshot;
}

public function getSnapshot():Bitmap {
var bitmap : Bitmap = new Bitmap(getSnapshotBitmapData());

return bitmap;
}
}

You'll see two important functions in there:
  1. getSnapshotBitmapData() - Returns a BitmapData object from the camera stream. You'll see that it creates a new BitmapData object, and draws the current frame from the video stream into the new BitmapData.

  2. getSnapshot() - Returns a Bitmap rendered from the BitmapData (from getSnapshotBitmapData)
In my MXML code, I have two panels: The first is called videoContainer, and it contains the video stream. In the creationComplete event of the videoContainer there is the following function:

private function attachCameraStream():void {
cameraStream = new CameraStream();
var ref : UIComponent = new UIComponent();
videoContainer.addChild( ref );
ref.addChild( cameraStream );
}

You can see that you need to create a new UIComponent, then attach the cameraStream (Sprite) to it. The second panel is not important... what is important is the Tile container inside of the panel, called "imagesTile". When the user clicks on the "Capture Image" button, the following function is executed:

private function captureSnapshot():void {
var uiComponent : UIComponent = new UIComponent();
uiComponent.width = cameraStream.cameraWidth;
uiComponent.height = cameraStream.cameraHeight;
uiComponent.addChild(cameraStream.getSnapshot());
imagesTile.addChild(uiComponent);
}

You can see that this creates a new UIComponent from the snapshot captured from the cameraStream instance. This UIComponent is then added as a child of the imagesTile object.

You can check out a working example here (requires Flash Player 9).

Friday, June 09, 2006

Hi Resolution Image Viewer In Flash 8

Here is a neat application widget that I created recently. A friend of mine at Revolution Web Design approached me about creating a Flash application to be used in displaying floorplans for a marketing site he is developing for a home builder. I said "sounds great", and started developing it. What is really cool about it is not necessarily what it does, but HOW I put it together. It is very generic and very configurable, so it can have a wide aray of uses. The wide array of uses definitely increases the coolness factor.

Here's the prototype for the initial purpose:
Floorplan Viewer

And here are some customizations I made on it:
Satellite Image Viewer
Image Viewer With Captions

Yes, they're all the same application, just configured for different purposes. You'll see that they all have the same elements, and function in exactly the same way. All of the configuration is in an XML file, so it's really easy to customize.

Here's basically how it works...
  1. The application loads and reads the configuration file. This tells the application where to get content from, what colors to display, what messages should be displayed, whether or not to cache urls, etc...

  2. The user selects an item from the list, the image is loaded into a Loader class object. In the "progress" event of the loader, the progress bar gets updated.

  3. The "complete" event of the loader shows the image and hides the scrollbar.

  4. The user can zoom in/out & reset the picture using the controls on the top right. The user can also zoom in by using the wheel on their mouse. The trick to zooming in is this: Increasing the _xscale or _yscale property on a Loader increases/decreases the size based on the position 0,0 of the object. In order to make it appear to zoom from the center of the object, you will actually need to shift the x,y position with respect to new size of the loader, and its old x,y position. Just have your resize function shift the x,y position after it increases the zoom scale. Presto: it now appears to zoom in from the center.