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