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 Responses to “Overriding Menu to include stage height bounds”

Leave a Reply