How to create a new Flash application with the ASAP Framework

Accompanying demos: Simple Demo (event handling) and Simple Application Demo (movie handling).

See ASAP Movie Management for an introduction to multi-movie projects.

The basics

  1. Download the latest framework from Sourceforge. Example: asap_framework_0.94.zip
  2. Unzip the framework in a clearly named folder (preferably containing the version number of the framework). Example: D:/Projects/ASAP/asap_framework_0.94/
  3. Create a new Flash file
  4. Save the fla in a new folder
  5. In the same folder, create a folder and name it scripts
  6. Add the full path to the framework to the classpath. In this case: D:/Projects/ASAP/asap_framework_0.93/
  7. Also add the scripts folder to the classpath, like this: ./scripts/
  8. Create a class called AppController that extends the class org.asapframework.management.movie.LocalController as found in the framework:
    import org.asapframework.management.movie.LocalController;
    
    class AppController extends LocalController {
    }
  9. In this class, create the following entry point
    public static function main (inTimeline:MovieClip) : Void {
    	var controller:AppController = new AppController(inTimeline);
    	inTimeline.controller = controller;
    	controller.start();
    }
  10. Create the constructor of the AppController class as follows:
    	public function AppController (inTimeline:MovieClip) {
    		super(inTimeline);
    	}
  11. The whole class then looks like this:
    import org.asapframework.management.movie.LocalController;
    
    class AppController extends LocalController {
    	public function AppController (inTimeline:MovieClip) {
    		super(inTimeline);
    	}
    
    	public static function main (inTimeline:MovieClip) : Void {
    		var controller:AppController = new AppController(inTimeline);
    		inTimeline.controller = controller;
    		controller.start();
    	}
    }
  12. On the first frame of the timeline, add the following code:
    AppController.main(this);
  13. Create the rest of the application, with the AppController class as top level controller of the application.

Controlling the main timeline

The AppController as created in the previous section gives you access to the timeline via either (public) getTimeline() or the (private) property mTimeline. To make the AppController? instance stop the timeline from playing, you can do:
	public function stopTheTimeline () : Void {
		mTimeline.stop();
	}

Access to movieclips on the timeline

All named movieclips on the main timeline are accessible as properties of the timeline property. Be aware that there is no compile time check on this. Example: A MovieClip on the timeline with the name block_mc can be controlled from the AppController class like this:
	mTimeline.block_mc._visible = false;
If a class has been attached to the movieclip, it can be cast to the right type:
	var myButton:EventButton = EventButton(mTimeline.button_mc);
	myButton.setSendEventOnRoll(true);

Access to the controller from lower classes

The preferred way of controlling contained objects is top-down. This means for example, that the AppController "talks" directly to the contained movieclips, and controls them. These objects, mostly ui objects, talk back to the controller via events. Good programming practice is to notify the controller of state changes of the ui object, and let the controller further deal with this – and let the ui object only do its main job: drawing itself and catching events.

Normally the controller will subscribe to events sent by contained objects in order to listen to their notifications. However, due to the nature of Flash, it isn't always possible for the controller to find the contained movieclips and subscribe to their events. Sometimes, ui objects (like buttons) need to have access to the controller of the main timeline in order to subscribe it to their events. This is typically the case for objects for which it is unknown when they will be loaded. The main controller for a movie can be found as follows:

var lc:LocalController = MovieManager.getInstance().getNearestLocalController(this);
The parameter to the call to getNearestLocalController() has to be of type MovieClip (if the class does not extend MovieClip, there is usually no reason to ask for the nearest controller).
This lookup method works even for deeply nested movieclips.
Example:
import org.asapframework.management.movie.MovieManager;
import org.asapframework.management.movie.LocalController;
import org.asapframework.events.Event;
import org.asapframework.ui.EventMovieClip;

class MyButton extends EventMovieClip {
	public static var ON_LOADED:String = "onMyButtonLoaded";

	private var mController:LocalController;

	public function MyButton () {
		super();
	}

	public function onLoad () : Void {
		// get the nearest local controller from the moviemanager
		mController = MovieManager.getInstance().getNearestLocalController(this);
		// let the controller listen to our ON_LOADED event
		addEventListener(MyButton.ON_LOADED, mController);
		// notify the controller we've loaded
		dispatchEvent(new Event(MyButton.ON_LOADED, this));
	}

	public function onUnload () : Void {
		removeEventListener(ON_LOADED, mController);
	}
}
Some classes in the framework add their nearest controller automatically as listener. The most used example is the EventButton class. This class, and all its derived classes, send the press, release & roll events to this controller.
Note that EventDelegate cannot be used in this case. The listener class has to check with the sending class what the literal names of the events are, and define the handler functions with the same literal names.

Event handling

Sending events

Events are handled via the dispatcher model. Any class can be enabled to dispatch events, and any object can add itself, or be added, as listener to the dispatching class instance. The framework exposes two base classes to enable classes to dispatch events.
  1. For classes that do not extend MovieClip? , the base class org.asapframework.events.Dispatcher is available. Example:
    import org.asapframework.events.Dispatcher;
    
    class MyXMLLoader extends Dispatcher {
    	public function MyXMLLoader () {
    		super();
    	}
    }
  2. For classes that do extend MovieClip? , the base class org.asapframework.ui.EventMovieClip is available. Example:
    import org.asapframework.ui.EventMovieClip;
    
    class MySendingMovieclip extends EventMovieClip {
    	public function MySendingMovieclip () {
    		super();
    	}
    }
Note the call to super() in both constructors. Both base classes make the following methods available to the derived class:
  • public addEventListener() to add a listener to the current instance
  • public removeEventListener() to remove a listener from the current instance
  • dispatchEvent() to send events to whoever is listening

Events are instances of the framework class org.asapframework.events.Event, or derived classes thereof. In order to send an event that does not require extra information to be sent with the event, use the Event class:

  1. define public constants for the names of events to be sent. Example:
    public static var ON_ALLXML_LOADED:String = "onAllXMLLoaded";
  2. Send the event where necessary:
    	dispatchEvent(new Event(DataManager.ON_ALLXML_LOADED, this));

If more information needs to be sent, create a derived event class. Also, define the name of the event(s) to be sent in this derived event class, rather than the class that sends the event, as in the previous example.
Example:

import org.asapframework.events.Event;	

class ButtonEvent extends Event {
public static var ON_BUTTON_PRESSED:String = "onButtonPressed";

public var buttonName:String;

	public function ButtonEvent (inType:String, inSender:MyButton, inName:String) {
		super(inType, inSender);
			
		buttonName = inName;
	}
}
In the sending class, send the event like this:
dispatchEvent(new ButtonEvent(ButtonEvent.ON_BUTTON_PRESSED, this, _name));
It is recommended to type constructor parameters of derived event classes as accurately as possible, to avoid abuse of these events by other classes.

Receiving events

The preferred method for connecting a listener to a sender, is by letting the listener add itself to the sender.
Example of a simple notification:
import org.asapframework.events.EventDelegate;
import org.asapframework.events.Event;

private function createSender () : Void {
var loader:MyXMLLoader = new MyXMLLoader();
loader.addEventListener(MyXMLLoader.ON_ALLXML_LOADED, EventDelegate.create(this, handleAllXMLLoaded));
loader.loadXML();

}
public function handleAllXMLLoaded (e:Event) : Void {
	// e.target == loader
	// e.type == "onAllXMLLoaded"
}
An example with a derived event:
import org.asapframework.events.EventDelegate;

function listenToButton () {
	var button:MySendingMovieclip = new MySendingMovieclip(timeline.button_mc);
	button.addEventListener(ButtonEvent.ON_BUTTON_PRESSED, EventDelegate.create(this, handleClick));
}

function handleClick (e:ButtonEvent) : Void {
	// e.target == button
	// e.type == "onButtonPressed"
	// e.buttonName = sender._name
}
Note the use of EventDelegate, the framework version of the Macromedia Delegate class. Use of this class has two advantages:
  • the existence of the handler method can be checked at compile time
  • the name of the handler can be different from the name of the event

Data management

Most applications require some form of data to be loaded and exposed to various areas of the application. In order to provide a single access point for all available data, a DataManager can be created according to the Singleton pattern. This ensures that only one instance is available at any time, and that it is available in all parts of the code.
The following code sets up the skeleton for the DataManager class:
import org.asapframework.events.Dispatcher;

class DataManager extends Dispatcher {
	private static var theInstance:DataManager = null;

	private function DataManager () {
	}

	public static function getInstance () : DataManager {
		if (theInstance == null) {
			theInstance = new DataManager();
		}
		return theInstance;
	}
}
Topic revision: r16 - 08 Sep 2007 - 21:56:40 - ArthurClemens
 
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding ASAP? Send feedback