Archive for June, 2008

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.

Vote in HexoSearch

Comments 4 Comments »

Sorry, I didn't have time to write a tutorial on BaseUI v2. I've added a property to bypass the resize of the DisplayObject (width and height).

It might be useful for a sprite animated that has a size that is changing all time. It will set the useInitialSize to true and you can't use it with a ratio set to RATIO_IN or RATIO_OUT.

The property is:

Actionscript:
  1. var el:ElementUI = baseUI.add(mySpriteAnimated);
  2. el.bypassSize = true;

Last version there.

Vote in HexoSearch

Comments 1 Comment »

I've been working on the second version of BaseUI, so I'm happy to release it today.

THIS IS NOT AN UPDATE.

This new version is quite different, as well as the syntax, so the code you have written for the previous version won't work with this one.

I didn't try it yet in a real project but you shouldn't find too much bugs, comment if you find some, I'll solve them.

I've been working a lot with Flex and everyone enjoy a lot the layouts I think. I build this new version taking a lot of features from Flex. In the demo I use the Flex Builder interface to set the properties on a DisplayObject, so it is working pretty much the same.

I didn't build the Flex layouts obviously, but I'm thinking about it. Anyway, BaseUI allows you to use those following properties on a DisplayObject:

x, y, left, right, top, bottom, width, height, horizontalCenter, verticalCenter, ratio, alignX, alignY

You'll discover some nice features, for example you can use Number or String to set the properties. I've done that because you can now use percentage value for the width and the height!

This will make you able to do a lot more things, have a try in the demo.

Here is some examples of the new syntax:

Actionscript:
  1. var baseUI:BaseUI = new BaseUI(this);
  2. var element:ElementUI = baseUI.add(mySprite);
  3. element.right = 10;
  4. element.bottom = "10";
  5. element.width = "50%"
  6. element.height = 200;
  7. addChild(mySprite);

Actionscript:
  1. var baseUI:BaseUI = new BaseUI(this);
  2. var element:ElementUI = baseUI.add(mySprite);
  3. element.properties = {right:10, verticalCenter:0};
  4. addChild(mySprite);

Actionscript:
  1. var baseUI:BaseUI = new BaseUI(this);
  2. var element:ElementUI = baseUI.add(mySprite);
  3. element.ratio = ElementUI.RATIO_IN;
  4. addChild(mySprite);

As the previous version, if you use the onStage property set to false (to set the reference on the parent instead of the stage), everything will work except the "ratio in" and "ratio out". I need to build a Layout class for that, probably the next step.

A memory system has been included to make your life easier if you need to switch between properties.
For example, if your width is set to 200 or "50%", and later you set a left and right version values. The width is not used anymore as it doesn't make sense, but the value is "memorized" and will be set back automatically if needed, if you set an horizontalCenter value for example. This is done internally, you don't have to do anything.

Have a look at the demo and you'll understand what I mean by values "memorized", basically it is working like the Flex Builder interface.

A tutorial will follow when I get a chance.

If you find any bugs, if you have some ideas to improve it or if you just want to talk about, please comment.

Here is the demo, the docs and the source.

Vote in HexoSearch

Comments 13 Comments »

You can find in the BaseUI page the new version 1.1.0

I've solved a couple of bugs and I've added a new feature.

When you have a ElementUI type element and the property alignX or alignY set to center, you can now set a value to two new properties: horizontalAlign and verticalAlign.

It is working like Flex, for example if you want your centered element 100 pixels more to the right, let's say 100 pixels from the center point, these properties will help you doing it. The syntax is:

Actionscript:
  1. element.alignX = ElementUI.ALIGN_CENTER;
  2. element.alignY = ElementUI.ALIGN_CENTER;
  3. element.horizontalAlign = 100;
  4. element.verticalAlign = -80;

I kept the way BaseUI is working with the elements, if the browser is too small the elements will always stay inside the window with the margin still working, it is also true with these two new properties.

I've updated the documentation and the demo.

Vote in HexoSearch

Comments No Comments »

I recently used ANT and compc to compile a SWC. I had to include another SWC with classes and jpg and some other classes as I needed to force them at compile-time to make the getDefinitionByName class working.

If you don't know getDefinitionByName (and registerClassAlias and getClassByAlias), it make us able to create instances of classes with a string (from a XML for example). The problem is the compiler doesn't include them at compile-time if they are not used.

You will find tons of people talking about that if you google it.

One trick is add a public var myClass:MyClass = null; in the code or use a array. Not really ideal as you have to do that for every class. Example:

Actionscript:
  1. public var myClassPage:MyClassPage = null;
  2. var PageClass:Class = getDefinitionByName("com.site.page.MyClassPage") as Class;
  3. var page:SuperClassPage = new PageClass();

Here is a class that will help you manage that if you need:

Actionscript:
  1. package com.soundstep.managers {
  2.    
  3.     import com.site.menu.basic.*;
  4.     import com.site.page.*;
  5.     import flash.net.*;
  6.  
  7.     /**
  8.      * <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
  9.      * <b>Class version:</b> BETA 1.0<br />
  10.      * <b>Actionscript version:</b> 3.0<br />
  11.      * <b>Copyright:</b>
  12.      * <br />
  13.      * <b>Date:</b> 05-2008<br />
  14.      * <b>Usage:</b>
  15.      * @example
  16.      * <listing version="3.0"></listing>
  17.      */
  18.    
  19.     public class ImportManager {
  20.  
  21.         //------------------------------------
  22.         // private, protected properties
  23.         //------------------------------------
  24.        
  25.         private static var INITIALIZED:Boolean = false;
  26.        
  27.         private static var importManager:ImportManager = new ImportManager();
  28.         private static var importer:Array = [
  29.             BasicMenu,
  30.             Home,
  31.             Page1,
  32.             Page2,
  33.             Page3,
  34.             Page4,
  35.             Page5,
  36.             PageSub21,
  37.             PageSub211,
  38.             PageSub22,
  39.             PageSub221,
  40.             PageSub222,
  41.             PageSub223,
  42.             PageSub23,
  43.             PageSub231,
  44.             PageSub232,
  45.             PageSub233,
  46.             PageSub31,
  47.             PageSub311,
  48.             PageSub32,
  49.             PageSub321,
  50.             PageSub33,
  51.             Page4,
  52.             PageSub41,
  53.             PageSub411
  54.         ];
  55.        
  56.         //------------------------------------
  57.         // public properties
  58.         //------------------------------------
  59.        
  60.         //------------------------------------
  61.         // constructor
  62.         //------------------------------------
  63.        
  64.         public function ImportManager() {
  65.             if (importManager) throw new Error("ImportManager is Singleton.");
  66.         }
  67.        
  68.         //
  69.         // PRIVATE, PROTECTED
  70.         //________________________________________________________________________________________________
  71.        
  72.         private static function init():void {
  73.             for each (var i:Class in importer) {
  74.                 registerClassAlias(String(i).substring(7, String(i).length-1), i);
  75.             }
  76.             INITIALIZED = true;
  77.         }
  78.        
  79.         // PUBLIC
  80.         //________________________________________________________________________________________________
  81.        
  82.         public static function getClass(className:String):Class {
  83.             if (!INITIALIZED) init();
  84.             for each (var i:Class in importer) {
  85.                 if (String(i).indexOf(className)) {
  86.                     return getClassByAlias(className);
  87.                     break;
  88.                 }
  89.             }
  90.             return null;
  91.         }
  92.        
  93.     }
  94. }

You can use it like that:

Actionscript:
  1. var PageClass:Class = ImportManager.getClass("MyClassPage");
  2. var page:SuperClassPage = new PageClass();

Anyway, this is not the subject of the post. "Revenons a nos moutons", as we say in France.

I didn't want to force the import of the classes at compile-time in this way. I had a SWC compiled with flash with some fonts, movies and jpg. I was using this SWC to compile a SWF with mxmlc. I set an Ant task with compc to compile this SWC + the classes I needed with the getDefinitionByName into another SWC. And then, compile my SWF with this unique SWC.

It should have worked very well if compc was compiling my SWC. I had error about flash.swf.tags.GenericTag... nice...

After a bit of research, I saw that Adobe knows about it and are working on it. The problem is the jpg that are included in the first SWC. Even if you try to compile a SWF with mxmc including a SWC with jpg inside, you will get this error. Here are some links where they talk about:

http://bugs.adobe.com/jira/browse/SDK-14888
http://bugs.adobe.com/jira/browse/SDK-14667

You can see that there is a patch there:
http://bugs.adobe.com/jira/secure/attachment/17851/GenericTag.patch

I don't know more about this bug and I'm not really a java man... anyway.

I had to find this GenericTag class that is extending flash.swf.Tag and make it extend flash.swf.tags.DefineTag (full path, not like it is written in the patch).

The class is located in a jar file, which you can open with winrar or similar:
\flex_sdk_3.0.0.477\lib\swfkit.jar

and in the jar, the class is there:
\flash\swf\tags\GenericTag.class

A "class" file is java class that is compiled. I found this nice tool to decompile it:
http://classeditor.sourceforge.net/

I change:
public class GenericTag extends flash.swf.Tag
by:
public class GenericTag extends flash.swf.tags.DefineTag

After that you just have to save the file and put it back in the jar. compc or mxmlc is now compiling without error.

I'll spare you this time, you can download the jar updated. This fix has been done for Flex SDK 3.0.0.477.

Vote in HexoSearch

Comments 5 Comments »