X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fg2d%2Fevents%2FNodeEventHandler.java;h=ac0e36f73804b8c171db1282dabe05707c6097b9;hp=d1f6e6ef2da50f32399b0b914d4bc02692738e21;hb=bf75fd9;hpb=21f879fcd72d7749836fb64375094ef29573fe8c diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/NodeEventHandler.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/NodeEventHandler.java index d1f6e6ef2..ac0e36f73 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/NodeEventHandler.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/NodeEventHandler.java @@ -20,10 +20,12 @@ import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; +import java.awt.event.InputEvent; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.List; import org.simantics.scenegraph.INode; import org.simantics.scenegraph.g2d.G2DFocusManager; @@ -31,6 +33,7 @@ import org.simantics.scenegraph.g2d.G2DSceneGraph; import org.simantics.scenegraph.g2d.IG2DNode; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; +import org.simantics.scenegraph.g2d.events.adapter.AWTMouseEventAdapter; import org.simantics.scenegraph.g2d.events.command.CommandEvent; /** @@ -44,6 +47,8 @@ public class NodeEventHandler implements IEventHandler { private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_HANDLER_SORT = false; + private static final IEventHandler[] NONE = {}; + public static class TreePreOrderComparator implements Comparator { static enum Order { @@ -146,120 +151,129 @@ public class NodeEventHandler implements IEventHandler { TreePreOrderComparator COMPARATOR = new TreePreOrderComparator(TreePreOrderComparator.Order.DESCENDING); /** - * FocusEvents are propagated to event handlers in undefined order. + * {@link FocusEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. */ - protected ListenerList focusListeners = new ListenerList(IEventHandler.class); + protected List focusListeners = new ArrayList(); + protected IEventHandler[] sortedFocusListeners = null; /** - * TimeEvents are propagated to events handlers in an undefined order. + * {@link TimeEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. */ - protected ListenerList timeListeners = new ListenerList(IEventHandler.class); + protected List timeListeners = new ArrayList(); + protected IEventHandler[] sortedTimeListeners = null; /** - * CommandEvents are propagated first to the scene graph focus node, then to - * event handler nodes in scene graph tree pre-order. + * {@link CommandEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. */ - protected ListenerList commandListeners = new ListenerList(IEventHandler.class); + protected List commandListeners = new ArrayList(); protected IEventHandler[] sortedCommandListeners = null; /** - * KeyEvents are propagated first to the scene graph focus node, then to - * event handler nodes in scene graph tree pre-order. + * {@link KeyEvent} are propagated first to the scene graph focus node, then + * to event handler nodes in scene graph tree pre-order. */ - protected ListenerList keyListeners = new ListenerList(IEventHandler.class); + protected List keyListeners = new ArrayList(); protected IEventHandler[] sortedKeyListeners = null; /** - * MouseEvents are propagated first to the scene graph focus node, then to - * event handler nodes in scene graph tree pre-order. + * {@link MouseEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. */ - protected ListenerList mouseListeners = new ListenerList(IEventHandler.class); + protected List mouseListeners = new ArrayList(); protected IEventHandler[] sortedMouseListeners = null; + + /** + * {@link MouseDragBegin} events are propagated first to the scene graph focus node, then + * to event handler nodes in scene graph tree pre-order. + */ + protected List mouseDragBeginListeners = new ArrayList(); + protected IEventHandler[] sortedMouseDragBeginListeners = null; /** * The scene graph this instance handles event propagation for. */ protected G2DSceneGraph sg; - - protected DragSource ds = new DragSource(); + + /** + * For proper initiation of native DnD operations within this AWT-based + * scenegraph system. + */ + protected DragSource ds = new DragSource(); public NodeEventHandler(G2DSceneGraph sg) { this.sg = sg; } + @SuppressWarnings("unused") private IEventHandler[] sort(IEventHandler[] sort) { if (DEBUG_HANDLER_SORT) - debug("sort " + sort.length + " handlers"); - IEventHandler[] copy = Arrays.copyOf(sort, sort.length); - Arrays.sort(copy, COMPARATOR); - return copy; + debug("copy sort " + sort.length + " handlers"); + return sortInplace(Arrays.copyOf(sort, sort.length)); } - - public void setRootPane(Component rootPane) { - - final DragSourceListener dsl = new DragSourceListener() { - - @Override - public void dropActionChanged(DragSourceDragEvent dsde) { - } - - @Override - public void dragOver(DragSourceDragEvent dsde) { - } - - @Override - public void dragExit(DragSourceEvent dse) { - } - - @Override - public void dragEnter(DragSourceDragEvent dsde) { - } - - @Override - public void dragDropEnd(DragSourceDropEvent dsde) { - } - }; - ds.createDefaultDragGestureRecognizer(rootPane, DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK, new DragGestureListener() { - - @Override - public void dragGestureRecognized(DragGestureEvent dge) { - MouseDragBegin event = new MouseDragBegin(NodeEventHandler.this, - 0, 0, 0, 0, 0, - new Point2D.Double(),new Point2D.Double(), - new Point2D.Double(),new Point2D.Double()); - handleMouseEvent(event, EventTypes.MouseDragBegin); - if(event.transferable != null) { - ds.startDrag(dge, null, event.transferable, dsl); - if (DEBUG_EVENTS) - debug("dragGestureRecognized: startDrag " + event.transferable); - } - } - }); - ds.addDragSourceListener(dsl); - + + private IEventHandler[] sortInplace(IEventHandler[] sort) { + if (DEBUG_HANDLER_SORT) + debug("in-place sort " + sort.length + " handlers"); + Arrays.sort(sort, COMPARATOR); + return sort; } -// @Override -// public void mouseReleased(MouseEvent event) { -// Point op = event.getPoint(); -// for (MouseListener l : mouseListeners.getListeners()) { -// MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l); -// l.mouseReleased(e); -// event.translatePoint((int)(op.getX()-event.getX()), (int)(op.getY()-event.getY())); -// if (e.isConsumed()) -// break; -// } -// } -// -// @Override -// public void mouseMoved(MouseEvent event) { -// for (MouseMotionListener l : mouseMotionListeners.getListeners()) { -// MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l); -// l.mouseMoved(e); -// if (e.isConsumed()) -// break; -// } -// } + public void setRootPane(Component rootPane) { + final DragSourceListener dsl = new DragSourceListener() { + @Override + public void dropActionChanged(DragSourceDragEvent dsde) { + } + @Override + public void dragOver(DragSourceDragEvent dsde) { + } + @Override + public void dragExit(DragSourceEvent dse) { + } + @Override + public void dragEnter(DragSourceDragEvent dsde) { + } + @Override + public void dragDropEnd(DragSourceDropEvent dsde) { + } + }; + DragGestureListener dgl = new DragGestureListener() { + @Override + public void dragGestureRecognized(DragGestureEvent dge) { + InputEvent ie = dge.getTriggerEvent(); + if (ie instanceof java.awt.event.MouseEvent) { + java.awt.event.MouseEvent e = (java.awt.event.MouseEvent) ie; + Point2D controlPos = AWTMouseEventAdapter.getControlPosition(e); + MouseDragBegin event = new MouseDragBegin(NodeEventHandler.this, + e.getWhen(), 0, + AWTMouseEventAdapter.getButtonStatus(e), + AWTMouseEventAdapter.getStateMask(e), + AWTMouseEventAdapter.getMouseButton(e), + // TODO: fix canvas position if necessary + new Point2D.Double(), + controlPos, + controlPos, + AWTMouseEventAdapter.getScreenPosition(e)); + + // Send MouseDragBegin to the scenegraph and see + // if anyone sets event.transferable to start DnD. + handleMouseDragBeginEvent(event, EventTypes.MouseDragBegin); + if (event.transferable != null) { + ds.startDrag(dge, null, event.transferable, dsl); + if (DEBUG_EVENTS) + debug("dragGestureRecognized: startDrag " + event.transferable); + } + } + } + }; + ds.createDefaultDragGestureRecognizer( + rootPane, + DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK, + dgl); + ds.addDragSourceListener(dsl); + } public boolean mousePressed(MouseButtonPressedEvent event) { G2DFocusManager.INSTANCE.clearFocus(); @@ -283,47 +297,65 @@ public class NodeEventHandler implements IEventHandler { } } - private boolean handleMouseEvent(MouseEvent e, int eventType) { - IEventHandler[] sorted = sortedMouseListeners; - if (sorted == null) - sortedMouseListeners = sorted = sort(mouseListeners.getListeners()); - return handleEvent(e, sg.getFocusNode(), sorted); - } - private boolean handleEvent(Event e, IG2DNode focusNode, IEventHandler[] handlers) { + int typeMask = EventTypes.toTypeMask(e); if (focusNode instanceof IEventHandler) { IEventHandler h = (IEventHandler) focusNode; - if (eats(h.getEventMask(), EventTypes.toTypeMask(e))) { + if (eats(h.getEventMask(), typeMask)) { if (h.handleEvent(e)) return true; } } for (IEventHandler l : handlers) { - if (l.handleEvent(e)) - return true; + if (eats(l.getEventMask(), typeMask)) { + if (l.handleEvent(e)) + return true; + } } return false; } + private boolean handleMouseEvent(MouseEvent e, int eventType) { + IEventHandler[] sorted = sortedMouseListeners; + if (sorted == null) + sortedMouseListeners = sorted = sortInplace(mouseListeners.toArray(NONE)); + return handleEvent(e, sg.getFocusNode(), sorted); + } + + private boolean handleMouseDragBeginEvent(MouseEvent e, int eventType) { + IEventHandler[] sorted = sortedMouseDragBeginListeners; + if (sorted == null) + sortedMouseDragBeginListeners = sorted = sortInplace(mouseDragBeginListeners.toArray(NONE)); + // Give null for focusNode because we want to propagate + // this event in scene tree pre-order only. + return handleEvent(e, null, sorted); + } + private boolean handleFocusEvent(FocusEvent e) { - return handleEvent(e, null, focusListeners.getListeners()); + IEventHandler[] sorted = sortedFocusListeners; + if (sorted == null) + sortedFocusListeners = sorted = sortInplace(focusListeners.toArray(NONE)); + return handleEvent(e, null, sorted); } private boolean handleTimeEvent(TimeEvent e) { - return handleEvent(e, null, timeListeners.getListeners()); + IEventHandler[] sorted = sortedTimeListeners; + if (sorted == null) + sortedTimeListeners = sorted = sortInplace(timeListeners.toArray(NONE)); + return handleEvent(e, null, sorted); } private boolean handleCommandEvent(CommandEvent e) { IEventHandler[] sorted = sortedCommandListeners; if (sorted == null) - sortedCommandListeners = sorted = sort(commandListeners.getListeners()); + sortedCommandListeners = sorted = sortInplace(commandListeners.toArray(NONE)); return handleEvent(e, sg.getFocusNode(), sorted); } private boolean handleKeyEvent(KeyEvent e) { IEventHandler[] sorted = sortedKeyListeners; if (sorted == null) - sortedKeyListeners = sorted = sort(keyListeners.getListeners()); + sortedKeyListeners = sorted = sortInplace(keyListeners.toArray(NONE)); return handleEvent(e, sg.getFocusNode(), sorted); } @@ -350,11 +382,13 @@ public class NodeEventHandler implements IEventHandler { case EventTypes.KeyReleased: return handleKeyEvent((KeyEvent) e); + case EventTypes.MouseDragBegin: + return handleMouseDragBeginEvent((MouseEvent) e, eventType); + case EventTypes.MouseButtonPressed: case EventTypes.MouseButtonReleased: case EventTypes.MouseClick: case EventTypes.MouseDoubleClick: - case EventTypes.MouseDragBegin: case EventTypes.MouseEnter: case EventTypes.MouseExit: case EventTypes.MouseMoved: @@ -378,17 +412,23 @@ public class NodeEventHandler implements IEventHandler { } if (eats(mask, EventTypes.FocusMask)) { focusListeners.add(item); + sortedFocusListeners = null; } if (eats(mask, EventTypes.KeyMask)) { keyListeners.add(item); sortedKeyListeners = null; } - if (eats(mask, EventTypes.MouseMask)) { + if (eats(mask, EventTypes.MouseDragBeginMask)) { + mouseDragBeginListeners.add(item); + sortedMouseDragBeginListeners = null; + } + if (eats(mask, EventTypes.MouseMask & ~EventTypes.MouseDragBeginMask)) { mouseListeners.add(item); sortedMouseListeners = null; } if (eats(mask, EventTypes.TimeMask)) { timeListeners.add(item); + sortedTimeListeners = null; } } @@ -404,17 +444,23 @@ public class NodeEventHandler implements IEventHandler { } if (eats(mask, EventTypes.FocusMask)) { removed |= focusListeners.remove(item); + sortedFocusListeners = null; } if (eats(mask, EventTypes.KeyMask)) { removed |= keyListeners.remove(item); sortedKeyListeners = null; } - if (eats(mask, EventTypes.MouseMask)) { + if (eats(mask, EventTypes.MouseDragBeginMask)) { + removed |= mouseDragBeginListeners.remove(item); + sortedMouseDragBeginListeners = null; + } + if (eats(mask, EventTypes.MouseMask & ~EventTypes.MouseDragBeginMask)) { removed |= mouseListeners.remove(item); sortedMouseListeners = null; } if (eats(mask, EventTypes.TimeMask)) { removed |= timeListeners.remove(item); + sortedTimeListeners = null; } return removed; }