]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java
Duplicate MouseWheelMovedEvent was not actually fixed
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / events / EventQueue.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.scenegraph.g2d.events;
13
14 import java.lang.reflect.Method;
15 import java.util.LinkedList;
16
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;
21
22 /**
23  * @see IEventQueue
24  * @author Toni Kalajainen
25  */
26 public class EventQueue implements IEventQueue, IEventHandler {
27
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>();
32
33     IEventHandler                         handler;
34
35     public EventQueue(IEventHandler handler) {
36         assert (handler != null);
37         this.handler = handler;
38     }
39
40     @Override
41     public int getEventMask() {
42         return EventTypes.AnyMask;
43     }
44
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));
47     
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) {
56                 return true;
57             }
58         }
59         return false;
60     }
61     
62     @Override
63     public synchronized void queueEvent(Event e) {
64         if (ignoreDuplicateMouseWheelMovedEvent(e))
65             return;
66         // coalesce with last
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)
74                     break;
75             }
76             if (coalesced == last)
77                 return;
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);
84                 return;
85             }
86         }
87
88         queue.addLast(e);
89         int index = queue.size() - 1;
90         fireEventAdded(e, index);
91     }
92
93     @Override
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)
103                     break;
104             }
105             if (coalesced == first)
106                 return;
107             if (coalesced != null) {
108                 // replace last with coalesced
109                 queue.remove(0);
110                 queue.addFirst(coalesced);
111                 fireEventAdded(coalesced, 0);
112                 return;
113             }
114         }
115
116         queue.addFirst(e);
117         fireEventAdded(e, 0);
118     }
119
120     public void handleEvents() {
121         int eventsHandled = 0;
122         Event[] events = null;
123         do {
124             synchronized (this) {
125                 events = queue.toArray(new Event[queue.size()]);
126                 queue.clear();
127             }
128             for (Event e : events) {
129                 if (EventTypes.passes(handler, e))
130                     handler.handleEvent(e);
131                 eventsHandled++;
132             }
133         } while (events.length > 0);
134         if (eventsHandled > 0)
135             fireQueueEmpty();
136     }
137
138     @Override
139     public void addEventCoalesceler(EventCoalescer coalescaler) {
140         coalescers.add(coalescaler);
141     }
142
143     @Override
144     public void removeEventCoalesceler(EventCoalescer coalescaler) {
145         coalescers.remove(coalescaler);
146     }
147
148     @Override
149     public boolean handleEvent(Event e) {
150         handleEvents();
151         return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;
152     }
153
154     @Override
155     public void addQueueListener(IEventQueueListener listener) {
156         listeners.add(listener);
157     }
158
159     @Override
160     public synchronized int size() {
161         return queue.size();
162     }
163
164     @Override
165     public synchronized boolean isEmpty() {
166         return queue.isEmpty();
167     }
168
169     @Override
170     public void removeQueueListener(IEventQueueListener listener) {
171         listeners.remove(listener);
172     }
173
174     Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");
175
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);
180     }
181
182     Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");
183
184     protected void fireQueueEmpty() {
185         for (IEventQueueListener eql : listeners.getListeners())
186             eql.onQueueEmpty(this);
187         listeners2.fireEventSync(onQueueEmpty, this);
188     }
189
190     @Override
191     public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
192         listeners2.add(thread, listener);
193     }
194
195     @Override
196     public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
197         listeners2.remove(thread, listener);
198     }
199
200 }