Kiwi – Testing with style for iOS

Posted in iOS on November 11th, 2012 by Mattes – 1 Comment

I’m very passionate about writing tests to ensure code quality and achieve better software design. When I started iOS development one of the first things I did was evaluating testing frameworks for iOS.

How it started out…

It didn’t take long to setup GHUnitOCMock and OCHamcrest. This combination allows unit testing, mocking and provides a better assertion syntax. I was very excited and tweeted about it. On this tweet I got a very interesting reply from my friend Maxim:

This made me curios. I started using Kiwi for my recent iOS project and fell more and more in love with it.

Presentation

In the following video I give a brief introduction to Kiwi and what makes it so special. It was captured during one of your 5-Minutes-of-Fame talks at Wooga.

Links

Flash Timeline Actions

Posted in ActionScript on January 29th, 2012 by Mattes – 2 Comments

Introduction

A proper designer-developer workflow is essential, especially in bigger teams. By separating logic and view (e.g. via MVC Design Pattern) we try to avoid dependencies between artists and programmers. Less coupling increases the speed of development and design.

Sometimes it is hard to avoid this coupling, especially if it comes to optimization. Let’s imagine an artist who wants to have sound within his timeline animation. He could just embed the sound and put it in the appropriate timeline frame. But if he then wants to use the same sound in another FLA it gets complicated. We don’t want the same sound to be loaded twice.

This post describes a pattern for triggering more sophisticated logic from the Flash timeline so artists can easily make use of it. For easier understanding I will stick to the sound example. But keep in mind that this pattern can be applied to other problems as well. I will give an example at the end of this post.

Please also note that this post focuses on timeline related actions. If you want to trigger sounds based on mouse clicks or just playing background sounds, you are perfectly fine doing this purely by code.

Alternative Approaches

Before discussing the actual solution in detail, I would like to briefly mention two alternatives and their particular drawbacks.

I already mentioned one solution: Embedding sounds within their respective FLA files. But using the same sound in other FLAs would cause it to be loaded multiple times. The browser can’t cache them either because they are embedded in different SWF files.

Another solution would be to trigger sounds programmatically by using frame labels. This means that your code would have to observe the timeline for execution of certain labels. You have to use some kind of configuration that tells the code which sound to play on which MovieClip and label. Parsing every MovieClip wouldn’t be a good idea in terms of performance.

Both alternatives have a drawback either for artists or programmers. Wouldn’t it be cool if we could trigger our logic from the timeline instead of heaving the logic observing it? Thats where ‘Timeline Actions’ enter the stage.

Timeline Actions

This illustration shows the relevant parts that I’ll explain in the following sections.

The basic concept

In the above image you can see two example asset files (red) which will be maintained by the artists. The sound logic (blue) is a separate SWF or part of the application maintained by the programmers. It’s responsible for loading, caching and playing the sounds. The goal is, that artists can trigger any sound by putting the following frame script into the timeline:

1
playSound("mySound");

Note: Because the playSound() is a top-level function it requires no import statement.

The sound logic should receive the string "mySound" and select the appropriate MP3 for playback. But how do you communicate from the assets (red) to the sound logic (blue)? It’s not a good idea to compile the sound logic into each asset. Thats why the first step is, to put just the communication logic into a very small library called “timeline-sound.swc” (green).

This library contains the playSound() function as well as a static SoundDelegate class. The SoundDelegate is the connection between playSound() and sound logic. The next section “Technical implementation” will give you more insight into the SWC contents.

Advanced ActionScript 3.0 Settings

You can reference the timeline-sound.swc in each FLA now. Therefore open your FLA and navigate to File -> ActionScript Settings… Here go to the second tab “Library path” and select the “Browse to SWC file” button (1). After choosing the timeline-sound.swc it shows up in the panel underneath (2). Now you can use the playSound() function as frame script without getting a compiler error. At the same time your sound logic keeps separate.

Technical implementation

This section will explain how top-level function, delegate and sound logic get wired together. Therefore lets see what the contents of the timeline-sound.swc are. You can browse and download the source code from GitHub or just read on.

Contents of 'timeline-sound.swc'

The SoundDelegate contains only static methods. Therefore it can be reached from anywhere in the application (including the top-level function playSound()). It’s implementation is rather simple. It basically just holds a reference to another instance that it delegates to (line 18). Again, for encapsulation reasons this is implemented as an interface ISoundAdapter (line 3).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SoundDelegate
{
    private static var adapter:ISoundAdapter;

    public static function init(adapter:ISoundAdapter = null):void
    {
        SoundDelegate.adapter = (adapter != null) ?
                adapter : new NullSoundAdapter();
    }

    public static function get initialized():Boolean
    {
        return adapter != null;
    }

    public static function playSound(key:String):void
    {
        adapter.playSound(key);
    }
}

You can also see an init() function (line 5) which is used to set the proper ISoundAdapter implementation. The ISoundAdapter defines just one method:

1
2
3
4
public interface ISoundAdapter
{
    function playSound(key:String):void;
}

In line 8 of the SoundDelegate listing you will also notice that a NullSoundAdapter is assigned in case no instance gets passed to this method. This null-implementation silently ignores every call to playSound(). And this is how the playSound() top-level function looks like:

1
2
3
4
5
6
7
public function playSound(title:String):void
{
    if (!SoundDelegate.initialized)
        SoundDelegate.init();

    SoundDelegate.playSound(title);
}

The function makes sure that the SoundDelegate class gets initialized. Because it will create the NullSoundAdapter by default, it is not very useful yet. Thats where the actual sound logic comes in. Whenever the logic is ready it calls the SoundDelegate and registers itself as SoundAdapter (line 5):

1
2
3
4
5
6
7
8
9
10
11
12
13
public class SoundLogic implements ISoundAdapter
{
    public function SoundLogic()
    {
        // Do this after sounds are loaded
        SoundDelegate.init(this);
    }

    public function playSound(key:String):void
    {
        // play the sound for 'key'
    }
}

The SoundLogic class implements the ISoundAdapter interface. Now whenever someone calls playSound("foo") the method SoundLogic.playSound() will be called with the string “foo“. Here you can now put all the logic that is necessary to play the sound for string “foo“.

Adding new sounds

Well you could now argue that, with this solution, adding new sounds still requires programmatic effort. In Magic Land (the game I worked on at wooga) we also found a proper solution for this. Before I can explain it you have to know that in our game the sound logic is encapsulated within a module (SWF). This module is loaded lazy because it is less important than other parts of the game. A user can already play our game while the sounds are still loading.

The idea is to embed all sounds that could be triggered from the timeline in a single FLA, so the artists can maintain it. Sounds have to be exported for ActionScript, where the linkage name matches the string that will be later used for the playSound() method parameter. In order to make the sounds available to the sound logic we chose to compile them into the sound module itself. This way we get good compression and have no additional loading effort. Note however that this approach wouldn’t make sense for large sound files.

sounds.fla

The question is now, how do we get new sounds automatically compiled into the sound module? What we did, we created a Sprite that contains all sounds. The FLA file then gets compiled into a SWC library and is part of the sound module classpath. To enforce the inclusion of the sound definitions the exported SoundInclusionContainer class is once referenced in the module:

1
2
3
4
5
// Sound module constructor
public function SoundModule()
{
    SoundInclusionContainer; // sound embedding
}

This way, whenever the sound module gets compiled, all linked sounds within the container will be made available for the playSound() method call. Now the complete flow of adding and using timeline sounds is independent of the programmers while providing an optimized sound loading experience.

Summary

This post showed how artists can easily link timeline animations to a more complex logic. As this post is more about the general idea I didn’t explain how the sound logic itself looks like.

I found another use cases for this pattern in our game Magic Land. We use it for displaying visual effects. Similar to sounds they are part of a separate module that is lazy loaded. On low performance computers we could disable the effects completely.

Finally, lets have a look on the pros and cons of this pattern.

Disadvantages

The artists won’t be able to hear the sound wile testing their sole assets. They have to start the game including the sound logic in order to hear something. In Magic Land the artists are able to build the game locally on their computer (probably a topic for another blog post). So they can hear how it feels in the actual game.

Another drawback is that each asset FLA that makes use of the timeline actions has to link the timeline-sound.swc, which adds 2 Kb. A solution would be to exclude the library for compiling and enforce it to compile in the main application. But then running the asset SWF outside the final application/game throws errors and timeline animations won’t be visible anymore.

Advantages

On the positive side programmers get less distracted by sound issues because artists can do everything on their own. They are free to add the playSound() call in any asset file, as long as they link the timeline-sound.swc into the FLA file.

At the same time the sounds itself can be loaded after more important stuff has been done loading. This leads to a much better user experience. Also imagine a user turned off sounds. Now you can just not load the sounds at all and the playSound() call will be silently ignored (null-implementation of ISoundAdapter).

Sources

You can find all source files for the timeline-sound library in this GitHub repository. If you have any questions feel free to comment below. Enjoy!

Context-aware Tasks

Posted in ActionScript on March 13th, 2011 by Mattes – 9 Comments

This article shows an useful way how to combine the Spicelib Task Framework with Parsley. This way you can access everything from the context during the execution of a Task:

“The Task Framework is a general abstraction for asynchronous operations. It allows nesting / grouping of Tasks in TaskGroup instances for concurrent or sequential execution” [source: Parsley Documentation]

One way to access the Context from within a Task would be to define it during the Parsley Configuration (Context). But this would mean, that the Task will not be removed until the context gets destroyed. Because a Task is only active during a limited time, this doesn’t make much sense.

Another approach would be, not to define the Task in the Context but passing in all the necessary dependencies within the constructor. Depending on the amount of required dependencies, the constructor can become quite big. Also Parsley features like Messaging are not directly supported anymore.

Solution

That’s why this solution utilizes the Dynamic Object feature of Parsley. It allows to add any instance to the Context during runtime and also removing it again, if not required anymore. For a Task this means that it needs to be added before the start() is called, and removed after the complete() has been triggered.

This adding/removing happens through the Context interface of Parsley. It should happen automatically in the Task to reduce the amount of code to write. In order to not have to pass the Context to each Task it could just be set once in the parent TaskGroup. The child Task then accesses it via the parent getter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SequentialContextTaskGroup extends
    SequentialTaskGroup implements IContextProvider
{
    private var _context:Context;

    public function SequentialContextTaskGroup(context:Context,
        name:String = null)
    {
        _context = context;
       
        super(name);
    }

    public function get context():Context
    {
        return _context;
    }
}

And this is how the IContextProvider interface looks like:

1
2
3
4
public interface IContextProvider
{
    function get context():Context;
}

The following AbstractContextTask is then responsible for adding itself to the Context as soon as it is started. It also removes itself as soon as the complete(), cancel() or skip() has been called. Furthermore it provides a doStartContext() method (read more in the next paragraph).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class AbstractContextTask extends Task
{
    private var _dynamicObject:DynamicObject;
   
    protected override function doStart():void
    {
        _dynamicObject = IContextProvider(parent)
            .context.addDynamicObject(this);

        doStartContext();
        super.doStart();
    }

    protected function doStartContext():void
    {
        /* base implementation does nothing */
    }

    protected override function doCancel():void
    {
        cleanContext();
        super.doCancel();
    }

    protected override function doSkip():void
    {
        cleanContext();
        super.doSkip();
    }

    protected override function complete():Boolean
    {
        cleanContext();
        return super.complete();
    }

    private function cleanContext():void
    {
        _dynamicObject.remove();
    }
}

The following class is a concrete implementation of AbstractContextTask. That’s why it gets the HintComponent injected (line 4). Please also note that this Task overrides the method doStartContext() (line 13). This way we ensure that the class already has been added to the Context.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ShowHintTask extends AbstractContextTask
{
    [Inject]
    public var hint:HintComponent;
   
    private var type:HintType;

    public function ShowHintTask(type:HintType)
    {
        this.type = type;
    }
       
    protected override function doStartContext():void
    {
        hint.showHint(type);
       
        complete();
    }
}

The following code shows how everything can be glued together. Note, that you don’t have to pass the Context to each task.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TaskController
{
    [Inject]
    public var context:Context;
   
    [Init]
    public function initialize():void
    {
        var taskGroup:SequentialContextTaskGroup
            = new SequentialContextTaskGroup(context);

        taskGroup.addTask(new ShowHintTask(HintType.ATTENTION));
        taskGroup.addTask(new PointToTask(new Point(3, 5)));
        // add more tasks here...

        taskGroup.start();
    }
}

Summary

This approach of Context-aware Tasks ensures that you don’t have a lot of Tasks at the same time in the Context. The adding and removing from the Context happens in an encapsulated class. The Task itself can directly access injected objects during execution time.

Links

Label validation with FlexUnit

Posted in ActionScript on January 18th, 2011 by Mattes – 2 Comments

While working in interdisciplinary teams where graphics are produced by artists and the code comes from the developers, a solid designer-developer work-flow is crucial. At my current project team at wooga we already established a very good work-flow. The artists can produce graphics and see them in the running application after committing them. Therefore we use SVN and the Hudson integration server.

The problem

In our project we use SWC asset libraries to have a compile time check and strong typed access to all our graphics. To add logic to MovieClip frames you could either put the code directly on the timeline or the artist defines labels which are then utilized from the code. In order to keep the view separated from the code you should always use the label approach. But this is also risky if the artist accidentally deletes or renames a label. The code would then behave unexpectedly without knowing it. The only way to see the problem is to start the application and test all the MovieClip logic.

The first approach

To protect the labels from unintended changes, our first approach was to check their existence wherever we used them in code. This means we had to provide a separate Vector that contained all the expected labels.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private static var labels:Vector.<String> = new Vector.<String>();
private var view:IconView;

public function IconMediator(view:IconView):void
{
    initializeLabels();
    assertLabelsExist(view);
}

private function initializeLabels():void
{
    if (labels.length == 0)
        labels.push(IconState.ON, IconState.OFF);
}

private function assertLabelsExist(view:ButtonRounded):void
{
    var requiredMatchesRemaining:int = labels.length;
   
    for each (var requiredLabel:String in labels)
    {
        for each (var label:FrameLabel in view.currentLabels)
        {
            if (requiredLabel == label.name)
                requiredMatchesRemaining--;
        }
    }
   
    if (requiredMatchesRemaining != 0)
        throw new IllegalArgumentError(
            'IconView requires all labels: ' + labels);
}

Beside this we defined the labels itself in an enumeration class to provide strong typed access.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class IconState
{
    public static const ON:IconState = new IconState("on");
    public static const OFF:IconState = new IconState("off");
   
    private var type:String;

    public function IconState(type:String)
    {
        this.type = type;
    }

    public function toString():String
    {
        return type;
    }
}

This approach leads to three main problems:

  1. Depending on when the validation is executed in code, it could still happen that you don’t see the problems immediately
  2. We create a lot of code that is only necessary for validation but not for the application itself
  3. We create redundancy because we have to maintain the Vector of expected labels and the enumeration class (IconState). When changing labels it is very likely that you forget to update the Vector.

The solution

Thats why we came up with a different approach. We moved the validation into the unit tests. Now the code is separated but still executed because of our integration server (Hudson with FlexUnit support). The normal application code is now much slimmer and better readable. The artists/developers are automatically notified by mail if their changes break the tests.

To solve point 3 I wrote an assertion method that can reflect on enumeration classes and check all the defined labels on a certain MovieClip.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public function assertLabelEnum(target:MovieClip,
    enumClass:Class):void
{
    var classInfo:ClassInfo = ClassInfo.forClass(enumClass);
    var properties:Array = classInfo.getStaticProperties();
    var expectedLabel : String;
    var type:*;
    var labelCounter:int = 0;
       
    for each (var property : Property in properties)
    {
        type = property.getValue(enumClass);
               
        if (type is String)
            expectedLabel = String(type);
        else if (type is enumClass)
            type["toString"]();
        else
            continue;
           
        labelCounter++;
        expectedLabel = type["toString"]();
           
        assertLabel(expectedLabel, target);
    }
       
    assertEquals("Amount of expected labels differs from the
        amount of existing labels"
, labelCounter,
        target.currentLabels.length);
}

This method internally calls another assertion method assertLabel(). This method can also be used independently for testing specific labels without using enumeration classes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function assertLabel(target:MovieClip,
    expectedLabel:String):void
{
    var found:Boolean = false;

    for each (var label:FrameLabel in target.currentLabels)
    {
        if (expectedLabel == label.name)
        {
            found = true;
            break;
        }
    }

    if (!found)
        fail("Expected label [" + expectedLabel + "] not
            found in "
+ target);
}

Note: I used the reflection library from spicelib to retrieve all the static members of the enumeration class. You can download the library here.

And this is how the test method would look like:

1
2
3
4
5
[Test]
public function test_icon_frame_labels():void
{
    assertLabelEnum(new IconView(), IconState);
}

Summary

We made very good experiences with this approach because unintended changes on the labels no longer lead to awkward behavior in the application itself. And of course the application code can focus on the main logic and is therefor better readable.

Strong typed constants

Posted in ActionScript on January 2nd, 2011 by Mattes – 7 Comments

Constants are commonly occurring in the ActionScript core classes. Typical examples are events (Event.COMPLETE) or general configurations (StageAlign.TOP_LEFT). These constants are typically of type String and grouped in one class.

If you want to set the align property of the Stage for example you have to know where to look up the different possible constants. This can be done by looking up the documentation or by guessing the potential class name (StageAlign). IDEs like FDT provide support for these constants by suggesting them in the auto completion.

However, the programmer is never enforced to use the existing constants and can assign any other string. This is error prone because the string is eventually misspelled. It is also annoying if you have to look up the documentation because your IDE doesn’t suggest them. If you use your own constants in an application or library then you are completely on your own.

Other programming languages like Java provide a special syntax for this problem: enum

1
public enum Direction {LEFT, RIGHT}

This enumerations can then be used strong typed in code. For example a function can define this as type in the signature. Assigning something else than one of the predefined constants (LEFT or RIGHT) would cause a compiler error:

1
2
3
public void applyDirection(Direction direction) {
    // use the enum here
}

The ActionScript language itself has no support for enumerations. But there is a solution: Instead of using constants of type String just use the type of the constants class itself.

1
2
3
4
5
public class Direction
{
    public static const LEFT:Direction = new Direction();
    public static const RIGHT:Direction = new Direction();
}

A function can then look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function applyDirection(direction:Direction):void
{
    switch (direction)
    {
        case Direction.LEFT:
            // use direction here...
            break;
        case Direction.RIGHT:
            // use direction here...
            break;
        default:
            throw new IllegalOperationError(
                "Unsupported direction " + direction);
    }
}
1
applyDirection(Direction.LEFT);

You would still be able to create new instances of Direction and assign them. But the implementation of applyDirection() relies on the predefined constants. An error would be thrown if another instance would be assigned. Furthermore the user can see the different possible constants because he knows which specific type is required.

If you want to trace the Direction or if you want to store more information this is no problem, too:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Direction
{
    public static const LEFT:Direction = new Direction("left");
    public static const RIGHT:Direction = new Direction("right");
   
    private var direction:String;
   
    public function Direction(direction:String)
    {
        this.direction = direction;
    }

    public function toString():String
    {
        return direction;
    }
}

Right now, this approach is the only way to provide type save enumerations in ActionScript. You should always use them if you write third party libraries. Also in projects with multiple developers this makes sense.

Update 2011/03/13: In order to to restrict the enum to the predefined constants you could combine the declaration with a singleton enforcing approach. Just expect an instance of a nested class in the constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package
{
    public class Direction
    {
        public static const LEFT:Direction = new Direction(
            new EnumEnforcer(), "left");
        public static const RIGHT:Direction = new Direction(
            new EnumEnforcer(), "right");

        private var direction:String;
   
        public function Direction(enumEnforcer:EnumEnforcer,
            direction:String)
        {
            this.direction = direction;
        }

        public function toString():String
        {
            return direction;
        }
    }
}

class EnumEnforcer
{
}

Of course this is still not 100% save because you could just pass in null. In this case an error could be thrown. But this would happen at runtime only then.

Thanks to Thijs for pointing out this problem in the comments and Peter Höche for suggesting this solution.

Review: Logging with Trazzle

Posted in Libraries on November 14th, 2010 by Mattes – 1 Comment

A few weeks ago I discovered an ActionScript 3.0 Logger called Trazzle.

It’s available for Mac only and provides a well-arranged, beautiful logging output, a performance monitor, bitmap logging and much more. In order to use this logger, you need to install the Logger Client and include the SWC files within your project.

All source files are available on GitHub as well as a simple example.

Usage

I assume the author tried to build a logger that is very easy to use. Therefor he provides package level functions which allow fast access to the core features. The logger classes behind can also be used. But this should not be part of this post.

The first step is to initialize to logging framework:

1
zz_init(stage, "Logger app title");

Please note: The logging only works if you import the class TrazzleLogger. The reason why the demo application works: the StatusBar class holds a reference to TrazzleLogger. But normal logging will retrieve the reference only dynamically at runtime, so you have to take care of importing it on your own.

After initialization you can trigger the log messages. By default they will be displayed as plain white text. To make use of the different log levels you have to prepend one of the following characters:

1
2
3
4
5
6
7
8
log("normal");
log("d debug");
log("i info");
log("n notice");
log("w warning");
log("e error");
log("c critical");
log("f fatal");

This syntax is one of the main differences to other logging frameworks. Because of this convention it es very fast to use. You don’t have to retrieve a logger instance and define a strong typed log level. Unfortunately the drawback is, you have to know the convention and you are responsible to use it correctly as there is no compile time check.

You can also use the classical printf behavior which allows to define a string with placeholders that will be replaced at runtime. Again, in order to use this feature you have to make sure that the method printf is compiled into the application.

1
logf("There is a difference between %s and %s", "good", "evil");

Furthermore with the function zz_inspect(object) you should be able to see all the fields and values of an instance. For some reason I didn’t get it to work. Please comment below if you found a solution.

Filtering

In contrast to other logging frameworks it is not possible to configure the logging visibility for certain packages and log levels from within the flash client. Instead the configuration will completely take place in the Trazzle application by using the filters window. Here you can define and combine different rules. Excluding specific packages is not possible. You can save each filter set for later usage.

Performance Monitor

The performance monitor gives you a chronological sequence of the memory consumption and the frames per second (fps). It worked for me but I have not really tested it.

Conclusion

Using the trazzle logging framework will force you to use the Trazzle application which is available for OS X only. So if you work in larger teams you have to take into consideration that you can not exchange the logging appender easily.

What I think is a bit strange, is that you have to manually import the TrazzleLogger in order to use it via the package level functions. This makes it difficult to enable/disable the logging on different environments like on debug and release stages. Reading traces is also very exhausting because you have to read small grey text on a black background. And if you copy the text into another editor it is broken by the line numbers. The other log messages are better readable (see first image).

Apart from this cons you get an easy to use logger which has useful additional features like bitmap data output. With this feature I was able to easily find a bitmap that accidentally prevented clicks. What I especially like is the StackTrace which you can see for each log entry. Because the logger is very easy and fast to use you can eventually use him for some special cases only.

One final note: To see the line numbers you have to compile with the compiler flag “-verbose-stacktraces”.

Short-lived Commands with Parsley

Posted in ActionScript on October 31st, 2010 by Mattes – 4 Comments

This week we had to decide on a MVC Framework for our next game at Wooga. In the end we had to decide between Robotlegs and Parsley. Both of them had pros and cons which I will maybe explain at a later time.

One aspect we came across was the support of Short-lived Command Objects. These Commands hold no state and will be garbage collected after execution. In Robotlegs they are supported via the ICommandMap interface. Parsley also provides an implementation of this pattern called DynamicCommand. In contrast to Robotlegs, Parsley provides 4 different ways to build and configure a context:

  • MXML: DynamicCommand Tag. Only for Flex projects.
  • XML: DynamicCommand Node. No compiler check on types possible.
  • ActionScript: No way to configure dynamic Commands.
  • Configuration DSL: Programmatic configuration of Dynamic Commands.

Because our game should not use the Flex framework, the last option is our only choice if we want to have strongly typed Command mappings like in Robotlegs.

DynamicCommands via Configuration DSL

Because a documentation is not available for this case it was a bit tricky to find the solution (thanks for the hint, Jens). This was the first result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var contextBuilder:ContextBuilder = ContextBuilder.newSetup()
    .viewRoot(this)
    .newBuilder();

var targetDef:DynamicObjectDefinition = contextBuilder
    .objectDefinition()
        .forClass(CommandType)
            .asDynamicObject()
                .build();

DynamicCommandBuilder
    .newBuilder(targetDef)
        .builder
            .messageType(MessageType)
            .stateful(false)
        .build();

contextBuilder.config(ActionScriptConfig.forClass(MainConfig));
contextBuilder.build();

Note that you can not use the ActionScriptContexBuilder.build() notation anymore. Instead you have to configure the whole context via the DSL. In line 18, the actual configuration (MainConfig) which contains all object definitions is passed in.

Because this configuration is very hard to read and redundant if you want to map several Commands, I encapsulated the mapping to a separate class CommandMap. Now the configuration looks like this:

1
2
3
4
5
6
7
8
9
10
var contextBuilder:ContextBuilder = ContextBuilder.newSetup()
.viewRoot(this)
.newBuilder();

var commandMap:CommandMap = new CommandMap(contextBuilder);
commandMap.register(LoginCommand, LoginRequest);
commandMap.register(LogoutCommand, LogoutRequest);

contextBuilder.config(ActionScriptConfig.forClass(MainConfig));
contextBuilder.build();

Until now I found no way to map or un-map Commands after the context has been built. The only way would be to destroy the context they are registered in.

To get a better impression how short-lived commands are used in Parsley, I implemented a small example, which you can access on GitHub. The CommandMap class can be found here.

And this is how the login example looks like. Invalid credentials lead to an error pop up. Valid login works with “admin” and password “test“:

Summary

The Robotlegs implementation is very straight forward. Commands can be mapped and un-mapped at any time. This is not possible in Parsley. But you have other features that give maybe similar results (for example MessageInterceptors).

Because Parsley reflects on the types you can pass data directly to the execute method. This way, each concrete execute method can receive strong typed parameters (see line 9). No framework class has to be extended for custom Commands. This is how a command can look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LogoutCommand
{
    [Inject]
    public var service:ISessionService;
   
    [MessageDispatcher]
    public var dispatcher:Function;
   
    public function execute(message:LogoutRequest) : ServiceRequest
    {
        return service.logout(message.sessionId);
    }
   
    public function result(success:Boolean) : void
    {
        dispatcher(new LogoutSuccess(success));
    }
}

I also like the native support of synchronous and asynchronous Commands in Parsley. No special configuration is necessary, because Parsley reflects on the return type of the execute() method (line 9, ServiceRequest).

Links:

Icon Badge for Windows

Posted in Air Icon Badge, Libraries on March 14th, 2010 by Mattes – 4 Comments

Until now the Air Icon Badge library implementation only supports the OS X dock icon. Nevertheless it is easy to extend the implementation for utilizing it as Windows system tray icon. In this article I will demonstrate how this could be realized.

Demo

Therefore I extended the existing example implementation. Just choose “Window Tray Icon” from the right panel for previewing the new icon.

And this is how it will look like on Windows XP (Windows Vista and 7 will look the same).

Implementation

The first class that I create is the SystemTrayIconBuilder (it must implement IconBuilder interface). This class is responsible for composing the system tray icon. It also sets the general icon size to 16 by 16 pixels.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SystemTrayIconBuilder extends AbstractIconBuilder
implements IconBuilder
{
public override function createNewIcon(width : int,
height : int) : void
{
super.createNewIcon(16, 16);
}

public override function addBackground(
background : Bitmap) : void
{
background.width = background.height = 16;

container.addChild(background);
}

public override function addBadge(label : String) : void
{
var badge : TrayIconBadge = new TrayIconBadge();
badge.label.text = label;

container.addChild(badge);
}
}

Please note the the TrayIconBadge class used in this example (line 17) is a MovieClip designed and exported (swc) with the Flash IDE. I used a pixel font for better readability. Because of the small icon size the visible letter count is also limited.

The next step is to create a custom SystemTrayIconBadge which has to implement the IconBadge interface. To avoid redundancies I extend the DockIconBadge class and override the factory method “createIconBuilder()“.

1
2
3
4
5
6
7
public class SystemTrayIconBadge extends DockIconBadge
{
protected override function createIconBuilder() : IconBuilder
{
return new SystemTrayIconBuilder();
}
}

The last step is to build the CrossPlatformIconBadgeFactory which implements IconBadgeFactory. It is responsible for detecting the users operating system and returning the corresponding IconBadge. Again I extend the existing factory class to avoid redundancies:

1
2
3
4
5
6
7
8
9
10
11
public class CrossPlatformIconBadgeFactory extends
AirIconBadgeFactroy
{
public override function create() : IconBadge
{
if (NativeApplication.supportsSystemTrayIcon)
return new SystemTrayIconBadge();

return super.create();
}
}

Finally for using the new factory it has to be assigned to the AirIconBadge class.

1
2
AirIconBadge.factory = new CrossPlatformIconBadgeFactory();
AirIconBadge.label = "1";

Summary

As you can see, it is very little effort to add the windows system tray icon capability. You are free to (re)use this example. Binaries and sources can be downloaded from the google code project site.

Any comments will be appreciated.

Icon Badge Library for Air

Posted in Air Icon Badge, Libraries on February 8th, 2010 by Mattes – 11 Comments

Introduction

Adobe Air is often used to build feed readers or social media clients. This kind of applications can retrieve new data while they are running in the background. In that case it would be great to inform the user about the amount of new items. With OS X you can use the dock icon for that purpose. The Cocoa Framework allows to display a user defined text consistently on top of the application dock tile (icon). E.g. the screenshot at the right shows 2 unread mails in the inbox.

Native and emulated badge

Unfortunately the Air runtime allows no access to this native functionality. Thats why the idea for this library came up. It tries to emulate the native badge with the possibilities Air provides (see left image). Until now only the OS X badge is supported but a Windows implementation is possible, too. I will demonstrate the extensibility in one of the following blog posts.

Demo

If you have a Mac, you can download this Air application where the badge shows up on the real application icon. Running this application on windows will have no visual effect.

None Mac users can use the following demo that shows a preview of the dock icon:

You can browse the sources for this example on the google code repository.

Usage

To show the badge label you can use the static facade AirIconBadge. Internally it will create an IconBadge appropriate for the current operating system. Note: only one implementation for OS X is provided until now! Windows or Linux users won’t see a badge label.

With the static property label you can assign any string that should be displayed. Thats it.

1
AirIconBadge.label = "1";

If you assign an empty string or null, no badge will be displayed. To remove the current badge label you can also call the method clearLabel().

By default the biggest icon defined within the application descriptor will be loaded and shown. If no icon has been defined or the path is incorrect you must assign a customIcon in order to see the label. You can also assign a customIcon if you want to replace the default icon temporarily. Removing the customIcon will show up the default icon again.

1
AirIconBadge.customIcon = new CustomIconBitmap();

If neither of the icons could be loaded, no badge will be displayed. In this case an error event will be dispatched (UpdateErrorEvent). To get status information about the internals you can register for the InformationEvent. Both events will be dispatched by the IconBadge witch is statically stored within the AirIconBadge.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var iconBadge : IconBadge = AirIconBadge.iconBadge;
iconBadge.addEventListener(UpdateErrorEvent.UPDATE_ERROR,
handleError);
iconBadge.addEventListener(InformationEvent.INFORMATION,
handleInformation);

function handleError(event : UpdateErrorEvent) : void
{
    // do some error handling
}

function handleInformation(event : InformationEvent) : void
{
    trace(event.information.toString());
}

Download

All sources, binaries and examples are available for download under the MIT license.

Whats next

The documentation (especially the ASDocs) will be improved as well as the sources. If you have questions or feature requests, please let my know. The next blog posts will give you a deeper insight in the architecture and extensibility of this library.