]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java
b0a9c752b4cbecdad1d38f73574251971eb79502
[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.utils.datastructures.ListenerList;
18 import org.simantics.utils.threads.IThreadWorkQueue;
19 import org.simantics.utils.threads.SyncListenerList;
20
21 /**
22  * @see IEventQueue
23  * @author Toni Kalajainen
24  */
25 public class EventQueue implements IEventQueue, IEventHandler {
26
27     ListenerList<IEventQueueListener>     listeners    = new ListenerList<IEventQueueListener>(IEventQueueListener.class);
28     SyncListenerList<IEventQueueListener> listeners2   = new SyncListenerList<IEventQueueListener>(IEventQueueListener.class);
29     ListenerList<EventCoalescer>          coalescers = new ListenerList<EventCoalescer>(EventCoalescer.class);
30     LinkedList<Event>                     queue        = new LinkedList<Event>();
31
32     IEventHandler                         handler;
33
34     public EventQueue(IEventHandler handler) {
35         assert (handler != null);
36         this.handler = handler;
37     }
38
39     @Override
40     public int getEventMask() {
41         return EventTypes.AnyMask;
42     }
43
44     @Override
45     public synchronized void queueEvent(Event e) {
46         // coalesce with last
47         EventCoalescer[] css = coalescers.getListeners();
48         if (css.length > 0 && !queue.isEmpty()) {
49             Event last = queue.get(queue.size() - 1);
50             Event coalesced = null;
51             for (EventCoalescer ecs : css) {
52                 coalesced = ecs.coalesce(last, e);
53                 if (coalesced != null)
54                     break;
55             }
56             if (coalesced == last)
57                 return;
58             if (coalesced != null) {
59                 // replace last with coalesced
60                 queue.remove(queue.size() - 1);
61                 queue.addLast(coalesced);
62                 int index = queue.size() - 1;
63                 fireEventAdded(coalesced, index);
64                 return;
65             }
66         }
67
68         queue.addLast(e);
69         int index = queue.size() - 1;
70         fireEventAdded(e, index);
71     }
72
73     @Override
74     public synchronized void queueFirst(Event e) {
75         // coalescale with first
76         EventCoalescer[] css = coalescers.getListeners();
77         if (css.length > 0 && !queue.isEmpty()) {
78             Event first = queue.get(0);
79             Event coalesced = null;
80             for (EventCoalescer ecs : css) {
81                 coalesced = ecs.coalesce(e, first);
82                 if (coalesced != null)
83                     break;
84             }
85             if (coalesced == first)
86                 return;
87             if (coalesced != null) {
88                 // replace last with coalesced
89                 queue.remove(0);
90                 queue.addFirst(coalesced);
91                 fireEventAdded(coalesced, 0);
92                 return;
93             }
94         }
95
96         queue.addFirst(e);
97         fireEventAdded(e, 0);
98     }
99
100     public void handleEvents() {
101         int eventsHandled = 0;
102         Event[] events = null;
103         do {
104             synchronized (this) {
105                 events = queue.toArray(new Event[queue.size()]);
106                 queue.clear();
107             }
108             for (Event e : events) {
109                 if (EventTypes.passes(handler, e))
110                     handler.handleEvent(e);
111                 eventsHandled++;
112             }
113         } while (events.length > 0);
114         if (eventsHandled > 0)
115             fireQueueEmpty();
116     }
117
118     @Override
119     public void addEventCoalesceler(EventCoalescer coalescaler) {
120         coalescers.add(coalescaler);
121     }
122
123     @Override
124     public void removeEventCoalesceler(EventCoalescer coalescaler) {
125         coalescers.remove(coalescaler);
126     }
127
128     @Override
129     public boolean handleEvent(Event e) {
130         handleEvents();
131         return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;
132     }
133
134     @Override
135     public void addQueueListener(IEventQueueListener listener) {
136         listeners.add(listener);
137     }
138
139     @Override
140     public synchronized int size() {
141         return queue.size();
142     }
143
144     @Override
145     public synchronized boolean isEmpty() {
146         return queue.isEmpty();
147     }
148
149     @Override
150     public void removeQueueListener(IEventQueueListener listener) {
151         listeners.remove(listener);
152     }
153
154     Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");
155
156     protected void fireEventAdded(Event e, int index) {
157         for (IEventQueueListener eql : listeners.getListeners())
158             eql.onEventAdded(this, e, index);
159         listeners2.fireEventSync(onEventAdded, this, e, index);
160     }
161
162     Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");
163
164     protected void fireQueueEmpty() {
165         for (IEventQueueListener eql : listeners.getListeners())
166             eql.onQueueEmpty(this);
167         listeners2.fireEventSync(onQueueEmpty, this);
168     }
169
170     @Override
171     public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
172         listeners2.add(thread, listener);
173     }
174
175     @Override
176     public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {
177         listeners2.remove(thread, listener);
178     }
179
180 }