Posts Tagged “framework”

As requested, I Just made a quick demo how to implement the SomaAssets plugin in your application.

See the demo.
Download the demo.
View source.
Demo on github.

I'll make a quick descrition here. I'll be using the following XML config:

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <loader connection="1">
  3.     <asset id="image0" src="assets/img/image0.jpg" smoothing="true" transparent="true"/>
  4.     <asset id="image1" src="assets/img/image1.jpg" smoothing="true" transparent="true"/>
  5.     <group id="group0">
  6.         <group id="group00">
  7.             <asset id="image2" src="assets/img/image2.jpg" smoothing="true" transparent="true"/>
  8.             <asset id="image3" src="assets/img/image3.jpg" smoothing="true" transparent="true"/>
  9.         </group>
  10.         <group id="group01">
  11.             <asset id="css" src="assets/css/stylesheet.css" preventCache="true" weight="352"/>
  12.             <asset id="json" src="assets/json/data.json" preventCache="true" weight="582"/>
  13.             <asset id="sound" src="assets/sounds/sample.mp3" preventCache="true" weight="16718"/>
  14.             <asset id="text" src="assets/text/text.txt" preventCache="true" weight="574"/>
  15.             <asset id="xml" src="assets/xml/sample.xml" preventCache="true" weight="79"/>
  16.             <asset id="video" src="assets/video/sample.flv" weight="1550580"/>
  17.             <asset id="zip" src="assets/zip/file.zip" weight="3493"/>
  18.         </group>
  19.     </group>
  20. </loader>

First step, I create a SomaCore application.

Actionscript:
  1. public function Main() {
  2.     _app = new SomaApplication(this);
  3. }

In the application facade, I create a command from a SomaAssets just to demo how to monitor the assets loading at a framework level. I also register 3 views and 3 mediators to show how to get the assets at different moments. I create the plugin SomaAssets and I finally create a simple wire class "InitializeWire" to handle some global events (config loaded, assets loaded, etc).

Actionscript:
  1. package com.soma.plugins.assets.demo {
  2.  
  3.     import com.soma.plugins.assets.demo.commands.ExampleAssetCommand;
  4.     import com.soma.plugins.assets.events.SomaAssetsEvent;
  5.     import com.soma.core.Soma;
  6.     import com.soma.core.di.SomaInjector;
  7.     import com.soma.core.interfaces.ISoma;
  8.     import com.soma.plugins.assets.SomaAssets;
  9.     import com.soma.plugins.assets.demo.views.ImageGroup;
  10.     import com.soma.plugins.assets.demo.views.ImageGroupMediator;
  11.     import com.soma.plugins.assets.demo.views.ImageWhenAllLoaded;
  12.     import com.soma.plugins.assets.demo.views.ImageWhenAllLoadedMediator;
  13.     import com.soma.plugins.assets.demo.views.ImageWhenNotLoaded;
  14.     import com.soma.plugins.assets.demo.views.ImageWhenNotLoadedMediator;
  15.     import com.soma.plugins.assets.demo.wires.InitializeWire;
  16.     import com.soma.plugins.assets.vo.SomaAssetsVO;
  17.  
  18.     /**
  19.      * @author Romuald Quantin
  20.      */
  21.     public class SomaApplication extends Soma implements ISoma {
  22.  
  23.         private var _container:Main;
  24.  
  25.         public function SomaApplication(container:Main) {
  26.             _container = container;
  27.             super(_container.stage, SomaInjector);
  28.         }
  29.        
  30.         // create a command for a demo purpose to monitor the assets that are loaded
  31.         override protected function registerCommands():void {
  32.             addCommand(SomaAssetsEvent.ASSET_LOADED, ExampleAssetCommand);
  33.         }
  34.        
  35.         // register mediators to views
  36.         // the views won't be created at the same moment to show how you can handle your loading
  37.         override protected function registerViews():void {
  38.             mediators.mapView(ImageWhenAllLoaded, ImageWhenAllLoadedMediator);
  39.             mediators.mapView(ImageWhenNotLoaded, ImageWhenNotLoadedMediator);
  40.             mediators.mapView(ImageGroup, ImageGroupMediator);
  41.         }
  42.        
  43.         // create the plugin and register an external assets configuration to load
  44.         override protected function registerPlugins():void {
  45.             createPlugin(SomaAssets, new SomaAssetsVO(this, "xml/assets.xml"));
  46.         }
  47.        
  48.         // create an wire where you could handle the "global" loading process
  49.         override protected function start():void {
  50.             injector.createInstance(InitializeWire);
  51.         }
  52.        
  53.         // just the document class to add some views to
  54.         public function get container():Main {
  55.             return _container;
  56.         }
  57.        
  58.     }
  59. }

In the InitializeWire class, I add some event listeners to handle errors, when the XML config is loaded and when the assets are all loaded. I used it mostly to create views and mediators at different moments of the loading process to show you how to handle you loaders, events and assets.

Actionscript:
  1. package com.soma.plugins.assets.demo.wires {
  2.  
  3.     import com.soma.plugins.assets.demo.views.ImageGroup;
  4.     import com.soma.core.interfaces.IWire;
  5.     import com.soma.core.wire.Wire;
  6.     import com.soma.plugins.assets.demo.SomaApplication;
  7.     import com.soma.plugins.assets.demo.views.ImageWhenAllLoaded;
  8.     import com.soma.plugins.assets.demo.views.ImageWhenNotLoaded;
  9.     import com.soma.plugins.assets.events.SomaAssetsEvent;
  10.     import flash.display.DisplayObjectContainer;
  11.     import org.assetloader.core.IAssetLoader;
  12.  
  13.     /**
  14.      * @author Romuald Quantin
  15.      */
  16.     public class InitializeWire extends Wire implements IWire {
  17.        
  18.         [Inject(name="assets")]
  19.         public var loader:IAssetLoader;
  20.        
  21.         // register some SomaAssets events for monitoring
  22.         override public function initialize():void {
  23.             addEventListener(SomaAssetsEvent.CONFIG_LOADED, configLoaded);
  24.             addEventListener(SomaAssetsEvent.LOADER_COMPLETE, assetsComplete);
  25.             addEventListener(SomaAssetsEvent.ERROR, assetsErrorHandler);
  26.         }
  27.        
  28.         // shortcut to get the document class
  29.         private function get container() :D isplayObjectContainer {
  30.             return SomaApplication(instance).container;
  31.         }
  32.  
  33.         // in case there's an error for both the assets config or the assets
  34.         private function assetsErrorHandler(event:SomaAssetsEvent):void {
  35.             trace("Asset Error:", event.errorMessage, event.errorType);
  36.         }
  37.        
  38.         // the external XML assets config has been loaded here
  39.         private function configLoaded(event:SomaAssetsEvent):void {
  40.             container.addChild(new ImageWhenNotLoaded());
  41.             container.addChild(new ImageGroup());
  42.             trace("config loaded");
  43.             loader.start();
  44.         }
  45.        
  46.         // all assets container in the config XML have been loaded here
  47.         private function assetsComplete(event:SomaAssetsEvent):void {
  48.             container.addChild(new ImageWhenAllLoaded());
  49.         }
  50.  
  51.     }
  52. }

In the ImageWhenAllLoadedMediator mediator, I inject directly an asset (Bitmap) as everything is loaded when the mediator gets created.

Actionscript:
  1. package com.soma.plugins.assets.demo.views {
  2.  
  3.     import com.soma.core.interfaces.IMediator;
  4.     import com.soma.core.mediator.Mediator;
  5.  
  6.     import flash.display.Bitmap;
  7.  
  8.     /**
  9.      * @author Romuald Quantin
  10.      */
  11.     public class ImageWhenAllLoadedMediator extends Mediator implements IMediator {
  12.  
  13.         [Inject]
  14.         public var view:ImageWhenAllLoaded;
  15.        
  16.         // all the assets are loaded at this point
  17.         // we can inject the asset (or loaders)
  18.         [Inject(name="image0")]
  19.         public var image:Bitmap;
  20.        
  21.         override public function initialize():void {
  22.             image.scaleX = image.scaleY = 0.1;
  23.             image.x = 130;
  24.             view.addChild(image);
  25.         }
  26.        
  27.         override public function dispose():void {
  28.             while (view.numChildren> 0) view.removeChildAt(0);
  29.             view = null;
  30.             image = null;
  31.         }
  32.        
  33.     }
  34. }

The ImageWhenNotLoadedMediator mediator gets created when the XML config has been loaded. The assets are not loaded yet and I show how to retrieve the loader of a specific asset to monitor when it starts, the loading progress and when it has been completed.

Actionscript:
  1. package com.soma.plugins.assets.demo.views {
  2.  
  3.     import flash.display.Bitmap;
  4.     import com.soma.core.interfaces.IMediator;
  5.     import com.soma.core.mediator.Mediator;
  6.  
  7.     import org.assetloader.core.ILoader;
  8.     import org.assetloader.events.AssetLoaderErrorEvent;
  9.     import org.assetloader.events.AssetLoaderEvent;
  10.     import org.assetloader.events.AssetLoaderProgressEvent;
  11.  
  12.     /**
  13.      * @author Romuald Quantin
  14.      */
  15.     public class ImageWhenNotLoadedMediator extends Mediator implements IMediator {
  16.  
  17.         [Inject]
  18.         public var view:ImageWhenNotLoaded;
  19.        
  20.         // here we get the loader of an asset for monitoring purpose
  21.         // this one is an ImageLoader but we keep the interface as a type
  22.         [Inject(name="image1")]
  23.         public var imageLoader:ILoader;
  24.        
  25.         // add some listeners to monitor the loading of a single loader
  26.         override public function initialize():void {
  27.             imageLoader.addEventListener(AssetLoaderErrorEvent.ERROR, errorHandler);
  28.             imageLoader.addEventListener(AssetLoaderEvent.START, startHandler);
  29.             imageLoader.addEventListener(AssetLoaderProgressEvent.PROGRESS, progressHandler);
  30.             imageLoader.addEventListener(AssetLoaderEvent.COMPLETE, completeHandler);
  31.         }
  32.  
  33.         private function errorHandler(event:AssetLoaderErrorEvent):void {
  34.             trace("Error", event.errorType, event.message);
  35.         }
  36.  
  37.         private function startHandler(event:AssetLoaderEvent):void {
  38.             trace("Loading started (" + ILoader(event.currentTarget).id + ")");
  39.         }
  40.  
  41.         private function progressHandler(event:AssetLoaderProgressEvent):void {
  42.             trace("Loading progress (" + ILoader(event.currentTarget).id + ") progress:", event.progress, ", speed:", event.speed);
  43.         }
  44.        
  45.         // the loader is complete, the asset is ready
  46.         private function completeHandler(event:AssetLoaderEvent):void {
  47.             trace("Loading completed (" + ILoader(event.currentTarget).id + ")");
  48.             var image:Bitmap = event.data;
  49.             image.scaleX = image.scaleY = 0.1;
  50.             view.addChild(image);
  51.         }
  52.        
  53.         override public function dispose():void {
  54.             while (view.numChildren> 0) view.removeChildAt(0);
  55.             view = null;
  56.             imageLoader = null;
  57.         }
  58.        
  59.     }
  60. }

The ImageGroupMediator mediator does the same job as the mediator above but applied to an IAssetLoader (loader containing others loaders). The way to monitor the loading process is exactly the same. I also show different ways to retrieve the assets of this group, once the groupe has been loaded. You will notice the special injection name of the loader, it is a path generated from the XML config using the group and assets ids and a delimiter.

Actionscript:
  1. package com.soma.plugins.assets.demo.views {
  2.  
  3.     import flash.display.Bitmap;
  4.     import com.soma.plugins.assets.SomaAssets;
  5.     import com.soma.core.interfaces.IMediator;
  6.     import com.soma.core.mediator.Mediator;
  7.     import org.assetloader.core.IAssetLoader;
  8.     import org.assetloader.core.ILoader;
  9.     import org.assetloader.events.AssetLoaderErrorEvent;
  10.     import org.assetloader.events.AssetLoaderEvent;
  11.     import org.assetloader.events.AssetLoaderProgressEvent;
  12.     import flash.utils.Dictionary;
  13.  
  14.     /**
  15.      * @author Romuald Quantin
  16.      */
  17.     public class ImageGroupMediator extends Mediator implements IMediator {
  18.  
  19.         [Inject]
  20.         public var view:ImageGroup;
  21.        
  22.         // here we get the plugin
  23.         [Inject(name="assets")]
  24.         public var assets:SomaAssets;
  25.  
  26.         // here we get a group using a path (ids + delimiter)
  27.         [Inject(name="group0/group00")]
  28.         public var imageGroup:IAssetLoader;
  29.        
  30.         // add some listeners to monitor the loading of a single group
  31.         override public function initialize():void {
  32.             imageGroup.addEventListener(AssetLoaderErrorEvent.ERROR, errorHandler);
  33.             imageGroup.addEventListener(AssetLoaderEvent.START, startHandler);
  34.             imageGroup.addEventListener(AssetLoaderProgressEvent.PROGRESS, progressHandler);
  35.             imageGroup.addEventListener(AssetLoaderEvent.COMPLETE, completeHandler);
  36.         }
  37.  
  38.         private function errorHandler(event:AssetLoaderErrorEvent):void {
  39.             trace("Error", event.errorType, event.message);
  40.         }
  41.  
  42.         private function startHandler(event:AssetLoaderEvent):void {
  43.             trace("Loading started (" + ILoader(event.currentTarget).id + ")");
  44.         }
  45.  
  46.         private function progressHandler(event:AssetLoaderProgressEvent):void {
  47.             trace("Loading progress (" + ILoader(event.currentTarget).id + ") progress:", event.progress, ", speed:", event.speed);
  48.         }
  49.  
  50.         // now the group is loaded, get the 2 images from the group
  51.         private function completeHandler(event:AssetLoaderEvent):void {
  52.             trace("Loading completed (" + ILoader(event.currentTarget).id + ")");
  53.             var images:Dictionary = event.data;
  54.             trace("asset from dictionary", images["image3"]);
  55.             trace("asset from loader:", imageGroup.getAsset("image3"));
  56.             trace("asset from plugin:", assets.getAssets("group0/group00/image3"));
  57.             var image2:Bitmap = images["image2"];
  58.             var image3:Bitmap = images["image3"];
  59.             image2.x = 290;
  60.             image2.scaleX = image2.scaleY = 0.1;
  61.             image3.x = 340;
  62.             image3.scaleX = image3.scaleY = 0.1;
  63.             view.addChild(image2);
  64.             view.addChild(image3);
  65.         }
  66.        
  67.         override public function dispose():void {
  68.             while (view.numChildren> 0) view.removeChildAt(0);
  69.             view = null;
  70.             imageGroup = null;
  71.         }
  72.        
  73.     }
  74. }

The ExampleAssetCommand command is just a demo to show that you can use the SomaAssetsEvent class to directly create commands from it. In this example I used the type SomaAssetsEvent.ASSET_LOADED. The command will get created every time an asset is loaded.

Actionscript:
  1. package com.soma.plugins.assets.demo.commands {
  2.  
  3.     import com.soma.core.controller.Command;
  4.     import com.soma.core.interfaces.ICommand;
  5.     import com.soma.plugins.assets.SomaAssets;
  6.     import com.soma.plugins.assets.demo.SomaApplication;
  7.     import com.soma.plugins.assets.events.SomaAssetsEvent;
  8.  
  9.     import flash.display.DisplayObjectContainer;
  10.     import flash.events.Event;
  11.     import flash.media.Sound;
  12.     import flash.media.Video;
  13.     import flash.net.NetStream;
  14.     import flash.text.TextField;
  15.     import flash.utils.getQualifiedClassName;
  16.  
  17.     /**
  18.      * @author Romuald Quantin
  19.      */
  20.     public class ExampleAssetCommand extends Command implements ICommand {
  21.        
  22.         [Inject]
  23.         public var evt:SomaAssetsEvent;
  24.        
  25.         [Inject(name="assets")]
  26.         public var assets:SomaAssets;
  27.        
  28.         // just some examples
  29.         public function execute(event:Event):void {
  30.             var container:DisplayObjectContainer = SomaApplication(instance).container;
  31.             trace("Command Example (" + evt.path + ")> " + assets.getLoader(evt.path).type + " Loaded: " +  getQualifiedClassName(evt.asset));
  32.             // you can use a switch to find the assets:
  33.             switch (evt.path) {
  34.                 case "group0/group01/css":
  35.                     break;
  36.                 case "group0/group01/json":
  37.                     break;
  38.                 case "group0/group01/sound":
  39.                     var sound:Sound = evt.asset;
  40.                     sound.play(0);
  41.                     break;
  42.                 case "group0/group01/text":
  43.                     var textfield:TextField = new TextField();
  44.                     textfield.multiline = textfield.wordWrap = true;
  45.                     textfield.text = evt.asset;
  46.                     container.addChild(textfield);
  47.                     break;
  48.                 case "group0/group01/xml":
  49.                     break;
  50.                 case "group0/group01/video":
  51.                     var video:Video = new Video();
  52.                     var stream:NetStream = evt.asset;
  53.                     container.addChild(video);
  54.                     video.y = 80;
  55.                     video.smoothing = true;
  56.                     video.attachNetStream(stream);
  57.                     stream.resume();
  58.                     break;
  59.                 case "group0/group01/zip":
  60.                     break;
  61.             }
  62.         }
  63.        
  64.     }
  65. }

This implementation is just an example as it could be handled in very different ways, but that should get you started.

Vote in HexoSearch

Comments No Comments »

Two new releases today, an asset loader and the SomaCore plugin: SomaAssets.

The AssetLoader library is a port from Matan's AssetLoader library to be event-based, it makes you able to load and manage multiple assets (image, video, xml, sound, etc) in your application.

SomaAssets is a plugin based on the AssetLoader library to easily access to your assets and effectively integrate them in your SomaCore application with paths and automatic mapping name generation for injection.

Special thanks to Matan for his help with the AssetLoader and his joy in general, a pleasure to "meet" him.

You can read the SomaAssets wiki section to get started with it, but I'll post below a few hints of what you can easily do with it within a SomaCore application.

AssetLoader source
AssetLoader wiki
SomaAssets source
SomaAssets wiki

Easily create the plugin and add a XML config file for the assets.

Actionscript:
  1. createPlugin(SomaAssets, new SomaAssetsVO(this, "xml/assets_config.xml"))

Easily retrieve the assets with paths through the XML config.

Actionscript:
  1. var image:Bitmap = assets.getAssets("group0/group00/img0");

Easily retrieve the plugin, main loader, config and assets with injection in a SomaCore application. The following mapping names have been automatically generated from the XML config.

Actionscript:
  1. [Inject(name="assets")]
  2. public var plugin:SomaAssets;
  3.  
  4. [Inject(name="assets")]
  5. public var loader:IAssetLoader;
  6.  
  7. [Inject(name="group0/group00/img0")]
  8. public var loaderType1:ImageLoader;
  9.  
  10. [Inject(name="group0/group00/img0")]
  11. public var assetType1:Bitmap;

Vote in HexoSearch

Comments 3 Comments »

I've added some more information on the SomaCore wiki.

You can find some code and explanation how to use, create and remove Wires within the framework, using injection or not. I also explained how to monitor and control the application flow with methods you are used to, such as dispatchEvent, addEventListener, preventDefault and so on.

You can also find explanation to handle the views in the framework.

Last addition is a diagram showing the commands flow from other framework elements, I've added it to the previous SomaCore diagram.

SomaCore Diagram


Next step in the wiki are about commands and 2 others diagrams related to them.

Hope that will help to get you started.

Vote in HexoSearch

Comments No Comments »

I'll be writing in the next days a series of wiki, manual, best practices with tons of code example. It should help you to get started. I will be explaining in-depth how SomaCore works and what you can do with it.

The first one is about the Framework Instance. The different ways to create a SomaCore application, what is required, how to enable dependency injection and how to access to this instance.

Vote in HexoSearch

Comments 2 Comments »

SomaCore is a lightweight AS3 MVC event-based framework that provides a very flexible structure for your Flash, Flex and AIR projects.

The main addition in this version 2 is Dependency Injection, but it is up to you how you want to use SomaCore because injection is optional.

Information

SomaCore Main Page (tutorials, demos, source)
Repository SomaCore (github)
Repository Demos (github)
Repository Plugins (github)
Documentation

Don't want to read, just show me some code!

SomaCore Hello World
SomaCore CafeTownSend (Flex)
Twitter Search demo (pure as3)

SomaCore is both a registry and dependency injection framework

As a base, SomaCore is a registry framework, much like PureMVC. The framework makes you able to add and remove elements to the framework instance to be able to access them from anywhere (such as addView, getView, addWire, getWire, addModel, getModel, addCommand, and so on).

Enable injection

You are now able to use dependency injection. It can be enabled by sending an ISomaInjector class to the constructor of the Soma class:

Actionscript:
  1. public class SomaApplication extends Soma implements ISoma {
  2.     public function SomaApplication(stage:Stage) {
  3.         super(stage, SomaInjector);
  4.     }
  5. }

The injector is accessible from framework instances, wires and commands using the property injector.

Here is a quick example:

Actionscript:
  1. injector.mapToInstance(MyModel, new MyModel());
  2. injector.mapSingleton(MyWire);
  3. injector.getInstance(MyWire);

Actionscript:
  1. package  {
  2.     import com.soma.core.wire.Wire;
  3.     import com.soma.core.interfaces.IWire;
  4.    
  5.     public class MyWire extends Wire implements IWire {
  6.  
  7.         [Inject]
  8.         public var model:MyModel;
  9.        
  10.         override public function initialize():void {
  11.             // called when the wire has been registered to the framework
  12.             trace(model, " is injected");
  13.         }
  14.        
  15.         override public function dispose():void {
  16.             // called when the wire has been removed from the framework
  17.         }
  18.        
  19.     }
  20. }

Inspirations

Before going further, I have to give some credits.

When I first tried Robotlegs, one part strikes me as it was solving a problem I had for a while: The mediator system: being able to build your application and add mediators regardless of any kind of structure and very easily. This workflow was so nice that it made me rethink a lot of things.

SomaCore has some capabilities that made me build the framework and I wasn't ready to give them up. But I felt that this mediator workflow in SomaCore would just be amazing and a great addition.

I built these tools and frameworks to make my developer life easier, I then share them to other developers. If my work makes them enjoy their coding, that's good enough for me.

So before asking myself too many questions, I reproduced the mediator system in SomaCore. It is now very similar to Robotlegs but it can also be used without enabling injection. That is the first part of the credits: a big one to Robotlegs that has been an amazing inspiration to SomaCore, as big as PureMVC has been for the version 1.

The second credit would go to the library SwiftSuspenders, the same one that Robolegs is using to handle its dependency injection. It is very lightweight and has good performance.

Mediators

Here is how it works, you can map a view to another class (the mediator), and every time this "mapped view" will be added to a display list, the mediator class will be instantiated with a reference to this view. The mediator class will also be destroyed when the view is removed from the display list. Everything is automatic and handled by the framework.

In SomaCore the Mediator class is extending the Wire class which gives access to everything in the framework.

Mapping a view (example in a wire):

Actionscript:
  1. mediator.mapView(MySprite, MySpriteMediator);

The mediator get instantiated when the view is added to the display list

Actionscript:
  1. addChild(new MySprite());

Mediator example:

Actionscript:
  1. package {
  2.     import com.soma.core.interfaces.IMediator;
  3.     import com.soma.core.mediator.Mediator;
  4.     public class MySpriteMediator extends Mediator implements IMediator {
  5.        
  6.         [Inject]
  7.         public var view:MySprite;
  8.        
  9.         override public function initialize():void {
  10.             // called when the mediator has been created and registered to the framework
  11.             trace(view == viewComponent);
  12.         }
  13.        
  14.         override public function dispose():void {
  15.             // called when the mediator has been destroyed by the framework
  16.         }
  17.        
  18.     }
  19. }

From version 1 to version 2

Only minor changes:

1. initialize and dispose methods in wires and models are now public.

Actionscript:
  1. package  {
  2.     import com.soma.core.interfaces.IModel;
  3.     import com.soma.core.model.Model;
  4.     public class ModelExample extends Model implements IModel {
  5.         override public function initialize():void {
  6.             // called when the model has been registered to the framework
  7.         }
  8.         override public function dispose():void {
  9.             // called when the model has been removed from the framework
  10.         }
  11.     }
  12. }

2. the framework instance property has changed from soma to instance.

Actionscript:
  1. package  {
  2.     import com.soma.core.wire.Wire;
  3.     import com.soma.core.interfaces.IWire;
  4.     public class WireExample extends Wire implements IWire {
  5.         override protected function initialize():void {
  6.             // called when the wire has been registered to the framework
  7.             trace("my framework instance:", instance)
  8.         }
  9.         override protected function dispose():void {
  10.             // called when the wire has been removed from the framework
  11.         }
  12.     }
  13. }

3. a public setup method is available in your framework instance.

Actionscript:
  1. var app:ISoma = new Soma();
  2. app.setup(stage, SomaInjector);

4. an initialize and start protected methods have been added in the Soma instance.

Actionscript:
  1. package  {
  2.     import com.soma.core.Soma;
  3.     import com.soma.core.interfaces.ISoma;
  4.     import com.soma.core.di.SomaInjector;
  5.     import flash.display.Stage;
  6.     public class SomaApplication extends Soma implements ISoma {
  7.         public function SomaApplication(stage:Stage) {
  8.             super(stage, SomaInjector);
  9.         }
  10.         override protected function initialize():void {
  11.            
  12.         }
  13.         override protected function registerCommands():void {
  14.            
  15.         }
  16.         override protected function registerModels():void {
  17.            
  18.         }
  19.         override protected function registerViews():void {
  20.            
  21.         }
  22.         override protected function registerWires():void {
  23.            
  24.         }
  25.         override protected function registerPlugins():void {
  26.            
  27.         }
  28.         override protected function start():void {
  29.            
  30.         }
  31.     }
  32. }

SomaCore features

Here are some features that might makes you enjoy the framework.

Stage as single event dispatcher

SomaCore is using a single event dispatcher: the stage, and a system of event interception to handles its commands system. As the commands in SomaCore are normal built-in events with the property bubbles set to true, this makes you able to dispatch commands straight from a view removing potential layers (like mediators) to handles communications from the views to the framework.

This also makes you able to communicate between different modules (or swf files) as they all share the same stage.

Seamless commands and events integration

The commands in SomaCore are normal built-in events and the framework has a seamless integration with the flash event system. Seamless meaning that the built-in syntax is in use: dispatchEvent, addEventListener, and so on.

Register a command:

Actionscript:
  1. addCommand(MyEvent.DO_SOMETHING, MyCommand);

Dispatch a command from a framework elements (wires, commands, models, etc) or views:

Actionscript:
  1. dispatchEvent(new MyEvent(MyEvent.DO_SOMETHING));

Monitoring commands from wires, mediators, or models:

Actionscript:
  1. addEventListener(MyEvent.DO_SOMETHING, myEventHandler);

Commands monitoring

This capability is probably one of the most important to me. SomaCore makes you able to listen to commands from any wires and mediators, but also makes you able to stop the execution of any command (if the event is set as cancelable) using event.preventDefault().

Actionscript:
  1. package  {
  2.     import com.soma.core.wire.Wire;
  3.     import com.soma.core.interfaces.IWire;
  4.     public class WireExample extends Wire implements IWire {
  5.         override public function initialize():void {
  6.             // called when the wire has been registered to the framework
  7.             addEventListener(MyEvent.DO_SOMETHING, myEventHandler);
  8.         }
  9.         private function myEventHandler(event:MyEvent):void {
  10.             // the command MyEvent.DO_SOMETHING has been dispatched
  11.             // I can monitor it here (possible from any wires and mediators)
  12.             // for some reasons, I decide to stop the execution of this command:
  13.             event.preventDefault();
  14.         }
  15.         override public function dispose():void {
  16.             // called when the wire has been removed from the framework
  17.             removeEventListener(MyEvent.DO_SOMETHING, myEventHandler);
  18.         }
  19.     }
  20. }

Easy way to map a mediator to a view

This is the workflow I reproduced from Robotlegs. It allows you to build you application, let's say... complicated layouts, structure, tons of views, and so on. But at any point, if the framework needs to talk to a specific view, you can easily map a mediator to this view:

Actionscript:
  1. mediator.mapView(MyView, MyViewMediator);

For the other way around: a view needs to talk to the framework, mediators are not necessarily needed as you can dispatch commands straight from views in SomaCore. The commands are just normal events. The only requirement is that the view needs to be on the stage (added to a display list, after a ADDED_TO_STAGE event) in order for the stage to get the command.

Flexibility (injection, not injection, or both)

As the injection is optional in the framework, you are free to code the way you like, in the registry way like PureMVC way or in the injection way like Robotlegs, or even using both ways in the same time.

For some reasons, you might want to avoid injection, describeType, getElementByName, not comfortable yet with the concept, portability, optimal performance for games, etc. This is still possible with SomaCore.

Here are the built-in registry methods without injection:

Actionscript:
  1. addWire(MyWire.NAME, new MyWire());
  2. getWire(MyWire.NAME);
  3. addModel(MyModel.NAME, new MyModel());
  4. getModel(MyModel.NAME);
  5. addView(MY_SPRITE_NAME, new Sprite());
  6. getView(MY_SPRITE_NAME);

With injection, you might do something like:

Actionscript:
  1. injector.mapSingleton(MyModel);
  2. injector.createInstance(MyWire);

Actionscript:
  1. // MyWire injectee class
  2. [Inject]
  3. public var model:MyModel;

You can also use both:

Actionscript:
  1. var wire:MyWire = new MyWire();
  2. injector.mapToInstance(MyWire, wire);
  3. addWire(MyWire.NAME, wire);

Making you able to get the wire back this 2 ways:

Actionscript:
  1. [Inject]
  2. public var wire:MyWire;

Actionscript:
  1. getWire(MyWire.NAME)

Plugins system

An easy way to add plugins to the framework, the SomaDebugger is the first one but I have plans to write others.

Debugger

The SomaDebugger especially built to work with SomaCore (even if it can be used without).

Actionscript:
  1. protected function registerPlugins():void {
  2.     createPlugin(SomaDebugger, new SomaDebuggerVO(this, SomaDebugger.NAME_DEFAULT, getCommands(), true, false));
  3. }

Lightweight

SomaCore is lightweight, here are the size compiled of the framework:

9.46 KB (9 693 bytes) - injector not enabled
14.83 KB (15 185 bytes) - injector enabled

Next steps

I'll make new documents for code examples, best practices, and so on to help you get started.
Maybe a javascript version as a developer has made an amazing port of SomaCore.

If you're looking for more information about the dependency injection part before I write documents, check the README file from the injection library: SwiftSuspenders.

Try SomaCore out, it is really easy to get started with. You'll feel at home very quickly with its flexibility and well integrated command system with built-in events.

Vote in HexoSearch

Comments 4 Comments »