]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java
Option to disable duplicate MouseWheelMovedEvent in G2D EventQueue
[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     /**
46      * 
47      */
48     private MouseWheelMovedEvent lastMouseWheelMovedEvent;
49     
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));
52     
53     private boolean ignoreDuplicateMouseWheelMovedEvent(Event e) {
54         if (IGNORE_DUPLICATE && e instanceof MouseWheelMovedEvent) {
55             if (e.time > 0 && (lastMouseWheelMovedEvent != null && lastMouseWheelMovedEvent.time < 0)) {
56                 return true;
57             }
58             lastMouseWheelMovedEvent = (MouseWheelMovedEvent) e;
59         }
60         return false;
61     }
62     
63     @Override
64     public synchronized void queueEvent(Event e) {
65         if (ignoreDuplicateMouseWheelMovedEvent(e))
66             return;
67         // coalesce with last
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)
75                     break;
76             }
77             if (coalesced == last)
78                 return;
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);
85                 return;
86             }
87         }
88
89         queue.addLast(e);
90         int index = queue.size() - 1;
91         fireEventAdded(e, index);
92     }
93
94     @Override
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)
104                     break;
105             }
106             if (coalesced == first)
107                 return;
108             if (coalesced != null) {
109                 // replace last with coalesced
110                 queue.remove(0);
111                 queue.addFirst(coalesced);
112                 fireEventAdded(coalesced, 0);
113                 return;
114             }
115         }
116
117         queue.addFirst(e);
118         fireEventAdded(e, 0);
119     }
120
121     public void handleEvents() {
122         int eventsHandled = 0;
123         Event[] events = null;
124         do {
125             synchronized (this) {
126                 events = queue.toArray(new Event[queue.size()]);
127                 queue.clear();
128             }
129             for (Event e : events) {
130                 if (EventTypes.passes(handler, e))
131                     handler.handleEvent(e);
132                 eventsHandled++;
133             }
134         } while (events.length > 0);
135         if (eventsHandled > 0)
136             fireQueueEmpty();
137     }
138
139     @Override
140     public void addEventCoalesceler(EventCoalescer coalescaler) {
141         coalescers.add(coalescaler);
142     }
143
144     @Override
145     public void removeEventCoalesceler(EventCoalescer coalescaler) {
146         coalescers.remove(coalescaler);
147     }
148
149     @Override
150     public boolean handleEvent(Event e) {
151         handleEvents();
152         return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;
153     }
154
155     @Override
156     public void addQueueListener(IEventQueueListener listener) {
157         listeners.add(listener);
158     }
159
160     @Override
161     public synchronized int size() {
162         return queue.size();
163     }
164
165     @Override
166     public synchronized boolean isEmpty() {
167         return queue.isEmpty();
168     }
169
170     @Override
171     public void removeQueueListener(IEventQueueListener listener) {
172         listeners.remove(listener);
173     }
174
175     Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");
176
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);
181     }
182
183     Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");
184
185     protected void fireQueueEmpty() {
186         for (IEventQueueListener eql : listeners.getListeners())
187             eql.onQueueEmpty(this);
188         listeners2.fireEventSync(onQueueEmpty, this);
189     }
190
191     @Override
192     public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
193         listeners2.add(thread, listener);
194     }
195
196     @Override
197     public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
198         listeners2.remove(thread, listener);
199     }
200
201 }