]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ContextUtil.java
Merge commit 'bd5bc6e45f700e755b61bd112631796631330ecb'
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / participant / ContextUtil.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2013 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.diagram.participant;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.Collections;\r
17 import java.util.Map;\r
18 import java.util.concurrent.ConcurrentHashMap;\r
19 \r
20 import org.eclipse.ui.contexts.IContextActivation;\r
21 import org.eclipse.ui.contexts.IContextService;\r
22 import org.simantics.g2d.canvas.ICanvasContext;\r
23 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
24 import org.simantics.utils.ObjectUtils;\r
25 import org.simantics.utils.threads.IThreadWorkQueue;\r
26 import org.simantics.utils.threads.ThreadUtils;\r
27 \r
28 /**\r
29  * ContextUtil manages the activeness of Eclipse Workbench UI context related to\r
30  * an ICanvasContext and an IContextService (possibly local to a workbench part).\r
31  * \r
32  * @author Tuukka Lehtonen\r
33  */\r
34 public class ContextUtil extends AbstractCanvasParticipant {\r
35 \r
36     private static final boolean                  DEBUG = false;\r
37 \r
38     private final IContextService                 service;\r
39 \r
40     private final IThreadWorkQueue                thread;\r
41 \r
42     private final Map<String, IContextActivation> activations = new ConcurrentHashMap<String, IContextActivation>();\r
43 \r
44     public ContextUtil(IContextService service, IThreadWorkQueue contextManipulationThread) {\r
45         assert service != null;\r
46         assert contextManipulationThread != null;\r
47         this.service = service;\r
48         this.thread = contextManipulationThread;\r
49     }\r
50 \r
51     public void inContextThread(Runnable r) {\r
52         exec(r, true);\r
53     }\r
54 \r
55     private void debug(String s) {\r
56         debug(false, s);\r
57     }\r
58 \r
59     private void debug(boolean trace, String s) {\r
60         if (DEBUG) {\r
61             System.out.println(getClass().getSimpleName() + "(" + ObjectUtils.hashCode(getContext()) + "): " + s);\r
62             if (trace) {\r
63                 StackTraceElement[] es = new Exception().getStackTrace();\r
64                 int e = 0;\r
65                 System.out.println("Invoked from: ");\r
66                 for (int i = 0; i < 2 && e < es.length; ++e) {\r
67                     if (es[e].getClassName().equals(getClass().getName()))\r
68                         continue;\r
69                     System.out.println("\t" + es[e].toString());\r
70                     ++i;\r
71                 }\r
72             }\r
73         }\r
74     }\r
75 \r
76     private void checkThread() {\r
77         if (!thread.currentThreadAccess()) {\r
78             throw new IllegalStateException("not in context thread, use ContextUtil.inContextThread(Runnable)");\r
79         }\r
80     }\r
81 \r
82     private void exec(Runnable r) {\r
83         exec(r, false);\r
84     }\r
85 \r
86     private void exec(Runnable r, boolean allowSchedule) {\r
87         if (!allowSchedule)\r
88             checkThread();\r
89 \r
90         // Context access thread is disposed already?\r
91         if (thread.getThread() == null)\r
92             return;\r
93 \r
94         if (thread.currentThreadAccess()) {\r
95             if (DEBUG)\r
96                 debug("RUNNING " + r);\r
97             r.run();\r
98         } else {\r
99             if (DEBUG)\r
100                 debug("SCHEDULING " + r);\r
101             ThreadUtils.asyncExec(thread, r);\r
102         }\r
103     }\r
104 \r
105     @Override\r
106     public void removedFromContext(ICanvasContext ctx) {\r
107         exec(new Runnable() {\r
108             @Override\r
109             public void run() {\r
110                 deactivateAll();\r
111             }\r
112         }, true);\r
113         super.removedFromContext(ctx);\r
114     }\r
115 \r
116     private void doActivate(String contextId) {\r
117         if(!activations.containsKey(contextId)) {\r
118             IContextActivation activation = service.activateContext(contextId);\r
119             if (activation != null) {\r
120                 if (DEBUG)\r
121                     debug("ACTIVATED context: " + contextId);\r
122                 activations.put(contextId, activation);\r
123             }\r
124         } else {\r
125             if (DEBUG)\r
126                 debug("TRIED TO ACTIVATE DUPLICATE CONTEXT: " + contextId);\r
127         }\r
128     }\r
129 \r
130     public void activate(final String contextId) {\r
131         checkThread();\r
132         if (DEBUG)\r
133             debug(true, "activate(" + contextId + ")");\r
134         assert contextId != null;\r
135         exec(new Runnable() {\r
136             @Override\r
137             public void run() {\r
138                 doActivate(contextId);\r
139             }\r
140         });\r
141     }\r
142 \r
143     public void activate(final Collection<String> contextIds) {\r
144         if (DEBUG)\r
145             debug(true, "activate contexts (" + contextIds + ")");\r
146         if (contextIds.isEmpty())\r
147             return;\r
148         exec(new Runnable() {\r
149             @Override\r
150             public void run() {\r
151                 for (String id : contextIds) {\r
152                     doActivate(id);\r
153                 }\r
154             }\r
155         });\r
156     }\r
157 \r
158 //    public void deactivate(String contextId) {\r
159 //        checkThread();\r
160 //        assert contextId != null;\r
161 //        final IContextActivation activation = activations.remove(contextId);\r
162 //        if (activation == null) {\r
163 //            debug("WARNING: cannot deactivate inactive context: " + contextId);\r
164 //            return;\r
165 //        }\r
166 //        exec(new Runnable() {\r
167 //            @Override\r
168 //            public void run() {\r
169 //                if (DEBUG_ACTIVATIONS)\r
170 //                    debug("DE-ACT context: " + activation.getContextId());\r
171 //                service.deactivateContext(activation);\r
172 //            }\r
173 //        });\r
174 //    }\r
175 \r
176     public void deactivate(Collection<String> contextIds) {\r
177         checkThread();\r
178         assert contextIds != null;\r
179         for(String id : contextIds) {\r
180             final IContextActivation a = activations.remove(id);\r
181             if (DEBUG)\r
182                 debug(true, "deactivate(" + id + "): " + a);\r
183             if (a != null)\r
184                 exec(new Runnable() {\r
185                     @Override\r
186                     public void run() {\r
187                         if (DEBUG)\r
188                             debug("DE-ACT context: " + a.getContextId());\r
189                         service.deactivateContext(a);\r
190                     }\r
191                 });\r
192         }\r
193     }\r
194 \r
195     public void deactivate(IContextActivation activation) {\r
196         checkThread();\r
197         assert activation != null;\r
198         final IContextActivation a = activations.remove(activation.getContextId());\r
199         if (DEBUG)\r
200             debug(true, "deactivate(" + activation + "): " + a);\r
201         if (a == activation)\r
202             exec(new Runnable() {\r
203                 @Override\r
204                 public void run() {\r
205                     if (DEBUG)\r
206                         debug("DE-ACT context: " + a.getContextId());\r
207                     service.deactivateContext(a);\r
208                 }\r
209             });\r
210     }\r
211 \r
212     public void deactivateAll() {\r
213         checkThread();\r
214         final Collection<IContextActivation> acts = getActivations();\r
215         if (DEBUG)\r
216             debug(true, "DE-ACTIVATE ALL INVOKED, " + acts.size() + " contexts to deactivate");\r
217         activations.clear();\r
218         exec(new Runnable() {\r
219             @Override\r
220             public void run() {\r
221                 if (DEBUG)\r
222                     debug("\tDE-ACTIVATE ALL " + acts.size() + " contexts:");\r
223                 for (IContextActivation a : acts) {\r
224                     if (DEBUG)\r
225                         debug("\t\tDE-ACT context: " + a.getContextId());\r
226                     service.deactivateContext(a);\r
227                 }\r
228             }\r
229         });\r
230     }\r
231 \r
232     public synchronized Collection<IContextActivation> getActivations() {\r
233         return Collections.unmodifiableCollection(new ArrayList<IContextActivation>(activations.values()));\r
234     }\r
235 \r
236     public synchronized Collection<String> getActivatedContextIds() {\r
237         return Collections.unmodifiableCollection(new ArrayList<String>(activations.keySet()));\r
238     }\r
239 \r
240 }\r