1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.scenegraph.g2d.events;
14 import java.lang.reflect.Method;
15 import java.util.LinkedList;
17 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
18 import org.simantics.utils.datastructures.ListenerList;
19 import org.simantics.utils.threads.IThreadWorkQueue;
20 import org.simantics.utils.threads.SyncListenerList;
24 * @author Toni Kalajainen
26 public class EventQueue implements IEventQueue, IEventHandler {
28 ListenerList<IEventQueueListener> listeners = new ListenerList<IEventQueueListener>(IEventQueueListener.class);
29 SyncListenerList<IEventQueueListener> listeners2 = new SyncListenerList<IEventQueueListener>(IEventQueueListener.class);
30 ListenerList<EventCoalescer> coalescers = new ListenerList<EventCoalescer>(EventCoalescer.class);
31 LinkedList<Event> queue = new LinkedList<Event>();
33 IEventHandler handler;
35 public EventQueue(IEventHandler handler) {
36 assert (handler != null);
37 this.handler = handler;
41 public int getEventMask() {
42 return EventTypes.AnyMask;
45 private static final String DISABLE_DUPLICATE_REMOVAL = "org.simantics.scenegraph.g2d.events.disableDuplicateMouseWheelEvent";
46 private static final boolean IGNORE_DUPLICATE = !Boolean.parseBoolean(System.getProperty(DISABLE_DUPLICATE_REMOVAL));
48 private boolean ignoreDuplicateMouseWheelMovedEvent(Event e) {
49 if (IGNORE_DUPLICATE && e instanceof MouseWheelMovedEvent) {
50 MouseWheelMovedEvent event = (MouseWheelMovedEvent) e;
51 // if (e.time > 0 && (lastMouseWheelMovedEvent != null && lastMouseWheelMovedEvent.time < 0)) {
52 // apparently this is a better way to distinguish between SWT & AWT events
53 // SWT based event constructs the scrollAmount to = 0
54 // See org.simantics.g2d.event.adapter.SWTMouseEventAdapter.mouseScrolled(MouseEvent) L171
55 if (event.scrollAmount != MouseWheelMovedEvent.SCROLL_AMOUNT_ZERO) {
63 public synchronized void queueEvent(Event e) {
64 if (ignoreDuplicateMouseWheelMovedEvent(e))
67 EventCoalescer[] css = coalescers.getListeners();
68 if (css.length > 0 && !queue.isEmpty()) {
69 Event last = queue.get(queue.size() - 1);
70 Event coalesced = null;
71 for (EventCoalescer ecs : css) {
72 coalesced = ecs.coalesce(last, e);
73 if (coalesced != null)
76 if (coalesced == last)
78 if (coalesced != null) {
79 // replace last with coalesced
80 queue.remove(queue.size() - 1);
81 queue.addLast(coalesced);
82 int index = queue.size() - 1;
83 fireEventAdded(coalesced, index);
89 int index = queue.size() - 1;
90 fireEventAdded(e, index);
94 public synchronized void queueFirst(Event e) {
95 // coalescale with first
96 EventCoalescer[] css = coalescers.getListeners();
97 if (css.length > 0 && !queue.isEmpty()) {
98 Event first = queue.get(0);
99 Event coalesced = null;
100 for (EventCoalescer ecs : css) {
101 coalesced = ecs.coalesce(e, first);
102 if (coalesced != null)
105 if (coalesced == first)
107 if (coalesced != null) {
108 // replace last with coalesced
110 queue.addFirst(coalesced);
111 fireEventAdded(coalesced, 0);
117 fireEventAdded(e, 0);
120 public void handleEvents() {
121 int eventsHandled = 0;
122 Event[] events = null;
124 synchronized (this) {
125 events = queue.toArray(new Event[queue.size()]);
128 for (Event e : events) {
129 if (EventTypes.passes(handler, e))
130 handler.handleEvent(e);
133 } while (events.length > 0);
134 if (eventsHandled > 0)
139 public void addEventCoalesceler(EventCoalescer coalescaler) {
140 coalescers.add(coalescaler);
144 public void removeEventCoalesceler(EventCoalescer coalescaler) {
145 coalescers.remove(coalescaler);
149 public boolean handleEvent(Event e) {
151 return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;
155 public void addQueueListener(IEventQueueListener listener) {
156 listeners.add(listener);
160 public synchronized int size() {
165 public synchronized boolean isEmpty() {
166 return queue.isEmpty();
170 public void removeQueueListener(IEventQueueListener listener) {
171 listeners.remove(listener);
174 Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");
176 protected void fireEventAdded(Event e, int index) {
177 for (IEventQueueListener eql : listeners.getListeners())
178 eql.onEventAdded(this, e, index);
179 listeners2.fireEventSync(onEventAdded, this, e, index);
182 Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");
184 protected void fireQueueEmpty() {
185 for (IEventQueueListener eql : listeners.getListeners())
186 eql.onQueueEmpty(this);
187 listeners2.fireEventSync(onQueueEmpty, this);
191 public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
192 listeners2.add(thread, listener);
196 public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
197 listeners2.remove(thread, listener);