javaswingworldwind

Disable globe movement on click in World Wind


I am trying to disable movement of the globe on mouse click in World Wind. I expected to be able to do:

void disableGlobeDrag(WorldWindowGLCanvas ww) {
    ww.addMouseMotionListener(new MyMouseMotionListener());
}

where MyMouseMotionListener consumes all of the mouse events. This is not working so instead I have to do:

void disableGlobeDrag(WorldWindowGLCanvas ww) {
    for(MouseMotionListener l : ww.getMouseMotionListeners()) {
        if(l.getClass().toString().equals("class gov.nasa.worldwind.awt.AWTInputHandler")) {
            ww.removeMouseMotionListener(l);
        }
    }
}

Is it expected that consumed mouse events should still reach the gov.nasa.worldwind.awt.AWTInputHandler listener?

Update: WorldWindowGLCanvas is just calling addMouseMotionListener() on java.awt.Component so apparently I don't understand how consuming events works.

Update 2: despite sharing interfaces with Swing, calling WorldWindowGLCanvas.removeMouseMotionListener() with AWTInputHandler as the argument will prevent all other MouseMotionListeners from receiving events. The add and remove methods on AWTInputHandler should be used instead.


Solution

  • Unfortunately removing the MouseMotionListener as @trashgod suggested does not work since there is some World Wind specific behavior happening: removing gov.nasa.worldwind.awt.AWTInputHandler causes other MouseMotionListeners to stop receiving event notifications.

    To disable globe dragging and still receive events in another MouseMotionListener the following steps were necessary:

    Get a reference to World Wind's AWTInputHandler:

    AWTInputHandler wwHandler = null;
    // get World Wind's AWTInputHandler class:
    for (MouseMotionListener l : ww.getMouseMotionListeners()) {
        if(l instanceof AWTInputHandler) {
            wwHandler = (AWTInputHandler)l;
            break;
        }
    }
    

    Create a MouseMotionListener which consumes events:

    public class MyMouseMotionListener implements MouseMotionListener {
        @Override
        public void mouseDragged(MouseEvent e) {
            // consume the event so the globe position does not change
            e.consume();
            if (e.getSource() instanceof WorldWindowGLCanvas) {
                // get the position of the mouse
                final WorldWindowGLCanvas canvas = ((WorldWindowGLCanvas) e.getSource());
                final Position p = canvas.getCurrentPosition();
                // do something with the position here
            }
        }
        @Override
        public void mouseMoved(MouseEvent e) {
            e.consume();
        }
    }
    

    Add the mouse motion listener to the AWTInputHandler:

    if(wwHandler != null) {
        wwHandler.addMouseMotionListener(new MyMouseMotionListener());
    } else {
        // I don't think this should happen unless the AWTInputHandler
        // is explicitly removed by client code
        logger.error("Couldn't find AWTInputHandler");
    }
    

    That said, I have no idea why WorldWindowGLCanvas is using Component.addMouseMotionListener() rather than AWTInputHandler.addMouseMotionListener().