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=1c1ac8a37a7b523ace66705188f148c1972ed763;hp=d1f6e6ef2da50f32399b0b914d4bc02692738e21;hb=1ee8004c71eaa9818fe1a49e16d0463adbf559f6;hpb=969bd23cab98a79ca9101af33334000879fb60c5 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..1c1ac8a37 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 @@ -1,331 +1,367 @@ -/******************************************************************************* - * Copyright (c) 2007, 2011 Association for Decentralized Information Management in - * Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ +/******************************************************************************* + * Copyright (c) 2007, 2011 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ package org.simantics.scenegraph.g2d.events; -import java.awt.Component; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragGestureEvent; -import java.awt.dnd.DragGestureListener; -import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceDragEvent; -import java.awt.dnd.DragSourceDropEvent; -import java.awt.dnd.DragSourceEvent; -import java.awt.dnd.DragSourceListener; -import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; - -import org.simantics.scenegraph.INode; -import org.simantics.scenegraph.g2d.G2DFocusManager; -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.command.CommandEvent; - -/** - * Delivers events (mouse, key, focus, command, time) to scene graph nodes that - * have registered to receive them. - * - * @author Tuukka Lehtonen +import java.awt.Component; +import java.awt.GraphicsEnvironment; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +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; +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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Delivers events (mouse, key, focus, command, time) to scene graph nodes that + * have registered to receive them. + * + * @author Tuukka Lehtonen */ public class NodeEventHandler implements IEventHandler { - - private static final boolean DEBUG_EVENTS = false; - private static final boolean DEBUG_HANDLER_SORT = false; - - public static class TreePreOrderComparator implements Comparator { - - static enum Order { - ASCENDING, - DESCENDING - } - - static class Temp { - ArrayList path1 = new ArrayList(); - ArrayList path2 = new ArrayList(); - } - - private transient ThreadLocal temp = new ThreadLocal() { - protected Temp initialValue() { - return new Temp(); - } - }; - - Order order; - - public TreePreOrderComparator(Order order) { - this.order = order; - } - - void getTreePath(INode node, ArrayList result) { - result.clear(); - for (INode parent = node.getParent(); parent != null; parent = parent.getParent()) - result.add(parent); - } - - void notSameGraph(INode o1, INode o2) { - throw new IllegalStateException("nodes " + o1 + " and " + o2 - + " not part of same scene graph.\n\t root 1: " + o1.getRootNode() + "\n\troot 2: " - + o2.getRootNode()); - } - - @Override - public int compare(IEventHandler e1, IEventHandler e2) { - if (e1 == e2) - return 0; - - Temp tmp = temp.get(); - ArrayList path1 = tmp.path1; - ArrayList path2 = tmp.path2; - - // Get path to root node for both nodes - INode o1 = (INode) e1; - INode o2 = (INode) e2; - getTreePath(o1, path1); - getTreePath(o2, path2); - - // Sanity checks: nodes part of same scene graph - INode root1 = path1.isEmpty() ? o1 : path1.get(path1.size() - 1); - INode root2 = path2.isEmpty() ? o2 : path2.get(path2.size() - 1); - if (root1 != root2) - notSameGraph(o1, o2); - - try { - // Find first non-matching nodes in the paths starting from the root node - int i1 = path1.size() - 1; - int i2 = path2.size() - 1; - for (; i1 >= 0 && i2 >= 0; --i1, --i2) { - INode p1 = path1.get(i1); - INode p2 = path2.get(i2); - if (p1 != p2) { - break; - } - } - - // Pre-order: a node that is on the tree path of another node is first - if (i1 < 0) - return Order.ASCENDING == order ? -1 : 1; - if (i2 < 0) - return Order.ASCENDING == order ? 1 : -1; - - INode n1 = path1.get(i1); - INode n2 = path2.get(i2); - IG2DNode g1 = n1 instanceof IG2DNode ? (IG2DNode) n1 : null; - IG2DNode g2 = n2 instanceof IG2DNode ? (IG2DNode) n2 : null; - if (g1 != null && g2 != null) { - int z1 = g1.getZIndex(); - int z2 = g2.getZIndex(); - int c = compare(z1, z2); - return order == Order.ASCENDING ? c : -c; - } - // Can't sort non-IG2DNodes. - return 0; - } finally { - // Don't hold on to objects unnecessarily - path1.clear(); - path2.clear(); - } - } - - private int compare(int v1, int v2) { - return v1 < v2 ? -1 : (v1 > v2 ? 1 : 0); - } - }; - - TreePreOrderComparator COMPARATOR = new TreePreOrderComparator(TreePreOrderComparator.Order.DESCENDING); - - /** - * FocusEvents are propagated to event handlers in undefined order. - */ - protected ListenerList focusListeners = new ListenerList(IEventHandler.class); - - /** - * TimeEvents are propagated to events handlers in an undefined order. - */ - protected ListenerList timeListeners = new ListenerList(IEventHandler.class); - - /** - * CommandEvents 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 IEventHandler[] sortedCommandListeners = null; - - /** - * KeyEvents 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 IEventHandler[] sortedKeyListeners = null; - - /** - * MouseEvents 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 IEventHandler[] sortedMouseListeners = null; - - /** - * The scene graph this instance handles event propagation for. - */ - protected G2DSceneGraph sg; - - protected DragSource ds = new DragSource(); - - public NodeEventHandler(G2DSceneGraph sg) { + + private static final Logger LOGGER = LoggerFactory.getLogger(NodeEventHandler.class); + + 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 { + ASCENDING, + DESCENDING + } + + static class Temp { + ArrayList path1 = new ArrayList(); + ArrayList path2 = new ArrayList(); + } + + private transient ThreadLocal temp = new ThreadLocal() { + protected Temp initialValue() { + return new Temp(); + } + }; + + Order order; + + public TreePreOrderComparator(Order order) { + this.order = order; + } + + void getTreePath(INode node, ArrayList result) { + result.clear(); + for (; node != null; node = node.getParent()) + result.add(node); + } + + void notSameGraph(INode o1, INode o2) { + throw new IllegalStateException("nodes " + o1 + " and " + o2 + + " not part of same scene graph.\n\t root 1: " + o1.getRootNode() + "\n\troot 2: " + + o2.getRootNode()); + } + + @Override + public int compare(IEventHandler e1, IEventHandler e2) { + if (e1 == e2) + return 0; + + Temp tmp = temp.get(); + ArrayList path1 = tmp.path1; + ArrayList path2 = tmp.path2; + + try { + // Get path to root node for both nodes + getTreePath((INode) e1, path1); + getTreePath((INode) e2, path2); + + // Sanity checks: nodes part of same scene graph + if (path1.get(path1.size() - 1) != path2.get(path2.size() - 1)) + notSameGraph((INode)e1, (INode)e2); + + // Find first non-matching nodes in the paths starting from the root node + int i1 = path1.size() - 1; + int i2 = path2.size() - 1; + for (; i1 >= 0 && i2 >= 0; --i1, --i2) { + INode p1 = path1.get(i1); + INode p2 = path2.get(i2); + if (p1 != p2) { + break; + } + } + + // Pre-order: a node that is on the tree path of another node is first + if (i1 < 0) + return Order.ASCENDING == order ? -1 : 1; + if (i2 < 0) + return Order.ASCENDING == order ? 1 : -1; + + return compare(path1.get(i1), path2.get(i2)); + } finally { + // Don't hold on to objects unnecessarily + path1.clear(); + path2.clear(); + } + } + + private int compare(INode n1, INode n2) { + if(n1 instanceof IG2DNode) { + if(n2 instanceof IG2DNode) { + int z1 = ((IG2DNode)n1).getZIndex(); + int z2 = ((IG2DNode)n2).getZIndex(); + int c = Integer.compare(z1, z2); + return order == Order.ASCENDING ? c : -c; + } + else + return -1; // sort IG2DNodes before non-IG2DNodes + } + else { + if(n2 instanceof IG2DNode) + return 1; + else + return 0; // all non-IG2DNodes are equal in comparison + } + } + }; + + TreePreOrderComparator COMPARATOR = new TreePreOrderComparator(TreePreOrderComparator.Order.DESCENDING); + + /** + * {@link FocusEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. + */ + protected List focusListeners = new ArrayList(); + protected IEventHandler[] sortedFocusListeners = null; + + /** + * {@link TimeEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. + */ + protected List timeListeners = new ArrayList(); + protected IEventHandler[] sortedTimeListeners = null; + + /** + * {@link CommandEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. + */ + protected List commandListeners = new ArrayList(); + protected IEventHandler[] sortedCommandListeners = null; + + /** + * {@link KeyEvent} are propagated first to the scene graph focus node, then + * to event handler nodes in scene graph tree pre-order. + */ + protected List keyListeners = new ArrayList(); + protected IEventHandler[] sortedKeyListeners = null; + + /** + * {@link MouseEvent} are propagated first to the scene graph focus node, + * then to event handler nodes in scene graph tree pre-order. + */ + 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; + + public NodeEventHandler(G2DSceneGraph sg) { this.sg = sg; } - - 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; - } - - 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); - - } - -// @Override -// public void mouseReleased(MouseEvent event) { + + @SuppressWarnings("unused") + private IEventHandler[] sort(IEventHandler[] sort) { + if (DEBUG_HANDLER_SORT) + debug("copy sort " + sort.length + " handlers"); + return sortInplace(Arrays.copyOf(sort, sort.length)); + } + + private IEventHandler[] sortInplace(IEventHandler[] sort) { + if (DEBUG_HANDLER_SORT) + debug("in-place sort " + sort.length + " handlers"); + Arrays.sort(sort, COMPARATOR); + return sort; + } + + public void setRootPane(Component rootPane) { + if (GraphicsEnvironment.isHeadless()) { + LOGGER.info("Disabling DragSource in headless environments"); + return; + } + final DragSource ds = new DragSource(); + 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(); + try { // Point op = event.getPoint(); // for (MouseListener l : mouseListeners.getListeners()) { // MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l); -// l.mouseReleased(e); +// l.mousePressed(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 boolean mousePressed(MouseButtonPressedEvent event) { - G2DFocusManager.INSTANCE.clearFocus(); - try { -// Point op = event.getPoint(); -// for (MouseListener l : mouseListeners.getListeners()) { -// MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l); -// l.mousePressed(e); -// event.translatePoint((int)(op.getX()-event.getX()), (int)(op.getY()-event.getY())); -// if (e.isConsumed()) -// break; -// } - return false; - } finally { - if (sg.getRootPane() != null) { - if (G2DFocusManager.INSTANCE.getFocusOwner() == null) { - sg.getRootPane().requestFocusInWindow(); - //sg.getRootPane().repaint(); //TODO : why repaint here? FocusOwner seems to be always null, so this causes unnecessary delays when interacting the canvas. - } - } - } - } - - 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) { - if (focusNode instanceof IEventHandler) { - IEventHandler h = (IEventHandler) focusNode; - if (eats(h.getEventMask(), EventTypes.toTypeMask(e))) { - if (h.handleEvent(e)) - return true; - } - } - for (IEventHandler l : handlers) { - if (l.handleEvent(e)) - return true; - } - return false; - } - - private boolean handleFocusEvent(FocusEvent e) { - return handleEvent(e, null, focusListeners.getListeners()); - } - - private boolean handleTimeEvent(TimeEvent e) { - return handleEvent(e, null, timeListeners.getListeners()); - } - - private boolean handleCommandEvent(CommandEvent e) { - IEventHandler[] sorted = sortedCommandListeners; - if (sorted == null) - sortedCommandListeners = sorted = sort(commandListeners.getListeners()); - return handleEvent(e, sg.getFocusNode(), sorted); - } - - private boolean handleKeyEvent(KeyEvent e) { - IEventHandler[] sorted = sortedKeyListeners; - if (sorted == null) - sortedKeyListeners = sorted = sort(keyListeners.getListeners()); - return handleEvent(e, sg.getFocusNode(), sorted); - } + return false; + } finally { + if (sg.getRootPane() != null) { + if (G2DFocusManager.INSTANCE.getFocusOwner() == null) { + sg.getRootPane().requestFocusInWindow(); + //sg.getRootPane().repaint(); //TODO : why repaint here? FocusOwner seems to be always null, so this causes unnecessary delays when interacting the canvas. + } + } + } + } + + 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(), typeMask)) { + if (h.handleEvent(e)) + return true; + } + } + for (IEventHandler l : handlers) { + 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) { + IEventHandler[] sorted = sortedFocusListeners; + if (sorted == null) + sortedFocusListeners = sorted = sortInplace(focusListeners.toArray(NONE)); + return handleEvent(e, null, sorted); + } + + private boolean handleTimeEvent(TimeEvent e) { + 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 = sortInplace(commandListeners.toArray(NONE)); + return handleEvent(e, sg.getFocusNode(), sorted); + } + + private boolean handleKeyEvent(KeyEvent e) { + IEventHandler[] sorted = sortedKeyListeners; + if (sorted == null) + sortedKeyListeners = sorted = sortInplace(keyListeners.toArray(NONE)); + return handleEvent(e, sg.getFocusNode(), sorted); + } @Override public int getEventMask() { @@ -333,116 +369,130 @@ public class NodeEventHandler implements IEventHandler { } @Override - public boolean handleEvent(Event e) { - if (DEBUG_EVENTS) - debug("handle event: " + e); + public boolean handleEvent(Event e) { + if (DEBUG_EVENTS) + debug("handle event: " + e); int eventType = EventTypes.toType(e); switch (eventType) { - case EventTypes.Command: - return handleCommandEvent((CommandEvent) e); - - case EventTypes.FocusGained: - case EventTypes.FocusLost: - return handleFocusEvent((FocusEvent) e); - - case EventTypes.KeyPressed: - case EventTypes.KeyReleased: - return handleKeyEvent((KeyEvent) e); - - case EventTypes.MouseButtonPressed: - case EventTypes.MouseButtonReleased: - case EventTypes.MouseClick: - case EventTypes.MouseDoubleClick: - case EventTypes.MouseDragBegin: - case EventTypes.MouseEnter: - case EventTypes.MouseExit: - case EventTypes.MouseMoved: - case EventTypes.MouseWheel: - return handleMouseEvent((MouseEvent) e, eventType); - + case EventTypes.Command: + return handleCommandEvent((CommandEvent) e); + + case EventTypes.FocusGained: + case EventTypes.FocusLost: + return handleFocusEvent((FocusEvent) e); + + case EventTypes.KeyPressed: + 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.MouseEnter: + case EventTypes.MouseExit: + case EventTypes.MouseMoved: + case EventTypes.MouseWheel: + return handleMouseEvent((MouseEvent) e, eventType); + case EventTypes.Time: - return handleTimeEvent((TimeEvent) e); - } + return handleTimeEvent((TimeEvent) e); + } return false; - } - - public void add(IEventHandler item) { - if (!(item instanceof IG2DNode)) - throw new IllegalArgumentException("event handler must be an IG2DNode"); - - int mask = item.getEventMask(); - if (eats(mask, EventTypes.CommandMask)) { - commandListeners.add(item); - sortedCommandListeners = null; - } - if (eats(mask, EventTypes.FocusMask)) { - focusListeners.add(item); - } - if (eats(mask, EventTypes.KeyMask)) { - keyListeners.add(item); - sortedKeyListeners = null; - } - if (eats(mask, EventTypes.MouseMask)) { - mouseListeners.add(item); - sortedMouseListeners = null; - } - if (eats(mask, EventTypes.TimeMask)) { - timeListeners.add(item); - } - } - - public boolean remove(IEventHandler item) { - if (!(item instanceof IG2DNode)) - throw new IllegalArgumentException("event handler must be an IG2DNode"); - - int mask = item.getEventMask(); - boolean removed = false; - if (eats(mask, EventTypes.CommandMask)) { - removed |= commandListeners.remove(item); - sortedCommandListeners = null; - } - if (eats(mask, EventTypes.FocusMask)) { - removed |= focusListeners.remove(item); - } - if (eats(mask, EventTypes.KeyMask)) { - removed |= keyListeners.remove(item); - sortedKeyListeners = null; - } - if (eats(mask, EventTypes.MouseMask)) { - removed |= mouseListeners.remove(item); - sortedMouseListeners = null; - } - if (eats(mask, EventTypes.TimeMask)) { - removed |= timeListeners.remove(item); - } - return removed; - } - - private static boolean eats(int handlerMask, int eventTypeMask) { - return (handlerMask & eventTypeMask) != 0; - } - - private void debug(String msg) { - System.out.println(getClass().getSimpleName() + ": " + msg); - } - - public void dispose() { - commandListeners.clear(); - commandListeners = null; - focusListeners.clear(); - focusListeners = null; - keyListeners.clear(); - keyListeners = null; - mouseListeners.clear(); - mouseListeners = null; - sg = null; - sortedCommandListeners = null; - sortedKeyListeners = null; - sortedMouseListeners = null; - - timeListeners.clear(); - timeListeners = null; - } - + } + + public void add(IEventHandler item) { + if (!(item instanceof IG2DNode)) + throw new IllegalArgumentException("event handler must be an IG2DNode"); + + int mask = item.getEventMask(); + if (eats(mask, EventTypes.CommandMask)) { + commandListeners.add(item); + sortedCommandListeners = null; + } + if (eats(mask, EventTypes.FocusMask)) { + focusListeners.add(item); + sortedFocusListeners = null; + } + if (eats(mask, EventTypes.KeyMask)) { + keyListeners.add(item); + sortedKeyListeners = null; + } + 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; + } + } + + public boolean remove(IEventHandler item) { + if (!(item instanceof IG2DNode)) + throw new IllegalArgumentException("event handler must be an IG2DNode"); + + int mask = item.getEventMask(); + boolean removed = false; + if (eats(mask, EventTypes.CommandMask)) { + removed |= commandListeners.remove(item); + sortedCommandListeners = null; + } + 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.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; + } + + private static boolean eats(int handlerMask, int eventTypeMask) { + return (handlerMask & eventTypeMask) != 0; + } + + private void debug(String msg) { + System.out.println(getClass().getSimpleName() + ": " + msg); + } + + public void dispose() { + commandListeners.clear(); + commandListeners = null; + focusListeners.clear(); + focusListeners = null; + keyListeners.clear(); + keyListeners = null; + mouseListeners.clear(); + mouseListeners = null; + sg = null; + sortedCommandListeners = null; + sortedKeyListeners = null; + sortedMouseListeners = null; + + timeListeners.clear(); + timeListeners = null; + } + }