Overriding Menu to include stage height bounds

I was working on a custom menu component uses Menu. Turns out that Menu doesnt inherintly understand the stage height of the application. What I ended up doing was creating CustomMenu which extends Menu and adds in height bounds for the root and any sub menu.

package com.lejnieks.poc.ui.components.menu
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.geom.Point;
 
	import mx.controls.Menu;
	import mx.controls.listClasses.IListItemRenderer;
	import mx.controls.menuClasses.IMenuItemRenderer;
	import mx.core.Application;
	import mx.core.ScrollPolicy;
	import mx.core.mx_internal;
	import mx.managers.PopUpManager;
 
	use namespace mx_internal;
 
	public class CustomMenu extends Menu
	{
		private var xpos:Object = 0;
		private var ypos:Object = 0;
 
		private const END_OF_SCREEN_MENU_PADDING:Number = 5;
 
		public function CustomMenu()
		{
			super();
		}
 
		public static function createMenu(parent:DisplayObjectContainer, mdp:Object, showRoot:Boolean=true):CustomMenu
		{
			var menu:CustomMenu = new CustomMenu();
				menu.tabEnabled = false;
				menu.owner = DisplayObjectContainer(Application.application);
				menu.showRoot = showRoot;
 
			popUpMenu(menu, parent, mdp);
 
			return menu;
		}
 
		override mx_internal function openSubMenu(row:IListItemRenderer):void
		{
			supposedToLoseFocus = true;
 
			var r:Menu = getRootMenu();
			var menu:Menu;
 
			if (!IMenuItemRenderer(row).menu)
			{
				menu = new TIPSMenu();
				menu.parentMenu = this;
				menu.owner = this;
				menu.showRoot = showRoot;
				menu.dataDescriptor = r.dataDescriptor;
				menu.styleName = r;
				menu.labelField = r.labelField;
				menu.labelFunction = r.labelFunction;
				menu.iconField = r.iconField;
				menu.iconFunction = r.iconFunction;
				menu.itemRenderer = r.itemRenderer;
				menu.rowHeight = r.rowHeight;
				menu.scaleY = r.scaleY;
				menu.scaleX = r.scaleX;
 
				if (row.data &&
					_dataDescriptor.isBranch(row.data) &&
					_dataDescriptor.hasChildren(row.data))
				{
					menu.dataProvider = _dataDescriptor.getChildren(row.data);
				}
 
				menu.sourceMenuBar = sourceMenuBar;
				menu.sourceMenuBarItem = sourceMenuBarItem;
 
				IMenuItemRenderer(row).menu = menu;
				PopUpManager.addPopUp(menu, r, false);
			}
			else
			{
				menu = IMenuItemRenderer(row).menu;
			}
 
			super.openSubMenu(row);
		}
 
		override public function show(x:Object=null, y:Object=null):void
		{
			this.xpos = x;
			this.ypos = y;
 
			var absoluteHeightOfSubMenu:Number = this.height + this.ypos;
			var appHeight:Number = Application.application.height;
 
			if( absoluteHeightOfSubMenu > appHeight )
			{
				this.ypos = Number(this.ypos) - (absoluteHeightOfSubMenu - appHeight) - END_OF_SCREEN_MENU_PADDING;
			}
 
			super.show(x, this.ypos);
		}
	}
}

Im overriding show() so that when the menu displays, if the menus height + its absolute position is greater than the application height, then it will move the menus y position up by the difference of the menu height + menu y position, and then I add in just a bit of extra padding so the menu doesn’t butt up against the bottom of the application




2 Comments

speak up

Add your comment below, or trackback from your own site.

Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

*Required Fields