-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in 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
-package org.simantics.scenegraph.g2d.events;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.LinkedList;\r
-\r
-import org.simantics.utils.datastructures.ListenerList;\r
-import org.simantics.utils.threads.IThreadWorkQueue;\r
-import org.simantics.utils.threads.SyncListenerList;\r
-\r
-/**\r
- * @see IEventQueue\r
- * @author Toni Kalajainen\r
- */\r
-public class EventQueue implements IEventQueue, IEventHandler {\r
-\r
- ListenerList<IEventQueueListener> listeners = new ListenerList<IEventQueueListener>(IEventQueueListener.class);\r
- SyncListenerList<IEventQueueListener> listeners2 = new SyncListenerList<IEventQueueListener>(IEventQueueListener.class);\r
- ListenerList<EventCoalescer> coalescers = new ListenerList<EventCoalescer>(EventCoalescer.class);\r
- LinkedList<Event> queue = new LinkedList<Event>();\r
-\r
- IEventHandler handler;\r
-\r
- public EventQueue(IEventHandler handler) {\r
- assert (handler != null);\r
- this.handler = handler;\r
- }\r
-\r
- @Override\r
- public int getEventMask() {\r
- return EventTypes.AnyMask;\r
- }\r
-\r
- @Override\r
- public synchronized void queueEvent(Event e) {\r
- // coalesce with last\r
- EventCoalescer[] css = coalescers.getListeners();\r
- if (css.length > 0 && !queue.isEmpty()) {\r
- Event last = queue.get(queue.size() - 1);\r
- Event coalesced = null;\r
- for (EventCoalescer ecs : css) {\r
- coalesced = ecs.coalesce(last, e);\r
- if (coalesced != null)\r
- break;\r
- }\r
- if (coalesced == last)\r
- return;\r
- if (coalesced != null) {\r
- // replace last with coalesced\r
- queue.remove(queue.size() - 1);\r
- queue.addLast(coalesced);\r
- int index = queue.size() - 1;\r
- fireEventAdded(coalesced, index);\r
- return;\r
- }\r
- }\r
-\r
- queue.addLast(e);\r
- int index = queue.size() - 1;\r
- fireEventAdded(e, index);\r
- }\r
-\r
- @Override\r
- public synchronized void queueFirst(Event e) {\r
- // coalescale with first\r
- EventCoalescer[] css = coalescers.getListeners();\r
- if (css.length > 0 && !queue.isEmpty()) {\r
- Event first = queue.get(0);\r
- Event coalesced = null;\r
- for (EventCoalescer ecs : css) {\r
- coalesced = ecs.coalesce(e, first);\r
- if (coalesced != null)\r
- break;\r
- }\r
- if (coalesced == first)\r
- return;\r
- if (coalesced != null) {\r
- // replace last with coalesced\r
- queue.remove(0);\r
- queue.addFirst(coalesced);\r
- fireEventAdded(coalesced, 0);\r
- return;\r
- }\r
- }\r
-\r
- queue.addFirst(e);\r
- fireEventAdded(e, 0);\r
- }\r
-\r
- public void handleEvents() {\r
- int eventsHandled = 0;\r
- Event[] events = null;\r
- do {\r
- synchronized (this) {\r
- events = queue.toArray(new Event[queue.size()]);\r
- queue.clear();\r
- }\r
- for (Event e : events) {\r
- if (EventTypes.passes(handler, e))\r
- handler.handleEvent(e);\r
- eventsHandled++;\r
- }\r
- } while (events.length > 0);\r
- if (eventsHandled > 0)\r
- fireQueueEmpty();\r
- }\r
-\r
- @Override\r
- public void addEventCoalesceler(EventCoalescer coalescaler) {\r
- coalescers.add(coalescaler);\r
- }\r
-\r
- @Override\r
- public void removeEventCoalesceler(EventCoalescer coalescaler) {\r
- coalescers.remove(coalescaler);\r
- }\r
-\r
- @Override\r
- public boolean handleEvent(Event e) {\r
- handleEvents();\r
- return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;\r
- }\r
-\r
- @Override\r
- public void addQueueListener(IEventQueueListener listener) {\r
- listeners.add(listener);\r
- }\r
-\r
- @Override\r
- public synchronized int size() {\r
- return queue.size();\r
- }\r
-\r
- @Override\r
- public synchronized boolean isEmpty() {\r
- return queue.isEmpty();\r
- }\r
-\r
- @Override\r
- public void removeQueueListener(IEventQueueListener listener) {\r
- listeners.remove(listener);\r
- }\r
-\r
- Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");\r
-\r
- protected void fireEventAdded(Event e, int index) {\r
- for (IEventQueueListener eql : listeners.getListeners())\r
- eql.onEventAdded(this, e, index);\r
- listeners2.fireEventSync(onEventAdded, this, e, index);\r
- }\r
-\r
- Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");\r
-\r
- protected void fireQueueEmpty() {\r
- for (IEventQueueListener eql : listeners.getListeners())\r
- eql.onQueueEmpty(this);\r
- listeners2.fireEventSync(onQueueEmpty, this);\r
- }\r
-\r
- @Override\r
- public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {\r
- listeners2.add(thread, listener);\r
- }\r
-\r
- @Override\r
- public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {\r
- listeners2.remove(thread, listener);\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 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.lang.reflect.Method;
+import java.util.LinkedList;
+
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
+import org.simantics.utils.datastructures.ListenerList;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.SyncListenerList;
+
+/**
+ * @see IEventQueue
+ * @author Toni Kalajainen
+ */
+public class EventQueue implements IEventQueue, IEventHandler {
+
+ ListenerList<IEventQueueListener> listeners = new ListenerList<IEventQueueListener>(IEventQueueListener.class);
+ SyncListenerList<IEventQueueListener> listeners2 = new SyncListenerList<IEventQueueListener>(IEventQueueListener.class);
+ ListenerList<EventCoalescer> coalescers = new ListenerList<EventCoalescer>(EventCoalescer.class);
+ LinkedList<Event> queue = new LinkedList<Event>();
+
+ IEventHandler handler;
+
+ public EventQueue(IEventHandler handler) {
+ assert (handler != null);
+ this.handler = handler;
+ }
+
+ @Override
+ public int getEventMask() {
+ return EventTypes.AnyMask;
+ }
+
+ private static final String DISABLE_DUPLICATE_REMOVAL = "org.simantics.scenegraph.g2d.events.disableDuplicateMouseWheelEvent";
+ private static final boolean IGNORE_DUPLICATE = !Boolean.parseBoolean(System.getProperty(DISABLE_DUPLICATE_REMOVAL));
+
+ private boolean ignoreDuplicateMouseWheelMovedEvent(Event e) {
+ if (IGNORE_DUPLICATE && e instanceof MouseWheelMovedEvent) {
+ MouseWheelMovedEvent event = (MouseWheelMovedEvent) e;
+ // if (e.time > 0 && (lastMouseWheelMovedEvent != null && lastMouseWheelMovedEvent.time < 0)) {
+ // apparently this is a better way to distinguish between SWT & AWT events
+ // SWT based event constructs the scrollAmount to = 0
+ // See org.simantics.g2d.event.adapter.SWTMouseEventAdapter.mouseScrolled(MouseEvent) L171
+ if (event.scrollAmount != MouseWheelMovedEvent.SCROLL_AMOUNT_ZERO) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized void queueEvent(Event e) {
+ if (ignoreDuplicateMouseWheelMovedEvent(e))
+ return;
+ // coalesce with last
+ EventCoalescer[] css = coalescers.getListeners();
+ if (css.length > 0 && !queue.isEmpty()) {
+ Event last = queue.get(queue.size() - 1);
+ Event coalesced = null;
+ for (EventCoalescer ecs : css) {
+ coalesced = ecs.coalesce(last, e);
+ if (coalesced != null)
+ break;
+ }
+ if (coalesced == last)
+ return;
+ if (coalesced != null) {
+ // replace last with coalesced
+ queue.remove(queue.size() - 1);
+ queue.addLast(coalesced);
+ int index = queue.size() - 1;
+ fireEventAdded(coalesced, index);
+ return;
+ }
+ }
+
+ queue.addLast(e);
+ int index = queue.size() - 1;
+ fireEventAdded(e, index);
+ }
+
+ @Override
+ public synchronized void queueFirst(Event e) {
+ // coalescale with first
+ EventCoalescer[] css = coalescers.getListeners();
+ if (css.length > 0 && !queue.isEmpty()) {
+ Event first = queue.get(0);
+ Event coalesced = null;
+ for (EventCoalescer ecs : css) {
+ coalesced = ecs.coalesce(e, first);
+ if (coalesced != null)
+ break;
+ }
+ if (coalesced == first)
+ return;
+ if (coalesced != null) {
+ // replace last with coalesced
+ queue.remove(0);
+ queue.addFirst(coalesced);
+ fireEventAdded(coalesced, 0);
+ return;
+ }
+ }
+
+ queue.addFirst(e);
+ fireEventAdded(e, 0);
+ }
+
+ public void handleEvents() {
+ int eventsHandled = 0;
+ Event[] events = null;
+ do {
+ synchronized (this) {
+ events = queue.toArray(new Event[queue.size()]);
+ queue.clear();
+ }
+ for (Event e : events) {
+ if (EventTypes.passes(handler, e))
+ handler.handleEvent(e);
+ eventsHandled++;
+ }
+ } while (events.length > 0);
+ if (eventsHandled > 0)
+ fireQueueEmpty();
+ }
+
+ @Override
+ public void addEventCoalesceler(EventCoalescer coalescaler) {
+ coalescers.add(coalescaler);
+ }
+
+ @Override
+ public void removeEventCoalesceler(EventCoalescer coalescaler) {
+ coalescers.remove(coalescaler);
+ }
+
+ @Override
+ public boolean handleEvent(Event e) {
+ handleEvents();
+ return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;
+ }
+
+ @Override
+ public void addQueueListener(IEventQueueListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override
+ public synchronized int size() {
+ return queue.size();
+ }
+
+ @Override
+ public synchronized boolean isEmpty() {
+ return queue.isEmpty();
+ }
+
+ @Override
+ public void removeQueueListener(IEventQueueListener listener) {
+ listeners.remove(listener);
+ }
+
+ Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");
+
+ protected void fireEventAdded(Event e, int index) {
+ for (IEventQueueListener eql : listeners.getListeners())
+ eql.onEventAdded(this, e, index);
+ listeners2.fireEventSync(onEventAdded, this, e, index);
+ }
+
+ Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");
+
+ protected void fireQueueEmpty() {
+ for (IEventQueueListener eql : listeners.getListeners())
+ eql.onQueueEmpty(this);
+ listeners2.fireEventSync(onQueueEmpty, this);
+ }
+
+ @Override
+ public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
+ listeners2.add(thread, listener);
+ }
+
+ @Override
+ public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
+ listeners2.remove(thread, listener);
+ }
+
+}