Archive for the ‘Flash’ tag
Route Framework: Routes
Summary
Before we start, I want to point out, that this article covers low-level API of Route Framework. In most case you don’t want to worry about low-level, unless you building your own framework on top or with Route Framework
Center of Route Framework are IRoute and it’s implementor Route hence the name of the framework. Route sort of inspired by Agent Oriented1 approach minus concurrency and proactivity and EventHandlers from Mate Framework2. Generally it consists of three types of instances: ISensor, IPattern and IAction.
Simply put:
- Sensor get’s messages from Environment, which uses some way to send and receive messages, whether it’s
flash.events.Eventor some custom solution. - After sensor received message, it parses it if needed and passes it’s to
IRoute.perceive( percept:Object );method. In future we’ll call “sensed” message – percept. IRoutewill match percept againstIPattern- If successful Route will then execute it’s
IAction
.
This allows IRoute to be very agile Inversion of Control3 container. Each part of a framwork is simple enough system that can be easily modified.
Percept
Plainly speaking percept can be anything: Object, String, Event or any kind of instance. Whatever Sensor retrieves from Application and passes to Route considered to be Percept. Percept will then be matched against Patterns and passed along to Actions assigned to current Route.
Sensor
In lamen terms Sensor is an Event Listener or an instance of Observer. It simply receives messages from Application/Environment. Of course Sensors can be internal too. For example there could be a Sensor that listens to internal messages of other Routes, but that’s more rare case.
Pattern
Plainly put, Patterns used by Route to see if Actions will be executed. For example Handle Route:
route( Handle, { event: SampleEvent.BIND_PLEASE, generator: SampleEvent } ).
<route:Handle event="{SampleEvent.BIND_PLEASE}" generator="{SampleEvent}"/>
Uses two patterns, to filter by Event.type and actual Class of Event.
Actions
Actions are variation on Command Design Pattern5. Predefined actions in package eu.kiichigo.route.actions cover basic Application manipulation such as: Apply/Bind/Copy data, run closure or method on class, invoke RPC operation and such. You can extend Action, AsyncAction or Actions classes in order to create custom functionality.
There is two major things you can do with actions: assign predicates and group actions
Conclusion
This covers basic logic of Route, once again, this is low-level API which most programmers should not concern themselves with.
Footnotes
[1] PDF: Shoham, “Agent-oriented Programming”.
[2] Mate Framework.
[3] Martin Fowler about IoC.
[4] Command Pattern at Wikipedia.
Route Framework: Sensors and Routing
In Model View Controller or Delegate Model architectures special place is reserved to messaging system. When it comes to ActionScript, we usually utilise one of three solutions:
flash.events.Event/flash.events.IEventDispatcher.
custom Observer implementation.
AS3 Signals by Robert Penner.
Usually Application Framework comes tightly coupled with some or another messaging library. It might work in many cases, but sometimes it might be a serious bottleneck*. Route Framework can switch messaging systems easily by subclassing just 2 classes: Sensor, that will receive messages, and Route to wrap sensor and pattern in it.
Let’s consider following example with custom Observer Implementation:
IMessage.as
package observer
{
public interface IMessage
{
/**
* IMessage name, can be used for additional filtering.
*/
function get name():String;
/**
* @private
*/
function set name( value:String ):void;
/**
* Any data that can be sent with IMessage
*/
function get data():Object;
/**
* @private
*/
function set data( value:Object ):void;
}
}
IObserver.as
package observer
{
public interface IObserver
{
/**
* Invoked automatically by instance of IObservable. Should contain any update logic.
*
* @param message IMessage sent by IObservable
*/
function update( message:IMessage ):void;
}
}
IObservable.as
package observer
{
public interface IObservable
{
/**
* Adds an instance of IObserver to notify queue.
*
* @param observer IObserver to be added.
*/
function add( observer:IObserver ):void;
/**
* Use this methods, to notify all instances of IObserver added to current IObservable.
*
* @param message IMessage to be sent.
*/
function notify( message:IMessage ):void;
}
}
You can check actual implementation of this interfaces in sources, but implementation does not really matter in this case.
In order to teach Route to accept Messages all we need is to subclass Sensor and Route as follows:
package observer
{
import eu.kiichigo.route.pattern.*;
import eu.kiichigo.route.pattern.match.type;
import eu.kiichigo.route.routes.*;
/**
* Version of IRoute to work with custom Observer pattern implementation.
* Fluent style:
*
* route( Receive, { from: "idOfObserver" } );
*
* MXML Syntax:
*
*
*
*
* @author David "nirth" Sergey
*
*/
public class Receive extends Route implements IRoute
{
public function Receive()
{
super();
// Setup pattern to filter out messages of correct type.
var p:IPattern = new Pattern;
p.matcher = type;
p.store( "type", IMessage );
// Inject pattern.
pattern = p;
// Inject Sensor.
sensor = new ObserverSensor;
}
// Receive.from is simple proxy get-set accesor
/**
* @copy ObserverSensor#from
*/
public function get from():Object
{
return ( sensor as ObserverSensor ).from;
}
/**
* @private
*/
public function set from( value:Object ):void
{
( sensor as ObserverSensor ).from = value;
}
}
}
import eu.kiichigo.route.sensors.Sensor;
import observer.IMessage;
import observer.IObserver;
import observer.Messenger;
class ObserverSensor extends Sensor implements IObserver
{
/**
* @copy observer.IObserver#update
*/
public function update( message:IMessage ):void
{
send( message );
}
/**
* @private
*/
protected var _from:Object;
/**
* Indicates an instance of IObservable that this ISensor is listening too.
*/
public function get from():Object
{
return _from;
}
/**
* @private
*/
public function set from( value:Object ):void
{
//ToDo: Handle removal from old Messenger here.
_from = value;
Messenger.get( value ).add( this );
}
}
Now our class has nice readable class name and accessor name, and it’s actually reads as: “Receive from accessorId” as in example:
const router:IRouter = new Router().
route( Receive, { from: "leftButtons" } ).
action( Run, { closure: Alert.show, arguments: ["Received message from leftButtons"] } ).
route( Receive, { from: "rightButtons" } ).
action( Run, { closure: Alert.show, arguments: ["Received message from rightButtons"] } ).
end;
Alternatively you can use MXML Syntax too:
<route:Router>
<observer:Receive from="leftButtons">
<route:Run closure="{ Alert.show }" arguments="{ ['Received message from leftButtons'] }" />
</observer:Receive>
<observer:Receive from="rightButtons">
<route:Run closure="{ Alert.show }" arguments="{ ['Received message from rightButtons'] }" />
</observer:Receive>
</route:Router>
* Another framework that handles decoupling of messaging from mvc logic very nicely is Parsley framework.
RESTful (Prototyping) Framework
That was a long long time since I wrote something about Flex, But looks like I found some time for both Game and RIA industries.
I want to share some of my RESTful client library ideas and concepts. I’m trying to build something very laconic, light and still powerful to connect to various REST Services.
Please note, current version is PREVIEW, which means far before ALPHA, I’m just trying around some stuff, can be not pretty.
So, here is how I want this stuff to work:
Let’s say we have imaginary Social Network, with following REST Operations:
- http://api.socnet.com/users/search
- http://api.socnet.com/users/show
- http://api.socnet.com/users/friends/list
- http://api.socnet.com/photos/new_ones
I can build (IMO) pretty Service structure right in MXML:
<kii:Service id="main" endPoint="http://api.socnet.com/"> <kii:Service id="users" endPoint="users"> <kii:Service id="friends" endPoint="friends"/> </kii:Service> <kii:Service id="photos" endPoint="photos"/> </kii:Service>
And then access it simly like this:
users.post('show', {some_param: someParam});
fiends.get('list');
photos.get('new_ones', {limit: 25});
Later on I can extend Service classes to include concrete methods like Users.list() and Users.update(); but framework is ready to use and might be much more useful than HTTPService right out of box. Again I’m not sure whether I will be using this framework for prototypes only or for release projects too.
You can get source code and binaries from Google Code
ContextMenuManager Class
I dont like the way we create and modify items with ContextMenu class in ActionScript 3.0, first we have to create item, then add event listener, then push our item to ContextMenu.customItems, I think this is quite alot of code for simple task. And there is one more disadvanage, we cannot subclass ContextMenu items, this means we cannot create subclass which would add some items by default.
All this inspired me to create my own class which would manage ContextMenu instance. Then I’ve added methods like remove, insert, getItem.
Read the rest of this entry »
Flash and Frames
Example #1
I think it’s known fact by now, but I’ll mention it anyway.
When we create MovieClip in libriary, and write some script there, Adobe Flash generates class for us automaticaly.
Lets try it, create new *.fla file (for those who forgot how to do it: File > New > Flash Document), and create MovieClip in the libriary. Type this in first frame:
var a:String = "hello world";
Put this mc on the stage and name it mc1, then type in first frame of the root
var mc2:MoveClip = new MovieClip();
trace(getQualifiedClassName(mc1));
trace(getQualifiedClassName(mc2));
Test it, and you’ll see something like that:
Timeline1_395ece48f06854b8f8eb3bfbbaf2af9
flash.display::MovieClip
I dont really know the reason why we do it (MovieClip and Sprite is dynamic class by default), but I like it anyways, it feels more OOPish ![]()
Read the rest of this entry »