-/*******************************************************************************\r
- * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
+/*******************************************************************************
+ * 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;\r
-import java.awt.dnd.DnDConstants;\r
-import java.awt.dnd.DragGestureEvent;\r
-import java.awt.dnd.DragGestureListener;\r
-import java.awt.dnd.DragSource;\r
-import java.awt.dnd.DragSourceDragEvent;\r
-import java.awt.dnd.DragSourceDropEvent;\r
-import java.awt.dnd.DragSourceEvent;\r
-import java.awt.dnd.DragSourceListener;\r
-import java.awt.event.InputEvent;\r
-import java.awt.geom.Point2D;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.Comparator;\r
-import java.util.List;\r
-\r
-import org.simantics.scenegraph.INode;\r
-import org.simantics.scenegraph.g2d.G2DFocusManager;\r
-import org.simantics.scenegraph.g2d.G2DSceneGraph;\r
-import org.simantics.scenegraph.g2d.IG2DNode;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
-import org.simantics.scenegraph.g2d.events.adapter.AWTMouseEventAdapter;\r
-import org.simantics.scenegraph.g2d.events.command.CommandEvent;\r
-
-/**\r
- * Delivers events (mouse, key, focus, command, time) to scene graph nodes that\r
- * have registered to receive them.\r
- * \r
- * @author Tuukka Lehtonen\r
+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.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 {
-\r
- private static final boolean DEBUG_EVENTS = false;\r
- private static final boolean DEBUG_HANDLER_SORT = false;\r
-\r
- private static final IEventHandler[] NONE = {};\r
-\r
- public static class TreePreOrderComparator implements Comparator<IEventHandler> {\r
-\r
- static enum Order {\r
- ASCENDING,\r
- DESCENDING\r
- }\r
-\r
- static class Temp {\r
- ArrayList<INode> path1 = new ArrayList<INode>();\r
- ArrayList<INode> path2 = new ArrayList<INode>();\r
- }\r
-\r
- private transient ThreadLocal<Temp> temp = new ThreadLocal<Temp>() {\r
- protected Temp initialValue() {\r
- return new Temp();\r
- }\r
- };\r
-\r
- Order order;\r
-\r
- public TreePreOrderComparator(Order order) {\r
- this.order = order;\r
- }\r
-\r
- void getTreePath(INode node, ArrayList<INode> result) {\r
- result.clear();\r
- for (INode parent = node.getParent(); parent != null; parent = parent.getParent())\r
- result.add(parent);\r
- }\r
-\r
- void notSameGraph(INode o1, INode o2) {\r
- throw new IllegalStateException("nodes " + o1 + " and " + o2\r
- + " not part of same scene graph.\n\t root 1: " + o1.getRootNode() + "\n\troot 2: "\r
- + o2.getRootNode());\r
- }\r
-\r
- @Override\r
- public int compare(IEventHandler e1, IEventHandler e2) {\r
- if (e1 == e2)\r
- return 0;\r
-\r
- Temp tmp = temp.get();\r
- ArrayList<INode> path1 = tmp.path1;\r
- ArrayList<INode> path2 = tmp.path2;\r
-\r
- // Get path to root node for both nodes\r
- INode o1 = (INode) e1;\r
- INode o2 = (INode) e2;\r
- getTreePath(o1, path1);\r
- getTreePath(o2, path2);\r
-\r
- // Sanity checks: nodes part of same scene graph\r
- INode root1 = path1.isEmpty() ? o1 : path1.get(path1.size() - 1);\r
- INode root2 = path2.isEmpty() ? o2 : path2.get(path2.size() - 1);\r
- if (root1 != root2)\r
- notSameGraph(o1, o2);\r
-\r
- try {\r
- // Find first non-matching nodes in the paths starting from the root node\r
- int i1 = path1.size() - 1;\r
- int i2 = path2.size() - 1;\r
- for (; i1 >= 0 && i2 >= 0; --i1, --i2) {\r
- INode p1 = path1.get(i1);\r
- INode p2 = path2.get(i2);\r
- if (p1 != p2) {\r
- break;\r
- }\r
- }\r
-\r
- // Pre-order: a node that is on the tree path of another node is first\r
- if (i1 < 0)\r
- return Order.ASCENDING == order ? -1 : 1;\r
- if (i2 < 0)\r
- return Order.ASCENDING == order ? 1 : -1;\r
-\r
- INode n1 = path1.get(i1);\r
- INode n2 = path2.get(i2);\r
- IG2DNode g1 = n1 instanceof IG2DNode ? (IG2DNode) n1 : null;\r
- IG2DNode g2 = n2 instanceof IG2DNode ? (IG2DNode) n2 : null;\r
- if (g1 != null && g2 != null) {\r
- int z1 = g1.getZIndex();\r
- int z2 = g2.getZIndex();\r
- int c = compare(z1, z2);\r
- return order == Order.ASCENDING ? c : -c;\r
- }\r
- // Can't sort non-IG2DNodes.\r
- return 0;\r
- } finally {\r
- // Don't hold on to objects unnecessarily\r
- path1.clear();\r
- path2.clear();\r
- }\r
- }\r
-\r
- private int compare(int v1, int v2) {\r
- return v1 < v2 ? -1 : (v1 > v2 ? 1 : 0);\r
- }\r
- };\r
-\r
- TreePreOrderComparator COMPARATOR = new TreePreOrderComparator(TreePreOrderComparator.Order.DESCENDING);\r
-\r
- /**\r
- * {@link FocusEvent} are propagated first to the scene graph focus node,\r
- * then to event handler nodes in scene graph tree pre-order.\r
- */\r
- protected List<IEventHandler> focusListeners = new ArrayList<IEventHandler>();\r
- protected IEventHandler[] sortedFocusListeners = null;\r
-\r
- /**\r
- * {@link TimeEvent} are propagated first to the scene graph focus node,\r
- * then to event handler nodes in scene graph tree pre-order.\r
- */\r
- protected List<IEventHandler> timeListeners = new ArrayList<IEventHandler>();\r
- protected IEventHandler[] sortedTimeListeners = null;\r
-\r
- /**\r
- * {@link CommandEvent} are propagated first to the scene graph focus node,\r
- * then to event handler nodes in scene graph tree pre-order.\r
- */\r
- protected List<IEventHandler> commandListeners = new ArrayList<IEventHandler>();\r
- protected IEventHandler[] sortedCommandListeners = null;\r
-\r
- /**\r
- * {@link KeyEvent} are propagated first to the scene graph focus node, then\r
- * to event handler nodes in scene graph tree pre-order.\r
- */\r
- protected List<IEventHandler> keyListeners = new ArrayList<IEventHandler>();\r
- protected IEventHandler[] sortedKeyListeners = null;\r
-\r
- /**\r
- * {@link MouseEvent} are propagated first to the scene graph focus node,\r
- * then to event handler nodes in scene graph tree pre-order.\r
- */\r
- protected List<IEventHandler> mouseListeners = new ArrayList<IEventHandler>();\r
- protected IEventHandler[] sortedMouseListeners = null;\r
-\r
- /**\r
- * {@link MouseDragBegin} events are propagated first to the scene graph focus node, then\r
- * to event handler nodes in scene graph tree pre-order.\r
- */\r
- protected List<IEventHandler> mouseDragBeginListeners = new ArrayList<IEventHandler>();\r
- protected IEventHandler[] sortedMouseDragBeginListeners = null;\r
-
- /**\r
- * The scene graph this instance handles event propagation for.\r
- */\r
- protected G2DSceneGraph sg;\r
-\r
- /**\r
- * For proper initiation of native DnD operations within this AWT-based\r
- * scenegraph system.\r
- */\r
- protected DragSource ds = new DragSource();\r
-
- public NodeEventHandler(G2DSceneGraph sg) {\r
+
+ 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<IEventHandler> {
+
+ static enum Order {
+ ASCENDING,
+ DESCENDING
+ }
+
+ static class Temp {
+ ArrayList<INode> path1 = new ArrayList<INode>();
+ ArrayList<INode> path2 = new ArrayList<INode>();
+ }
+
+ private transient ThreadLocal<Temp> temp = new ThreadLocal<Temp>() {
+ protected Temp initialValue() {
+ return new Temp();
+ }
+ };
+
+ Order order;
+
+ public TreePreOrderComparator(Order order) {
+ this.order = order;
+ }
+
+ void getTreePath(INode node, ArrayList<INode> 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<INode> path1 = tmp.path1;
+ ArrayList<INode> 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<IEventHandler> focusListeners = new ArrayList<IEventHandler>();
+ 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<IEventHandler> timeListeners = new ArrayList<IEventHandler>();
+ 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<IEventHandler> commandListeners = new ArrayList<IEventHandler>();
+ 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<IEventHandler> keyListeners = new ArrayList<IEventHandler>();
+ 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<IEventHandler> mouseListeners = new ArrayList<IEventHandler>();
+ 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<IEventHandler> mouseDragBeginListeners = new ArrayList<IEventHandler>();
+ protected IEventHandler[] sortedMouseDragBeginListeners = null;
+
+ /**
+ * The scene graph this instance handles event propagation for.
+ */
+ protected G2DSceneGraph sg;
+
+ public NodeEventHandler(G2DSceneGraph sg) {
this.sg = sg;
}
-\r
- @SuppressWarnings("unused")\r
- private IEventHandler[] sort(IEventHandler[] sort) {\r
- if (DEBUG_HANDLER_SORT)\r
- debug("copy sort " + sort.length + " handlers");\r
- return sortInplace(Arrays.copyOf(sort, sort.length));\r
- }\r
-\r
- private IEventHandler[] sortInplace(IEventHandler[] sort) {\r
- if (DEBUG_HANDLER_SORT)\r
- debug("in-place sort " + sort.length + " handlers");\r
- Arrays.sort(sort, COMPARATOR);\r
- return sort;\r
- }\r
-\r
- public void setRootPane(Component rootPane) {\r
- final DragSourceListener dsl = new DragSourceListener() {\r
- @Override\r
- public void dropActionChanged(DragSourceDragEvent dsde) {\r
- }\r
- @Override\r
- public void dragOver(DragSourceDragEvent dsde) {\r
- }\r
- @Override\r
- public void dragExit(DragSourceEvent dse) {\r
- }\r
- @Override\r
- public void dragEnter(DragSourceDragEvent dsde) {\r
- }\r
- @Override\r
- public void dragDropEnd(DragSourceDropEvent dsde) {\r
- }\r
- };\r
- DragGestureListener dgl = new DragGestureListener() {\r
- @Override\r
- public void dragGestureRecognized(DragGestureEvent dge) {\r
- InputEvent ie = dge.getTriggerEvent();\r
- if (ie instanceof java.awt.event.MouseEvent) {\r
- java.awt.event.MouseEvent e = (java.awt.event.MouseEvent) ie;\r
- Point2D controlPos = AWTMouseEventAdapter.getControlPosition(e);\r
- MouseDragBegin event = new MouseDragBegin(NodeEventHandler.this,\r
- e.getWhen(), 0,\r
- AWTMouseEventAdapter.getButtonStatus(e),\r
- AWTMouseEventAdapter.getStateMask(e),\r
- AWTMouseEventAdapter.getMouseButton(e),\r
- // TODO: fix canvas position if necessary\r
- new Point2D.Double(),\r
- controlPos,\r
- controlPos,\r
- AWTMouseEventAdapter.getScreenPosition(e));\r
-\r
- // Send MouseDragBegin to the scenegraph and see\r
- // if anyone sets event.transferable to start DnD.\r
- handleMouseDragBeginEvent(event, EventTypes.MouseDragBegin);\r
- if (event.transferable != null) {\r
- ds.startDrag(dge, null, event.transferable, dsl);\r
- if (DEBUG_EVENTS)\r
- debug("dragGestureRecognized: startDrag " + event.transferable);\r
- }\r
- }\r
- }\r
- };\r
- ds.createDefaultDragGestureRecognizer(\r
- rootPane,\r
- DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK,\r
- dgl);\r
- ds.addDragSourceListener(dsl);\r
- }\r
-
- public boolean mousePressed(MouseButtonPressedEvent event) {\r
- G2DFocusManager.INSTANCE.clearFocus();\r
- try {\r
-// Point op = event.getPoint();\r
-// for (MouseListener l : mouseListeners.getListeners()) {\r
-// MouseEvent e = (MouseEvent) NodeUtil.transformEvent(event,(IG2DNode) l);\r
-// l.mousePressed(e);\r
-// event.translatePoint((int)(op.getX()-event.getX()), (int)(op.getY()-event.getY()));\r
-// if (e.isConsumed())\r
-// break;\r
-// }\r
- return false;\r
- } finally {\r
- if (sg.getRootPane() != null) {\r
- if (G2DFocusManager.INSTANCE.getFocusOwner() == null) {\r
- sg.getRootPane().requestFocusInWindow();\r
- //sg.getRootPane().repaint(); //TODO : why repaint here? FocusOwner seems to be always null, so this causes unnecessary delays when interacting the canvas.\r
- }\r
- }\r
- }\r
- }\r
-\r
- private boolean handleEvent(Event e, IG2DNode focusNode, IEventHandler[] handlers) {\r
- int typeMask = EventTypes.toTypeMask(e);\r
- if (focusNode instanceof IEventHandler) {\r
- IEventHandler h = (IEventHandler) focusNode;\r
- if (eats(h.getEventMask(), typeMask)) {\r
- if (h.handleEvent(e))\r
- return true;\r
- }\r
- }\r
- for (IEventHandler l : handlers) {\r
- if (eats(l.getEventMask(), typeMask)) {\r
- if (l.handleEvent(e))\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- private boolean handleMouseEvent(MouseEvent e, int eventType) {\r
- IEventHandler[] sorted = sortedMouseListeners;\r
- if (sorted == null)\r
- sortedMouseListeners = sorted = sortInplace(mouseListeners.toArray(NONE));\r
- return handleEvent(e, sg.getFocusNode(), sorted);\r
- }\r
-\r
- private boolean handleMouseDragBeginEvent(MouseEvent e, int eventType) {\r
- IEventHandler[] sorted = sortedMouseDragBeginListeners;\r
- if (sorted == null)\r
- sortedMouseDragBeginListeners = sorted = sortInplace(mouseDragBeginListeners.toArray(NONE));\r
- // Give null for focusNode because we want to propagate\r
- // this event in scene tree pre-order only.\r
- return handleEvent(e, null, sorted);\r
- }\r
-\r
- private boolean handleFocusEvent(FocusEvent e) {\r
- IEventHandler[] sorted = sortedFocusListeners;\r
- if (sorted == null)\r
- sortedFocusListeners = sorted = sortInplace(focusListeners.toArray(NONE));\r
- return handleEvent(e, null, sorted);\r
- }\r
-\r
- private boolean handleTimeEvent(TimeEvent e) {\r
- IEventHandler[] sorted = sortedTimeListeners;\r
- if (sorted == null)\r
- sortedTimeListeners = sorted = sortInplace(timeListeners.toArray(NONE));\r
- return handleEvent(e, null, sorted);\r
- }\r
-\r
- private boolean handleCommandEvent(CommandEvent e) {\r
- IEventHandler[] sorted = sortedCommandListeners;\r
- if (sorted == null)\r
- sortedCommandListeners = sorted = sortInplace(commandListeners.toArray(NONE));\r
- return handleEvent(e, sg.getFocusNode(), sorted);\r
- }\r
-\r
- private boolean handleKeyEvent(KeyEvent e) {\r
- IEventHandler[] sorted = sortedKeyListeners;\r
- if (sorted == null)\r
- sortedKeyListeners = sorted = sortInplace(keyListeners.toArray(NONE));\r
- return handleEvent(e, sg.getFocusNode(), sorted);\r
- }\r
+
+ @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 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 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() {
}
@Override
- public boolean handleEvent(Event e) {\r
- if (DEBUG_EVENTS)\r
- debug("handle event: " + e);\r
+ public boolean handleEvent(Event e) {
+ if (DEBUG_EVENTS)
+ debug("handle event: " + e);
int eventType = EventTypes.toType(e);
switch (eventType) {
- case EventTypes.Command:\r
- return handleCommandEvent((CommandEvent) e);\r
-\r
- case EventTypes.FocusGained:\r
- case EventTypes.FocusLost:\r
- return handleFocusEvent((FocusEvent) e);\r
-\r
- case EventTypes.KeyPressed:\r
- case EventTypes.KeyReleased:\r
- return handleKeyEvent((KeyEvent) e);\r
-\r
- case EventTypes.MouseDragBegin:\r
- return handleMouseDragBeginEvent((MouseEvent) e, eventType);\r
-\r
- case EventTypes.MouseButtonPressed:\r
- case EventTypes.MouseButtonReleased:\r
- case EventTypes.MouseClick:\r
- case EventTypes.MouseDoubleClick:\r
- case EventTypes.MouseEnter:\r
- case EventTypes.MouseExit:\r
- case EventTypes.MouseMoved:\r
- case EventTypes.MouseWheel:\r
- return handleMouseEvent((MouseEvent) e, eventType);\r
-\r
+ 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);\r
- }\r
+ return handleTimeEvent((TimeEvent) e);
+ }
return false;
- }\r
-\r
- public void add(IEventHandler item) {\r
- if (!(item instanceof IG2DNode))\r
- throw new IllegalArgumentException("event handler must be an IG2DNode");\r
-\r
- int mask = item.getEventMask();\r
- if (eats(mask, EventTypes.CommandMask)) {\r
- commandListeners.add(item);\r
- sortedCommandListeners = null;\r
- }\r
- if (eats(mask, EventTypes.FocusMask)) {\r
- focusListeners.add(item);\r
- sortedFocusListeners = null;\r
- }\r
- if (eats(mask, EventTypes.KeyMask)) {\r
- keyListeners.add(item);\r
- sortedKeyListeners = null;\r
- }\r
- if (eats(mask, EventTypes.MouseDragBeginMask)) {\r
- mouseDragBeginListeners.add(item);\r
- sortedMouseDragBeginListeners = null;\r
- }\r
- if (eats(mask, EventTypes.MouseMask & ~EventTypes.MouseDragBeginMask)) {\r
- mouseListeners.add(item);\r
- sortedMouseListeners = null;\r
- }\r
- if (eats(mask, EventTypes.TimeMask)) {\r
- timeListeners.add(item);\r
- sortedTimeListeners = null;\r
- }\r
- }\r
-\r
- public boolean remove(IEventHandler item) {\r
- if (!(item instanceof IG2DNode))\r
- throw new IllegalArgumentException("event handler must be an IG2DNode");\r
-\r
- int mask = item.getEventMask();\r
- boolean removed = false;\r
- if (eats(mask, EventTypes.CommandMask)) {\r
- removed |= commandListeners.remove(item);\r
- sortedCommandListeners = null;\r
- }\r
- if (eats(mask, EventTypes.FocusMask)) {\r
- removed |= focusListeners.remove(item);\r
- sortedFocusListeners = null;\r
- }\r
- if (eats(mask, EventTypes.KeyMask)) {\r
- removed |= keyListeners.remove(item);\r
- sortedKeyListeners = null;\r
- }\r
- if (eats(mask, EventTypes.MouseDragBeginMask)) {\r
- removed |= mouseDragBeginListeners.remove(item);\r
- sortedMouseDragBeginListeners = null;\r
- }\r
- if (eats(mask, EventTypes.MouseMask & ~EventTypes.MouseDragBeginMask)) {\r
- removed |= mouseListeners.remove(item);\r
- sortedMouseListeners = null;\r
- }\r
- if (eats(mask, EventTypes.TimeMask)) {\r
- removed |= timeListeners.remove(item);\r
- sortedTimeListeners = null;\r
- }\r
- return removed;\r
- }\r
-\r
- private static boolean eats(int handlerMask, int eventTypeMask) {\r
- return (handlerMask & eventTypeMask) != 0;\r
- }\r
-\r
- private void debug(String msg) {\r
- System.out.println(getClass().getSimpleName() + ": " + msg);\r
- }\r
-\r
- public void dispose() {\r
- commandListeners.clear();\r
- commandListeners = null;\r
- focusListeners.clear();\r
- focusListeners = null;\r
- keyListeners.clear();\r
- keyListeners = null;\r
- mouseListeners.clear();\r
- mouseListeners = null;\r
- sg = null;\r
- sortedCommandListeners = null;\r
- sortedKeyListeners = null;\r
- sortedMouseListeners = null;\r
-\r
- timeListeners.clear();\r
- timeListeners = null;\r
- }\r
-\r
+ }
+
+ 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;
+ }
+
}