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