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;
48 private MouseWheelMovedEvent lastMouseWheelMovedEvent;
50 private static final String DISABLE_DUPLICATE_REMOVAL = "org.simantics.scenegraph.g2d.events.disableDuplicateMouseWheelEvent";
51 private static final boolean IGNORE_DUPLICATE = !Boolean.parseBoolean(System.getProperty(DISABLE_DUPLICATE_REMOVAL));
53 private boolean ignoreDuplicateMouseWheelMovedEvent(Event e) {
54 if (IGNORE_DUPLICATE && e instanceof MouseWheelMovedEvent) {
55 if (e.time > 0 && (lastMouseWheelMovedEvent != null && lastMouseWheelMovedEvent.time < 0)) {
58 lastMouseWheelMovedEvent = (MouseWheelMovedEvent) e;
64 public synchronized void queueEvent(Event e) {
65 if (ignoreDuplicateMouseWheelMovedEvent(e))
68 EventCoalescer[] css = coalescers.getListeners();
69 if (css.length > 0 && !queue.isEmpty()) {
70 Event last = queue.get(queue.size() - 1);
71 Event coalesced = null;
72 for (EventCoalescer ecs : css) {
73 coalesced = ecs.coalesce(last, e);
74 if (coalesced != null)
77 if (coalesced == last)
79 if (coalesced != null) {
80 // replace last with coalesced
81 queue.remove(queue.size() - 1);
82 queue.addLast(coalesced);
83 int index = queue.size() - 1;
84 fireEventAdded(coalesced, index);
90 int index = queue.size() - 1;
91 fireEventAdded(e, index);
95 public synchronized void queueFirst(Event e) {
96 // coalescale with first
97 EventCoalescer[] css = coalescers.getListeners();
98 if (css.length > 0 && !queue.isEmpty()) {
99 Event first = queue.get(0);
100 Event coalesced = null;
101 for (EventCoalescer ecs : css) {
102 coalesced = ecs.coalesce(e, first);
103 if (coalesced != null)
106 if (coalesced == first)
108 if (coalesced != null) {
109 // replace last with coalesced
111 queue.addFirst(coalesced);
112 fireEventAdded(coalesced, 0);
118 fireEventAdded(e, 0);
121 public void handleEvents() {
122 int eventsHandled = 0;
123 Event[] events = null;
125 synchronized (this) {
126 events = queue.toArray(new Event[queue.size()]);
129 for (Event e : events) {
130 if (EventTypes.passes(handler, e))
131 handler.handleEvent(e);
134 } while (events.length > 0);
135 if (eventsHandled > 0)
140 public void addEventCoalesceler(EventCoalescer coalescaler) {
141 coalescers.add(coalescaler);
145 public void removeEventCoalesceler(EventCoalescer coalescaler) {
146 coalescers.remove(coalescaler);
150 public boolean handleEvent(Event e) {
152 return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;
156 public void addQueueListener(IEventQueueListener listener) {
157 listeners.add(listener);
161 public synchronized int size() {
166 public synchronized boolean isEmpty() {
167 return queue.isEmpty();
171 public void removeQueueListener(IEventQueueListener listener) {
172 listeners.remove(listener);
175 Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");
177 protected void fireEventAdded(Event e, int index) {
178 for (IEventQueueListener eql : listeners.getListeners())
179 eql.onEventAdded(this, e, index);
180 listeners2.fireEventSync(onEventAdded, this, e, index);
183 Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");
185 protected void fireQueueEmpty() {
186 for (IEventQueueListener eql : listeners.getListeners())
187 eql.onQueueEmpty(this);
188 listeners2.fireEventSync(onQueueEmpty, this);
192 public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
193 listeners2.add(thread, listener);
197 public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
198 listeners2.remove(thread, listener);