views:

56

answers:

3

So I'm trying to build a tool that will allow me and other users to all open the same .swf, and then I as the Admin user am able to interact with mine while they all see my mouse movements and button clicks etc on theirs.

I'm using BlazeDS to manage this and I'm getting data sent back and forth etc - no difficulties there. The issue I'm running into is this:

In an "Admin" instance, I click a button. I capture that X and Y, then tell Blaze to tell my clients to dispatch a Click event at that X and Y. On my client side, I get that data and dispatch a Click event at that X and Y - but the click is actually caught at the stage level. The click on my client side takes place UNDER all of my buttons and other content - so the whole thing fails.

Does this make sense? Is there a way to tell it to start the click event at the top?

A: 

Sounds like you need to set focus to the top most component of the x and y positions before dispatching the click event.

That said, I wonder what the use case is for something like this; as opposed to using a screen sharing tool such as Connect.

www.Flextras.com
It's an internal tool with specific requirements.What do you mean set focus? I'm trying to do myLoadedSWF.dispatchEvent() etc - are you saying I'd need to introspect the loaded .swf and dispatch the event on the actual button etc I'd like to have intercept it?
Myk
I'm not sure how to explain focus. The element with focus is the one that is active. You should try to set the focususing the FocusManager http://livedocs.adobe.com/flex/3/langref/mx/managers/FocusManager.html and then dispatch the appropriate event on the focused object.
www.Flextras.com
Yeah, that's not what I need. Focus is great for tabbing through but I need literally 1:1 mouse event duplication between Admin and Client.
Myk
You're original problem said that the event was being caught at stage level on the 'client' after you click on your 'server'. I suspect--and still do--that your 'client' is dispatching the 'server' event from the wrong component. Maybe you need a "coordinatesToObject" function.
www.Flextras.com
A: 

This seems like a poor way to implement what you are trying to do. If you "click" in the admin tool you are probably actually triggering some event. Why not trigger that event instead of sending the mouse click?

I'd just keep a map of actions and then when something happens in the Admin interface send the key to the action.

e.g.

In the admin:

myButton.addEventListener(MouseEvent.CLICK, handleClickButton);

function handleClickButton(event:MouseEvent):void
{
    doSomeAction();
    sendTriggerToClient(MyActions.SOME_TRIGGER);
}

In the client:

var actionMap:Object = {};
actionMap[MyActions.SOME_TRIGGER] = doSomeAction;

function receiveTriggerFromAdmin(trigger:String):void
{
    var responseFunc:Function = actionMap[trigger];
    responseFunc();
}

I hope that pseudo-code makes sense. Just abstract what happens as a result of a click into a separate function (doSomeAction) and then have the admin send a message before calling that function. In the client wait for any trigger that comes through and map it to the same function.

James Fassett
If it were up to me we'd have a complete MVC integration on all assets being loaded into this tool - then we just sync up the model to a central server, bind state to that model and only allow the admin to write updates to it.Unfortunately, this tool needs to support a vast expanse of already written .swf files. I'd like to avoid going in and retooling all of their existing content to a good architecture. This is meant to be a tool that allows someone to demo any one of their apps to any number of clients at once.So, yes - good thought, but unfortunately doesn't solve this problem.
Myk
To be more specific - the client and the admin are effectively the same application. I just have an "admin" flag I trigger in the one that I want to use to broadcast. I have to be able to use this to load in any .swf. Does that make sense?
Myk
+1  A: 

If you are unable to architect the loaded swf's to use a better architecture you could try something a little more hackish to get buttons working.

Have a look at the methods getObjectsUnderPoint and areInaccessibleObjectsUnderPoint of the DisplayObjectContainer. Combined with hasEventListener you should be able to emulate what you want.

Here is some untested pseudo-code:

function detectClick(pt:Point):void
{
    var objsUnderPoint:Array = containerStage.getObjectsUnderPoint(pt);
    var clickable:Array = [];
    for each(dispObj:DisplayObject in objsUnderPoint)
    {
        if(dispObj.hasEventListener(MouseEvent.CLICK))
        {
            clickable.push(dispObj);
        }
    }

    if(clickable.length)
    {
         // sort on depth here
         // that might be tricky since you'll be looking at grandchildren
         // and not just children but it is doable.
         var topMostClickable:DisplayObject = ???
         topMostClickable.dispatchEvent(new MouseEvent(MouseEvent.CLICK, true, false));
    }
}

areInaccessibleObjectsUnderPoint is important if you think their might be security restrictions (e.g. cross-domain issues) so you can debug if things go wrong.

Also note that you may want to (or need to) fill in more details of the MouseEvent (like the proper target, localX, localyY etc.)

James Fassett
I think this is exactly what I need. Let me wire it up and see how it goes, thanks!
Myk
Still a little tricky to implement this consistently, but this answer was spot on. Thanks, accepted.
Myk