Tuesday, December 13, 2011

Spring Actionscript 2.0 Progress Report - Part V

Its been quite a while since the last progress report, I'm sorry to admit that I haven't been able to spend as much time working on Spring Actionscript 2.0 as I had hoped. Sadly, work and life in general got in the way.
Nevertheless there have been some exciting changes to the code base. Not a lot of extra features, but more a refinement of the existing stuff.

Multiple root views

An application context used to be only tied to one root view. I was, wrongfully, under the impression that a context will always be wiring one module or sub application.
Until I ran into a situation during my own current project where a tab navigator was managed by a parent context with child contexts managing the actual screens in each tab. Only it was possible for multiple tabs to be managed by the same child context.
So, to support this the application context now receives an optional Vector of DisplayObjects as a constructor parameter. After context creation its also to possible to add root views at runtime using the new addRootView() method on the application context. So the views do not necessarily need to be known at the time of creation of the context.

MXMLApplicationContext cleaned up
Admittedly, the MXMLApplicationContext had turned into a bit of a mess. The MXML component acted as a sort of wrapper for an internal DefaultApplicationContext, which somehow seemed like a good idea at the time but lead to nasty issues in practice. (Thanks to this forum post I realized the error of my ways: Spring Actionscript forum link)
So, the MXMLApplicationContext got refactored heavily and while fine-tuning the multi-module support I added some nifty extra possibilities for child contexts.
Originally, as described in Progress Report Part III, the addChildContext() method signature looked like this:
function addChildContext(childContext:IApplicationContext, shareDefinitions:Boolean=true, shareSingletons:Boolean=true, shareEventBus:Boolean=true):void;
This now has changed to a slightly more readable form:
function addChildContext(childContext:IApplicationContext, settings:ContextShareSettings=null):IApplicationContext;
As you'll see the most interesting parameter here is the one called settings. This parameter is of type ContextShareSettings and this can describe the various ways that a parent context will share its data with a child context. This class has four properties:
  1. shareDefinitions - If true all definitions that do not have their childContextAccess set to NONE or SINGLETON will be cloned and added to the child context.
  2. shareProperties - If true all the external properties will be added to the child context
  3. shareSingletons - If true all of the singletons in the parent's cache will be added to the child's cache, provided that an object with the same name doesn't already exist in the child context. Using this also explicitly added singleton can be shared (an explicit singleton means a cached object that doesn't have a corresponding object definition)
  4. eventBusShareSettings - This property is of type EventBusShareSettings, which describes the way that the context eventbuses will be linked to each other.
An EventBusShareSettings instance has these properties:
  1. shareRegularEvents - If true, all regular events, so events that are dispatched without a topic will be shared.
  2. sharedTopics - A Vector of topics whose events will be shared.
  3. shareKind - This property is of type EventBusShareKind as described below.
The  EventBusShareKind enumeration has these values:
  • NONE - The eventbuses will not be connected.
  • BOTH_WAYS - Events dispatched by the parent will be routed to the child's eventbus, and vice versa, events dispatched by the child will be routed to the parent.
  • CHILD_LISTENS_TO_PARENT - Events dispatched by the parent will be routed to the child's eventbus.
  • PARENT_LISTENS_TO_CHILD - Events dispatched by the child will be routed to the parent's eventbus.
Some events were added to this process as well, the application context now dispatches four types of ChildContextEvents:

  1. AFTER_CHILD_CONTEXT_REMOVE
  2. BEFORE_CHILD_CONTEXT_REMOVE
  3. BEFORE_CHILD_CONTEXT_ADD
  4. AFTER_CHILD_CONTEXT_ADD
The names speak for themselves, but the most interesting ones are the BEFORE_CHILD_CONTEXT_ADD and BEFORE_CHILD_CONTEXT_REMOVE.
These events are cancelable, so when preventDefault() is called on them the specified logic will not be executed. So in these cases the child will not be added, or not removed.


Multi-module support and automatic child context detection
The Flex extensions for Spring Actionscript have been further fleshed out in the multi-module support department.
The MXMLApplicationContext has a new property called modulePolicy that determines what a context will do when it encounters a Flex module on the stage. This modulePolicy is an enum with two values:
  • AUTOWIRE - Try to autowire the module
  • IGNORE - Do nothing
By default this property has a value of ModulePolicy.AUTOWIRE, so if your application just needs one context and configuration, but loads its UI in parts there is nothing to be changed. Just add an MXMLApplicationContext and you're good to go.
However, when modules are loaded with their own context that is responsible for wiring the module, set this property to ModulePolicy.IGNORE.

Also new in this drop of Spring Actionscript 2.0 is the fact that MXML based contexts now automatically can detect the creation of child contexts. So all that is needed is to add a context to your module and things will get sorted automatically.
When a new context is detected it will be automatically added to the parent context. The way that an application context determines whether it is a parent context or a child context is by checking the systemManager's isTopLevelRoot property of one of its root views. If this property is true then it assumes its the parent, if not, it assumes its a child.
When a parent adds the child it, naturally, invokes its own addChildContext() method. To specify the ContextShareSettings instance for this call it is possible to do so using the defaultShareSettings property on the MXMLApplicationContext.

If different settings are needed for different childcontexts there is the ChildContextEvents, when listening for the BEFORE_CHILD_CONTEXT_ADD event it is possible to assign a ContextShareSettings instance to the ChildContextEvent.shareSettings property,
If the ContextShareSettings instance is not capable of describing the way that the contexts ought to be shared there is event the possibility to completely override the sharing logic.
This is done by assigning a Function to the ChildContextEvent.customAddChildFunction property, this function needs to have this signature:
function(parentContext:IApplicationContext, childContext:IApplicationContext, settings:ContextShareSettings);
 A sample application that demonstrates the functionality described above here can be viewed here:

Cafe Townsend - Multi-module implementation

The application has 'view source' enabled so its implementation can be checked out easily.

Oh, and before I forget, this functionality can be turned off completely by setting the autoAddChildren property on the MXML context to false.

Popup and tooltip wiring
The MXML based contexts are now able to automatically detect popups and tooltips for wiring purposes. So it is no longer necessary to register a popup after creation, it is automatically picked by the regular stagewiring.
There was some dirty hacking needed to get this working, if you're interested in the nasty details, then check out the PopupAndTooltipWireManager class.

Logging
The framework now reports its internal behavior much more elaborately than before, its not completely finished yet, but there is already an enormous slew of statements waiting for you to be checked out.
Internally we use the mighty as3commons-logging library by Martin Heidegger which, as it should, is turned off by default.
To see the log statements turn up in your trace log all you need to do is add this line of code before the context gets initialized:

LOGGER_FACTORY.setup = new SimpleTargetSetup(new TraceTarget());
 (Don't forget to add the as3commons-logging .swc to your project of course)
The as3commons-logging library offers a host of other logging targets as well, check out its documentation for more details on that.

In conclusion
The documentation has been added to steadily, you can check this out at the usual location:
Spring Actionscript 2.0 - Beta docs

New snapshots have been deployed to the maven repository, so using the 2.0-SNAPSHOT artifact will get updated automatically, should you be using that.

If you have any questions or suggestions, check out the user forums:
Spring Actionscript forum

You can follow me on twitter: @mechhead
Or follow Spring Actionscript: @springas

Our JIRA bugbase can be reached here:
SpringSource JIRA

Thanks for taking the time again to plow through this pile of text, until next time, happy coding!

Roland

2 comments:

  1. Where I can find you e-mail. I have some issue about as3-commons bytecode library?

    ReplyDelete
  2. Please use the issue tracker at google code for as3-bytecode bug reports:

    https://code.google.com/p/as3-commons/issues/list

    cheers,

    Roland

    ReplyDelete

About Me

My Photo

Co-Owner at Stack & Heap (http://www.stackandheap.com)
Lead developer for the Spring Actionscript (http://www.springactionscript.org) and AS3Commons (http://www.as3commons.org) projects.
I like noise.