September 13, 2009

AS3 Signals Getting Stronger

A lot has happened in the last four days.

What Happen? We Git Signal


The majority of commenters preferred Github to Google Code so I moved the Signals project there:

http://github.com/robertpenner/as3-signals

I am experimenting with mirroring back to the Google Code SVN. It's going ok so far.

Committing Early and Often


I made about 20 commits to Github this weekend. Some highlights:
  • The package is now org.osflash.signals (previously com.robertpenner).
    I wanted it to have more of a community feel. Thanks Aral for the namespace!
  • Listener priority is now supported in ISignal.add().
  • ISignal.dispatch() can now send any number of arguments to listeners.
    Zero or ten, it's up to you.
  • Various classes and APIs were renamed for clarity.
  • More unit tests and fixes.

Going Native


Since my last post about connecting EventDispatchers to Signals, I had another idea for integration:

Why not use EventDispatcher for the actual dispatching but wrap it in a Signal facade?

Presenting the NativeSignal class, which lets you have your cake and eat it too.
  1. Take any EventDispatcher, e.g. Sprite.
  2. Create a NativeSignal that targets an event of the dispatcher:
    // in a subclass:
    click = new NativeSignal(this, 'click', MouseEvent);
    
    // or decorating an instance:
    click = new NativeSignal(theDispatcher, 'click', MouseEvent);
  3. Enjoy the Signal APIs and features.
  4. Dispatch from the NativeSignal or the EventDispatcher. Both use Flash's native dispatchEvent()
If you're hesitant to put your trust in new dispatching code, or you want to keep your EventDispatcher options open, this is the gateway drug for you. You don't have to give up anything. All the native functionality stays, and the ISignal interface can be piped in like frosting, wherever you like. Doesn't that sound delicious?

Get Connected

September 9, 2009

The Community Responds to AS3 Signals

The community response to my Signals event system has been very encouraging. In the two days since I opened it to the public, there have been dozens of comments on my announcement and re-tweets. People have been quite positive and interested. No one has told me I'm wasting my time (you could be the first!).

The best part has been people's insights for improving Signals. I'm been rapidly integrating them as you can see in my commits for the last two days. A special thanks goes out to Richard Lord for helping me understand AS3 event bubbling and how to implement it in Signal.

Connecting EventDispatchers to Signals


[EDIT: I renamed EventDispatcherSignal to NativeRelaySignal]

I received a very clever idea by Jacob Wright for relaying EventDispatcher events to Signal listeners. I implemented it in a new EventDispatcherSignal NativeRelaySignal class. It lets you easily wire, say, a Sprite to send native events through your own signals. The same goes for any object that implements IEventDispatcher.

Here's how you could create a Sprite subclass that uses a Signal for the click event:

public function MySprite()
{
 click = new NativeRelaySignal(this, 'click', MouseEvent);
}

// listen elsewhere
function onClick(e:MouseEvent):void { ... }

mySpriteInstance.click.add(onClick);
// fire a MouseEvent manually to test
mySpriteInstance.dispatchEvent(new MouseEvent()); // onClick is fired

The implementation of wiring the Signal to the IEventDispatcher is very simple:

[EDIT] I added listener count checking to avoid bugs (thanks to Richard Lord).

// in NativeRelaySignal.as
override public function add(listener:Function, priority:int = 0):void
{
 var prevListenerCount:uint = listeners.length;
 // Try to add first because it may throw an exception.
 super.add(listener);
 // Account for cases where the same listener is added twice.
 if (prevListenerCount == 0 && listeners.length == 1)
  IEventDispatcher(target).addEventListener(_name, dispatch, false, priority);
}

Also, Jacob's twin Tyler sent me some mind-bending ideas for radical memory efficiency. He takes lazy instantiation to a whole new level. I'm still reeling from thinking about things like Signal inheriting from Array and using a getter's arguments.callee as an index into a Dictionary. We'll see how this evolves.

Github vs Google Code


Question: Who would prefer using Github for the Signals project, rather than Google Code? I've used Git a bit and would be open to moving to it if contributors preferred that.

September 7, 2009

My New AS3 Event System: Signals

I have more critiquing of AS3 events I could do, but I figured I'd throw my hat in the ring.

I've been working on something I call Signals. It's a new approach for AS3 events, inspired by C# events and signals/slots in Qt.

Today I created my first-ever Google Code project:

http://code.google.com/p/as3-signals/

EDIT: I moved the project to Github. http://github.com/robertpenner/as3-signals

I listed features with short code samples there. I'm having a hard time pasting them into Blogger without re-doing it all. Here are the Concept and Philosophy sections for a start:

The Concept

  • A Signal is essentially a mini-dispatcher specific to one event, with its own array of listeners.
  • A Signal gives an event a concrete membership in a class.
  • Listeners subscribe to real objects, not to string-based channels.
  • Event string constants are no longer needed.

Philosophy

  • Composition and interfaces are favored over inheritance.
  • Events in interfaces are a good thing.
  • Event types are classes, not strings.
  • Event classes should focus on the data they contain, not on who sends them.
  • Event classes should not contain string constants that various other classes use.
  • Test-Driven Development (TDD) is essential and fun.
  • So far, not a single static keyword in the source.
  • No singletons.

The Project Home Page has the feature listing and code examples.

I want Signals to be really good, and I'm open to changing anything and everything to improve it. So please check it out and post your impressions, critiques and suggestions.