      */
     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.

    {
        try {
            if (item is XML) {
                return String(item.@command);

            } else if (item is Object) {
                return String(item.command);
            }
        } catch (e :Error) {
            // fall through


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. 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 }
 * ];
 *
