views:

44

answers:

1

I'm trying to set up a menu. Because this menu can have a varying number of entries, I'm generating it instead of hard-coding it. The Menu object contains an Array of MenuEntry objects, and each MenuEntry has a framework.Button object which contains the text and box that actually gets drawn to the screen. I can add a MouseEvent.Click event to the Button, but not the MenuEntry. If I do it that way, though, I'm unable to access the data in the MenuEntry object that contains the button, so I don't know which MenuEntry was clicked.

The only solution I can think of involves checking the mouse position against the position of each MenuEntry, depending on the number of Menu Entries. This does not seem like the right way to do it, though, as it is not scalable. I tried having the MenuEntry class extend the Button class, so theoretically, the MenuEntry itself could dispatch mouse click events, but that didn't work.

+3  A: 

In case MenuEntry objects are not display objects, you can iterate through the array of MenuEntry and compare if the button is same as e.currentTarget to find the MenuEntry that was clicked.

button.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(e:MouseEvent):void
{
  var t:DisplayObject = DisplayObject(e.currentTarget);
  var menuEntry:MenuEntry;
  for(var i:Number = 0; i < menuEntries.length; i++)
  {
    if(menuEntries[i].button == t)
    {
      menuEntry = t;
      break;
    }
  }
  trace(menuEntry);
}

If MenuEntry items are indeed display objects, you can get a reference to them from the button's parent property

box.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(e:MouseEvent):void
{
  var t:DisplayObject = DisplayObject(e.currentTarget);
  trace(t);//traces box
  trace(t.parent);/* traces box's parent which can be 
                     the same as root if box is added
                     as child to the root */
  trace(t.root);//traces the root 
  traceParents(t);
}

traceParents(t:DisplayObject):void
{
  var p:DisplayObjectContainer = t.parent;
  while(p != null)
  {
    trace(p);
    p = p.parent;
  }
}
Amarghosh
That doesn't work. I'm trying to set up a menu. Because this menu can have a varying number of entries, I'm generating it instead of hard-coding it. The Menu object contains an array of MenuEntry object, and each MenuEntry has a framework.Button object which contains the text and box that actually gets drawn to the screen. I can add a MouseEvent.Click event to the Button, but not the MenuEntry. If I do it that way, though, I'm unable to access the data in the MenuEntry object that contains the button, so I don't know which MenuEntry was clicked.
VGambit
Just wanted to further clarify that my understanding of the parent property in Actionscript 3.0 was completely incorrect. It refers to the parent type in the object's hierarchy, not a reference to the object that the target is a member of.
VGambit
@VGambit `parent` does refer to the immediate object that the calling object is a member of - not it's type. What's preventing you from adding listener to `MenuEntry`? Is button the immediate child or a grand child of `MenuEntry`?
Amarghosh
This is the error I get if I try to add a listener directly to MenuEntry: ReferenceError: Error #1069: Property addEventListener not found on MenuEntry and there is no default value.
VGambit
I tried adding more .parents to the currentTarget, and it seems to be going through each drawable parent, not the abstract objects in between. event.currentTarget traces to Button, its parent traces to Box, then Game, then Preloader.
VGambit
Is the Button added to MenuItem or something else? what's the parent of Preloader - if you keep on traversing, when does it hit null/stage?
Amarghosh
@VGambit - `parent` goes thru each `DisplayObject` - Flash isn't aware of abstractions in your code - it knows about display objects and display object containers.
Amarghosh
The Button object is a member of MenuEntry. I tried making MenuEntry extend DisplayObject/DisplayObjectContainer, but got an error saying it could not be instantiated.
VGambit
@VGambit wait a sec - `MenuEntry` is not a DisplayObjectContainer? Then what is it? Can you edit the question and add the output of `traceParent(t)` function call that I just added to my code?
Amarghosh
It needs 5 .parents before it reaches the stage. None of the .parents represent any code I've written. The currentTarget is the Button object within the MenuEntry. I want to access the data in the MenuEntry that contains the Button that has the click event listener. A MenuEntry is just an object that contains two pieces of information that describes what kind of MenuEntry it is. The actual term MenuEntry refers to the data type, not the object name.
VGambit
@VGambit From the way you said (menu contains menuentry items which in turn contains buttons) it appeared that both menu and menuentry items are display objects (which is the normal way of doing it, rather than naming it `Box`). Iterate thru the array of menuitems and compare `if(menuitem.button == e.currentTarget)` to find the menuitem that was clicked.
Amarghosh
That's exactly the solution I was looking for. Thanks. Change your answer to that, and I will accept it.
VGambit
@VGambit done :)
Amarghosh