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