]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/e4/DiagramViewer.java
Bringing layers back to life
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / e4 / DiagramViewer.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  *     Semantum Oy - issue #4384
12  *******************************************************************************/
13 package org.simantics.modeling.ui.diagramEditor.e4;
14
15 import java.awt.Color;
16 import java.awt.dnd.DnDConstants;
17 import java.util.Collections;
18 import java.util.Set;
19 import java.util.concurrent.TimeUnit;
20 import java.util.function.Supplier;
21
22 import org.eclipse.core.runtime.Assert;
23 import org.eclipse.core.runtime.IAdaptable;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.SubMonitor;
26 import org.eclipse.core.runtime.jobs.Job;
27 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
28 import org.eclipse.e4.ui.services.EContextService;
29 import org.eclipse.jface.action.IStatusLineManager;
30 import org.eclipse.jface.resource.JFaceResources;
31 import org.eclipse.jface.resource.LocalResourceManager;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.Display;
34 import org.eclipse.swt.widgets.Shell;
35 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
36 import org.simantics.Simantics;
37 import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
38 import org.simantics.db.ReadGraph;
39 import org.simantics.db.Resource;
40 import org.simantics.db.Session;
41 import org.simantics.db.WriteGraph;
42 import org.simantics.db.common.primitiverequest.PossibleAdapter;
43 import org.simantics.db.common.procedure.adapter.ListenerDelegate;
44 import org.simantics.db.common.procedure.adapter.ListenerSupport;
45 import org.simantics.db.common.request.ParametrizedRead;
46 import org.simantics.db.common.request.WriteRequest;
47 import org.simantics.db.common.utils.CommonDBUtils;
48 import org.simantics.db.common.utils.TagUtil;
49 import org.simantics.db.exception.DatabaseException;
50 import org.simantics.db.layer0.request.combinations.Combinators;
51 import org.simantics.db.management.ISessionContext;
52 import org.simantics.db.management.ISessionContextProvider;
53 import org.simantics.db.request.Read;
54 import org.simantics.diagram.DiagramTypeUtils;
55 import org.simantics.diagram.adapter.FlagClassFactory;
56 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
57 import org.simantics.diagram.adapter.IDiagramLoader;
58 import org.simantics.diagram.connection.ModelledConnectionAdvisor;
59 import org.simantics.diagram.handler.ConnectionCommandHandler;
60 import org.simantics.diagram.handler.CopyPasteStrategy;
61 import org.simantics.diagram.handler.DefaultCopyPasteStrategy;
62 import org.simantics.diagram.handler.DeleteHandler;
63 import org.simantics.diagram.handler.ExpandSelectionHandler;
64 import org.simantics.diagram.handler.SimpleElementTransformHandler;
65 import org.simantics.diagram.handler.e4.CopyPasteHandler;
66 import org.simantics.diagram.layer.ILayersViewPage;
67 import org.simantics.diagram.participant.PointerInteractor2;
68 import org.simantics.diagram.participant.SGFocusParticipant;
69 import org.simantics.diagram.participant.e4.ContextUtil;
70 import org.simantics.diagram.query.DiagramRequests;
71 import org.simantics.diagram.runtime.RuntimeDiagramManager;
72 import org.simantics.diagram.stubs.DiagramResource;
73 import org.simantics.diagram.symbolcontribution.SymbolProviderFactory;
74 import org.simantics.diagram.synchronization.CopyAdvisor;
75 import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;
76 import org.simantics.diagram.synchronization.SynchronizationHints;
77 import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
78 import org.simantics.diagram.ui.DiagramModelHints;
79 import org.simantics.diagram.ui.SWTPopupMenuParticipant;
80 import org.simantics.diagram.ui.WorkbenchSelectionProvider;
81 import org.simantics.g2d.canvas.Hints;
82 import org.simantics.g2d.canvas.ICanvasContext;
83 import org.simantics.g2d.canvas.ICanvasParticipant;
84 import org.simantics.g2d.canvas.impl.CanvasContext;
85 import org.simantics.g2d.chassis.AWTChassis;
86 import org.simantics.g2d.chassis.ICanvasChassis;
87 import org.simantics.g2d.chassis.IChassisListener;
88 import org.simantics.g2d.chassis.SWTChassis;
89 import org.simantics.g2d.connection.IConnectionAdvisor;
90 import org.simantics.g2d.diagram.DiagramClass;
91 import org.simantics.g2d.diagram.DiagramHints;
92 import org.simantics.g2d.diagram.IDiagram;
93 import org.simantics.g2d.diagram.handler.PickRequest.PickFilter;
94 import org.simantics.g2d.diagram.impl.Diagram;
95 import org.simantics.g2d.diagram.participant.DelayedBatchElementPainter;
96 import org.simantics.g2d.diagram.participant.DiagramParticipant;
97 import org.simantics.g2d.diagram.participant.ElementInteractor;
98 import org.simantics.g2d.diagram.participant.ElementPainter;
99 import org.simantics.g2d.diagram.participant.Selection;
100 import org.simantics.g2d.diagram.participant.TerminalPainter;
101 import org.simantics.g2d.diagram.participant.ZOrderHandler;
102 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
103 import org.simantics.g2d.element.ElementClassProviders;
104 import org.simantics.g2d.element.ElementClasses;
105 import org.simantics.g2d.element.IElement;
106 import org.simantics.g2d.element.IElementClassProvider;
107 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
108 import org.simantics.g2d.elementclass.connection.ConnectionClass;
109 import org.simantics.g2d.page.DiagramDesc;
110 import org.simantics.g2d.participant.BackgroundPainter;
111 import org.simantics.g2d.participant.CanvasBoundsParticipant;
112 import org.simantics.g2d.participant.CanvasGrab;
113 import org.simantics.g2d.participant.GridPainter;
114 import org.simantics.g2d.participant.KeyUtil;
115 import org.simantics.g2d.participant.MouseUtil;
116 import org.simantics.g2d.participant.Notifications;
117 import org.simantics.g2d.participant.PageBorderParticipant;
118 import org.simantics.g2d.participant.PanZoomRotateHandler;
119 import org.simantics.g2d.participant.PointerPainter;
120 import org.simantics.g2d.participant.RenderingQualityInteractor;
121 import org.simantics.g2d.participant.RulerPainter;
122 import org.simantics.g2d.participant.SymbolUtil;
123 import org.simantics.g2d.participant.TimeParticipant;
124 import org.simantics.g2d.participant.TransformUtil;
125 import org.simantics.g2d.participant.WorkbenchStatusLine;
126 import org.simantics.g2d.participant.ZoomToAreaHandler;
127 import org.simantics.g2d.tooltip.TerminalTooltipParticipant;
128 import org.simantics.g2d.utils.CanvasUtils;
129 import org.simantics.layer0.utils.triggers.IActivation;
130 import org.simantics.layer0.utils.triggers.IActivationManager;
131 import org.simantics.modeling.ModelingResources;
132 import org.simantics.modeling.mapping.ComponentCopyAdvisor;
133 import org.simantics.modeling.mapping.ElementCopyAdvisor;
134 import org.simantics.modeling.mapping.MappedElementCopyAdvisor;
135 import org.simantics.modeling.mapping.ModelingSynchronizationHints;
136 import org.simantics.modeling.ui.diagramEditor.DiagramEditorStates;
137 import org.simantics.modeling.ui.diagramEditor.DiagramLayersPage;
138 import org.simantics.modeling.ui.diagramEditor.DiagramOutlinePage;
139 import org.simantics.modeling.ui.diagramEditor.EditorState;
140 import org.simantics.modeling.ui.diagramEditor.PopulateElementMonitorDropParticipant;
141 import org.simantics.modeling.ui.diagramEditor.handlers.e4.LinkBrowsingHandler;
142 import org.simantics.modeling.ui.diagramEditor.handlers.e4.StructuralBrowsingHandler;
143 import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;
144 import org.simantics.modeling.ui.preferences.DiagramPreferences;
145 import org.simantics.project.ontology.ProjectResource;
146 import org.simantics.scenegraph.INode;
147 import org.simantics.scenegraph.g2d.snap.GridSnapAdvisor;
148 import org.simantics.scenegraph.utils.NodeUtil;
149 import org.simantics.structural.stubs.StructuralResource2;
150 import org.simantics.structural2.modelingRules.IModelingRules;
151 import org.simantics.ui.jobs.SessionGarbageCollectorJob;
152 import org.simantics.ui.workbench.IPropertyPage;
153 import org.simantics.ui.workbench.IResourceEditorInput;
154 import org.simantics.ui.workbench.IResourceEditorInput2;
155 import org.simantics.ui.workbench.TitleRequest;
156 import org.simantics.ui.workbench.TitleUpdater;
157 import org.simantics.ui.workbench.ToolTipRequest;
158 import org.simantics.ui.workbench.editor.input.InputValidationCombinators;
159 import org.simantics.utils.DataContainer;
160 import org.simantics.utils.datastructures.hints.HintContext;
161 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
162 import org.simantics.utils.datastructures.hints.IHintContext;
163 import org.simantics.utils.datastructures.hints.IHintContext.Key;
164 import org.simantics.utils.datastructures.hints.IHintListener;
165 import org.simantics.utils.datastructures.hints.IHintObservable;
166 import org.simantics.utils.threads.AWTThread;
167 import org.simantics.utils.threads.IThreadWorkQueue;
168 import org.simantics.utils.threads.SWTThread;
169 import org.simantics.utils.threads.ThreadUtils;
170 import org.simantics.utils.ui.ErrorLogger;
171 import org.simantics.utils.ui.ExceptionUtils;
172 import org.simantics.utils.ui.workbench.WorkbenchUtils;
173
174 import com.kitfox.svg.SVGCache;
175
176 /**
177  * @author Toni Kalajainen
178  * @author Tuukka Lehtonen
179  */
180 public class DiagramViewer 
181   //extends EditorPart implements IResourceEditorPart2, 
182     implements ListenerSupport, IAdaptable {
183
184     public interface DiagramViewerHost {
185         void doSetPartName(String name);
186         void doSetTitleToolTip(String name);
187     }
188
189     public static final String                     DIAGRAMMING_CONTEXT      = "org.simantics.modeling.ui.diagramming";
190     private static final String                     PREFERENCE_VIRTUAL_GRAPH = "preferences";
191
192     private static final boolean                    PROFILE                  = false;
193
194     ParametrizedRead<IResourceEditorInput, Boolean> INPUT_VALIDATOR =
195         Combinators.compose(
196                 InputValidationCombinators.or(
197                         // Normal configuration diagrams of a model
198                         Combinators.compose(
199                                 InputValidationCombinators.hasURI(),
200                                 InputValidationCombinators.partialFunction(ModelingResources.URIs.DiagramToComposite)
201                         ),
202                         // Configuration diagrams of a component type
203                         Combinators.compose(
204                                 InputValidationCombinators.hasURI(),
205                                 Combinators.compose(
206                                         InputValidationCombinators.partialFunction(StructuralResource2.URIs.Defines),
207                                         InputValidationCombinators.partialFunction(ModelingResources.URIs.DiagramToComposite)
208                                 )
209                         )
210                 ),
211                 InputValidationCombinators.extractInputResource()
212         );
213
214     protected EditorState                editorState;
215
216     protected boolean                    disposed           = false;
217     protected IThreadWorkQueue           swt;
218     protected IStatusLineManager         statusLineManager;
219     protected Display                    display;
220     protected LocalResourceManager       resourceManager;
221     protected SWTChassis                 c;
222     protected IDiagram                   sourceDiagram;
223     protected DataContainer<IDiagram>    sourceDiagramContainer = new DataContainer<IDiagram>();
224     protected CanvasContext              canvasContext;
225     protected ISessionContextProvider    sessionContextProvider;
226     protected ISessionContext            sessionContext;
227     protected Resource                   diagramResource;
228     protected GraphToDiagramSynchronizer synchronizer;
229     protected IActivation                activation;
230     protected ContextUtil                contextUtil;
231     protected SWTPopupMenuParticipant    popupMenuParticipant;
232     
233     protected DiagramPreferences         diagramPreferences;
234     protected DiagramDesc                diagramDesc;
235     protected GridSnapAdvisor            snapAdvisor;
236
237     private RuntimeDiagramManager        runtimeDiagramManager;
238
239     protected WorkbenchSelectionProvider selectionProvider;
240
241     public Resource getRuntime() {
242         RuntimeDiagramManager rtdm = runtimeDiagramManager;
243         return (rtdm == null) ? null : rtdm.getRuntimeDiagram();
244     }
245
246     public ParametrizedRead<IResourceEditorInput, Boolean> getInputValidator() {
247         return INPUT_VALIDATOR;
248     }
249
250     protected void addDropParticipants(ICanvasContext ctx) {
251         ctx.getDefaultHintContext().setHint(Hints.KEY_ALLOWED_DRAG_ACTIONS, DnDConstants.ACTION_COPY);
252
253         ctx.add(new PopulateElementDropParticipant(synchronizer, getPart()));
254         ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));
255     }
256
257     protected CopyPasteStrategy getCopyPasteStrategy() {
258                 try {
259                         CopyPasteStrategy cpStrategy = Simantics.getSession().syncRequest(new PossibleAdapter<CopyPasteStrategy>(getResourceEditorInput().getResource(), CopyPasteStrategy.class));
260                         if(cpStrategy != null) return cpStrategy;
261                 } catch (DatabaseException e) {
262                 }
263                 return new DefaultCopyPasteStrategy();
264     }
265
266     protected CopyAdvisor getCopyAdvisor() {
267                 try {
268                         CopyAdvisor advisor = Simantics.getSession().syncRequest(new PossibleAdapter<CopyAdvisor>(getResourceEditorInput().getResource(), CopyAdvisor.class));
269                         if(advisor != null) return advisor;
270                 } catch (DatabaseException e) {
271                 }
272                 return new MappedElementCopyAdvisor(new ElementCopyAdvisor(), new ComponentCopyAdvisor());
273     }
274     
275     /**
276      * @param ctx
277      * TODO: change argument from CanvasContext to ICanvasContext
278      */
279     protected void addKeyBindingParticipants(CanvasContext ctx) {
280         //ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );
281         ctx.add(new DeleteHandler(statusLineManager));
282         ctx.add(new CopyPasteHandler(getCopyPasteStrategy(), statusLineManager).setWorkbenchSite(getPart()));
283         ctx.add(new ConnectionCommandHandler());
284     }
285
286     protected void addPopupmenu(ICanvasContext ctx) {
287         ctx.add(popupMenuParticipant);
288     }
289
290     protected void addWorkbenchSelectionProvider(ICanvasContext ctx) {
291         ctx.add(selectionProvider);
292     }
293
294     protected void addViewManipulationParticipants(CanvasContext ctx) {
295         ctx.add(new PanZoomRotateHandler());
296         //ctx.add(new MousePanZoomInteractor());
297         //ctx.add(new MultitouchPanZoomRotateInteractor());
298         // ctx.add( new OrientationRestorer() );
299         ctx.add(new ZoomToAreaHandler());
300     }
301
302     protected void addDiagramParticipants(ICanvasContext ctx) {
303         ctx.add(new ZOrderHandler());
304         ctx.add(getPointerInteractor());
305         ctx.add(new ElementInteractor());
306         ctx.add(new Selection());
307         ctx.add(new DiagramParticipant());
308         ctx.add(new ElementPainter());
309         //ctx.add(new ElementHeartbeater());
310         //ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));
311         //ctx.add(new TooltipParticipant());
312         ctx.add(new TerminalTooltipParticipant());
313     }
314
315     protected void addPainterParticipants(ICanvasContext ctx) {
316         ctx.add(new RenderingQualityInteractor());
317         ctx.add(new TerminalPainter(true, true, false, true));
318         ctx.add(new DelayedBatchElementPainter(PickFilter.FILTER_MONITORS, 500, TimeUnit.MILLISECONDS));
319     }
320
321     protected void addStructureParticipants(ICanvasContext ctx) {
322         addWorkbenchSelectionProvider(ctx);
323         // Add visual browsing capabilities for structural models
324         ctx.add(new StructuralBrowsingHandler(sessionContext, getPart(), getResourceEditorInput()));
325         ctx.add(new LinkBrowsingHandler(this, sessionContext));
326     }
327
328     /**
329      * Override to add any diagram/canvas participants to the canvas context
330      * initialized for the editor.
331      * 
332      * @param ctx
333      */
334     protected void addOtherParticipants(CanvasContext ctx) {
335     }
336
337     public static Set<String> defaultPropertyBrowseContexts = Collections.singleton(ProjectResource.URIs.ProjectBrowseContext);
338
339     protected Set<String> getPropertyPageContexts() {
340         try {
341             return BrowseContext.getBrowseContextClosure(Simantics.getSession(), defaultPropertyBrowseContexts);
342         } catch (DatabaseException e) {
343             ExceptionUtils.logAndShowError("Failed to load modeled browse contexts for property page, see exception for details.", e);
344             return defaultPropertyBrowseContexts;
345         }
346     }
347
348     protected IPropertyPage createPropertyPage(MPart part, Set<String> contexts) {
349 //        #TODO Finish this when we are going to use full E4 workbench
350 //        return new StandardPropertyPage(part, contexts);
351         return null;
352     }
353
354     protected String getPopupId() {
355         return "#ModelingDiagramPopup";
356     }
357
358     protected void getPreferences() {
359         this.diagramPreferences = DiagramPreferenceUtil.getPreferences();
360     }
361
362     protected void initSession() {
363         sessionContextProvider = Simantics.getSessionContextProvider();
364         sessionContext = sessionContextProvider.getSessionContext();
365     }
366
367     protected void readNames() {
368         String name = getResourceEditorInput().getName();
369         host.doSetPartName(name);
370         host.doSetTitleToolTip(name);
371     }
372
373     class ChassisListener implements IChassisListener {
374         @Override
375         public void chassisClosed(ICanvasChassis sender) {
376             // Prevent deadlock while disposing which using syncExec would result in.
377             final ICanvasContext ctx = canvasContext;
378             ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {
379                 @Override
380                 public void run() {
381                     if (ctx != null) {
382                         saveEditorState(ctx);
383                         ctx.getHintStack().removeKeyHintListener(GridPainter.KEY_GRID_ENABLED, canvasHintListener);
384                         ctx.getHintStack().removeKeyHintListener(RulerPainter.KEY_RULER_ENABLED, canvasHintListener);
385                         final AWTChassis awtChassis = c.getAWTComponent();
386                         if (awtChassis != null)
387                             awtChassis.setCanvasContext(null);
388                         ctx.dispose();
389                     }
390
391                     sourceDiagramContainer.set(null);
392                     sourceDiagramContainer = null;
393
394                     if (sourceDiagram != null)
395                         sourceDiagram.dispose();
396
397                     if(synchronizer != null) {
398                         synchronizer.dispose();
399                         // Let GC work.
400                         synchronizer = null;
401                     }
402
403                     if (runtimeDiagramManager != null) {
404                         runtimeDiagramManager.dispose();
405                         runtimeDiagramManager = null;
406                     }
407                 }
408             });
409             c.removeChassisListener(ChassisListener.this);
410         }
411     }
412
413     protected void createChassis(Composite parent) {
414         resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
415         c = new SWTChassis(parent, 0);
416
417         Object task = BEGIN("DV.precreateParticipants");
418         createCustomParticipants();
419         END(task);
420
421         c.populate(component -> {
422             if (!disposed) {
423                 c.addChassisListener(new ChassisListener());
424                 initializeCanvas();
425             }
426         });
427     }
428
429     protected void beforeSetCanvasContext(ICanvasContext canvasContext2) {
430     }
431
432     /**
433      * Invoke this only from the AWT thread.
434      * @param context
435      */
436     protected void setCanvasContext(ICanvasContext context) {
437         // Cannot directly invoke SWTChassis.setCanvasContext only because it
438         // needs to be invoked in the SWT thread and AWTChassis.setCanvasContext in the
439         // AWT thread, but directly invoking SWTChassis.setCanvasContext would call both
440         // in the SWT thread which would cause synchronous scheduling of AWT
441         // runnables which is always a potential source of deadlocks.
442         c.getAWTComponent().setCanvasContext(canvasContext);
443         swt.asyncExec(new Runnable() {
444             @Override
445             public void run() {
446                 if (!c.isDisposed())
447                     // For AWT, this is a no-operation.
448                     c.setCanvasContext(canvasContext);
449             }
450         });
451     }
452
453     public void createPartControl(Composite parent) {
454         //ProfileObserver.begin = System.nanoTime();
455         display = parent.getDisplay(); 
456         swt = SWTThread.getThreadAccess(display);
457         statusLineManager = WorkbenchUtils.getStatusLine(WorkbenchUtils.getActiveWorkbenchPart());
458
459         Object task = BEGIN("DV.initSession");
460         initSession();
461         END(task);
462
463         diagramResource = getResourceEditorInput().getResource();
464         readNames();
465         getPreferences();
466
467         // DiagramViewerSelectionProvider MUST be created and attached to the
468         // workbench site:
469         //   1. in SWT thread!
470         //   2. here before returning from createPartControl
471         selectionProvider = createSelectionProvider();
472
473         try {
474             this.runtimeDiagramManager = RuntimeDiagramManager.track(sessionContext.getSession(), diagramResource, getResourceEditorInput(), this);
475
476             // Create the canvas context here before finishing createPartControl
477             // to give DiagramViewerActionContributor a chance to work.
478             // The context can be created in SWT thread without scheduling
479             // to the context thread and having potential deadlocks.
480             IThreadWorkQueue thread = AWTThread.getThreadAccess();
481             this.canvasContext = new CanvasContext(thread);
482             this.canvasContext.setLocked(true);
483
484             task = BEGIN("DV.createChassis");
485             createChassis(parent);
486             END(task);
487         } catch (DatabaseException e) {
488             ErrorLogger.defaultLogError(e);
489         }
490     }
491
492     /**
493      * @return
494      */
495     protected WorkbenchSelectionProvider createSelectionProvider() {
496 //        #TODO Finish this when we are going to use full E4 workbench        
497 //        return new DiagramViewerSelectionProvider(swt, getPart(), sourceDiagramContainer);
498         return null;
499     }
500
501         /**
502      * A method invoked before chassis construction for creating such
503      * {@link ICanvasParticipant}s that need to be constructed in the SWT
504      * thread.
505      * 
506      * Use it for creating any such canvas participants during the viewer 
507      * construction and add them to the {@link ICanvasContext} later on from
508      * the AWT thread.
509      */
510     protected void createCustomParticipants() {
511 //        #TODO Finish this when we are going to use full E4 workbench
512 //        popupMenuParticipant = new SWTPopupMenuParticipant(getPart(), c, display, getPopupId());
513     }
514
515     /**
516      * Invoke this only from the AWT thread.
517      */
518     protected void initializeCanvas() {
519         Object canvasInit = BEGIN("DV.canvasInitialization");
520
521         Object task = BEGIN("DV.createViewerCanvas");
522         initializeCanvasContext(canvasContext);
523         END(task);
524
525         beforeSetCanvasContext(canvasContext);
526         //FullscreenUtils.addFullScreenHandler(canvasContext, s, canvasProvider);
527
528         // Without this all diagram participants will crash like there's no tomorrow.
529         // Just trying to keep the behavior a bit more sane in case of
530         // errors instead of flooding the console with exceptions.
531         canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, Diagram.spawnNew(DiagramClass.DEFAULT));
532
533         // Changes in ruler/grid activity shall be written as
534         // workspace-persistent diagram-specific preferences.
535         canvasContext.getHintStack().addKeyHintListener(GridPainter.KEY_GRID_ENABLED, canvasHintListener);
536         canvasContext.getHintStack().addKeyHintListener(RulerPainter.KEY_RULER_ENABLED, canvasHintListener);
537
538         task = BEGIN("DV.setCanvasContext");
539         setCanvasContext(canvasContext);
540         END(task);
541
542         // Finish loading in a worker thread because it may be a time consuming
543         // process to load a large diagram and we don't want unnecessary AWT
544         // thread contention.
545         Job loadJob = new DiagramViewerLoadJob(this);
546         loadJob.schedule();
547
548         END(canvasInit);
549     }
550
551     protected void activateUiContexts(ContextUtil util) {
552         util.activate(DIAGRAMMING_CONTEXT);
553     }
554
555     /**
556      * @param monitor the progress monitor to use for reporting progress to the
557      *        user. It is the caller's responsibility to call done() on the
558      *        given monitor. Accepts <code>null</code>, indicating that no
559      *        progress should be reported and that the operation cannot be
560      *        cancelled.
561      */
562     protected void performActivation(IProgressMonitor monitor) {
563         SubMonitor progress = SubMonitor.convert(monitor, "Activate Mapping", 100);
564         IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class);
565         if (activationManager != null) {
566             activation = activationManager.activate(diagramResource);
567         }
568         progress.worked(100);
569     }
570
571     protected void onCreated() {
572     }
573
574     /**
575      * @param diagram
576      */
577     protected void scheduleZoomToFit(IDiagram diagram) {
578         if (diagram == null)
579             throw new IllegalStateException("diagram is null");
580
581         CanvasUtils.scheduleZoomToFit(swt, () -> disposed, canvasContext, diagram);
582     }
583
584     /**
585      * Subclasses may override but should always invoke super.
586      * 
587      * @param diagram
588      * @param initialHints
589      * @throws DatabaseException
590      */
591     protected void fillInitialDiagramHints(Resource diagram, IHintContext initialHints) throws DatabaseException {
592         IModelingRules modelingRules = sessionContext.getSession().syncRequest(
593                 DiagramRequests.getModelingRules(diagram, null));
594         if (modelingRules != null) {
595             initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules);
596             initialHints.setHint(DiagramHints.CONNECTION_ADVISOR,
597                     getConnectionAdvisor(modelingRules, sessionContext.getSession()));
598         }
599
600         initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor());
601         initialHints.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, Boolean.TRUE);
602         initialHints.setHint(DiagramHints.KEY_ALLOW_CONNECTION_BRANCHING, Boolean.TRUE);
603         initialHints.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.TRUE);
604     }
605
606     /**
607      * @param monitor the progress monitor to use for reporting progress to the
608      *        user. It is the caller's responsibility to call done() on the
609      *        given monitor. Accepts <code>null</code>, indicating that no
610      *        progress should be reported and that the operation cannot be
611      *        cancelled.
612      * @param r
613      * @return
614      * @throws DatabaseException
615      */
616     protected IDiagram loadDiagram(IProgressMonitor monitor, final Resource r) throws DatabaseException {
617         // Pre-load modeling rules and possibly other hints too since they are
618         // needed already while loading the diagram contents.
619         IHintContext initialHints = new HintContext();
620         fillInitialDiagramHints(r, initialHints);
621         IDiagram d = loadDiagram(monitor, r, initialHints);
622         return d;
623     }
624
625     /**
626      * @param monitor the progress monitor to use for reporting progress to the
627      *        user. It is the caller's responsibility to call done() on the
628      *        given monitor. Accepts <code>null</code>, indicating that no
629      *        progress should be reported and that the operation cannot be
630      *        cancelled.
631      * @param diagram
632      * @param initialHints
633      * @return
634      * @throws DatabaseException
635      */
636     protected IDiagram loadDiagram(IProgressMonitor monitor, Resource diagram, IHintContext initialHints) throws DatabaseException {
637         RuntimeDiagramManager rtdm = runtimeDiagramManager;
638         Resource runtimeDiagram = rtdm != null ? rtdm.getRuntimeDiagram() : null;
639         IDiagramLoader loader = synchronizer;
640         if (rtdm == null || runtimeDiagram == null || loader == null)
641                 return null;
642         IDiagram d = sessionContext.getSession().syncRequest(
643                 DiagramRequests.loadDiagram(monitor, getResourceEditorInput().getModel(null), diagram,
644                         runtimeDiagram, null, loader, initialHints));
645         return d;
646     }
647
648     protected void beforeSetDiagram(IDiagram diagram) {
649     }
650
651     protected PointerInteractor getPointerInteractor() {
652         return new PointerInteractor2(true, true, true, false, true, false, synchronizer.getElementClassProvider());
653     }
654
655     protected IConnectionAdvisor getConnectionAdvisor(IModelingRules modelingRules, Session session) {
656         return new ModelledConnectionAdvisor(modelingRules, sessionContext.getSession());
657     }
658
659     protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) {
660         try {
661             return sessionContext.getSession().syncRequest(new Read<GraphToDiagramSynchronizer>() {
662                 @Override
663                 public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException {
664                     GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx, createElementClassProvider(graph));
665                     initializeSynchronizationContext(graph, sync);
666                     return sync;
667                 }
668             });
669         } catch (DatabaseException e) {
670             throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e);
671         }
672     }
673
674     protected void initializeSynchronizationContext(ReadGraph graph, IModifiableSynchronizationContext context) {
675         context.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph));
676     }
677
678     protected IElementClassProvider createElementClassProvider(ReadGraph graph) {
679         DiagramResource dr = DiagramResource.getInstance(graph);
680         return ElementClassProviders.mappedProvider(
681                 ElementClasses.CONNECTION, ConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(dr.RouteGraphConnection)),
682                 ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)
683         );
684     }
685     
686     protected SimpleElementTransformHandler getTransformHandler() {
687         return new SimpleElementTransformHandler(true, true, true);
688     }
689
690     public void initializeCanvasContext(CanvasContext ctx) {
691         IHintContext h = ctx.getDefaultHintContext();
692
693         // The canvas context should not be painted until it is ready to avoid
694         // unnecessary visual glitches.
695         h.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);
696
697         Object task = BEGIN("createSynchronizer");
698         this.synchronizer = createSynchronizer(ctx, sessionContext);
699         END(task);
700
701         EContextService contextService = getPart().getContext().get(EContextService.class);
702         contextUtil = new ContextUtil(contextService, swt);
703
704         // Support & Util Participants
705         ctx.add(new TransformUtil());
706         ctx.add(new MouseUtil());
707         ctx.add(new KeyUtil());
708         ctx.add(contextUtil);
709         ctx.add(new WorkbenchStatusLine(statusLineManager));
710         ctx.add(new CanvasGrab());
711         ctx.add(new SymbolUtil());
712         ctx.add(new TimeParticipant());
713         ctx.add(new CanvasBoundsParticipant());
714         ctx.add(new Notifications());
715
716         ctx.add(new SGFocusParticipant(c, DIAGRAMMING_CONTEXT));
717
718         // Debug participant(s)
719         // ctx.add( new PointerPainter() );
720         // ctx.add( new HandPainter() );
721         h.setHint(PointerPainter.KEY_PAINT_POINTER, true);
722
723         // Pan & Zoom & Rotate
724         addViewManipulationParticipants(ctx);
725
726         ctx.add(getTransformHandler());
727         ctx.add(new ExpandSelectionHandler(statusLineManager));
728
729         // Key bindings
730         addKeyBindingParticipants(ctx);
731
732         // Grid & Ruler & Background
733         ctx.add(new GridPainter());
734         ctx.add(new RulerPainter());
735         ctx.add(new BackgroundPainter());
736
737         h.setHint(Hints.KEY_DISPLAY_PAGE, diagramPreferences.get(DiagramPreferences.P_DISPLAY_PAGE_SIZE));
738         h.setHint(Hints.KEY_DISPLAY_MARGINS, diagramPreferences.get(DiagramPreferences.P_DISPLAY_MARGINS));
739         ctx.add(new PageBorderParticipant());
740
741         // h.setHint(Hints.KEY_GRID_COLOR, new Color(0.9f, 0.9f, 0.9f));
742         // h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.LIGHT_GRAY);
743         h.setHint(Hints.KEY_GRID_COLOR, new Color(0.9f, 0.9f, 0.9f));
744         h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE);
745         h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f));
746         h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK);
747
748         ////// Diagram Participants //////
749         addDiagramParticipants(ctx);
750         addPainterParticipants(ctx);
751
752         /////// D'n'D ///////
753         addDropParticipants(ctx);
754
755         h.setHint(ElementPainter.KEY_SELECTION_FRAME_COLOR, Color.MAGENTA);
756         h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);
757
758         h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 100000.0);
759         h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0);
760
761         Double snapResolution = diagramPreferences.get(DiagramPreferences.P_SNAP_GRID_SIZE);
762         this.snapAdvisor = new GridSnapAdvisor(snapResolution);
763         h.setHint(DiagramHints.SNAP_ADVISOR, this.snapAdvisor);
764         h.setHint(GridPainter.KEY_GRID_SIZE, snapResolution);
765         h.setHint(GridPainter.KEY_GRID_ENABLED, Boolean.FALSE);
766
767         // Workbench selection provider
768         addStructureParticipants(ctx);
769
770         // Pop-up menu
771         addPopupmenu(ctx);
772
773         // Load page frame description settings
774         loadPageSettings(ctx);
775
776         addOtherParticipants(ctx);
777
778         ctx.assertParticipantDependencies();
779         ctx.setLocked(false);
780     }
781
782     protected void loadPageSettings(ICanvasContext ctx) {
783         DiagramDesc diagramDesc = null;
784
785         // load diagram page configuration
786         if (diagramResource != null) {
787             try {
788                 diagramDesc = sessionContext.getSession().syncRequest(DiagramRequests.getDiagramDesc(diagramResource));
789             } catch (DatabaseException e) {
790                 ErrorLogger.defaultLogError(e);
791             }
792         }
793
794         if (diagramDesc == null) {
795             // Take page description from the preferences if nothing else is available.
796             final DiagramDesc desc = diagramDesc = diagramPreferences.getDiagramDesc();
797
798             // Write page configuration to graph
799             sessionContext.getSession().asyncRequest(new WriteRequest() {
800                 @Override
801                 public void perform(WriteGraph graph) throws DatabaseException {
802                         CommonDBUtils.selectClusterSet(graph, diagramResource);
803                     DiagramGraphUtil.setDiagramDesc(graph, diagramResource, desc);
804                 }
805             }, e -> {
806                 if (e != null)
807                     ErrorLogger.defaultLogError("Failed to write default diagram page description to database, see exception for details", e);
808             });
809         }
810
811         setDiagramDesc(ctx, diagramDesc);
812
813         // Create a listener to react to page setting changes.
814         sessionContext.getSession().asyncRequest(DiagramRequests.getDiagramDesc(diagramResource),
815                 new ListenerDelegate<DiagramDesc>(this) {
816             @Override
817             public void execute(final DiagramDesc result) {
818                 if (result != null && canvasContext != null) {
819                     ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {
820                         @Override
821                         public void run() {
822                             if (!disposed)
823                                 setDiagramDesc(canvasContext, result);
824                         }
825                     });
826                 }
827             }
828         });
829     }
830
831     protected void setDiagramDesc(ICanvasContext ctx, DiagramDesc diagramDesc) {
832         if (diagramDesc == null)
833             throw new NullPointerException("null diagram desc");
834
835         if (diagramDesc.equals(this.diagramDesc))
836             return;
837
838         this.diagramDesc = diagramDesc;
839         IHintContext hints = ctx.getDefaultHintContext();
840         hints.setHint(Hints.KEY_PAGE_DESC, diagramDesc.getPageDesc());
841         hints.setHint(Hints.KEY_DISPLAY_PAGE, diagramDesc.isPageBordersVisible());
842         hints.setHint(Hints.KEY_DISPLAY_MARGINS, diagramDesc.isMarginsVisible());
843         hints.setHint(GridPainter.KEY_GRID_ENABLED, diagramDesc.isGridVisible());
844         hints.setHint(RulerPainter.KEY_RULER_ENABLED, diagramDesc.isRulerVisible());
845         snapAdvisor.setResolution(diagramDesc.getGridSize());
846         hints.setHint(GridPainter.KEY_GRID_SIZE, diagramDesc.getGridSize());
847     }
848
849     /**
850      * Must be invoked from the AWT thread only.
851      * 
852      * @param state
853      * @param ctx
854      */
855     protected void applyEditorState(final EditorState state, final ICanvasContext ctx) {
856         final IDiagram diagram = ctx.getHintStack().getHint(DiagramHints.KEY_DIAGRAM);
857
858         if (state.viewTransform != null && state.viewTransform.getDeterminant() != 0) {
859             for (PanZoomRotateHandler h : ctx.getItemsByClass(PanZoomRotateHandler.class)) {
860                 h.setTransform(state.viewTransform);
861             }
862         }
863
864         if (diagram != null) {
865             if (state.viewTransform != null)
866                 diagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
867
868             if (state.toolMode != null)
869                 ctx.getDefaultHintContext().setHint(Hints.KEY_TOOL, state.toToolMode());
870             else
871                 ctx.getDefaultHintContext().setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);
872
873             final Set<IElement> selected = DiagramEditorStates.toElements(state.selection, diagram);
874             if (!selected.isEmpty()) {
875                 for (Selection s : ctx.getItemsByClass(Selection.class)) {
876                     s.setSelection(0, selected);
877                 }
878             }
879         }
880     }
881
882     protected EditorState getSavedEditorState(ICanvasContext ctx) {
883         return DiagramEditorStates.toEditorState(ctx, true, true, true);
884     }
885
886     protected void saveEditorState(ICanvasContext ctx) {
887         DiagramEditorStates.saveEditorState(PREFERENCE_VIRTUAL_GRAPH, diagramResource, getSavedEditorState(ctx) , DiagramViewer.this);
888     }
889
890     private boolean firstFocus = true;
891
892     public void setFocus() {
893         
894         if(c != null) {
895                 c.setFocus();
896
897                 if (firstFocus) {
898                     // This is a workaround for using the symbol viewer in multi-page
899                     // editors which causes the first zoom-to-fit scheduling to happen
900                     // already before the controls have been laid out properly.
901                     firstFocus = false;
902                     firstTimeSetFocus();
903                 }
904                 
905         }
906         
907     }
908
909     protected void firstTimeSetFocus() {
910         // [Tuukka@2010-02-11]
911         // Removed since this is actually a workaround for multi-page editors.
912         //scheduleZoomToFit();
913     }
914
915     public void dispose() {
916         // Deactivate all contexts here because after this the context service
917         // in question will not be available.
918         if (contextUtil != null) {
919             contextUtil.deactivateAll();
920         }
921
922         disposed = true;
923         if (activation != null) {
924             activation.deactivate();
925             activation = null;
926         }
927
928         if (resourceManager != null) {
929                 resourceManager.dispose();
930                 resourceManager = null;
931         }
932         //super.dispose();
933     }
934
935 //    protected Resource getInputResource() {
936 //        return getResourceInput().getResource();
937 //    }
938 //
939 //    public IResourceEditorInput getResourceInput() {
940 //        return (IResourceEditorInput) getEditorInput();
941 //    }
942 //
943 //    public IResourceEditorInput2 getResourceInput2() {
944 //        return (IResourceEditorInput2) getEditorInput();
945 //    }
946
947     public void init(DiagramViewerHost _host, MPart part, IResourceEditorInput2 input) {
948
949         if (!(input instanceof IResourceEditorInput))
950             throw new RuntimeException("Invalid input: must be IResourceEditorInput");
951
952         setHost(_host);
953         setPart(part);
954         setResourceEditorInput(input);
955
956         // Set initial part name according to the name given by IEditorInput
957         host.doSetPartName(getResourceEditorInput().getName());
958
959         Session session = Simantics.peekSession();
960         if (session != null) {
961             Supplier<Boolean> disposedCallback = () -> disposed;
962             Display display = part.getContext().get(Shell.class).getDisplay();
963             session.asyncRequest(
964                     new TitleRequest(part.getElementId(), getResourceEditorInput()),
965                     new TitleUpdater(display, host::doSetPartName, disposedCallback));
966             session.asyncRequest(
967                     new ToolTipRequest(part.getElementId(), getResourceEditorInput()),
968                     new TitleUpdater(display, host::doSetTitleToolTip, disposedCallback));
969         }
970
971         try {
972             // Read previous editor state from the database
973             editorState = DiagramEditorStates.readEditorState(getResourceEditorInput().getResource());
974         } catch (DatabaseException e) {
975             exception(e);
976         }
977     }
978
979     @SuppressWarnings("rawtypes")
980     @Override
981     public Object getAdapter(Class adapter) {
982 //        System.out.println("diagramViewer getAdapter " + adapter);
983         // Property view support
984         if (adapter == IPropertyPage.class)
985             return createPropertyPage(getPart(), getPropertyPageContexts());
986         // Provide symbols for the editor
987         if (adapter == SymbolProviderFactory.class) {
988             try {
989                 return DiagramTypeUtils.readSymbolProviderFactory(sessionContext.getSession(), diagramResource);
990             } catch (DatabaseException e) {
991                 ErrorLogger.defaultLogError(getClass() + " failed to adapt to SymbolProviderFactory, see exception for details.", e);
992                 return null;
993             }
994         }
995         // Outline view support
996         if (adapter == IContentOutlinePage.class)
997             return new DiagramOutlinePage(sessionContextProvider, getResourceEditorInput());
998         // Role view support
999         if (adapter == ILayersViewPage.class)
1000             return new DiagramLayersPage(canvasContext);
1001         // Support external steering of the diagram canvas, zooming etc.
1002         if (adapter == ICanvasContext.class)
1003             return canvasContext;
1004         // Support scene graph debugger view
1005         if (adapter == INode.class) {
1006             if (canvasContext != null) {
1007                 INode node = canvasContext.getCanvasNode();
1008                 if (node != null)
1009                     return NodeUtil.getRootNode(node);
1010             }
1011             return null;
1012         }
1013         // Support retrieval of the current diagram.
1014         if (adapter == IDiagram.class)
1015             return sourceDiagram;
1016         // Why is this here ??
1017         if (adapter == Session.class)
1018             return sessionContext.getSession();
1019         if(adapter == RuntimeDiagramManager.class)
1020             return runtimeDiagramManager;
1021         if (adapter == Resource.class)
1022             return getRuntime();
1023         if (adapter == ICanvasChassis.class)
1024                 return c;
1025
1026         return null;
1027     }
1028
1029     //-------------------------------------------------------------------------
1030     // Profiling aid
1031
1032     protected static Object BEGIN(String name) {
1033         if (PROFILE) {
1034             //return ThreadLog.BEGIN(name);
1035         }
1036         return null;
1037     }
1038
1039     protected static void END(Object task) {
1040         if (PROFILE) {
1041             //((Task) task).end();
1042         }
1043     }
1044
1045     //-------------------------------------------------------------------------
1046     // implement ListenerSupport
1047
1048     @Override
1049     public void exception(Throwable t) {
1050         ErrorLogger.defaultLogError(t);
1051     }
1052
1053     @Override
1054     public boolean isDisposed() {
1055         return disposed;
1056     }
1057
1058     protected void collectGarbage() {
1059         SessionGarbageCollectorJob.getInstance().schedule(0);
1060         AWTThread.getThreadAccess().asyncExec(new Runnable() {
1061             @Override
1062             public void run() {
1063                 //System.out.println("BEFORE CLEAR: " + SVGCache.getSVGUniverse().report());
1064                 SVGCache.getSVGUniverse().clearUnreferenced();
1065                 //System.out.println("AFTER CLEAR: " + SVGCache.getSVGUniverse().report());
1066             }
1067         });
1068     }
1069
1070     //-------------------------------------------------------------------------
1071     // Listener for certain canvas context hint changes
1072
1073     IHintListener canvasHintListener = new HintListenerAdapter() {
1074         @Override
1075         public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
1076             if (key == GridPainter.KEY_GRID_ENABLED) {
1077                 boolean v = Boolean.TRUE.equals(newValue);
1078                 if (diagramDesc.isGridVisible() != v)
1079                     setGlobalPreference(DiagramResource.URIs.DisplayGrid, v);
1080             } else if (key == RulerPainter.KEY_RULER_ENABLED) {
1081                 boolean v = Boolean.TRUE.equals(newValue);
1082                 if (diagramDesc.isRulerVisible() != v)
1083                     setGlobalPreference(DiagramResource.URIs.DisplayRuler, v);
1084             }
1085         }
1086     };
1087
1088     private <T> void setGlobalPreference(final String preferenceURI, boolean value) {
1089         TagUtil.execute(Simantics.getSession(), PREFERENCE_VIRTUAL_GRAPH, preferenceURI, value, Simantics.getProjectResource());
1090     }
1091
1092     /*
1093      * --------------------------------------------------------------------
1094      * Changes related to removal of EditorPart extension from here on down
1095      * --------------------------------------------------------------------
1096      */
1097
1098     private MPart part;
1099     private DiagramViewerHost host;
1100     private IResourceEditorInput2 resourceEditorInput = null;
1101
1102     public MPart getPart() {
1103         return part;
1104     }
1105
1106 //    public IEditorSite getEditorSite() {
1107 //        return (IEditorSite) getSite();
1108 //    }
1109
1110 //    public IEditorInput getEditorInput() {
1111 //        return editorInput;
1112 //    }
1113
1114 //    protected void setPartName(String partName) {
1115 ////        if (compatibilityTitleListener != null) {
1116 ////            removePropertyListener(compatibilityTitleListener);
1117 ////            compatibilityTitleListener = null;
1118 ////        }
1119 ////
1120 ////        super.setPartName(partName);
1121 //    }
1122  
1123 //    protected void setTitleToolTip(String toolTip) {
1124 ////        toolTip = Util.safeString(toolTip);
1125 ////        //Do not send changes if they are the same
1126 ////        if (Util.equals(this.toolTip, toolTip)) {
1127 ////                    return;
1128 ////            }
1129 ////        this.toolTip = toolTip;
1130 ////        firePropertyChange(IWorkbenchPart.PROP_TITLE);
1131 //    }
1132
1133     protected void setHost(DiagramViewerHost host) {
1134         this.host = host;
1135     }
1136
1137     protected void setPart(MPart part) {
1138         this.part = part;
1139     }
1140
1141     protected void setResourceEditorInput(IResourceEditorInput2 input) {
1142         Assert.isLegal(input != null);
1143         resourceEditorInput = input;
1144     }
1145     
1146     public IResourceEditorInput2 getResourceEditorInput() {
1147         return resourceEditorInput;
1148     }
1149
1150     public Composite getComposite() {
1151         return c;
1152     }
1153
1154 }