From 20a9685cc4ed3b98df16d1004b008c9695975cdf Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Fri, 1 Dec 2006 03:06:42 +0000 Subject: [PATCH] Allow menu items to be configured with a callback function directly (to which any args will be passed), instead of only dispatching controller commands. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4465 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../com/threerings/mx/controls/CommandMenu.as | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/as/com/threerings/mx/controls/CommandMenu.as b/src/as/com/threerings/mx/controls/CommandMenu.as index adfbcfbc2..0f8901466 100644 --- a/src/as/com/threerings/mx/controls/CommandMenu.as +++ b/src/as/com/threerings/mx/controls/CommandMenu.as @@ -7,18 +7,23 @@ import flash.geom.Rectangle; import mx.controls.Menu; import mx.core.mx_internal; +import mx.core.ScrollPolicy; import mx.events.MenuEvent; import com.threerings.mx.events.CommandEvent; /** * A pretty standard menu that can submit CommandEvents if menu items - * have "command" and possibly "arg" properties. + * have "command" and possibly "arg" properties. Commands are submitted to + * controllers for processing. Alternatively, you may specify + * "callback" properties that specify a function closure to call, with the + * "arg" property containing either a single arg or an array of args. * * Example dataProvider array: * [ { label: "Go home", icon: homeIconClass, * command: Controller.GO_HOME, arg: homeId }, * { type: "separator"}, + { label: "Crazytown", callback: setCrazy, arg: [ true, false ] }, * { label: "Other places", children: subMenuArray } * ]; * @@ -32,6 +37,7 @@ public class CommandMenu extends Menu super(); addEventListener(MenuEvent.ITEM_CLICK, itemClicked); +// addEventListener(MenuEvent.MENU_SHOW, handleMenuShown); } /** @@ -74,14 +80,42 @@ public class CommandMenu extends Menu */ protected function itemClicked (event :MenuEvent) :void { + var arg :Object = getItemArgument(event.item); var cmd :String = getItemCommand(event.item); - if (cmd != null) { + var fn :Function; + if (cmd == null) { + fn = getItemCallback(event.item); + } + if (cmd != null || fn != null) { event.stopImmediatePropagation(); - var arg :Object = getItemArgument(event.item); - CommandEvent.dispatch(mx_internal::parentDisplayObject, cmd, arg); + if (cmd != null) { + CommandEvent.dispatch(mx_internal::parentDisplayObject, cmd, arg); + + } else { + try { + var args :Array = (arg as Array); + if (args == null && arg != null) { + args = [ arg ]; + } + fn.apply(null, args); + + } catch (err :Error) { + Log.getLog(this).warning("Unable to call menu callback: " + + event.item); + } + } } } +// /** +// * Callback for MenuEvent.MENU_SHOW. +// */ +// protected function handleMenuShown (event :MenuEvent) :void +// { +// // just ensure that every menu can scroll +// event.menu.verticalScrollPolicy = ScrollPolicy.ON; +// } + /** * Get the command for the specified item, if any. * Somewhat similar to bits in the DefaultDataDescriptor. @@ -90,10 +124,29 @@ public class CommandMenu extends Menu { try { if (item is XML) { - return String(item.@command); + return (item.@command as String); } else if (item is Object) { - return String(item.command); + return (item.command as String); + } + } catch (e :Error) { + // fall through + } + + return null; + } + + /** + * Get the callback function for the specified item, if any. + */ + protected function getItemCallback (item :Object) :Function + { + try { + if (item is XML) { + return (item.@callback as Function); + + } else if (item is Object) { + return (item.callback as Function); } } catch (e :Error) { // fall through