1 | /* |
2 | * Copyright 2007, SDQ, IPD, University of Karlsruhe |
3 | */ |
4 | package de.uka.ipd.sdq.pcm.gmf.usage.providers; |
5 | |
6 | import java.util.ArrayList; |
7 | import java.util.HashMap; |
8 | import java.util.Iterator; |
9 | import java.util.List; |
10 | import java.util.Map; |
11 | |
12 | import org.eclipse.core.resources.IFile; |
13 | import org.eclipse.core.resources.IMarker; |
14 | import org.eclipse.core.resources.IResource; |
15 | import org.eclipse.core.runtime.CoreException; |
16 | import org.eclipse.draw2d.FlowLayout; |
17 | import org.eclipse.draw2d.Label; |
18 | import org.eclipse.emf.transaction.util.TransactionUtil; |
19 | import org.eclipse.emf.workspace.util.WorkspaceSynchronizer; |
20 | import org.eclipse.gef.EditDomain; |
21 | import org.eclipse.gef.EditPart; |
22 | import org.eclipse.gef.editparts.AbstractConnectionEditPart; |
23 | import org.eclipse.gmf.runtime.common.core.service.AbstractProvider; |
24 | import org.eclipse.gmf.runtime.common.core.service.IOperation; |
25 | import org.eclipse.gmf.runtime.common.ui.resources.FileChangeManager; |
26 | import org.eclipse.gmf.runtime.common.ui.resources.IFileObserver; |
27 | import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; |
28 | import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; |
29 | import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain; |
30 | import org.eclipse.gmf.runtime.diagram.ui.services.decorator.AbstractDecorator; |
31 | import org.eclipse.gmf.runtime.diagram.ui.services.decorator.CreateDecoratorsOperation; |
32 | import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecorator; |
33 | import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorProvider; |
34 | import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget; |
35 | import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil; |
36 | import org.eclipse.gmf.runtime.notation.Diagram; |
37 | import org.eclipse.gmf.runtime.notation.Edge; |
38 | import org.eclipse.gmf.runtime.notation.View; |
39 | import org.eclipse.swt.graphics.Image; |
40 | import org.eclipse.ui.ISharedImages; |
41 | import org.eclipse.ui.PlatformUI; |
42 | |
43 | import de.uka.ipd.sdq.pcm.gmf.usage.edit.parts.UsageScenarioEditPart; |
44 | import de.uka.ipd.sdq.pcm.gmf.usage.part.PalladioComponentModelUsageDiagramEditor; |
45 | import de.uka.ipd.sdq.pcm.gmf.usage.part.PalladioComponentModelUsageDiagramEditorPlugin; |
46 | import de.uka.ipd.sdq.pcm.gmf.usage.part.PalladioComponentModelVisualIDRegistry; |
47 | |
48 | /** |
49 | * @generated |
50 | */ |
51 | public class PalladioComponentModelValidationDecoratorProvider extends |
52 | AbstractProvider implements IDecoratorProvider { |
53 | |
54 | /** |
55 | * @generated |
56 | */ |
57 | private static final String KEY = "validationStatus"; //$NON-NLS-1$ |
58 | |
59 | /** |
60 | * @generated |
61 | */ |
62 | private static final String MARKER_TYPE = PalladioComponentModelUsageDiagramEditorPlugin.ID |
63 | + ".diagnostic"; //$NON-NLS-1$ |
64 | |
65 | /** |
66 | * @generated |
67 | */ |
68 | private static MarkerObserver fileObserver; |
69 | |
70 | /** |
71 | * @generated |
72 | */ |
73 | private static Map/*<String, List<IDecorator>>*/allDecorators = new HashMap(); |
74 | |
75 | /** |
76 | * @generated |
77 | */ |
78 | public void createDecorators(IDecoratorTarget decoratorTarget) { |
79 | EditPart editPart = (EditPart) decoratorTarget |
80 | .getAdapter(EditPart.class); |
81 | if (editPart instanceof GraphicalEditPart |
82 | || editPart instanceof AbstractConnectionEditPart) { |
83 | Object model = editPart.getModel(); |
84 | if ((model instanceof View)) { |
85 | View view = (View) model; |
86 | if (!(view instanceof Edge) && !view.isSetElement()) { |
87 | return; |
88 | } |
89 | } |
90 | EditDomain ed = editPart.getViewer().getEditDomain(); |
91 | if (!(ed instanceof DiagramEditDomain)) { |
92 | return; |
93 | } |
94 | if (((DiagramEditDomain) ed).getEditorPart() instanceof PalladioComponentModelUsageDiagramEditor) { |
95 | decoratorTarget.installDecorator(KEY, new StatusDecorator( |
96 | decoratorTarget)); |
97 | } |
98 | } |
99 | } |
100 | |
101 | /** |
102 | * @generated |
103 | */ |
104 | public boolean provides(IOperation operation) { |
105 | if (!(operation instanceof CreateDecoratorsOperation)) { |
106 | return false; |
107 | } |
108 | IDecoratorTarget decoratorTarget = ((CreateDecoratorsOperation) operation) |
109 | .getDecoratorTarget(); |
110 | View view = (View) decoratorTarget.getAdapter(View.class); |
111 | return view != null |
112 | && UsageScenarioEditPart.MODEL_ID |
113 | .equals(PalladioComponentModelVisualIDRegistry |
114 | .getModelID(view)); |
115 | } |
116 | |
117 | /** |
118 | * @generated |
119 | */ |
120 | public static void refreshDecorators(View view) { |
121 | refreshDecorators(ViewUtil.getIdStr(view), view.getDiagram()); |
122 | } |
123 | |
124 | /** |
125 | * @generated |
126 | */ |
127 | private static void refreshDecorators(String viewId, Diagram diagram) { |
128 | final List decorators = viewId != null ? (List) allDecorators |
129 | .get(viewId) : null; |
130 | if (decorators == null || decorators.isEmpty() || diagram == null) { |
131 | return; |
132 | } |
133 | final Diagram fdiagram = diagram; |
134 | PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { |
135 | |
136 | public void run() { |
137 | try { |
138 | TransactionUtil.getEditingDomain(fdiagram).runExclusive( |
139 | new Runnable() { |
140 | |
141 | public void run() { |
142 | for (Iterator it = decorators.iterator(); it |
143 | .hasNext();) { |
144 | IDecorator decorator = (IDecorator) it |
145 | .next(); |
146 | decorator.refresh(); |
147 | } |
148 | } |
149 | }); |
150 | } catch (Exception e) { |
151 | PalladioComponentModelUsageDiagramEditorPlugin |
152 | .getInstance().logError( |
153 | "Decorator refresh failure", e); //$NON-NLS-1$ |
154 | } |
155 | } |
156 | }); |
157 | } |
158 | |
159 | /** |
160 | * @generated |
161 | */ |
162 | public static class StatusDecorator extends AbstractDecorator { |
163 | |
164 | /** |
165 | * @generated |
166 | */ |
167 | private String viewId; |
168 | |
169 | /** |
170 | * @generated |
171 | */ |
172 | public StatusDecorator(IDecoratorTarget decoratorTarget) { |
173 | super(decoratorTarget); |
174 | try { |
175 | final View view = (View) getDecoratorTarget().getAdapter( |
176 | View.class); |
177 | TransactionUtil.getEditingDomain(view).runExclusive( |
178 | new Runnable() { |
179 | |
180 | public void run() { |
181 | StatusDecorator.this.viewId = view != null ? ViewUtil |
182 | .getIdStr(view) |
183 | : null; |
184 | } |
185 | }); |
186 | } catch (Exception e) { |
187 | PalladioComponentModelUsageDiagramEditorPlugin.getInstance() |
188 | .logError("ViewID access failure", e); //$NON-NLS-1$ |
189 | } |
190 | } |
191 | |
192 | /** |
193 | * @generated |
194 | */ |
195 | public void refresh() { |
196 | removeDecoration(); |
197 | View view = (View) getDecoratorTarget().getAdapter(View.class); |
198 | if (view == null || view.eResource() == null) { |
199 | return; |
200 | } |
201 | EditPart editPart = (EditPart) getDecoratorTarget().getAdapter( |
202 | EditPart.class); |
203 | if (editPart == null || editPart.getViewer() == null) { |
204 | return; |
205 | } |
206 | |
207 | // query for all the validation markers of the current resource |
208 | String elementId = ViewUtil.getIdStr(view); |
209 | if (elementId == null) { |
210 | return; |
211 | } |
212 | int severity = IMarker.SEVERITY_INFO; |
213 | IMarker foundMarker = null; |
214 | IResource resource = WorkspaceSynchronizer |
215 | .getFile(view.eResource()); |
216 | if (resource == null || !resource.exists()) { |
217 | return; |
218 | } |
219 | IMarker[] markers = null; |
220 | try { |
221 | markers = resource.findMarkers(MARKER_TYPE, true, |
222 | IResource.DEPTH_INFINITE); |
223 | } catch (CoreException e) { |
224 | PalladioComponentModelUsageDiagramEditorPlugin.getInstance() |
225 | .logError("Validation markers refresh failure", e); //$NON-NLS-1$ |
226 | } |
227 | if (markers == null || markers.length == 0) { |
228 | return; |
229 | } |
230 | Label toolTip = null; |
231 | for (int i = 0; i < markers.length; i++) { |
232 | IMarker marker = markers[i]; |
233 | String attribute = marker |
234 | .getAttribute( |
235 | org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID, |
236 | ""); //$NON-NLS-1$ |
237 | if (attribute.equals(elementId)) { |
238 | int nextSeverity = marker.getAttribute(IMarker.SEVERITY, |
239 | IMarker.SEVERITY_INFO); |
240 | Image nextImage = getImage(nextSeverity); |
241 | if (foundMarker == null) { |
242 | foundMarker = marker; |
243 | toolTip = new Label(marker.getAttribute( |
244 | IMarker.MESSAGE, ""), //$NON-NLS-1$ |
245 | nextImage); |
246 | } else { |
247 | if (toolTip.getChildren().isEmpty()) { |
248 | Label comositeLabel = new Label(); |
249 | FlowLayout fl = new FlowLayout(false); |
250 | fl.setMinorSpacing(0); |
251 | comositeLabel.setLayoutManager(fl); |
252 | comositeLabel.add(toolTip); |
253 | toolTip = comositeLabel; |
254 | } |
255 | toolTip.add(new Label(marker.getAttribute( |
256 | IMarker.MESSAGE, ""), //$NON-NLS-1$ |
257 | nextImage)); |
258 | } |
259 | severity = (nextSeverity > severity) ? nextSeverity |
260 | : severity; |
261 | } |
262 | } |
263 | if (foundMarker == null) { |
264 | return; |
265 | } |
266 | |
267 | // add decoration |
268 | if (editPart instanceof org.eclipse.gef.GraphicalEditPart) { |
269 | if (view instanceof Edge) { |
270 | setDecoration(getDecoratorTarget().addConnectionDecoration( |
271 | getImage(severity), 50, true)); |
272 | } else { |
273 | int margin = -1; |
274 | if (editPart instanceof org.eclipse.gef.GraphicalEditPart) { |
275 | margin = MapModeUtil.getMapMode( |
276 | ((org.eclipse.gef.GraphicalEditPart) editPart) |
277 | .getFigure()).DPtoLP(margin); |
278 | } |
279 | setDecoration(getDecoratorTarget() |
280 | .addShapeDecoration(getImage(severity), |
281 | IDecoratorTarget.Direction.NORTH_EAST, |
282 | margin, true)); |
283 | } |
284 | getDecoration().setToolTip(toolTip); |
285 | } |
286 | } |
287 | |
288 | /** |
289 | * @generated |
290 | */ |
291 | private Image getImage(int severity) { |
292 | String imageName = ISharedImages.IMG_OBJS_ERROR_TSK; |
293 | switch (severity) { |
294 | case IMarker.SEVERITY_ERROR: |
295 | imageName = ISharedImages.IMG_OBJS_ERROR_TSK; |
296 | break; |
297 | case IMarker.SEVERITY_WARNING: |
298 | imageName = ISharedImages.IMG_OBJS_WARN_TSK; |
299 | break; |
300 | default: |
301 | imageName = ISharedImages.IMG_OBJS_INFO_TSK; |
302 | } |
303 | return PlatformUI.getWorkbench().getSharedImages().getImage( |
304 | imageName); |
305 | } |
306 | |
307 | /** |
308 | * @generated |
309 | */ |
310 | public void activate() { |
311 | if (viewId == null) { |
312 | return; |
313 | } |
314 | |
315 | // add self to global decorators registry |
316 | List list = (List) allDecorators.get(viewId); |
317 | if (list == null) { |
318 | list = new ArrayList(2); |
319 | list.add(this); |
320 | allDecorators.put(viewId, list); |
321 | } else if (!list.contains(this)) { |
322 | list.add(this); |
323 | } |
324 | |
325 | // start listening to changes in resources |
326 | View view = (View) getDecoratorTarget().getAdapter(View.class); |
327 | if (view == null) { |
328 | return; |
329 | } |
330 | Diagram diagramView = view.getDiagram(); |
331 | if (diagramView == null) { |
332 | return; |
333 | } |
334 | if (fileObserver == null) { |
335 | FileChangeManager.getInstance().addFileObserver( |
336 | fileObserver = new MarkerObserver(diagramView)); |
337 | } |
338 | } |
339 | |
340 | /** |
341 | * @generated |
342 | */ |
343 | public void deactivate() { |
344 | if (viewId == null) { |
345 | return; |
346 | } |
347 | |
348 | // remove self from global decorators registry |
349 | List list = (List) allDecorators.get(viewId); |
350 | if (list != null) { |
351 | list.remove(this); |
352 | if (list.isEmpty()) { |
353 | allDecorators.remove(viewId); |
354 | } |
355 | } |
356 | |
357 | // stop listening to changes in resources if there are no more decorators |
358 | if (fileObserver != null && allDecorators.isEmpty()) { |
359 | FileChangeManager.getInstance() |
360 | .removeFileObserver(fileObserver); |
361 | fileObserver = null; |
362 | } |
363 | super.deactivate(); |
364 | } |
365 | } |
366 | |
367 | /** |
368 | * @generated |
369 | */ |
370 | static class MarkerObserver implements IFileObserver { |
371 | |
372 | /** |
373 | * @generated |
374 | */ |
375 | private Diagram diagram; |
376 | |
377 | /** |
378 | * @generated |
379 | */ |
380 | private MarkerObserver(Diagram diagram) { |
381 | this.diagram = diagram; |
382 | } |
383 | |
384 | /** |
385 | * @generated |
386 | */ |
387 | public void handleFileRenamed(IFile oldFile, IFile file) { |
388 | } |
389 | |
390 | /** |
391 | * @generated |
392 | */ |
393 | public void handleFileMoved(IFile oldFile, IFile file) { |
394 | } |
395 | |
396 | /** |
397 | * @generated |
398 | */ |
399 | public void handleFileDeleted(IFile file) { |
400 | } |
401 | |
402 | /** |
403 | * @generated |
404 | */ |
405 | public void handleFileChanged(IFile file) { |
406 | } |
407 | |
408 | /** |
409 | * @generated |
410 | */ |
411 | public void handleMarkerAdded(IMarker marker) { |
412 | if (marker |
413 | .getAttribute( |
414 | org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID, |
415 | null) != null) { |
416 | handleMarkerChanged(marker); |
417 | } |
418 | } |
419 | |
420 | /** |
421 | * @generated |
422 | */ |
423 | public void handleMarkerDeleted(IMarker marker, Map attributes) { |
424 | String viewId = (String) attributes |
425 | .get(org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID); |
426 | refreshDecorators(viewId, diagram); |
427 | } |
428 | |
429 | /** |
430 | * @generated |
431 | */ |
432 | public void handleMarkerChanged(IMarker marker) { |
433 | if (!MARKER_TYPE.equals(getType(marker))) { |
434 | return; |
435 | } |
436 | String viewId = marker |
437 | .getAttribute( |
438 | org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID, |
439 | ""); //$NON-NLS-1$ |
440 | refreshDecorators(viewId, diagram); |
441 | } |
442 | |
443 | /** |
444 | * @generated |
445 | */ |
446 | private String getType(IMarker marker) { |
447 | try { |
448 | return marker.getType(); |
449 | } catch (CoreException e) { |
450 | PalladioComponentModelUsageDiagramEditorPlugin.getInstance() |
451 | .logError("Validation marker refresh failure", e); //$NON-NLS-1$ |
452 | return ""; //$NON-NLS-1$ |
453 | } |
454 | } |
455 | } |
456 | } |