JMEDesktop and events

The only thing left for drag and drop is:


     public JMEDesktop( String name ) {
         super( name );

+        JMEDragAndDrop.getInstance().setDesktop(this);
         inputHandler = new InputHandler();



and

JMEDragSourceEvent.java, JMEDndException.java, JMEDropTargetEvent.java, JMEMouseDragGestureRecognizer.java, JMEDragSourceListener.java, JMEDropTargetListener.java, JMEDragAndDrop.java, JMEDragGestureListener.java and JMEDragGestureEvent.java from http://www.world-of-mystery.de/download/dnd.zip
There is also a TestJMEDragAndDrop.java in this zip file.

Irrisor, could you implement this into your baby when you get time? :slight_smile:

It's not so easy to judge how Swing is solving this problem - drag and drop is platform dependant.

But what I could see is that in a Swing applet the AWT events are only dispatched to a component that can handle the event while JMEDesktop sent it to my example JLabel which does not have any listeners registered (the event would be lost on a simple JLabel so there is no point to sent it there).

I began to wonder how Swing magically knows where to send the event to and there are package protected members in Component to find out whether a component can handle a certain event and they are used in the dispatching. We are not in this package so we have to find a work around. Furthermore it's not Component's duty in Swing to dispatch the event to the correct target but it's done before the event is queued as you can see in AWTListener output.



There are mouseDown() … etc. functions marked deprecated. Is that would you mean?



AFAIR you would have a problem in Swing as well if you add mouse listeners to a sub-component of a drag source but want to get the events on this sub-component dispatched to the drag source. For such a case you would most likely make the sub-component a drag source.



Regarding multiple desktops: This will get a bit more complicated as there can only be one drag and drop manager. I read the remark that there are issues with multiple JMEDesktops in javadoc so I thought this might not be a big problem. It won't stop you using multiple desktops - only the last one created will have a working drag and drop.

With multiple desktops we have to keep track of mouse events across multiple desktops (e.g. on frame1, desktop1 dragging to frame2, desktop2 JMEDesktop would have to send the mouse drag events to frame1 even with the mouse cursor on desktop2). I cannot see how JMEDesktop handles that today and IMHO this will make things more complicated than it's worth while.

I wonder if this is a really a good idea:


+            while (comp != null && comp.getMouseListeners().length == 0)
+               comp = comp.getParent();


Would this mean that dnd does not work any more if people subscribe a listener for the dragged component? What about components that implement the onMouseXXX methods instead of a listener - wouldn't they miss events? (I'm not sure whether these are deprecated though)
How did you come to the idea to do it this way, Galun? Is it like this in normal Swing event dispatching? Where?

Another point: I would like to allow using multiple JMEDesktops (some people already do this). But that line

JMEDragAndDrop.getInstance().setDesktop(this);


tells me dnd will work with only one desktop? Can this be avoided?

Maybe we can copy the behaviour of swings event dispatching. I did not investigate on that yet, but I believe it uses the event.isConsumed() stuff to decide whether it gets passed on to parent components…



Regarding multiple desktops: I'm going to need it in a project some time in the future so it will most probably be implemented. Why can't the dnd manager be per desktop? Why does it have to be a singleton?

For Swing there is only one drag and drop manager which is implemented on system level. You can drag and drop from a Swing application to a native application and vice versa. I tried to use the native manager but it fails because it does not work with lwjgl keeping the mouse grabbed.

That means if we want to copy the behaviour it would make sense to have one drag and drop manager per jME application. That's the reason I made it a singleton. Furthermore drag sources have to register with the dnd manager and that is of course easier if it's a singleton.

It's a question of design: Is a drag and drop manager per desktop useful? I think there should be one per application and should work across existing desktops. As I wrote this is not so easy as it has to work with multiple desktops at once. This is something that could be done in a second step and should be implemented by someone who uses multiple desktops. Currently I don't see a point in having more than one per application so I'm not the right person to ask for support.



On the other hand I could live with a dnd manager per desktop because I'll have only one JMEDesktop. But keep in mind that all drag sources have to register to the dnd manager, i.e. they have to find their manager and if it's a reference in JMEDesktop they have to find their JMEDesktop instance.

Any news or decisions on dnd in jME?

I have committed your files to CVS with a slight modification:

JMEDesktop does not initialize dnd support itself. Instead a program has to create JMEDragAndDrop for each desktop:

new JMEDragAndDrop( desktop );


To register a component the dragAndDropSupport (or JMEDesktop they belong to) has to be known. This allows to use multiple desktops with dnd support.
I have altered the test accordingly.

Open issues:
- no javadoc
- when start dragging in the test the crate flashes in the upper right corner
- the ACTION_COPY, ACTION_MOVE etc. stuff does not seem to be used - should it be deleted?
- listeners being empty does not necessarily mean the conponent cannot receive the event - a better workaround for accessing eventEnabled (package local in swing) should be found

Ah, thank you.



The flashing is because the dragPanel is made visible but the location is not set yet. Either we could defer the drawing to the next drag action or calculate the position in startDrag.

The easy way is to remove these two lines in startDrag():


//        dragPanel.setVisible( true );
//        dragPanel.validate();


The panel will be set to visible anyway and on the next drag event the panel will be painted.

It's true, I didn't use the drag flags but copied the behaviour from Swing. I have no objections to remove this flag as for me the program logic has to decide what the drag should mean. I use it mostly for dragging inventory item icons which can only be a move or action icons which can only be a copy. For Swing it makes sense to have this flag but I haven't found a useful application of this type flag in my game.

Meanwhile I extended the DnD so that a "freedrop" is possible. That means you can drag an icon from a container onto the desktop and the drag action will still succeed. I use that for dropping items on the ground, i.e. I get a 3d coordinate from the drop location.

The reason for checking the event listeners was that I think it's useless to deliver the event to a component that does not listen and I had several events sent to the wrong component.



I'll prepare a patch with the latest changes and maybe we can discuss that in #jme as there are some issues I had to work around.



http://www.world-of-mystery.de/download/dnd.diff

http://www.world-of-mystery.de/download/dndtest.diff

I have applied your patch - Cool already some javadoc :slight_smile:



If you want to discuss something with me please do it here.

As you can see in the patch I had to reconstruct the drop target in some cases.

The problem is the mouse listener in the recognizer gets some mouse exit events dispatched by AWT. For some containers it may happen that a mouse drag event is converted to a mouse exit event. The recognizer takes that and clears the drop target which led to unsucessful dnd operations. I haven't found a proper solution to check if it's a "real" exit event from JMEDesktop or one that comes from somewhere inside Swing. At a drop event I double check if there is a drop target below the mouse so that the drop can succeed as it should be.

In the test program it happened in about one out of ten tries.

Even if this cures the drop we miss drag over events on the drop target and it's not an ideal solution.

Galun, your patch caused a problem for Nodwick with mouse listeners - see this thread. Can you both figure out what to do to allow his mouse listeners and dnd?

I removed the two loops and drag and drop in TestJmeDesktop still works. I don't really have an explanation for this and I'm quite sure it was an issue. Maybe I did something later that obsoleted this fix.

For me it's OK to remove these loops.

Removed in CVS, too.

I just got the newest code (which was quite a difference to the version i used to work on).

By chance i ran the drag and drop test (running jdk 1.6 with java 5 compliant compiles).

Didn't work.

Nothing… not even a debug message.



Can anyone reproduce that ?

I tried the test too, it didn't work, no debug.



Dev comments?