You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@flex.apache.org by Dave Glasser <dg...@pobox.com> on 2015/08/10 18:44:30 UTC

Re: [BASE64] Re: Using Flex Drag Manager in AIR WindowedApplication

Alex, you're correct that DragManagerImpl does not seem to be designed to work in a multi-window AIR app. But with a few mods to DragManagerImpl and DragProxy, everything seems to be working as it should, in both the AIR app and the browser app, with the mods compiled into both.
In the constructor of the top-level (only) child of the main window, which is invoked in the main window's createChildren() method I did:
    ...
    if(Singleton.getInstance("mx.managers::IDragManager") is DragManagerImpl) {
        DragManagerImpl(DragManagerImpl.getInstance()).addEventListener("popUpChildren", onPopUpChildren);
    }
}

private function onPopUpChildren(evt:Event):void {
    evt.preventDefault();
}



And in DragManagerImpl.doDrag, I changed this:
var e:Event; 
if (hasEventListener("popUpChildren"))
    e = new DragEvent("popUpChildren", false, true, dragProxy);
if (!e || dispatchEvent(e))    
    sm.popUpChildren.addChild(dragProxy);    

to this:

var e:Event; 
if (hasEventListener("popUpChildren"))
    e = new DragEvent("popUpChildren", false, true, dragProxy);
if (!e || dispatchEvent(e))    
    sm.popUpChildren.addChild(dragProxy);    
else {
    dragInitiator.systemManager.popUpChildren.addChild(dragProxy);
}

and in DragManagerImpl.endDrag, I changed this:
if (dragProxy)
{
    sm.popUpChildren.removeChild(dragProxy);    


which would throw an error, because dragProxy was no longer parented by sm, to this:
if (dragProxy)
{
    var sysMgr:ISystemManager = dragProxy.parent as ISystemManager;
    if(sysMgr) {
        sysMgr.popUpChildren.removeChild(dragProxy);    
    }

This solved the problem with the drag image, but the mouse cursor would still appear over the main window while dragging, and that's because the DragProxy is parented by a systemManager, and the cursorManager getter in UIComponent (which dragProxy uses) will always return the main CursorManager, CursorManager.getInstance():
public function get cursorManager():ICursorManager
{
    var o:DisplayObject = parent;

    while (o)
    {
        if (o is IUIComponent && "cursorManager" in o)
        {
            var cm:ICursorManager = o["cursorManager"];
            return cm;
        }

        o = o.parent;
    }

    return CursorManager.getInstance();
}

To fix this, I overrode the cursorManager getter in DragProxy:
override public function get cursorManager():ICursorManager {
    if(dragInitiator && "cursorManager" in dragInitiator) {
        return dragInitiator["cursorManager"];
    }
    return super.cursorManager;
}

And now, knock wood, everything seems to work perfectly, with the same code running in both the AIR app and the browser app. It won't support dragging an item from one native window into another, but I don't need that.

Thanks for your help.

      From: Alex Harui <ah...@adobe.com>
 To: "users@flex.apache.org" <us...@flex.apache.org>; Dave Glasser <dg...@pobox.com> 
 Sent: Monday, August 10, 2015 3:14 AM
 Subject: [BASE64] Re: Using Flex Drag Manager in AIR WindowedApplication
   
Interesting, looks like DragManager was never written to handle multiple
AIR windows.

I did see that there is an undocumented event dispatched by the
dragManager called “popUpChildren”.  I haven’t tried it, but it looks like
if you listen for that event and call event.preventDefault, you can
reparent the DragProxy that is referenced in the event.  You should
addChild the dragProxy in the systemManager.popUpChildren for the desired
AIR Window.

HTH,
-Alex



On 8/9/15, 2:51 PM, "Dave Glasser" <dg...@pobox.com> wrote:

>Thanks Rudolf, but that didn't work. Same exact behavior. And what's
>interesting is that the mouse cursor appears over the main application
>window when I'm dragging as well. It disappears in the window in which
>I'm dragging, but the app is obviously tracking the mouse location in the
>window in which I'm dragging, because when I (blindly) drag over
>something that won't accept the drop, the mouse cursor gets the
>additional red circle-X, and when I (blindly) drop over something that
>can accept it, the drop code works as expected.
>
>      From: Rudolf Schnetler <ru...@stripedog.com>
> To: users@flex.apache.org; Dave Glasser <dg...@pobox.com>
> Sent: Sunday, August 9, 2015 5:11 PM
> Subject: Re: Using Flex Drag Manager in AIR WindowedApplication
>  
>Try setting setting 'mouseChildren = false' in the application window
>before dragging and to true when drag finished.
>
>
>
>
>
>On Mon, Aug 10, 2015 at 5:22 AM, Dave Glasser <dg...@pobox.com> wrote:
>
>> I'm using Flex 4.13.0. I'm porting a browser-based Flex app to the AIR
>> platform, as a multi-window application. The main window will be used to
>> configure server connections, and the child windows will be login
>>sessions
>> to individual servers -- essentially what you would see in the
>> browser-based application.
>>
>> The code already uses a lot of drag/drop that works well in the browser.
>> It didn't work so well in the AIR app, so I switched the AIR app to not
>>use
>> the native drag manager, but rather the same DragManagerImpl class as
>>the
>> browser app, by doing this in the main MXML file:
>>
>> <s:WindowedApplication
>>    xmlns:fx="http://ns.adobe.com/mxml/2009"
>>    xmlns:mx="library://ns.adobe.com/flex/mx"
>>    xmlns:s="library://ns.adobe.com/flex/spark"
>>    useNativeDragManager="false">
>>
>>
>> Anyway, a lot of the problems I had with the native drag manager have
>>gone
>> away. But there's one huge new problem. The DragProxy is parented by the
>> main application window, so while I'm dragging something within a child
>> window, I see my dragImage (which is parented by the DragProxy) moving
>> around within the main application window.
>>
>> In DragManagerImpl.doDrag(), I see this:
>>
>>        // The drag proxy is a UIComponent with a single child -
>>        // an instance of the dragImage.
>>        dragProxy = new DragProxy(dragInitiator, dragSource);
>>
>>        var e:Event;
>>        if (hasEventListener("popUpChildren"))
>>            e = new DragEvent("popUpChildren", false, true, dragProxy);
>>        if (!e || dispatchEvent(e))
>>            sm.popUpChildren.addChild(dragProxy);
>>
>>
>> And here, sm seems to always be the ISystemManager of the main
>>application
>> window. I don't see any other code where the DragProxy is added to the
>> display list.
>>
>>
>> Does anyone have any ideas how I can get this to work?
>>
>>
>>
>>
>
>
>