ContextMenuManager
I dont like the way we create and modify items with ContextMenu class in ActionScript 3.0, first we have to create item, then add event listener, then push our item to ContextMenu.customItems, I think this is quite alot of code for simple task. And there is one more disadvanage, we cannot subclass ContextMenu items, this means we cannot create subclass which would add some items by default.
All this inspired me to create my own class which would manage ContextMenu instance. Then I’ve added methods like remove, insert, getItem.
Take a look on the code below, this code creates new item in new ContextMenu instance.
var myContextMenu:ContextMenu = new ContextMenu();
myContextMenu.hideBuiltInItems();
var item:ContextMenuItem = new ContextMenuItem("My Caption");
item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,myHandler);
myContextMenu.customItems.push(item);
myInteractiveObject.contextMenu = myContextMenu;
If we want to add second item, get read for 3 more lines of code, and what about 5, 10 items?. I want to do this task like this:
var cmm:CMManager = new CMManager(myInteractiveObject);
cmm.add("My Caption",myHandler);
That’s all folks, now lets think about something more complex, what if we want to create different type of controls, with different ContextMenu’s, but we also want all ContextMenu’s to have “About My Application” item. This is simple, just subclass CMManager:
package
{
import eu.orangeflash.managers.CMManager;
import flash.display.InteractiveObject;
import flash.ui.ContextMenu;
import flash.events.ContextMenuEvent;
public class MyCMM extends CMManager
{
public function MyCMM(target:InteractiveObject)
{
super(target);
add("About My Super Application",traceAbout);
}
private function traceAbout(event:ContextMenuEvent):void
{
trace("My Supper App");
}
}
}
Easy, isn’t it?, here is CMManager source code:
package eu.orangeflash.managers
{
import flash.display.InteractiveObject;
import flash.events.*;
import flash.errors.IllegalOperationError;
import flash.ui.*;
import flash.utils.getQualifiedClassName;
/**
* Class manages ContextMenu item, has methods such as add, remove, insert.
*
* @author Nirth
* @url http://orangeflash.eu
* @see ContextMenu, ContextMenuItem, ContextMenuEvent, EventDispatcher, InteractiveObject
*/
public class CMManager
extends EventDispatcher
{
protected var menu:ContextMenu;
protected var target:InteractiveObject;
/**
* Constructor, creates new CMManager isntance
*
* @param target Reference to InteractiveObject which menu will be managed
*/
public function CMManager(target:InteractiveObject, hideBuiltInItems:Boolean = true)
{
this.target = target;
menu = new ContextMenu();
if(hideBuiltInItems)
{
menu.hideBuiltInItems();
}
this.target.contextMenu = menu;
menu.addEventListener(ContextMenuEvent.MENU_SELECT,passEvent);
}
/**
* Method, adds new ContextMenuItem.
*
* @param caption Specifies the menu item caption (text) displayed in the context menu.
* @param handler Event handler for menu item.
* @param separatorBefore Indicates whether a separator bar should appear above the specified menu item.
* @param enabled Indicates whether the specified menu item is enabled or disabled.
* @param visible Indicates whether the specified menu item is visible when the Flash Player context menu is displayed.
*
* @return Reference to newly created ContextMenuItem
*/
public function add(caption:String,
handler:Function,
separatorBefore:Boolean = false,
enabled:Boolean = true,
visible:Boolean = true):ContextMenuItem
{
var result:ContextMenuItem = createItem(caption, handler, separatorBefore, enabled, visible);
menu.customItems.push(result);
return result;
}
/**
* Method, inserts new ContextMenuItem.
*
* @param id String or Number(int,uint). If id is string, ContextMenuManager will add before ContextMenuItem with captions which matches id, otherwise will be added item with index.
* @param caption Specifies the menu item caption (text) displayed in the context menu.
* @param handler Event handler for menu item.
* @param separatorBefore Indicates whether a separator bar should appear above the specified menu item.
* @param enabled Indicates whether the specified menu item is enabled or disabled.
* @param visible Indicates whether the specified menu item is visible when the Flash Player context menu is displayed.
*
* @return Reference to newly created ContextMenuItem
*/
public function insert( id:*,
caption:String,
handler:Function,
separatorBefore:Boolean = false,
enabled:Boolean = true,
visible:Boolean = true):ContextMenuItem
{
var result:ContextMenuItem = createItem(caption, handler, separatorBefore, enabled, visible);
var index:int = id is String ? getIndexByCaption(id) : id as int;
(menu.customItems as Array).splice(index,0,result);
return result;
}
/**
* Method, removes item from customItems array
*
* @param id String or Number(int,uint). If id is string, ContextMenuManager will remove ContextMenuItem with captions which matches id, otherwise will remove item with index.
*/
public function remove(id:*):void
{
if(id is String)
{
id = getIndexByCaption(id);
}
customItems.splice(id as Number,1);
}
/**
* Method. Hides all built-in menu items (except Settings) in the specified ContextMenu object. If the debugger version of Flash Player is running, the Debugging menu item appears, although it is dimmed for SWF files that do not have remote debugging enabled.
*
*/
public function hideBuiltInItems():void
{
menu.hideBuiltInItems();
}
/**
* Method, returns reference to ContextMenuItem by it's id.
*
* @param id String or Number(int,uint). If id is string, ContextMenuManager will return ContextMenuItem with captions which matches id, otherwise will return item with index.
*
* @return reference to the ContextMenuItem instance.
*/
public function getItem(id:*):ContextMenuItem
{
if(id is String)
{
id = getIndexByCaption(id);
}
return menu.customItems[id];
}
/**
* Property[read-only] An array of ContextMenuItem objects.
*
* @return An array of ContextMenuItem objects.
*/
public function get customItems():Array
{
return menu.customItems;
}
/**
* Property[read-only] An object that has the following properties of the ContextMenuBuiltInItems class: forwardAndBack, loop, play, print, quality, rewind, save, and zoom.
*
* @return An object that has the following properties of the ContextMenuBuiltInItems class.
*/
public function get builtInItems():ContextMenuBuiltInItems
{
return menu.builtInItems;
}
/**
* Property[read-only], returns reference to context menu.
*
* @return ContextMenu
*/
public function get contextMenu():ContextMenu
{
return menu;
}
/**
*@private
*/
protected function createItem(caption:String, handler:Function, separatorBefore:Boolean = false, enabled:Boolean = true, visible:Boolean = true):ContextMenuItem
{
var result:ContextMenuItem = new ContextMenuItem(caption,separatorBefore,enabled,visible);
result.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,handler);
result.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,passEvent);
return result;
}
/**
*@private
*/
protected function getIndexByCaption(caption:String):int
{
for ( var i:uint = 0 ; i < menu.customItems.length ; i ++ )
{
if(menu.customItems[i].caption == caption)
{
return i;
}
}
return -1;
}
/**
* @private
*/
protected function passEvent(event:ContextMenuEvent):void
{
dispatchEvent(new ContextMenuEvent( event.type,
event.bubbles,
event.cancelable,
event.mouseTarget,
event.contextMenuOwner));
}
}
}
September 16th, 2007 at 8:41 pm
[…] http://orangeflash.eu/?p=12 […]
November 15th, 2007 at 6:23 pm
hello!
i’m clueless … i’ve tried to import this class (made the folders for class etc. put this on 1st frame and nothing happenned)
do you have a working exmple with this ? a zip package maybe will be very appreciated, keep up the good work and thank you …
January 9th, 2008 at 4:33 am
Very nice job.
Do you know if there is a way to make the contextmenu appear via Actionscript rather than right clicking the mouse?
February 8th, 2008 at 1:19 am
This is great - Thanks!
Also helpful are the javadoc comments for those of us wanting to learn about documenting custom classes…
April 24th, 2008 at 3:49 am
2Hilary
I don’t think there is any.
2Nik
Thanks
2 Cristi
Oh, sorry i was not checking comments on this blog for a long time=(