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