PureMVC Architects Lounge

Announcements and General Discussion => Architecture => Topic started by: tobydeh on January 21, 2008, 05:26:38



Title: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 05:26:38
Hello,

When using the following syntax there appears to be a problem.

var notification:String = "notificationString"
var data:Object = {'myVar':10}
menuItemMC.btnBitmap.addEventListener(MouseEvent.MOUSE_UP,function()
{
    sendNotification(notification,data);
});

When this notification is caught i add a child to the display list. The actionscript inside that child is ignored.

If i simply send the notification outside of the addEventListener everything works as expected.

There appears to be a bug in adding children to the display list from the onNotification method when the notification was dispatched from a native flash event.

I have also tried to define the function instead of typing it inline and the problem still occurs.



Title: Re: sendNotification EventListener Bug
Post by: puremvc on January 21, 2008, 05:51:28
The view components should not be sending the notifications. The mediator for the movie clip should put an event listener on the mc, then in its handler method, send the notification.

-=Cliff>


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 05:53:14
That is exactly whats happening.

The view component in the Library dispatches an event, the mediator picks it up and dispatches a notification.

The StageMediator picks up that notification and places a child on into the display list.

The code i posted was taken from the mediator, not from the movieclip.


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 05:57:00
:
private function
buildMenuItem(text:String,notification:String,data:Object):MenuItemMC
{
var format:TextFormat = new TextFormat();
            format.font = "VAGRounded LT Bold";
            format.color = 0xBEBEBE;
format.letterSpacing=1;
            format.size = 10;

var menuItemMC:MenuItemMC = new MenuItemMC();
menuItemMC.itemLabel.autoSize = TextFieldAutoSize.LEFT;
menuItemMC.name = "MenuItem";
menuItemMC.itemLabel.text = text.toUpperCase();

menu.addChild(menuItemMC);
menuItemMC.itemLabel.setTextFormat(format);
positionMenuItem(menuItemMC);
menuItemMC.button.btnBitmap.addEventListener(MouseEvent.MOUSE_UP,function()
{
sendNotification(notification,data);
});

return menuItemMC;
}


Title: Re: sendNotification EventListener Bug
Post by: puremvc on January 21, 2008, 06:15:16
Ok, except from the code above you are trying to call send notification from inside an anonymous function you're setting as the mouseup handler. That won't work! The mediator should place an event listener on the mc POINTING TO A METHOD ON THE MEDIATOR.

-=Cliff>


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 06:16:36
Why would it not work? The notification is dispatched and received that is not the problem. In my first post i mentioned that i also used a normal function instead of  the inline one above and it made no difference.


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 06:27:44
Here is the MenuMediator class...

:
package com.prettypolly.view
{
import flash.utils.getDefinitionByName;
import flash.display.MovieClip;   
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import fl.events.ColorPickerEvent;
import flash.geom.Rectangle;
import flash.display.Stage;

    import org.puremvc.interfaces.*;
    import org.puremvc.patterns.mediator.Mediator;

    import com.prettypolly.ApplicationFacade;
import com.prettypolly.model.CategoriesDataProxy;
import com.prettypolly.view.components.Menu;
import com.prettypolly.view.*;
import flash.text.TextFieldAutoSize;
import flash.text.TextField;
import flash.text.TextFormat;
   
    /**
     * A Mediator for interacting with the LoadingScreen.
     */
    public class MenuMediator extends Mediator implements IMediator
    {
public static const NAME:String = 'MenuMediator';

private static const TOP_PADDING:int = 70;
private var menuItemCount:int = 0;

private var categoriesDataProxy:CategoriesDataProxy;

        public function MenuMediator(viewComponent:Object)
        {
            super(viewComponent);
   
categoriesDataProxy = facade.retrieveProxy(CategoriesDataProxy.NAME) as CategoriesDataProxy;
        }

protected function get menu():MenuMC
{
            return viewComponent as MenuMC;
        }

        override public function getMediatorName():String
        {
            return MenuMediator.NAME;
        }

        override public function listNotificationInterests():Array
        {
return [
ApplicationFacade.MENU_CATEGORIES_LOADED
];
        }

override public function handleNotification(note:INotification):void
        {
switch (note.getName())
{
// Application Updates

// Proxy Updates
case ApplicationFacade.MENU_CATEGORIES_LOADED:
buildMenuItems();
break;
            }
        }

public function initMenu():void
{
//temp
viewComponent.clrPicker.addEventListener(ColorPickerEvent.CHANGE, onChangeColor);

categoriesDataProxy.loadMenuCategories();
}

private function buildMenuItems():void
{
var oldMenuItem:DisplayObject;
while(oldMenuItem = menu.getChildByName("MenuItem")){ menu.removeChild(oldMenuItem); }
menuItemCount = 0;

var data:Object = new Object();
data.ContentMC = ContentHomeMC;
buildMenuItem("MEMBERS",ApplicationFacade.LOAD_CONTENT, data);

var menuCategories:XMLList = categoriesDataProxy.categories;
for(var i:int = 0; i < menuCategories.length(); i++)
{
buildMenuItem(menuCategories[i].name,ApplicationFacade.LOAD_CATEGORY,{'ContentMC':ContentCategoryMC,'categoryID':menuCategories[i].@categoryID});
}

buildMenuItem("LEGSPERTS",ApplicationFacade.LOAD_CONTENT,{'ContentMC':ContentHomeMC});
buildMenuItem("NEWS",ApplicationFacade.LOAD_CONTENT,{'ContentMC':ContentHomeMC});
buildMenuItem("THE STORY",ApplicationFacade.LOAD_CONTENT,{'ContentMC':ContentHomeMC})
buildMenuItem("HOME",ApplicationFacade.LOAD_CONTENT,{'ContentMC':ContentHomeMC});
}

private function buildMenuItem(text:String,notification:String,data:Object):MenuItemMC
{
var format:TextFormat = new TextFormat();
            format.font = "VAGRounded LT Bold";
            format.color = 0xBEBEBE;
format.letterSpacing=1;
            format.size = 10;

var menuItemMC:MenuItemMC = new MenuItemMC();
menuItemMC.itemLabel.autoSize = TextFieldAutoSize.LEFT;
menuItemMC.name = "MenuItem";
menuItemMC.itemLabel.text = text.toUpperCase();

menu.addChild(menuItemMC);
menuItemMC.itemLabel.setTextFormat(format);
positionMenuItem(menuItemMC);
menuItemMC.button.btnBitmap.addEventListener(MouseEvent.MOUSE_UP,function()
{
sendNotification(notification,data);
});

return menuItemMC;
}

private function positionMenuItem(menuItemMC:MenuItemMC):void
{
menuItemCount++;

menuItemMC.y = TOP_PADDING + ((menuItemMC.height+5) * menuItemCount);
menuItemMC.x = (menu.width/2) - (menuItemMC.width/2);
menuItemMC.button.x = (menuItemMC.width/2) - (menuItemMC.button.width/2);
}

private function onChangeColor(event:ColorPickerEvent):void
{
trace("Change Color: "+ event.color)
var stageMediator:StageMediator = facade.retrieveMediator(StageMediator.NAME) as StageMediator;
StageMediator.BG_COLOR = event.color;
stageMediator.setBgColor();
}
    }
}


Title: Re: sendNotification EventListener Bug
Post by: puremvc on January 21, 2008, 06:50:15
Ok. That still doesn't help the fact that you are adding an anonymous function as the event listener, and you should instead be passing a reference to a method on the mediator itself. This anoymous function doesn't have access to a sendNotification method.

-=Cliff>


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 06:54:28
Erm... of course it does. Try for yourself.


Title: Re: sendNotification EventListener Bug
Post by: puremvc on January 21, 2008, 07:27:38
In your original post, you said:

"If i simply send the notification outside of the addEventListener everything works as expected"

Sounded like a scope problem.

Can you expand on what you meant by that part?

-=Cliff>


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 07:33:34
yes, the following happens..

MenuMediator Loads and asks CategoriesProxy to loadCategories()

loadCategories invokes my httpservice and parses the XML

When MenuMediator hears ApplicationFacade.MENU_CATEGORIES_LOADED it calls buildMenuItems()

these items, when added to the display list, are broken.

If i call buildMenuItems() directly from the constructor, and comment out loadCategories() they appear as they should do.




Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 07:34:29
Sorry i forgot to mention i have the same problem on the event listeners on the menu buttons as i do on the event listeners on the url loader.


Title: Re: sendNotification EventListener Bug
Post by: puremvc on January 21, 2008, 08:46:05
Broken in what way?

-=Cliff>


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 09:15:13
The actionscript is ignored, e.g the stop() command on the first frame of MenuItemMC


Title: Re: sendNotification EventListener Bug
Post by: Joel Hooks on January 21, 2008, 09:49:28
:
protected function get menu():MenuMC
{
            return viewComponent as MenuMC;
        }

In the mediator class you posted the viewComponent being mediated is, what I assume to be, the full menu.

Then you have this:

:
private function buildMenuItem(text:String,notification:String,data:Object):MenuItemMC
{
var format:TextFormat = new TextFormat();
            format.font = "VAGRounded LT Bold";
            format.color = 0xBEBEBE;
format.letterSpacing=1;
            format.size = 10;

var menuItemMC:MenuItemMC = new MenuItemMC();
menuItemMC.itemLabel.autoSize = TextFieldAutoSize.LEFT;
menuItemMC.name = "MenuItem";
menuItemMC.itemLabel.text = text.toUpperCase();

menu.addChild(menuItemMC);
menuItemMC.itemLabel.setTextFormat(format);
positionMenuItem(menuItemMC);
menuItemMC.button.btnBitmap.addEventListener(MouseEvent.MOUSE_UP,function()
{
sendNotification(notification,data);
});

return menuItemMC;
}

Which is instantiating a menu item, and then expecting that menu item to send pureMVC Notification via an anonymous function. Yeah?

Is the menuItemMC mediated, or is it expected to be mediated via the menuMC? As it is, I think you are putting the sendNotification outside of the scope of the mediated viewComponent when you create an instance like this. Perhaps a 'BuildMenuCommand' that instantiates the menuItemMCs with individual dynamic mediators is in order?





Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 09:57:45
Joel i do'nt think you have understood the problem

MenuMC is a movieclip of the menu.

MenuItemMC is an individual menu "button" & text etc.

The anonymous function works fine and the notification is dispatched.

The problem is that when i add children to the stage after receiving a notification they ignore their time line scripts


Title: Re: sendNotification EventListener Bug
Post by: Joel Hooks on January 21, 2008, 10:20:23
Sorry, I misread the problem. No timelines to trip me up in Flex :>


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 10:33:24
Erm.. movieclips in flex have timelines.
And you have a thick kludgy pointless framework to trip you up :)


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 21, 2008, 03:34:22
OK... it turns out this is some sort of AS3 Bug.

Imagine the following hireachy: Stage->MenuMC->ItemMC->ButtonMC

The actionscript from the first frame of ButtonMC is being ignored. This seems to be for all children at or above level 2 (Stage being level 0)

I cannot seem to figure out what triggers this bug but it does not happen when i add the menu items BEFORE instantiating my URLLoader.

For the moment i have moved all code to frame2 which isn't a very elgant solution. Is anyone else familiar with this problem?


Title: Re: sendNotification EventListener Bug
Post by: puremvc on January 21, 2008, 10:23:01
He got his flex app in my flash animation, no he got his flash animation in my Flex app. Hey chill out guys and have a PureMVC flex- apimation :)

Seriously, though...

Can you duplicate the problem without the PureMVC framework?

From your description above you should be able to write simple actionscript classes that call one another that add menuMCs that exhibit this problem.

I can think of nothing in the paths through the framework that you've described that could cause this behavior.

I did not have time to test out anything today though, as it was a long workday. I did have this ugly voodoo-like gut feeling that somehow the event bubbling process might be ony going so deep or something.

-=Cliff> 


Title: Re: sendNotification EventListener Bug
Post by: shauno on January 22, 2008, 01:34:20
Hi!

Yes, I've had this problem quite a bit before. I don't use flex, but I do use the Flex SDK to compile my apps. On one project, it happened consistently with every single symbol.. and I ended up doing the same nasty hack (putting my actions on frame 2 of each symbol). It hasn't happened to me lately, so I haven't bothered looking into it. I switched to the Flex3 SDK recently, so maybe that helped to solve the issue. Just a stab in the dark.

Good luck!

Cheers,
shaun.

ps. I should mention that this was happening to me way before I'd even heard of PureMVC, so it's definitely a Flex / AS3 thing.


Title: Re: sendNotification EventListener Bug
Post by: tobydeh on January 22, 2008, 02:21:40
Yeah i cant seem to pin-point what is causing this problem, it is definitely something to do with events.. somewhere.

I will investigate further when i have time.