PDA

View Full Version : [solution] MX Components in pure actionscript...


shadowmint
07-27-2007, 03:21 PM
Problem: You want to use MX components using only actionscript.

Solution: Yes, it is very possible, as I will now describe.


Setup

Before starting you must ensure you have you the framework.swc in your library path. The details on how to achieve that in the Flex Builder can be found here: http://www.moock.org/blog/archives/000197.html

For anyone using the SDK, you shouldn't have any problems, the mx components appear to be automatically added to the path.

To test if you have the correct setup try compiling the minimal application:

package {

import mx.core.Application;

public class MXApp extends Application
{
public function MXApp()
{
}
}
}

NOTE: Running this application will generate runtime errors. However, you must be able to COMPILE it to proceed.


Problem Details

There are, as I see it, two major errors people encounter trying to use MX components:

1) The component is added but does not appear.

2) The application generates runtime errors.


Solution Details

The solution to (1) is simple. Any MX component must be a child of an class descended from mx.core.Application or it will not be visible.

Most actionscript applications extend flash.display.Sprite, but to use MX components the application must extend mx.core.Application.

The solution to (2) is more complex. Generally speaking it involves specifying the default style characteristics of the MX components. This is done via the CSSSyleDeclaration object, and MUST BE DONE before any MX component is loaded.

The style elements are listed in the adobe livedocs. For example, the base element, Application, lists:

Styles
backgroundGradientAlphas="[ 1.0, 1.0 ]"
backgroundGradientColors="undefined"
...

These values must all be specified before an Application instance can be created. The same applies for any other component; button, label, scrollbar. Indeed, the matter is further complicated by the fact that any component that CONTAINS other components requires that the child component style elements also be specified.

To specify the style elements first a CSSSyleDeclaration object is required for the type of application. Then the setStyle() is used to specify each style element. For example, for Application it might be:


style = new CSSStyleDeclaration ("Application");
style.setStyle("backgroundGradientAlphas", [ 1.0, 1.0 ]);
style.setStyle("backgroundGradientColors", undefined);
style.setStyle("horizontalAlign", "center");
style.setStyle("horizontalGap", "8");
...

NOTE: The name of the style declaration MUST match the MX component class name. It is possible however, to call style = new CSSStyleDeclaration (); and then bind a single style declaration to multiple components using mx.styles.StyleManager.setStyleDeclaration ("NAME", object, false). See the livedocs.

NOTE: It is important to pay attention to the livedocs. The style elements listed there may come in the form: "[ 1.0, 1.0 ]", or "undefined", or "mx.skins.halo.ScrollThumbSkin", or "No default". These are NOT TEXT STRINGS. Make sure the appropriate data is passed to setStyle().


Sample Application

The following is a sample actionscript application that compiles both under the Flex builder and the SDK to provide a single working swf file.

Note: This object uses Label, Application, Button, Scrollbar, HScrollBar, VScrollBar. That's about the minimum you can get away with, because the Application automatically adds a scrollbars, which includes buttons.


package {

import mx.containers.*;
import mx.controls.*;
import mx.core.*;
import mx.styles.*;
import mx.skins.halo.*;
import mx.events.FlexEvent;

public class MXApp extends Application
{
public function MXApp()
{
var style:CSSStyleDeclaration;

style = new CSSStyleDeclaration ("Application");
style.setStyle("backgroundGradientAlphas", [ 1.0, 1.0 ]);
style.setStyle("backgroundGradientColors", undefined);
style.setStyle("horizontalAlign", "center");
style.setStyle("horizontalGap", "8");
style.setStyle("modalTransparency", "0.5");
style.setStyle("modalTransparencyBlur", "3");
style.setStyle("modalTransparencyColor", "#DDDDDD");
style.setStyle("modalTransparencyDuration", "100");
style.setStyle("paddingBottom", "24");
style.setStyle("paddingTop", "24");
style.setStyle("verticalAlign", "left");
style.setStyle("verticalGap", "6");

style = new CSSStyleDeclaration ("ScrollBar");
style.setStyle("borderColor", "0xB7BABC");
style.setStyle("cornerRadius", "0");
style.setStyle("downArrowDisabledSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("downArrowDownSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("downArrowOverSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("downArrowUpSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("fillAlphas", [0.6, 0.4]);
style.setStyle("fillColors", [0xFFFFFF, 0xCCCCCC]);
style.setStyle("highlightAlphas", [0.3, 0.0]);
style.setStyle("thumbDownSkin", mx.skins.halo.ScrollThumbSkin);
style.setStyle("thumbIcon", undefined);
style.setStyle("thumbOverSkin", mx.skins.halo.ScrollThumbSkin);
style.setStyle("thumbUpSkin", mx.skins.halo.ScrollThumbSkin);
style.setStyle("trackColors", [0x94999b, 0xe7e7e7]);
style.setStyle("trackSkin", mx.skins.halo.ScrollTrackSkin);
style.setStyle("upArrowDisabledSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("upArrowDownSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("upArrowOverSkin", mx.skins.halo.ScrollArrowSkin);
style.setStyle("upArrowUpSkin", mx.skins.halo.ScrollArrowSkin);

style = new CSSStyleDeclaration ("HScrollBar");
style.setStyle ("repeatDelay", "500");
style.setStyle ("epeatInterval", "35");

style = new CSSStyleDeclaration ("VScrollBar");
style.setStyle ("repeatDelay", "500");
style.setStyle ("epeatInterval", "35");

style = new CSSStyleDeclaration ("Button");
style.setStyle("borderColor", "0xAAB3B3");
style.setStyle("color", "0x0B333C");
style.setStyle("cornerRadius", "4");
style.setStyle("disabledColor", "0xAAB3B3");
style.setStyle("disabledIcon", null);
style.setStyle("disabledSkin", mx.skins.halo.ButtonSkin);
style.setStyle("downIcon", null);
style.setStyle("downSkin", mx.skins.halo.ButtonSkin);
style.setStyle("fillAlphas", [0.6, 0.4]);
style.setStyle("fillColors", [0xE6EEEE, 0xFFFFFF]);
style.setStyle("focusAlpha", "0.5");
style.setStyle("focusRoundedCorners", "tl tr bl br");
style.setStyle("fontAntiAliasType", "advanced");
style.setStyle("fontFamily", "Verdana");
style.setStyle("fontGridFitType", "pixel");
style.setStyle("fontSharpness", "0");
style.setStyle("fontSize", "10");
style.setStyle("fontStyle", "normal");
style.setStyle("fontThickness", "0");
style.setStyle("fontWeight", "normal");
style.setStyle("highlightAlphas", [0.3, 0.0]);
style.setStyle("horizontalGap", "2");
style.setStyle("icon", null);
style.setStyle("leading", "2");
style.setStyle("overIcon", null);
style.setStyle("overSkin", mx.skins.halo.ButtonSkin);
style.setStyle("paddingBottom", "0");
style.setStyle("paddingLeft", "0");
style.setStyle("paddingRight", "0");
style.setStyle("paddingTop", "0");
style.setStyle("repeatDelay", "500");
style.setStyle("repeatInterval", "35");
style.setStyle("selectedDisabledIcon", null);
style.setStyle("selectedDisabledSkin", mx.skins.halo.ButtonSkin);
style.setStyle("selectedDownIcon", null);
style.setStyle("selectedDownSkin", mx.skins.halo.ButtonSkin);
style.setStyle("selectedOverIcon", null);
style.setStyle("selectedOverSkin", mx.skins.halo.ButtonSkin);
style.setStyle("selectedUpIcon", null);
style.setStyle("selectedUpSkin", mx.skins.halo.ButtonSkin);
style.setStyle("textAlign", "center");
style.setStyle("textDecoration", "none");
style.setStyle("textIndent", "0");
style.setStyle("textRollOverColor", "0x2B333C");
style.setStyle("textSelectedColor", "0x000000");
style.setStyle("upIcon", null);
style.setStyle("upSkin", mx.skins.halo.ButtonSkin);
style.setStyle("verticalGap", "2");

style = new CSSStyleDeclaration ("Label");
style.setStyle("color", "0x00ffffff");
style.setStyle("disabledColor", "0x00000000");
style.setStyle("fontAntiAliasType", "advanced");
style.setStyle("fontFamily", "Verdana");
style.setStyle("fontGridFitType", "pixel");
style.setStyle("fontSharpness", "0");
style.setStyle("fontSize", "10");
style.setStyle("fontStyle", "normal");
style.setStyle("fontThickness", "0");
style.setStyle("fontWeight", "normal");
style.setStyle("paddingLeft", "0");
style.setStyle("paddingRight", "0");
style.setStyle("paddingTop", "0");
style.setStyle("paddingBottom", "0");
style.setStyle("textAlign", "center");
style.setStyle("textDecoration", "normal");
style.setStyle("textIndent", "0");

this.addEventListener(FlexEvent.CREATION_COMPLETE, completedCallback);
}

private function completedCallback (E:FlexEvent):void
{
var lb:Label = new Label ();
lb.width = 100;
lb.height = 100;
lb.text = "Hello World";
addChild (lb);
}
}
}



End
Thanks to everyone who posted about this, it was a really annoying thing to struggle with when no-one knew the answer.

I hereby grant anyone who wants complete permission to take this post or any part of it and do with it as they please (even claim it was their own if they want :).

g'night.

dr_zeus
07-27-2007, 06:50 PM
Or just do this:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" layout="absolute">

<MyCustomApp/>

</mx:Application>

Where MyCustomApp refers to a Flex component built entirely with ActionScript with any number of subcomponents. Seems to me that my three lines of MXML code are easier to use than all the style initialization code you had to write.

shadowmint
10-12-2007, 06:13 AM
As an update to this: Turns out all the required style information can be found in the "defaults.css" file that comes with flex.

By loading the ("...path.../frameworks/default.css") file you can initialise all the mx components with a very few calls, and no need for any MXML at all.

(Use the URL loader, as this tutorial shows how: http://drawk.wordpress.com/2007/06/01/loading-external-css-stylesheets-in-flash9-as3-cs3/)

lucidmyth
10-18-2007, 12:53 PM
Thanks shadowmint,
I really appreciate you sharing this with us as information about pure as3 (non-MXML) is sparse