1 Reply Latest reply on Mar 12, 2010 8:57 AM by Flex harUI

    mx.controls.menu - set position of submenu flush with parent

    jpdev77sa

      My boss has issues with the Flex Menu control and it's submenu's being positioned slighty down and overlapping to the parent Menu. I have been able to change the position by extending the Menu class, but now the submenu's don't hide - they stick around when they should hide on parent item rollover or document click... anyone got a fast fix for this? I am still learning the basics, so any help with be appreciated.

       

      Thanks in advance.

       

      Custom Menu code attached: (scuse the spaced out code)

       

      package

       

      {

       

       

      import mx.controls.Menu;

       

      import mx.core.mx_internal;

       

      import flash.display.DisplayObjectContainer;

       

      import mx.controls.listClasses.IListItemRenderer;

       

      import mx.core.Application;

       

      import mx.controls.menuClasses.IMenuItemRenderer;

       

      import mx.managers.PopUpManager;

       

      import flash.geom.Point;

       

      import flash.display.DisplayObject;

       

      import flash.geom.Rectangle;

       

      import flash.utils.clearInterval;

       

       

      use namespace mx_internal;

       

       

       

      public class CustomMenu extends Menu

      {

       

      private var isDirectionLeft:Boolean = false;

       

      private var subMenu:Menu;

       

       

      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:CustomMenu;

       

       

      // check to see if the menu exists, if not create it

       

       

      if (!IMenuItemRenderer(row).menu)

      {

      menu =

      new CustomMenu();

      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 there's data and it has children then add the items

       

       

      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

      {

       

       

      //commented out can't resolve Implicit coercion error

       

       

      //menu = IMenuItemRenderer(row).menu;

      }

       

       

       

      var _do:DisplayObject = DisplayObject(row);

       

      var sandBoxRootPoint:Point = new Point(0,0);

      sandBoxRootPoint = _do.localToGlobal(sandBoxRootPoint);

       

      // when loadMovied, you may not be in global coordinates

       

       

      if (_do.root) //verify this is sufficient

      sandBoxRootPoint = _do.root.globalToLocal(sandBoxRootPoint);

       

       

       

      // showX, showY are in sandbox root coordinates

       

       

      var showY:Number = sandBoxRootPoint.y;

       

      var showX:Number;

       

      if (!isDirectionLeft)

      showX = sandBoxRootPoint.x + row.width+10;

       

      else

      showX = sandBoxRootPoint.x - menu.getExplicitOrMeasuredWidth();

       

       

       

      // convert to global coordinates to compare with getVisibleApplicationRect().

       

      // the screen is the visible coordinates of our sandbox (written in global coordinates)

       

      var screen:Rectangle = systemManager.getVisibleApplicationRect();

       

      var sbRoot:DisplayObject = systemManager.getSandboxRoot();

       

       

      var screenPoint:Point = sbRoot.localToGlobal(new Point(showX, showY));

       

       

      // do x

       

      var shift:Number = screenPoint.x + menu.getExplicitOrMeasuredWidth() - screen.right;

       

      if (shift > 0 || screenPoint.x < screen.x)

      {

       

      // if we want to ensure our parent's visible, let's

       

      // modify the shift so that we're not just on-screen

       

      // but we're also shifted away from our parent.

       

      var shiftForParent:Number = getExplicitOrMeasuredWidth() + menu.getExplicitOrMeasuredWidth();

       

       

      // if was going left, shift to right. otherwise, shift to left

       

      if (isDirectionLeft)

      shiftForParent *= -1;

       

      showX = Math.max(showX - shiftForParent, 0);

       

       

      // now make sure we're still on-screen again

      screenPoint =

      new Point(showX, showY);

      screenPoint = sbRoot.localToGlobal(screenPoint);

       

       

      // only shift if greater our position + width > width of screen

      shift = Math.max(0, screenPoint.x + width - screen.right);

       

      showX = Math.max(showX - shift, 0);

      }

       

      menu.isDirectionLeft =

      this.x > showX;

       

       

      // now do y

      shift = screenPoint.y + height - screen.bottom;

       

      if (shift > 0 || screenPoint.y < screen.y)

      showY = Math.max(showY - shift, 0);

       

      menu.show(showX, showY);

       

      subMenu = menu;

      clearInterval(openSubMenuTimer);

      openSubMenuTimer = 0;

      }

       

      }

      }