]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/EventQueue.java
Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / events / EventQueue.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph.g2d.events;\r
13 \r
14 import java.lang.reflect.Method;\r
15 import java.util.LinkedList;\r
16 \r
17 import org.simantics.utils.datastructures.ListenerList;\r
18 import org.simantics.utils.threads.IThreadWorkQueue;\r
19 import org.simantics.utils.threads.SyncListenerList;\r
20 \r
21 /**\r
22  * @see IEventQueue\r
23  * @author Toni Kalajainen\r
24  */\r
25 public class EventQueue implements IEventQueue, IEventHandler {\r
26 \r
27     ListenerList<IEventQueueListener>     listeners    = new ListenerList<IEventQueueListener>(IEventQueueListener.class);\r
28     SyncListenerList<IEventQueueListener> listeners2   = new SyncListenerList<IEventQueueListener>(IEventQueueListener.class);\r
29     ListenerList<EventCoalescer>          coalescers = new ListenerList<EventCoalescer>(EventCoalescer.class);\r
30     LinkedList<Event>                     queue        = new LinkedList<Event>();\r
31 \r
32     IEventHandler                         handler;\r
33 \r
34     public EventQueue(IEventHandler handler) {\r
35         assert (handler != null);\r
36         this.handler = handler;\r
37     }\r
38 \r
39     @Override\r
40     public int getEventMask() {\r
41         return EventTypes.AnyMask;\r
42     }\r
43 \r
44     @Override\r
45     public synchronized void queueEvent(Event e) {\r
46         // coalesce with last\r
47         EventCoalescer[] css = coalescers.getListeners();\r
48         if (css.length > 0 && !queue.isEmpty()) {\r
49             Event last = queue.get(queue.size() - 1);\r
50             Event coalesced = null;\r
51             for (EventCoalescer ecs : css) {\r
52                 coalesced = ecs.coalesce(last, e);\r
53                 if (coalesced != null)\r
54                     break;\r
55             }\r
56             if (coalesced == last)\r
57                 return;\r
58             if (coalesced != null) {\r
59                 // replace last with coalesced\r
60                 queue.remove(queue.size() - 1);\r
61                 queue.addLast(coalesced);\r
62                 int index = queue.size() - 1;\r
63                 fireEventAdded(coalesced, index);\r
64                 return;\r
65             }\r
66         }\r
67 \r
68         queue.addLast(e);\r
69         int index = queue.size() - 1;\r
70         fireEventAdded(e, index);\r
71     }\r
72 \r
73     @Override\r
74     public synchronized void queueFirst(Event e) {\r
75         // coalescale with first\r
76         EventCoalescer[] css = coalescers.getListeners();\r
77         if (css.length > 0 && !queue.isEmpty()) {\r
78             Event first = queue.get(0);\r
79             Event coalesced = null;\r
80             for (EventCoalescer ecs : css) {\r
81                 coalesced = ecs.coalesce(e, first);\r
82                 if (coalesced != null)\r
83                     break;\r
84             }\r
85             if (coalesced == first)\r
86                 return;\r
87             if (coalesced != null) {\r
88                 // replace last with coalesced\r
89                 queue.remove(0);\r
90                 queue.addFirst(coalesced);\r
91                 fireEventAdded(coalesced, 0);\r
92                 return;\r
93             }\r
94         }\r
95 \r
96         queue.addFirst(e);\r
97         fireEventAdded(e, 0);\r
98     }\r
99 \r
100     public void handleEvents() {\r
101         int eventsHandled = 0;\r
102         Event[] events = null;\r
103         do {\r
104             synchronized (this) {\r
105                 events = queue.toArray(new Event[queue.size()]);\r
106                 queue.clear();\r
107             }\r
108             for (Event e : events) {\r
109                 if (EventTypes.passes(handler, e))\r
110                     handler.handleEvent(e);\r
111                 eventsHandled++;\r
112             }\r
113         } while (events.length > 0);\r
114         if (eventsHandled > 0)\r
115             fireQueueEmpty();\r
116     }\r
117 \r
118     @Override\r
119     public void addEventCoalesceler(EventCoalescer coalescaler) {\r
120         coalescers.add(coalescaler);\r
121     }\r
122 \r
123     @Override\r
124     public void removeEventCoalesceler(EventCoalescer coalescaler) {\r
125         coalescers.remove(coalescaler);\r
126     }\r
127 \r
128     @Override\r
129     public boolean handleEvent(Event e) {\r
130         handleEvents();\r
131         return EventTypes.passes(handler, e) ? handler.handleEvent(e) : false;\r
132     }\r
133 \r
134     @Override\r
135     public void addQueueListener(IEventQueueListener listener) {\r
136         listeners.add(listener);\r
137     }\r
138 \r
139     @Override\r
140     public synchronized int size() {\r
141         return queue.size();\r
142     }\r
143 \r
144     @Override\r
145     public synchronized boolean isEmpty() {\r
146         return queue.isEmpty();\r
147     }\r
148 \r
149     @Override\r
150     public void removeQueueListener(IEventQueueListener listener) {\r
151         listeners.remove(listener);\r
152     }\r
153 \r
154     Method onEventAdded = SyncListenerList.getMethod(IEventQueueListener.class, "onEventAdded");\r
155 \r
156     protected void fireEventAdded(Event e, int index) {\r
157         for (IEventQueueListener eql : listeners.getListeners())\r
158             eql.onEventAdded(this, e, index);\r
159         listeners2.fireEventSync(onEventAdded, this, e, index);\r
160     }\r
161 \r
162     Method onQueueEmpty = SyncListenerList.getMethod(IEventQueueListener.class, "onQueueEmpty");\r
163 \r
164     protected void fireQueueEmpty() {\r
165         for (IEventQueueListener eql : listeners.getListeners())\r
166             eql.onQueueEmpty(this);\r
167         listeners2.fireEventSync(onQueueEmpty, this);\r
168     }\r
169 \r
170     @Override\r
171     public void addQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {\r
172         listeners2.add(thread, listener);\r
173     }\r
174 \r
175     @Override\r
176     public void removeQueueListener(IEventQueueListener listener, IThreadWorkQueue thread) {\r
177         listeners2.remove(thread, listener);\r
178     }\r
179 \r
180 }\r