explorers' club

explorations in dev, science, sci-fi, games, and other fun stuff!


Cool Find: Combining a Cairngorm-ish Command with Maté’s EventMap

So I am on the quest to create a hybrid MVC mini-framework that combines some of the best elements of Cairngorm, PureMVC and Maté.  The idea is to use the Command pattern from Cairngorm (because I like all my service/UX logic to be placed there and the EventMap’s dependencies on binding and MXML seem limiting), the Mediator pattern from PureMVC (which unclutters and decouples the views) and the EventMap and Injection logic from Maté (which will help to further decouple some of the command=>model logic).

Keep in mind I have only really been working with Maté for a couple of months and have only dived into actually understanding it in the last week or so.  So if you know of a better way of doing what I am trying to accomplish, please let me know and I can update the article.

This will mostly address how to decouple some of that command => model logic.  This means we are striving to get the command classes as model-agnostic as possible.  It also means there needs to be a slight modification to the current CairngormCommand structure.  We will keep the CairngormEvent in use because its data payload is useful in sending data back and forth from the event dispatchers/listeners.   In order for a command to send info back to a listener, it will need to extend EventDispatcher.  Then depending on the result or fault logic, it can dispatch an appropriate event with a data payload.  Here is some stub code:

public class SampleMateFriendlyCommand extends EventDispatcher implements IResponder
 public function execute (evt:Event):void
    //the function signature could be anything including execute (... args)
    //notice I am not implementing the ICommand interface as I want to have more flexibility

 public function result (data:Object):void
   //parse data object if needed.

   var evt:CairngormEvent = new CairngormEvent("success");
   evt.data = parsedResultDataObject;

 public function fault (info:Object):void
    //parse info object if needed.

    var evt:CairngormEvent = new CairngormEvent("fault");
    evt.data = parsedFaultInfoObject;

I like the Command pattern because I think of it in a military sense.  You issue a command to a soldier and that soldier executes the command, then generally reports back.  So this is akin to that analogy.  Next we need to see how to get the data back to the EventMap in order to wire the result/fault data into the appropriate places.  I tinkered with this for quite some time before stumbling upon this solution.  The Maté API docs are decent but fail to cover much beyond explaining the self explanatory.  I really hope they work on their API docs and really flesh out the information.

<mate:EventHandlers id="applicationCompleteHandler" type="{AppEvent.SAMPLE_MATE_COMMAND}" debug="true">
      <mate:AsyncCommandInvoker generator="{SampleMateFriendlyCommand}" successType="result">
                <mate:PropertySetter generator="{SomeModelObject}" targetKey="data" source="{scope.currentEvent.data}"/>

The AsyncCommandInvoker allows you to specify the event type that will trigger the successHandlers or the faultHandlers.  Accessing the data payload for the result or success event is done using scope.currentEvent.data.  Again I must reiterate that I stumbled upon this find because there was no documentation that I could find to support what I was trying to do.

The cool thing about this is that you have now freed up your commands so that they needn’t know about any specific model objects.  That is unless you really want to strongly type your result data objects.  This freedom allows for better testing as you can simply wire up a testing event map if you want to unit test.

Next up will be trying to wire mediators and their respective views into the event map.


Quick hint: Complex Component Development in MXML

Assume that you are creating a component in MXML such as some multi-state cell renderer or something that implements IDataRenderer.

All mx.core.Container subclasses have a convenient little event hook called dataChange.  Anytime you set a value to the data property, the component dispatches an event of type FlexEvent.DATA_CHANGE.  To hook into this you simple access it in MXML like so:

<mx:VBox dataChange="do something"/>

With this in mind I suggest that those wishing to do more complex visual changes to their component that {binding} cannot address do the following:

  • create a flag to indicate a data change has occured:
    private var bDataChange:Boolean = false;
  • connect the dataChange hook to the flag:
    <mx:VBox dataChange="bDataChange = true;"/>
  • address the data change in the call to update the display list:
    override protected function updateDisplayList (unscaledWidth:Number, unscaledHeight:Number):void
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        if (bDataChange)
            bDataChange = false;
            //do your custom logic here

The nice bit about this is that you are doing the necessary logic to update the display list when it makes sense to do so (via the already established update framework in the Flex API).  This will prevent many Null Pointer Exceptions (NPEs) due to a child component not being present when setting the component data from the overridden setter.  AND It also reduces the need to override the getter/setter for the data property in the first place.


jwolib – new release 2008.12.15

A user of the lib brought to my attention a major flaw in my default styling setup.  This new release address the default styling as well as a few things regarding the TileCanvas’s itemRenderer (IFactory) generator class (now can use UIComponent, should implement IDataRenderer for best use).

jwolib 2008.12.15 (includes src, asdocs & SWC) – link

1 Comment

Bitmap Fills oriented for Isometric Projection

Notes to self…

Given an image suitable for use as a bitmap fill, certain matrix transformations need to be done in order to orient the image to the xy, xz, and yz planes in the xyz octant.  Assume the following octant orientations:


Here are the following matrix tranformations:

  • XY plane orientation – this is the equivalent to rotating the image by 45º and then reducing the height by half the original scale.

    var m:Matrix = new Matrix();
    m.rotate(Math.PI / 4);
    var m2:Matrix = new Matrix();
    m2.scale(1, 0.5);

  • XZ plane orientation – this is simply skewing the image in the flash-based coordinate system along the  y axis.  Since most isometric projections (including the as3isolib) use a 2:1 ratio, we use Math.atan(0.5) rather than Math.PI / 6.

    var m:Matrix = new Matrix();
    m.b = Math.atan(0.5);

  • YZ plane orientation – same as the XZ plane however we use the skew value * -1;

    var m:Matrix = new Matrix();
    m.b = Math.atan(-0.5);