Posts Tagged “tutorial”

Hi everyone,

Before going on holiday, here is a BaseUI major release :)

Demo, source and code are at the end of the post or in the BaseUI main Page.

It means code written for the previous might not work for this version (even is there isn’t any major change in the structure, some internal code has been changed). If you want to update your code with this version, unless you were using the version 1, it won’t take a long time to adapt it.

I won’t explain in details the basics of BaseUI, you’ll find complete explanations in the tutorials in the BaseUI main page.

Before we could say that BaseUI was an assets manager, now it is becoming a real layout manager.

The two main classes BaseUI and ElementUI allow you to handle assets positioning by using properties on your DisplayObject like top, bottom, width, percentage width, horizontal center and so on, to make them working with the resize event (when the browser is resized by the user). It makes you able to handle liquid layouts, but also works with fixed layouts.

In the first version, BaseUI has been built mainly to work on the stage. It is working now from the version 2 with any reference, stage or another DisplayObject (see properties like onstage and reference).

As I’m also a Flex user and I’ve started to build layout for Flash taking example of the Flex framework.

In this version you’ll find a canvas, a horizontal box, a vertical box and a tile. Those new classes will be found in a layout package: CanvasUI, HBoxUI, VBoxUI and TileUI. All kind of components you can find in the Flex framework, even the name is very close so you don’t get lost with alien class name. Let’s keep things simple.

Before we start on the new classes, let’s see what the changes in BaseUI and ElementUI are. Well, almost nothing changed in appearance. Bugs have been solved and few methods and properties added.

BaseUI

Method: contains
Return true of false if the BaseUI instance already contains the DisplayObject, like you can find in a DisplayObjectContainer such as Sprite or MovieClip.

Property: autoRefresh (default true)
This is a global setting, meaning all the ElementUI created by adding DisplayObject to the BaseUI instance will get the same setting, it can be overridden in each ElementUI instance. By default, when you set a property on an ElementUI instance, the size and positions of the DisplayObject are automatically calculated and “refreshed”. Using autoRefresh set to false, you’ll have to refresh yourself the element by using the refresh methods. This applies only for setting properties, the elements will still be automatically “refreshed” when the Event.RESIZE is triggered. This property is useful if you have a lot of DisplayObject and you don’t want to execute some useless code.

ElementUI

Property: autoRefresh (default true)
See BaseUI autoRefresh description above.

Properties: forceReferenceHeight and forceReferenceWidth
BaseUI is using width and height to set the position of the DisplayObject, sometimes the size can be disturbed by mask or components. They are some properties to help you handle these problems, for example: useInitialSize or bypassSize. I’ve added these two properties and they are the strongest reference that will be used for calculate a new position.

Other layouts will be built, at least a Grid and another Canvas to handle overlapping. I'm basically waiting the official Flash Player 10 release as it has a nice text layout manager!

I’ll write a complete tutorial in the future, let’s see the layouts classes in details.

HBoxUI, VBoxUI and TileUI are subclasses of CanvasUI that is a subclass of MovieClip.

A canvas is containing:
- a Wrapper to handle the size of the canvas
- a Sprite container containing the children added in the canvas
- a Mask to hide the content that is outside of the canvas (optional)
- a Scrollpane component to handle scrollbars if the content is bigger than the canvas (optional)

CanvasUI

The main meaning of a canvas is having an area you can resize without having the content resized. As in Flex, the canvas is an absolute layout and children can overlap. It will be possible to handle some behaviors impossible without. It is also the easiest way to have a centered fixed area in the browser and easily handle ElementUI inside.

To create a canvas:

Actionscript:
  1. var canvas:CanvasUI = new CanvasUI();

A canvas constructor can take 4 optional parameters: width, height, layoutScroll, layoutMask. By default, CanvasUI build a mask to show only the content within the size specified and creates scrollbars (scrollpane instance) if the content is bigger than the size specified. If you don’t need the mask or the scrollbar, just set them to false when you create the instance. If you set the layoutScroll to false, you don’t need a scrollpane component in the flash library (or SWC for Flex SDK user), it will not be imported or created. For example:

Actionscript:
  1. var canvas:CanvasUI = new CanvasUI(200, 200, false, false);

A canvas has a background color and alpha (default is 0), you can set those values if you want to see your canvas:

Actionscript:
  1. canvas.canvasColor = 0xFF0000;
  2. canvas.canvasAlpha = 0.5;

You can use all the ElementUI properties, for example: top, bottom, width, ratio, etc… straight on the canvas. The only difference, unlike ElementUI, the width and height percentage is set with others properties (percentWidth and percentHeight). For example:

Actionscript:
  1. canvas.horizontalCenter = 0;
  2. canvas.percentWidth = “80%”; // or “80” or 80
  3. canvas.bottom = 20;
  4. canvas.height = 300;

A canvas has an internal BaseUI instance (for wrapper, mask and scrollpane) and another for the children. The internal BaseUI instance has the property autoRefresh set to false to keep good performance. It means when you are done setting the properties for the canvas, you must refresh it (this is only for the canvas, you don’t need to do that after adding children):

Actionscript:
  1. canvas.refresh();

You can add children as you would do with a Sprite or other DisplayObjectContainer using the addChild method. You can also use addChildUI to add a child and an ElementUI instance will be created. You can also set ElementUI properties on the children, for example:

Actionscript:
  1. var el:ElementUI = canvas.addChildUI(mySprite);
  2. el.ratio = ElementUI.RATIO_IN;
  3. el.properties = {top:10, bottom:10, left:10, right:10};

You have some methods to get or remove the ElementUI (see documentation):

Actionscript:
  1. var el:ElementUI = canvas.getChildUI(mySprite);
  2. canvas.getChildUI(mySprite).bottom = 20;
  3. canvas.getChildUIByName("mySprite").right = 20;
  4. canvas.removeChildUI(mySprite);

CanvasUI is a mix between inheritance and polymorphism to make behaviors working properly. Most of the MovieClip methods and properties are accessible from the canvas instance. You might find some missing or not working properly, testing all methods and properties between DisplayObjectContainer and MovieClip is a hudge work as some are applied on the wrapper, others on the canvas and others on the container. If you’ve got a problem, you can access to the internal elements through properties (see the documentation).

HBoxUI, VboxUI and TileUI

These layouts are subclassing the CanvasUI and you’re not free to set the position of the children, they are calculated internally. You’ll find some properties common in the Flex layouts.

HBox horizontally lays out its children one by one, you have access to properties like horizontalGap, alignChildren, verticalCenterChildren and padding. Here is an example:

Actionscript:
  1. var hbox:HBoxUI = new HBoxUI();
  2. addChild(hbox);
  3. hbox.horizontalGap = 5;
  4. hbox.alignChildren = HBoxUI.ALIGN_CENTER;
  5. hbox.verticalCenterChildren = 40;
  6. hbox.padding = new Padding(10, 10, 25, 10);
  7. hbox.name = "hbox";
  8. hbox.reference = this;
  9. hbox.percentWidth = "50%";
  10. hbox.height = 200;
  11. hbox.right = 20;
  12. hbox.bottom = 20;
  13. hbox.canvasAlpha = .4;
  14. hbox.refresh();
  15. hbox.addChild(mySprite1);
  16. hbox.addChild(mySprite2);
  17. hbox.addChild(mySprite3);

VBox vertically lays out its children one by one, you have access to properties like verticalGap, alignChildren, horizontalCenterChildren and padding. Here is an example:

Actionscript:
  1. var vbox:VBoxUI = new VBoxUI();
  2. addChildUI(vbox);
  3. vbox.alignChildren = VBoxUI.ALIGN_CENTER;
  4. vbox.horizontalCenterChildren = 40;
  5. vbox.padding = new Padding(10, 25, 10, 10);
  6. vbox.name = "vbox";
  7. vbox.reference = this;
  8. vbox.percentWidth = "50%";
  9. vbox.height = 200;
  10. vbox.right = 20;
  11. vbox.bottom = 20;
  12. vbox.canvasAlpha = .4;
  13. vbox.refresh();
  14. vbox.addChild(mySprite1);
  15. vbox.addChild(mySprite2);
  16. vbox.addChild(mySprite3);

TileUI lays out its children in a grid of equal-sized cells. You can set additional properties like horizontalGap, verticalGap, direction and padding. Here is an example:

Actionscript:
  1. var tile:TileUI = new TileUI();
  2. addChildUI(tile);
  3. tile.direction = TileUI.DIRECTION_HORIZONTAL;
  4. tile.padding = new Padding(10, 10, 10, 10);
  5. tile.name = "tile";
  6. tile.reference = this;
  7. tile.percentWidth = "50%";
  8. tile.height = 200;
  9. tile.right = 20;
  10. tile.bottom = 20;
  11. tile.canvasAlpha = .4;
  12. tile.refresh();
  13. tile.addChild(mySprite1);
  14. tile.addChild(mySprite2);
  15. tile.addChild(mySprite3);

Demo Tween

It is not working smoothly in some browsers (Firefox seems the slowest one), but you can easily tween a new position and size after a resize event. ElementUI is using an Event before applying the new values to the DisplayObject. You can add a listener, stop the propagation and handle yourself the movements. The demo link is at the end of the post or in the source.

I’ve included the demos in the source, Flex SDK users and Linux users will find a SWC of the Scrollpane classes and skin.

Hope you like it and find it useful.

Demo BaseUI
Demo CanvasUI
Demo HBoxUI
Demo VBoxUI
Demo TileUI
Demo Tween

BaseUI main page

Source

Documentation

Comments 10 Comments »

BaseUI will help you to manage your assets (a logo, footer, a menu, etc) in the browser, in a liquid layout or a fixed area.

BaseUI is managing a list of DisplayObject like Sprite, MovieClip, TextField, Bitmap, etc. You will be able to use properties like top, bottom, left, right, horizontalCenter, verticalCenter, width and height even with percentage, some ratio mode for backgrounds and other specific properties.

Here is the BaseUI main page to see the demo, the documentation and download the source.

BaseUI instance

BaseUI is not a Singleton, you can create as many instance as you wish.
Usually, I'm creating a main BaseUI instance in the main class, the entry point, to manage most of my elements. Example in the main class (which is extending Sprite or MovieClip):

Actionscript:
  1. var baseUI:BaseUI = new BaseUI(this);

BaseUI will refresh the position and size of your DisplayObject when the Event.RESIZE will trigger.

You can now add some DisplayObject to your list; it will return an instance of the ElementUI class:

Actionscript:
  1. var element1:ElementUI = BaseUI.add(mySprite);
  2. var element2:ElementUI = BaseUI.add(myBitmap);
  3. var element3:ElementUI = BaseUI.add(myTextField);

The public methods of the BaseUI class are:

Actionscript:
  1. baseUI.add(mySprite);
  2. baseUI.refresh();
  3. baseUI.getElement(mySprite);
  4. baseUI.remove(mySprite);
  5. baseUI.removeAll();

The public properties:

Actionscript:
  1. var elements:Array = baseUI.elements;
  2. var holder:DisplayObjectContainer = baseUI.holder

BaseUI manages 2 lists: a list of DisplayObject and a list of DisplayObject added to the display list. Only the second one will be "refreshed".

BaseUI will trigger 2 events, when you add a DisplayObject to the BaseUI instance and when you remove it:

Actionscript:
  1. baseUI.addEventListener(BaseEventUI.ADDED, addedHandler);
  2. baseUI.addEventListener(BaseEventUI.REMOVED, removedHandler);

Reference to the ElementUI

Before we start to change the size and position of an element, you have to understand on which DisplayObject you align or resize to.

An ElementUI instance has a property onStage, the default is true. It means if you add a 10 pixels top property, it will be 10 pixels from the top of the stage.

When I build a site, I'm using an element (like a logo, a menu, a page, a footer or whatever) like I would do in Photoshop, on a layer that is taking the whole area. That's why the onStage is set to true by default, you can change it like this:

Actionscript:
  1. element.onStage = false;

By doing this, you tell the Element to react, not with the stage anymore but with the parent DisplayObject. We will call it the DisplayObject reference, so the stage or the parent.

You have to be careful using an onStage property set to false, because it means the DisplayObject reference need to have a size to behave as expected.
For example, in a site, your main area is an invisible rectangle 800x600 (a container) that is always centered in the DisplayObject reference (the stage in my example). You can set the ElementUI onStage property of the DisplayObject in the container to false to make the elements behave as expected.

It means the invisible container will have to have a width and height. Here is a hack to do that:

Actionscript:
  1. var container:Sprite = new Sprite();
  2. container.graphics.beginFil(0xFF0000, 0);
  3. container.graphics.drawRect(0, 0, 800, 600);
  4. addChild(container);

I draw an invisible rectangle (the alpha is set to 0) in my container to be sure the DisplayObject reference (the container) of my ElementUI has a size, and then make the ElementUI inside behave as expected.

ElementUI properties

When you get the instance of the ElementUI class, you can use its properties, here are some examples:

To align a Sprite 10px from the bottom and right border:

Actionscript:
  1. element.bottom = 10;
  2. element.right = 10;

To center a Sprite:

Actionscript:
  1. element.horizontalCenter = 0;
  2. element.verticalCenter = 0;

To have a Sprite fitting the browser:

Actionscript:
  1. element.left = 0;
  2. element.right = 0;
  3. element.top = 0;
  4. element.bottom = 0;

You can also set (or get) all the properties in one time, like this:

Actionscript:
  1. element.properties = {top:10, bottom:10, horizontalCenter:-100};

BaseUI is flexible and will accept Number as well as String for the following properties:
x, y, left, right, top, bottom, width, height, horizontalCenter, verticalCenter

Actionscript:
  1. element.bottom = 10;

is the same as

Actionscript:
  1. element.bottom = "10";

For the width and the height, you can also use percentage values:

Actionscript:
  1. element.width = "80%";
  2. element.height = "80%";

In the ElementUI class, they are cases when a property shouldn’t be used, for example if you set a left and right value, the width property is not used anymore. When you do so, the class will memorize the width value in case it will be "turned on" by another property. For example, if you set horizontalCenter to 0, left and right will be memorized and turn on to NaN, the width value will be restored.

Everything is done automatically by the ElementUI class, you don’t have anything to do, see the demo for a better understanding.

You can refer to the documentation for a full list of the properties.

Refresh method

In some case you will have to manually refresh the element, for example if you change the width and the Event.RESIZE won’t be triggered.

You can refresh the element like that:

Actionscript:
  1. element.refresh();

This will work only if the alpha of the DisplayObject is superior to 0 and the visible property is set to true. Otherwise, you will have to force the refresh:

Actionscript:
  1. element.forceRefresh();

The ElementUI class dispatches an updated event when the Element has been refreshed, you can listen to it like that:

Actionscript:
  1. Element.addEventListener(BaseEventUI.UPDATED, updatedHandler);

To refresh all the elements of the BaseUI class, use:

Actionscript:
  1. BaseUI.refresh();

Ratio property

As in the precedent version, you can set the ratio property, I guess mainly for a background:

Actionscript:
  1. element.ratio = ElementUI.RATIO_IN;
  2. element.ratio = ElementUI.RATIO_OUT;

See the demo for the different behaviors.

To turn it off, just pass an empty String or whatever you want:

Actionscript:
  1. element.ratio = "none";

Some properties are bypassed when a ratio has been set as it doesn’t make sense, like width and height. Some others like top, bottom, left and right are still working.

In ratio set to RATIO_OUT, you can use the properties alignX and alignY:

Actionscript:
  1. element.alignX = ElementUI.ALIGN_CENTER;
  2. element.alignY = ElementUI.ALIGN_BOTTOM;

Known issue: if you set the ratio to RATIO_IN or RATIO_OUT with the property onstage set to false, it won’t work properly. Probably a further development will allow it.

Initial Size

When a DisplayObject is added in the BaseUI instance, an ElementUI is created and at this moment, the Element instance is recording the size of the DisplayObject. This is the initialWidth and initialHeight of the DisplayObject

This size is used to calculate the ratio of the DisplayObject for example.

An ElementUI instance has a property useInitialSize set by default to false, you can change it to true when you want the behavior of the ElementUI working with the initial size. It is useful for example when you have a mask in a Sprite that is disturbing the width and height of this Sprite.

Bypass Size

In some case, your DisplayObject will be animated making its size impossible to use. To prevent unexpected behaviors you can set the bypassSize property to false. Only the properties for position will be used.

Keep on screen

By default the property keepOnScreen is set to true (added in 2.0.4). This prevent the top-left corner of the DisplayObject to go off the screen.

Comments 4 Comments »

I had to get an AIR application without the OS window, let's say windowless or chromeless.

I needed to be able, with my own graphics, to minimize, restore, maximize, close, close in the system tray or dock, fullscreen and resize.

You can find several tutorials on Internet (with which I got inspired) but I put all these functionalities in one small example as it is convenient.

You need to set 2 parameters out of the code, in the XML description file:

Actionscript:
  1. <systemChrome>none</systemChrome>
  2. <transparent>true</transparent>

I won’t explain the code, I guess it is easy enough to find out. You can comment if something is not clear for you.

Here is the code of the main mxml file:

Actionscript:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" showFlexChrome="false" creationComplete="init()">
  3.  
  4. <mx:Script>
  5. <![CDATA[
  6.  
  7. [Embed(source="assets/iconDock.png")]
  8. [Bindable]
  9. public var IconDock:Class;
  10.  
  11. private function init():void {
  12.     registerMovementHandler();
  13.     setDock();
  14. }
  15.  
  16. public function registerMovementHandler():void {
  17.     appCanvas.addEventListener(MouseEvent.MOUSE_DOWN, mouseDrag);
  18.     btResizeBottomRight.addEventListener(MouseEvent.MOUSE_DOWN, resizeWindow);
  19.     btResizeBottomLeft.addEventListener(MouseEvent.MOUSE_DOWN, resizeWindow);
  20.     btResizeTopRight.addEventListener(MouseEvent.MOUSE_DOWN, resizeWindow);
  21.     btResizeTopLeft.addEventListener(MouseEvent.MOUSE_DOWN, resizeWindow);
  22. }
  23.  
  24. public function mouseDrag(e:MouseEvent):void {
  25.     if (e.target == e.currentTarget) stage.nativeWindow.startMove();
  26. }
  27.  
  28. public function resizeWindow(e:MouseEvent = null):void {
  29.     if (e.target == e.currentTarget) {
  30.         var corner:String;
  31.         switch(e.currentTarget){
  32.             case btResizeBottomRight:
  33.                 corner = NativeWindowResize.BOTTOM_RIGHT;
  34.                 break;
  35.             case btResizeBottomLeft:
  36.                 corner = NativeWindowResize.BOTTOM_LEFT;
  37.                 break;
  38.             case btResizeTopRight:
  39.                 corner = NativeWindowResize.TOP_RIGHT;
  40.                 break;
  41.             case btResizeTopLeft:
  42.                 corner = NativeWindowResize.TOP_LEFT;
  43.                 break;
  44.         }
  45.         stage.nativeWindow.startResize(corner);
  46.     }
  47. }
  48.  
  49. public function setDock():void {
  50.     if (NativeApplication.supportsSystemTrayIcon){
  51.         dockProperties();
  52.         SystemTrayIcon(NativeApplication.nativeApplication.icon).menu = dockMenu();
  53.     }
  54. }
  55.  
  56. private function dockProperties():void{
  57.     SystemTrayIcon(NativeApplication.nativeApplication.icon).tooltip = "Soundstep | chromeless window";
  58.     SystemTrayIcon(NativeApplication.nativeApplication.icon).addEventListener(MouseEvent.CLICK, undock);
  59. }
  60.  
  61. private function dockMenu():NativeMenu {
  62.     var menu:NativeMenu = new NativeMenu();
  63.     var open:NativeMenuItem = new NativeMenuItem("Open");
  64.     var close:NativeMenuItem = new NativeMenuItem("Close");
  65.     open.addEventListener(Event.SELECT, undock);
  66.     close.addEventListener(Event.SELECT, closeWindow);
  67.     menu.addItem(open);
  68.     menu.addItem(new NativeMenuItem("",true));
  69.     menu.addItem(close);
  70.     return menu;
  71. }
  72.  
  73. public function dock():void {
  74.     stage.nativeWindow.visible = false;
  75.     NativeApplication.nativeApplication.icon.bitmaps = [new IconDock() as Bitmap];
  76. }
  77.  
  78. public function undock(evt:Event):void {
  79.     stage.nativeWindow.visible = true;
  80.     stage.nativeWindow.orderToFront();
  81.     NativeApplication.nativeApplication.icon.bitmaps = [];
  82. }
  83.  
  84. public function closeWindow(e:Event = null):void {
  85.     stage.nativeWindow.close();
  86. }
  87.  
  88. public function setFullscreen():void {
  89.     var state:String = (stage.displayState == StageDisplayState.FULL_SCREEN) ? StageDisplayState.NORMAL : StageDisplayState.FULL_SCREEN;
  90.     stage.displayState = state;
  91. }
  92.  
  93. ]]>
  94. </mx:Script>
  95.  
  96. <mx:Canvas right="0" left="0" top="0" bottom="0" backgroundColor="#CF3232" id="appCanvas">
  97.  
  98.     <mx:Label buttonMode="true" mouseChildren="false" text="Min" top="10" color="#000000" id="btMin" click="minimize()" horizontalCenter="58"/>
  99.     <mx:Label buttonMode="true" mouseChildren="false" text="Max" top="10" color="#000000"  id="btMax" click="maximize()" horizontalCenter="-45"/>
  100.     <mx:Label buttonMode="true" mouseChildren="false" text="Close" top="10" color="#000000" id="btClose" click="closeWindow()" horizontalCenter="96"/>
  101.     <mx:Label buttonMode="true" mouseChildren="false" text="Restore" color="#000000" id="btRestore" click="restore()" top="10" horizontalCenter="-91"/>
  102.     <mx:Label buttonMode="true" mouseChildren="false" y="10" text="Tray/Dock" color="#000000" id="btSys" click="dock()" horizontalCenter="8"/>
  103.     <mx:Label buttonMode="true" mouseChildren="false" text="Fullscreen" color="#000000" horizontalCenter="0" bottom="10" id="btFullscreen" click="setFullscreen()"/>
  104.    
  105.     <mx:Canvas width="20" height="20" backgroundColor="#7B0707" borderStyle="none" borderColor="#FFFFFF" id="btResizeBottomRight" themeColor="#494949" right="0" bottom="0" />
  106.    
  107.     <mx:Canvas width="20" height="20" backgroundColor="#7B0707" borderStyle="none" borderColor="#FFFFFF" id="btResizeTopLeft" themeColor="#494949"  left="0" top="0" />
  108.    
  109.     <mx:Canvas width="20" height="20" backgroundColor="#7B0707" borderStyle="none" borderColor="#FFFFFF" id="btResizeBottomLeft" themeColor="#494949" bottom="0" left="0" />
  110.  
  111.     <mx:Canvas width="20" height="20" backgroundColor="#7B0707" borderStyle="none" borderColor="#FFFFFF" id="btResizeTopRight" themeColor="#494949" right="0" top="0" />
  112.  
  113. </mx:Canvas>
  114.    
  115. </mx:WindowedApplication>

You can download the source or install the AIR application:

In order to view this page
You must enable Javascript
And download the Flash Player
get flash player


Comments 3 Comments »

I made some experiments on how to easily access to data in a Flash site. It is probably a mix with good and bad ways but I think it is worth having a look.

What I’ve done here is get data with syntax that is similar to what you get using E4X in AS3. For example with XML and E4X you can use syntax like that:

xml..item[2].author.name.text();

I’m not saying that this experiment is a good practice but I want to show you what you can do by extending the Array class and extending the Proxy class in AS3. The Proxy class is the replacement of the __resolve we were using in AS2.

Let’s say we have a website that will load data from a database at the start, for example using AMFPHP or whatever, and we are going to fill this data at run-time.

In my example I have a kind of tree with countries > cities > people.

I would like to be able to loop easily through the data, as well as getting them with a friendly/readable syntax if needed.

In my example, I have a Singleton class that contains all the data. I don’t load the data in my example, I statically fill the class. I will access to the data like that:

Content.data

This will return me a array of data, which will contains an array of countries, each instance of the country array will contains an array of cities, which will contains an array of people, etc…

So I’d like to access to my data like this:

To browse the countries:
Content.data[0]
Content.data[1]

To browse the cities in the countries:
Content.data[0][0]
Content.data[0][1]

To browse the people in the cities:
Content.data[0][0][0]
Content.data[0][0][1]

That’s nice to loop through with a “for each” or whatever. An Array is a pretty nice tool to store data as you get some functions to manage it like push, splice, reverse, etc.

But these arrays have a problem, what if I need to get more info on my countries, like the weather, an ID or the surface of the country? I would like access to more data like that:

Content.data[0].name
Content.data[0].id

This is possible with an Array as it is one of the few classes in AS3 that are dynamic. It means you can set any property at run time. For example MovieClip is dynamic and Sprite is not, try to add properties at run-time on these classes to see the result. Some people are saying that is it a good and bad things. It is easy to use but you don’t know what kind of properties will be added in your Array at run-time.

So you don’t want that, and better, you want to control what kind of data they are going to put in your Array. We will get that by extending the Array class.

There’s a nice explanation here to extends an Array, as well as control the data type your custom Array class will accept.

So far it is not bad, we can easily access to our data, we can have properties on these arrays and finally we know that we will have the right type of content inside.

The other thing I want is access to my data with a nice E4X-like:

Content.data.France.name
Content.data.France.Paris.name

Easy, we just need a property France on this array and it is done. Well, the thing is we don’t know yet what this array will be filled with, so we are talking about dynamic properties. These dynamic properties will have to be added to the array when we create it because we said we want to control and we don’t want people adding their own properties.

How do we do that?

We’re going to use the Proxy class that make able us able to handle dynamic properties and dynamic calling.

We will have a class that will be an array (what you get when you call Content.data), a class for the countries, a class for the cities and a class for the people. The people class won’t be an array.

So we have the classes DataArray, CountryArray and CityArray that are extending the Array class. We will also have a Proxy class (a class that is extending the Proxy one) for each of the Array. I choose to a Proxy class for each Array class as it is easier to understand.

Let’s see a bit of code.

The Singleton Content class

Actionscript:
  1. package com.soundstep.data {
  2.  
  3.     /**
  4.      * <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
  5.      * <b>Class version:</b> 1.0<br />
  6.      * <b>Actionscript version:</b> 3.0<br />
  7.      * <b>Copyright:</b> Free to use and change (except to include in a framework), an notification email will be welcome for a commercia