Why would a Mediator not receive an event from a View?

jansensan's Avatar

jansensan

24 Feb, 2012 05:04 PM

Hello, I have been working with RobotLegs for a while now, and for the first time I encounter something I cannot understand. In a view, I dispatch an event to which the Mediator listens, however that event seems to only be able to happen once. It's a show / hide menu action depending on what happens in the video player.

The VideoBoard.videoExpandCollapseEventHandler() function gets called properly, then I want to dispatch to the mediator so that the appropriate model can be updated. Every trace within that function work, but in the mediator, it can happen only once, and never after. Is there something that removes the listener from the mediator without me requesting it?

Below is an excerpt of my code. Any help is appreciated!

// VideoBoardMediator.as (the mediator)

override public function onRegister():void
{
    // map events
    eventMap.mapListener    (   eventDispatcher, 
                                StateModelEvent.UPDATED, 
                                stateModelUpdatedHandler,
                                StateModelEvent
                            );
    eventMap.mapListener    (   view, 
                                VideoPlayerEvent.EXPAND_TO_FULLSCREEN, 
                                dispatchExpandVideo, 
                                VideoPlayerEvent
                            );
    eventMap.mapListener    (   view, 
                                VideoPlayerEvent.COLLAPSE_FROM_FULLSCREEN, 
                                dispatchCollapseVideo, 
                                VideoPlayerEvent
                            );

    // init view
    view.scale = configModel.scale;
    view.resize(configModel.width, configModel.height);
    view.init();

    // add videos
    var i:uint;
    var numLoops:uint = videoBoardModel.numVideoVOs;
    var vo:VideoVO;
    for(i = 0; i < numLoops; i++)
    {
        vo = videoBoardModel.videoVOs[i];
        view.addVideo(vo.id, vo.imageURL, vo.vimeoId, vimeoAppService.API_KEY);
    }
}


private function stateModelUpdatedHandler(event:StateModelEvent):void
{
    if(stateModel.currentState == State.VIDEOS)
    {
        view.showVideos();
    }
    else
    {
        view.hideVideos();
    }
}


private function dispatchExpandVideo(event:VideoPlayerEvent):void
{
    trace("\n", this, "---  dispatchExpandVideo  ---");
    dispatch(event);
}


private function dispatchCollapseVideo(event:VideoPlayerEvent):void
{
    trace("\n", this, "---  dispatchCollapseVideo  ---");
    dispatch(event);
}

// VideoBoard.as (the view)

private function videoExpandCollapseEventHandler(event:VideoPlayerEvent):void
{
    trace("\n", this, "---  videoExpandCollapseEventHandler  ---");

    var video:MultiTouchVideoPlayer = event.target as MultiTouchVideoPlayer;
    var duration:Number;
    var onCompleteFunction:Function;

    var params:Object = {};
    params.scaleX = 1;
    params.scaleY = 1;
    params.onCompleteParams = [video];
    switch(event.type)
    {
        case VideoPlayerEvent.EXPAND_TO_FULLSCREEN:
            _collapsedVideoX = video.x;
            _collapsedVideoY = video.y;
            _collapsedVideoRotation = video.rotation;

            duration = 0.45;
            params.x = _width * 0.5;
            params.y = _height * 0.5;
            params.width = _width;
            params.height = _height;
            params.rotation = 0;
            params.onComplete = videoExpandComplete;
            trace("dispatch expand");
            dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.EXPAND_TO_FULLSCREEN));
            break;

        case VideoPlayerEvent.COLLAPSE_FROM_FULLSCREEN:
            video.removeVimeoPlayer();
            duration = 0.33;
            params.x = _collapsedVideoX;
            params.y = _collapsedVideoY;
            params.rotation = _collapsedVideoRotation;
            params.onComplete = videoCollapseComplete;
            trace("dispatch collapse");
            dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.COLLAPSE_FROM_FULLSCREEN));
            break;
    }
    TweenMax.to(video, duration, params);
}
  1. Support Staff 1 Posted by Shaun Smith on 24 Feb, 2012 06:00 PM

    Shaun Smith's Avatar

    Have you added break points (or traces) to onRemove() to check if the mediator is being removed for some reason?

  2. Support Staff 2 Posted by Ondina D.F. on 24 Feb, 2012 06:02 PM

    Ondina D.F.'s Avatar

    Could it be that the view gets removed/added from/to stage when you switch between StageDisplayState.NORMAL and StageDisplayState.FULL_SCREEN and its mediator gets removed/added too ?
    Can you add an event listener in the view for addedToStage (flash.events.Event.ADDED_TO_STAGE) and removedFromStage (flash.events.Event.REMOVED_FROM_STAGE) to see if this ist the case?

  3. 3 Posted by jansensan on 24 Feb, 2012 06:44 PM

    jansensan's Avatar

    @Shaun: I tried after you suggested, to no avail. Since I have no plan on removing the mediator, I overrode the onRemove() and put a breakpoint on super.onRemove(), didnt get anything.

    @Ondina: Technically, I am no really going fullscreen, even though I use the terminology. I just expand the MultiTouchVideoPlayer to fit the screen, bring in over the other children, then hide the menu that is over all that. This part works. When I collapse, the video player goes bak to its original size, all the other children are visible and available, but since the mediator does not receive the event, I cannot tell the menu (another view with its own mediator) to go back on screen.

    Conceptually, I have been wondering about what's the best way to have views talk to each other. Since no data is to be exchanged, is it ok to simply have the mediator do eventDispatcher.dispatch(SomeEvent.EVENT) and then another mediator listen to the eventDispatcher, or is it better to have a model change state, and then all mediators that need to listen to that change do so? Currently, I tried both options and now am using the latter.

  4. 4 Posted by jansensan on 24 Feb, 2012 07:21 PM

    jansensan's Avatar

    Stupid question: could TweenMax affect anything in that flow? Or could the fact that I am using FP 11.2 beta?

  5. Support Staff 5 Posted by Ondina D.F. on 24 Feb, 2012 07:32 PM

    Ondina D.F.'s Avatar

    I also thought that TweenMax could do that, so I tried it 10 minutes ago:)
    It doesn’t add or remove the views.
    Are you sure you don’t switch between some states somehow?
    Is the view dispatching the events a subview of the mediated view?
    How does your custom event class look like? Can you paste it in here?

    As for FP 11.2 beta, I have no idea if it can be the cause of the issue.

  6. Support Staff 6 Posted by Ondina D.F. on 24 Feb, 2012 07:47 PM

    Ondina D.F.'s Avatar

    Try to dispatch another custom event from the view, that is not related to the VideoPlayer stuff, to see if the mediator can hear it.

  7. 7 Posted by jansensan on 24 Feb, 2012 07:59 PM

    jansensan's Avatar

    I have tried a couple of things here:

    • revert to FP v11.1
    • rename my custom class event (either the class itself, or the event type constant)
    • dispatch any event at all (I tried Event.SOUND_COMPLETE, just to see, didn't work)

    These things did not work. Below is the current event class:

    package com.f4.slideshowss12.event
    {
        import flash.events.Event;
    
    
        /**
         * @author Mat Janson Blanchet
         */
        public class MultiTouchVideoPlayerEvent extends Event
        {
            public  static  const   COLLAPSE    :String = "COLLAPSE";
            public  static  const   EXPAND      :String = "EXPAND";
            public  static  const   TOUCH       :String = "TOUCH";
    
    
            public function MultiTouchVideoPlayerEvent  (   type:String, 
                                                    bubbles:Boolean = false, 
                                                    cancelable:Boolean = false
                                                )
            {
                super(type, bubbles, cancelable);
            }
    
    
            override public function clone():Event
            {
                return new MultiTouchVideoPlayerEvent(type, bubbles, cancelable);
            }
        }
    }
    

    As for switching states, I am trying to achieve that :) I will add more traces along the way. I tried a couple of different breakpoints, but it did not clarify anything.

    At first, the mediated view was just redispatching the event a subview was sending, now I create a new one altogether. Hey, maybe I should null the event that the handler receives? I'll try that.

    I am loading a Vimeo player in my project, maybe something conflicts with their classes? I'll try to add some ApplicationDomain constraints.

    Thanks for your time! This is really confusing me as this is not where I thought I'd hit a wall :P

  8. Support Staff 8 Posted by Ondina D.F. on 24 Feb, 2012 08:19 PM

    Ondina D.F.'s Avatar

    The custom event looks fine, indeed :)

    I don’t think that’s the issue, but just try to set bubbles=true

    dispatch any event at all (I tried Event.SOUND_COMPLETE, just to see, didn't work)

    Can you try to dispatch that event from a really simple view, having just a button inside?

    I am loading a Vimeo player in my project, maybe something conflicts with their classes? I'll try to add some ApplicationDomain constraints.

    Good look! And please let us know about your findings.
    Sorry for not being able to help you. I have to go now. Maybe Shaun or someone else will give you more hints.
    Cheers,
    Ondina

  9. Support Staff 9 Posted by Shaun Smith on 24 Feb, 2012 09:13 PM

    Shaun Smith's Avatar

    Just a quickie: you're specifying VideoPlayerEvent as the concrete event type when mapping with the EventMap, but the event code you posted was for MultiTouchVideoPlayerEvent. When specifying a concrete event, the EventMap will ignore events that aren't that exact concrete type. Could this be the issue?

  10. 10 Posted by jansensan on 24 Feb, 2012 09:19 PM

    jansensan's Avatar

    Oh, no that's not it. I posted the most recent version of that class. As I mentioned in my previous reply, I tried renaming the class or constants, in case they were conflicting with who knows what.

  11. 11 Posted by jansensan on 24 Feb, 2012 09:20 PM

    jansensan's Avatar

    Is there a way that I could send you my src directory directly? (rather than posting it publicly here?) I mean that may help, that may not either

  12. Support Staff 12 Posted by Ondina D.F. on 24 Feb, 2012 10:13 PM

    Ondina D.F.'s Avatar

    I’m going to change the discussion to private. You can attach a zip file. After that I’ll delete the attachment and change the discussion to public again. OK?

  13. 13 Posted by jansensan on 24 Feb, 2012 10:14 PM

    jansensan's Avatar

    This works with me. Thanks!

  14. 14 Posted by jansensan on 24 Feb, 2012 10:42 PM

    jansensan's Avatar

    There is the full project. It has been built with FDT.

  15. 15 Posted by jansensan on 24 Feb, 2012 10:44 PM

    jansensan's Avatar

    You may not be able to expand the videos as multitouch is necessary. I'm using TuioPad http://code.google.com/p/tuiopad/ to be able to do so.

  16. Support Staff 16 Posted by Shaun Smith on 24 Feb, 2012 10:50 PM

    Shaun Smith's Avatar

    Cool, could you give some quick instructions for reproducing the bug

  17. Support Staff 17 Posted by Ondina D.F. on 24 Feb, 2012 10:58 PM

    Ondina D.F.'s Avatar

    There is a library missing. I can’t make it work;)

  18. 18 Posted by jansensan on 24 Feb, 2012 11:00 PM

    jansensan's Avatar

    Yes!

    If you have TuioPad installed on your phone, makes sur that in the header part, the host says "incoming connection", that's by clicking on the TCP button. Also, there is a message that says "current network adress is...", that adress should be put into deploy/flash-config.xml in the humanInterface ip attribute. You may also set the scale and fps to fit your screen.

    A menu is visible on the right when you load the app. Keep your finger down (or mouse) on the video section until the timer fills up. The video thumbnails will slide in. Here you do need multitouch, for you need to reverse pinch the thumbs to expand the video. At that moment, the menu hides automatically. When you pinch once in fullscreen mode, the video reverts to small mode, this is where the collapse event should fire but does not, leaving the menu out of sight.

    I hope that is helpful :)

  19. 19 Posted by jansensan on 24 Feb, 2012 11:05 PM

    jansensan's Avatar

    Can you tell me what could be missing? All is included. Attached is an image that shows all the libraries that should be there and added to class paths. The closed directories are not used yet.

    You're awesome for helping me!

  20. Support Staff 20 Posted by Ondina D.F. on 24 Feb, 2012 11:08 PM

    Ondina D.F.'s Avatar

    Can you tell me what could be missing?

    everything under net.jansensan

  21. 21 Posted by jansensan on 24 Feb, 2012 11:10 PM

    jansensan's Avatar

    For real? It should be there in the export... odd, anywho, here is the swc that should be in the libs/as3jansensanlib directory

  22. Support Staff 22 Posted by Ondina D.F. on 24 Feb, 2012 11:11 PM

    Ondina D.F.'s Avatar

    I got it, but I won't be able to use TuioPad though.

  23. Support Staff 23 Posted by Shaun Smith on 24 Feb, 2012 11:12 PM

    Shaun Smith's Avatar

    Here you do need multitouch, for you need to reverse pinch the thumbs to expand the video. At that moment, the menu hides automatically. When you pinch once in fullscreen mode, the video reverts to small mode, this is where the collapse event should fire but does not, leaving the menu out of sight.

    Where do these things happen in the code?

    I don't think I'll be able to get this up and running locally - too many pieces, and I don't have a phone to test on. Nevertheless, I'm sure we can get to the bottom of it.

  24. 24 Posted by jansensan on 24 Feb, 2012 11:17 PM

    jansensan's Avatar

    It happens in the com.f4.slideshowss12.view.videoboard package.

    VideoBoardMediator is the mediator
    VideoBoard is the mediated view
    MultiTouchVideoPlayer is a subview of VideoBoard
    VimeoPlayer is a subview of MultiTouchVideoPlayer

    MultiTouchVideoPlayer.dispatchExpand and MultiTouchVideoPlayer.dispatchCollapse are the functions that initially send the event.

    VideoBoard.videoExpandCollapseEventHandler() receives them and redispatches them to its mediator. The mediator dispatches the event further for commands. These are mapped in the com.f4.slideshowss12.controller.InitAppCommand class

    This will function only once the video is expanded, the full process works. Then afterwards visually the video can expand, but the events dont travel

  25. Support Staff 25 Posted by Shaun Smith on 24 Feb, 2012 11:19 PM

    Shaun Smith's Avatar

    As a test, everywhere where you have mediatorMap.mapView(..) (and where it makes sense to do so), try setting autoRemove to false (the last parameter of mapView), just to be sure that mediators aren't being removed.

    Just got your last message, will take a look..

  26. 26 Posted by jansensan on 24 Feb, 2012 11:30 PM

    jansensan's Avatar

    So I added those parameters, it works a couple of times now, then stops again... I guess it must be something I'm doing wrong?

  27. Support Staff 27 Posted by Shaun Smith on 24 Feb, 2012 11:37 PM

    Shaun Smith's Avatar

    If that's the case, then it sounds like something is being GC'd. Does VideoBoard ever leave the stage?

  28. 28 Posted by jansensan on 24 Feb, 2012 11:40 PM

    jansensan's Avatar

    It should not, as I always need it there. And it contains the videos, which are always visible, I do not take it out of the stage myself. I'll try something without the Vimeo stuff at all, see if it interferes. I have put it in it's own application domain, but that may not be enough.

  29. Support Staff 29 Posted by Shaun Smith on 24 Feb, 2012 11:41 PM

    Shaun Smith's Avatar

    In VideoBoardMediator's onRegister(), where you map the EXPAND and COLLAPSE handlers with the EventMap, try setting useWeakReference to false (the final parameter of mapListener). If that solves the issue then you've got GC issues.

  30. Support Staff 30 Posted by Shaun Smith on 24 Feb, 2012 11:43 PM

    Shaun Smith's Avatar

    Also, put a trace in the overridden onRemove() just to be sure that it's not getting called at any point.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac