]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/events/ListenerList.java
Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / events / ListenerList.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 /*\r
13  * 12.6.2007\r
14  */\r
15 package org.simantics.scenegraph.g2d.events;\r
16 \r
17 import java.lang.reflect.Array;\r
18 \r
19 import org.simantics.utils.threads.SyncListenerList;\r
20 \r
21 /**\r
22  * ListenerList is an efficient and synchronized list of listeners.\r
23  * The class is optimized for quick getListeners and slow add/remove.\r
24  * \r
25  * @see SyncListenerList for thread context switching listener list impl\r
26  * \r
27  * @author Toni Kalajainen\r
28  * @param <T> \r
29  */\r
30 public class ListenerList<T> {\r
31 \r
32     /**\r
33      * Array of listeners\r
34      */\r
35     private volatile T [] array;\r
36 \r
37     /** \r
38      * The class of T\r
39      */\r
40     private final Class<T> componentType;\r
41 \r
42     /**\r
43      * Construct new Listener List\r
44      * @param componentType the class of the listener type\r
45      */\r
46     public ListenerList(Class<T> componentType)\r
47     {\r
48         this.componentType = componentType;\r
49         array = createArray(0);\r
50     }\r
51 \r
52     public T[] getListeners()\r
53     {\r
54         return array;\r
55     }\r
56 \r
57     public synchronized void add(T listener)\r
58     {\r
59         int oldLength = array.length;\r
60         int newLength = oldLength + 1;\r
61         T newArray[] = createArray(newLength);\r
62         System.arraycopy(array, 0, newArray, 0, oldLength);\r
63         newArray[oldLength] = listener;\r
64         array = newArray;\r
65     }\r
66 \r
67     /**\r
68      * Removes the first occurance of listener.\r
69      * If the listener is added multiple times, then it must be removed\r
70      * as many times.\r
71      * \r
72      * @param listener a listener\r
73      * @return the listener that was removed from the list\r
74      */\r
75     public synchronized boolean remove(T listener)\r
76     {\r
77         int pos = getPos(listener);\r
78         if (pos<0) return false;\r
79 \r
80         int oldLength = array.length;\r
81         int newLength = oldLength -1;\r
82         T newArray[] = createArray(newLength);\r
83 \r
84         // Copy beginning\r
85         if (pos>0)\r
86             System.arraycopy(array, 0, newArray, 0, pos);\r
87 \r
88         // Copy ending\r
89         if (pos<newLength)\r
90             System.arraycopy(array, pos+1, newArray, pos, newLength-pos);\r
91 \r
92         array = newArray;\r
93         return true;\r
94     }\r
95 \r
96     private synchronized int getPos(T listener)\r
97     {\r
98         for (int i=0; i<array.length; i++)\r
99             if (array[i] == listener)\r
100                 return i;\r
101         return -1;\r
102     }\r
103 \r
104     public int size()\r
105     {\r
106         return array.length;\r
107     }\r
108 \r
109     public boolean isEmpty()\r
110     {\r
111         return array.length == 0;\r
112     }\r
113 \r
114     public void clear()\r
115     {\r
116         array = createArray(0);\r
117     }\r
118 \r
119     @SuppressWarnings("unchecked")\r
120     private T[] createArray(int size)\r
121     {\r
122         return (T[]) Array.newInstance(componentType, size);\r
123     }\r
124 \r
125 }\r