diff --git a/src/as/com/threerings/crowd/client/LocationDecoder.as b/src/as/com/threerings/crowd/client/LocationDecoder.as new file mode 100644 index 000000000..5fce22e3d --- /dev/null +++ b/src/as/com/threerings/crowd/client/LocationDecoder.as @@ -0,0 +1,70 @@ +// +// $Id: LocationDecoder.java 3914 2006-03-06 21:51:59Z mdb $ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.client { + +import com.threerings.crowd.client.LocationReceiver; +import com.threerings.presents.client.InvocationDecoder; + +/** + * Dispatches calls to a {@link LocationReceiver} instance. + */ +public class LocationDecoder extends InvocationDecoder +{ + /** The generated hash code used to identify this receiver class. */ + public static const RECEIVER_CODE :String = "58f2830e027f4f3377e100ef12332497"; + + /** The method id used to dispatch {@link LocationReceiver#forcedMove} + * notifications. */ + public static const FORCED_MOVE :int = 1; + + /** + * Creates a decoder that may be registered to dispatch invocation + * service notifications to the specified receiver. + */ + public function LocationDecoder (receiver :LocationReceiver) + { + this.receiver = receiver; + } + + // documentation inherited + public override function getReceiverCode () :String + { + return RECEIVER_CODE; + } + + // documentation inherited + public override function dispatchNotification ( + methodId :int, args :Array) :void + { + switch (methodId) { + case FORCED_MOVE: + (receiver as LocationReceiver).forcedMove( + (args[0] as int) + ); + return; + + default: + super.dispatchNotification(methodId, args); + } + } +} +} diff --git a/src/as/com/threerings/crowd/client/PlaceController.as b/src/as/com/threerings/crowd/client/PlaceController.as new file mode 100644 index 000000000..827f8d09d --- /dev/null +++ b/src/as/com/threerings/crowd/client/PlaceController.as @@ -0,0 +1,267 @@ +// +// $Id: PlaceController.java 3440 2005-03-30 01:09:30Z mdb $ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.client { + +import com.threerings.crowd.data.PlaceConfig; +import com.threerings.crowd.data.PlaceObject; +import com.threerings.crowd.util.CrowdContext; + +/** + * Controls the user interface that is used to display a place. When the + * client moves to a new place, the appropriate place controller is + * constructed and requested to create and display the appopriate user + * interface for that place. + */ +public /*abstract*/ class PlaceController /*extends Controller*/ +{ + /** + * Initializes this place controller with a reference to the context + * that they can use to access client services and to the + * configuration record for this place. The controller should create + * as much of its user interface that it can without having access to + * the place object because this will be invoked in parallel with the + * fetching of the place object. When the place object is obtained, + * the controller will be notified and it can then finish the user + * interface configuration and put the user interface into operation. + * + * @param ctx the client context. + * @param config the place configuration for this place. + */ + public function init (ctx :CrowdContext, config :PlaceConfig) :void + { + // keep these around + _ctx = ctx; + _config = config; + + // create our user interface + _view = createPlaceView(_ctx); + +// // initialize our delegates +// applyToDelegates(new DelegateOp() { +// public void apply (PlaceControllerDelegate delegate) { +// delegate.init(_ctx, _config); +// } +// }); + + // let the derived classes do any initialization stuff + didInit(); + } + + /** + * Derived classes can override this and perform any + * post-initialization processing they might need. They should of + * course be sure to call super.didInit(). + */ + protected function didInit () :void + { + } + + /** + * Returns a reference to the place view associated with this + * controller. This is only valid after a call has been made to {@link + * #init}. + */ + public function getPlaceView () :PlaceView + { + return _view; + } + + /** + * Returns the {@link PlaceConfig} associated with this place. + */ + public function getPlaceConfig () :PlaceConfig + { + return _config; + } + + /** + * Creates the user interface that will be used to display this place. + * The view instance returned will later be configured with the place + * object, once it becomes available. + * + * @param ctx a reference to the {@link CrowdContext} associated with + * this controller. + */ + protected function createPlaceView (ctx :CrowdContext) :PlaceView + { + return null; + } + + /** + * This is called by the location director once the place object has + * been fetched. The place controller will dispatch the place object + * to the user interface hierarchy via {@link + * PlaceViewUtil#dispatchWillEnterPlace}. Derived classes can override + * this and perform any other starting up that they need to do + */ + public function willEnterPlace (plobj :PlaceObject) :void + { + // keep a handle on our place object + _plobj = plobj; + + if (_view != null ) { + // let the UI hierarchy know that we've got our place + PlaceViewUtil.dispatchWillEnterPlace(_view, plobj); + // and display the user interface + _ctx.setPlaceView(_view); + } + +// // let our delegates know what's up +// applyToDelegates(new DelegateOp() { +// public void apply (PlaceControllerDelegate delegate) { +// delegate.willEnterPlace(plobj); +// } +// }); + } + + /** + * Called before a request is submitted to the server to leave the + * current place. As such, this method may be called multiple times + * before {@link #didLeavePlace} is finally called. The request to + * leave may be rejected, but if a place controller needs to flush any + * information to the place manager before it leaves, it should so do + * here. This is the only place in which the controller is guaranteed + * to be able to communicate to the place manager, as by the time + * {@link #didLeavePlace} is called, the place manager may have + * already been destroyed. + */ + public function mayLeavePlace (plobj :PlaceObject) :void + { +// // let our delegates know what's up +// applyToDelegates(new DelegateOp() { +// public void apply (PlaceControllerDelegate delegate) { +// delegate.mayLeavePlace(plobj); +// } +// }); + } + + /** + * This is called by the location director when we are leaving this + * place and need to clean up after ourselves and shutdown. Derived + * classes should override this method (being sure to call + * super.didLeavePlace) and perform any necessary + * cleanup. + */ + public function didLeavePlace (plobj :PlaceObject) :void + { +// // let our delegates know what's up +// applyToDelegates(new DelegateOp() { +// public void apply (PlaceControllerDelegate delegate) { +// delegate.didLeavePlace(plobj); +// } +// }); + + // let the UI hierarchy know that we're outta here + if (_view != null ) { + PlaceViewUtil.dispatchDidLeavePlace(_view, plobj); + _ctx.clearPlaceView(_view); + _view = null; + } + + _plobj = null; + } + + /** + * Handles basic place controller action events. Derived classes + * should be sure to call super.handleAction for events + * they don't specifically handle. + */ +// public boolean handleAction (final ActionEvent action) +// { +// final boolean[] handled = new boolean[1]; +// +// // let our delegates have a crack at the action +// applyToDelegates(new DelegateOp() { +// public void apply (PlaceControllerDelegate delegate) { +// // we take advantage of short-circuiting here +// handled[0] = handled[0] || delegate.handleAction(action); +// } +// }); +// +// // if they didn't handly it, pass it off to the super class +// return handled[0] ? true : super.handleAction(action); +// } + + /** + * Adds the supplied delegate to the list for this controller. + */ +// protected void addDelegate (PlaceControllerDelegate delegate) +// { +// if (_delegates == null) { +// _delegates = new ArrayList(); +// } +// _delegates.add(delegate); +// } + + /** + * Used to call methods in delegates. + */ +// protected static interface DelegateOp +// { +// public void apply (PlaceControllerDelegate delegate); +// } + + /** + * Applies the supplied operation to the registered delegates. + */ +// protected void applyToDelegates (DelegateOp op) +// { +// if (_delegates != null) { +// int dcount = _delegates.size(); +// for (int i = 0; i < dcount; i++) { +// op.apply((PlaceControllerDelegate)_delegates.get(i)); +// } +// } +// } + + /** + * Applies the supplied operation to the registered delegates that + * derive from the specified class. + */ +// protected void applyToDelegates (Class dclass, DelegateOp op) +// { +// if (_delegates != null) { +// int dcount = _delegates.size(); +// for (int i = 0; i < dcount; i++) { +// PlaceControllerDelegate delegate = +// (PlaceControllerDelegate)_delegates.get(i); +// if (dclass.isAssignableFrom(delegate.getClass())) { +// op.apply(delegate); +// } +// } +// } +// } + + /** A reference to the active client context. */ + protected var _ctx :CrowdContext; + + /** A reference to our place configuration. */ + protected var _config :PlaceConfig; + + /** A reference to the place object for which we're controlling a user + * interface. */ + protected var _plobj :PlaceObject; + + /** A reference to the root user interface component. */ + protected var _view :PlaceView; +} +} diff --git a/src/as/com/threerings/crowd/client/PlaceViewUtil.as b/src/as/com/threerings/crowd/client/PlaceViewUtil.as new file mode 100644 index 000000000..1e7bde7c9 --- /dev/null +++ b/src/as/com/threerings/crowd/client/PlaceViewUtil.as @@ -0,0 +1,90 @@ +// +// $Id: PlaceViewUtil.java 3098 2004-08-27 02:12:55Z mdb $ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.client { + +import flash.display.DisplayObjectContainer; + +import com.threerings.crowd.Log; +import com.threerings.crowd.data.PlaceObject; + +/** + * Provides a mechanism for dispatching notifications to all user + * interface elements in a hierarchy that implement the {@link PlaceView} + * interface. Look at the documentation for {@link PlaceView} for more + * explanation. + */ +public class PlaceViewUtil +{ + /** + * Dispatches a call to {@link PlaceView#willEnterPlace} to all UI + * elements in the hierarchy rooted at the component provided via the + * root parameter. + * + * @param root the component at which to start traversing the UI + * hierarchy. + * @param plobj the place object that is about to be entered. + */ + public static function dispatchWillEnterPlace ( + root :Object, plobj :PlaceObject) :void + { + dispatch(root, plobj, "willEnterPlace"); + } + + /** + * Dispatches a call to {@link PlaceView#didLeavePlace} to all UI + * elements in the hierarchy rooted at the component provided via the + * root parameter. + * + * @param root the component at which to start traversing the UI + * hierarchy. + * @param plobj the place object that is about to be entered. + */ + public static function dispatchDidLeavePlace ( + root :Object, plobj :PlaceObject) :void + { + dispatch(root, plobj, "didLeavePlace"); + } + + private static function dispatch ( + root :Object, plobj :PlaceObject, funct :String) :void + { + // dispatch the call on this component if it implements PlaceView + if (root is PlaceView) { + try { + (root as PlaceView)[funct](plobj); + } catch (e :Error) { + Log.warning("Component choked on " + funct + "() " + + "[component=" + root + ", plobj=" + plobj + "]."); + Log.logStackTrace(e); + } + } + + // now traverse all of this component's children + if (root is DisplayObjectContainer) { + var cont :DisplayObjectContainer = (root as DisplayObjectContainer); + for (var ii :int = 0; ii < cont.numChildren; ii++) { + dispatch(cont.getChildAt(ii), plobj, funct); + } + } + } +} +} diff --git a/src/as/com/threerings/util/ClassUtil.as b/src/as/com/threerings/util/ClassUtil.as index 8568055a2..a64a78b14 100644 --- a/src/as/com/threerings/util/ClassUtil.as +++ b/src/as/com/threerings/util/ClassUtil.as @@ -1,7 +1,5 @@ package com.threerings.util { -import flash.util.describeType; - public class ClassUtil { public static function getClassName (obj :Object) :String @@ -37,7 +35,7 @@ public class ClassUtil } // TODO: there's currently no way to determine final from the class - //var attrs :XMLList = describeType(type).elements("type"); + //var attrs :XMLList = flash.util.describeType(type).elements("type"); return false; } }