diff --git a/src/as/com/threerings/crowd/chat/client/ChatDirector.as b/src/as/com/threerings/crowd/chat/client/ChatDirector.as index be9f3f9fe..5d64834f7 100644 --- a/src/as/com/threerings/crowd/chat/client/ChatDirector.as +++ b/src/as/com/threerings/crowd/chat/client/ChatDirector.as @@ -21,8 +21,6 @@ package com.threerings.crowd.chat.client { -import mx.collections.ArrayCollection; - import com.threerings.util.ArrayUtil; import com.threerings.util.Hashtable; import com.threerings.util.Map; diff --git a/src/as/com/threerings/presents/client/Client.as b/src/as/com/threerings/presents/client/Client.as index 10e05ff3e..89e2c59a0 100644 --- a/src/as/com/threerings/presents/client/Client.as +++ b/src/as/com/threerings/presents/client/Client.as @@ -7,8 +7,7 @@ import flash.events.TimerEvent; import flash.utils.Timer; -import mx.core.Application; - +import com.threerings.util.MethodQueue; import com.threerings.util.ObserverList; import com.threerings.presents.data.ClientObject; @@ -28,9 +27,11 @@ public class Client extends EventDispatcher private static const log :Log = Log.getLog(Client); - public function Client (creds :Credentials) + public function Client (creds :Credentials, stage :Stage) { _creds = creds; + _stage = stage; + MethodQueue.setStage(stage); } /** @@ -97,7 +98,7 @@ public class Client extends EventDispatcher public function callLater (fn :Function, args :Array = null) :void { - Application.application.callLater(fn, args); + MethodQueue.callLater(fn, args); } /** @@ -105,7 +106,7 @@ public class Client extends EventDispatcher */ public function getStage () :Stage { - return Application.application.stage; + return _stage; } public function getHostname () :String @@ -371,6 +372,9 @@ public class Client extends EventDispatcher /** The credentials we used to authenticate with the server. */ protected var _creds :Credentials; + /** The stage upon which our client runs. */ + protected var _stage :Stage; + /** The version string reported to the server at auth time. */ protected var _version :String = ""; diff --git a/src/as/com/threerings/util/MethodQueue.as b/src/as/com/threerings/util/MethodQueue.as new file mode 100644 index 000000000..6454ccd94 --- /dev/null +++ b/src/as/com/threerings/util/MethodQueue.as @@ -0,0 +1,94 @@ +package com.threerings.util { + +import flash.display.Stage; + +import flash.events.Event; + +/** + * A simple mechanism for queueing functions to be called on the next frame. + * Similar to UIComponent's callLater, only flex-free. + */ +public class MethodQueue +{ + /** + * Set the stage which will be used for coordinating the use of the + * method queue. If no stage is set, functions will continue to pile up + * without being called. + */ + public static function setStage (stage :Stage) :void + { + if (_listening) { + removeListener(); + } + _stage = stage; + checkListen(); + } + + /** + * Call the specified method at the entry to the next frame. + */ + public static function callLater (fn :Function, args :Array = null) :void + { + _methodQueue.push([fn, args]); + if (!_listening) { + checkListen(); + } + } + + /** + * Stop listening for the frame event. + */ + protected static function removeListener () :void + { + _stage.removeEventListener(Event.ENTER_FRAME, handleEnterFrame); + _listening = false; + } + + /** + * Check to see if we should be listening for the next frame event. + */ + protected static function checkListen () :void + { + if (_stage != null && _methodQueue.length > 0) { + _stage.addEventListener(Event.ENTER_FRAME, handleEnterFrame); + _listening = true; + } + } + + /** + * Handle a frame event: call any queued functions. + */ + protected static function handleEnterFrame (event :Event) :void + { + // swap out the working set + var methods :Array = _methodQueue; + _methodQueue = []; + + // safely call each function + for each (var arr :Array in methods) { + try { + Function(arr[0]).apply(null, (arr[1] as Array)); + + } catch (e :Error) { + Log.getLog(MethodQueue).warning("Error calling deferred method " + + "[e=" + e + ", fn=" + arr[0] + "]."); + } + } + + // If no new functions were added while we were calling the current set, + // then remove the listener. + if (_methodQueue.length == 0) { + removeListener(); + } + } + + /** The stage we're working with. */ + protected static var _stage :Stage; + + /** The currently queued functions. */ + protected static var _methodQueue :Array = []; + + /** Are we presently listening for the frame event? */ + protected static var _listening :Boolean = false; +} +}