1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.ui.diagramEditor;
14 import java.awt.Color;
15 import java.awt.datatransfer.Transferable;
16 import java.awt.datatransfer.UnsupportedFlavorException;
17 import java.io.IOException;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.NullProgressMonitor;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.ui.IEditorInput;
23 import org.eclipse.ui.IEditorSite;
24 import org.eclipse.ui.PartInitException;
25 import org.eclipse.ui.contexts.IContextActivation;
26 import org.eclipse.ui.contexts.IContextService;
27 import org.eclipse.ui.part.EditorPart;
28 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
29 import org.simantics.Simantics;
30 import org.simantics.db.ReadGraph;
31 import org.simantics.db.Session;
32 import org.simantics.db.common.ResourceArray;
33 import org.simantics.db.exception.DatabaseException;
34 import org.simantics.db.management.ISessionContext;
35 import org.simantics.db.management.ISessionContextProvider;
36 import org.simantics.db.request.Read;
37 import org.simantics.db.service.SerialisationSupport;
38 import org.simantics.diagram.adapter.DefaultConnectionClassFactory;
39 import org.simantics.diagram.adapter.FlagClassFactory;
40 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
41 import org.simantics.diagram.handler.SimpleElementTransformHandler;
42 import org.simantics.diagram.layer.ILayersViewPage;
43 import org.simantics.diagram.query.DiagramRequests;
44 import org.simantics.diagram.stubs.DiagramResource;
45 import org.simantics.diagram.ui.DiagramModelHints;
46 import org.simantics.g2d.canvas.Hints;
47 import org.simantics.g2d.canvas.ICanvasContext;
48 import org.simantics.g2d.canvas.impl.CanvasContext;
49 import org.simantics.g2d.diagram.DiagramHints;
50 import org.simantics.g2d.diagram.IDiagram;
51 import org.simantics.g2d.diagram.participant.DiagramParticipant;
52 import org.simantics.g2d.diagram.participant.ElementInteractor;
53 import org.simantics.g2d.diagram.participant.ElementPainter;
54 import org.simantics.g2d.diagram.participant.Selection;
55 import org.simantics.g2d.diagram.participant.TerminalPainter;
56 import org.simantics.g2d.diagram.participant.ZOrderHandler;
57 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
58 import org.simantics.g2d.element.ElementClassProviders;
59 import org.simantics.g2d.element.ElementClasses;
60 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
61 import org.simantics.g2d.multileveldiagram.TransitionFunction;
62 import org.simantics.g2d.multileveldiagram.ZoomTransitionParticipant;
63 import org.simantics.g2d.participant.BackgroundPainter;
64 import org.simantics.g2d.participant.CanvasBoundsParticipant;
65 import org.simantics.g2d.participant.CanvasGrab;
66 import org.simantics.g2d.participant.GridPainter;
67 import org.simantics.g2d.participant.KeyToCommand;
68 import org.simantics.g2d.participant.KeyUtil;
69 import org.simantics.g2d.participant.MouseUtil;
70 import org.simantics.g2d.participant.MultitouchPanZoomRotateInteractor;
71 import org.simantics.g2d.participant.Notifications;
72 import org.simantics.g2d.participant.PageBorderParticipant;
73 import org.simantics.g2d.participant.PanZoomRotateHandler;
74 import org.simantics.g2d.participant.PointerPainter;
75 import org.simantics.g2d.participant.RulerPainter;
76 import org.simantics.g2d.participant.SymbolUtil;
77 import org.simantics.g2d.participant.TimeParticipant;
78 import org.simantics.g2d.participant.TransformUtil;
79 import org.simantics.g2d.participant.ZoomToAreaHandler;
80 import org.simantics.g2d.utils.CanvasUtils;
81 import org.simantics.layer0.utils.triggers.IActivation;
82 import org.simantics.modeling.ModelingResources;
83 import org.simantics.modeling.mapping.ModelingSynchronizationHints;
84 import org.simantics.scenegraph.g2d.events.command.CommandKeyBinding;
85 import org.simantics.scenegraph.g2d.events.command.Commands;
86 import org.simantics.simulation.experiment.IExperiment;
87 import org.simantics.ui.dnd.ResourceTransferData;
88 import org.simantics.ui.dnd.ResourceTransferUtils;
89 import org.simantics.ui.workbench.IResourceEditorInput;
90 import org.simantics.ui.workbench.IResourceEditorInput2;
91 import org.simantics.ui.workbench.IResourceEditorPart2;
92 import org.simantics.ui.workbench.ResourceEditorSupport;
93 import org.simantics.utils.datastructures.hints.HintContext;
94 import org.simantics.utils.datastructures.hints.IHintContext;
95 import org.simantics.utils.page.PageDesc;
96 import org.simantics.utils.page.PageOrientation;
97 import org.simantics.utils.threads.AWTThread;
98 import org.simantics.utils.threads.IThreadWorkQueue;
103 public class WikiDiagramViewer extends EditorPart implements IResourceEditorPart2 {
105 protected boolean disposed = false;
106 protected IDiagram sourceDiagram;
107 protected ICanvasContext canvasContext;
108 protected ResourceEditorSupport support;
109 protected ISessionContextProvider sessionContextProvider;
110 protected ISessionContext sessionContext;
111 protected GraphToDiagramSynchronizer synchronizer;
112 protected IActivation activation;
113 protected ResourceArray structuralPath = new ResourceArray();
114 protected IContextActivation contextActivation;
115 protected IExperiment experiment;
116 protected String layer = null;
118 public WikiDiagramViewer() {
121 protected void addDropParticipants(ICanvasContext ctx) {
122 // FIXME This is a workaround so that this participant can be disabled
124 ctx.add(new PopulateElementDropParticipant(synchronizer));
125 ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));
128 protected void addKeyBindingParticipants(CanvasContext ctx) {
129 ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );
132 public void setExperiment(IExperiment experiment) {
133 sourceDiagram.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment);
136 public void init(ResourceArray structuralPath, String layer, IExperiment experiment) {
137 this.experiment = experiment;
139 this.structuralPath = structuralPath;
141 sessionContextProvider = Simantics.getSessionContextProvider();
142 sessionContext = sessionContextProvider.getSessionContext();
144 canvasContext = createViewerCanvas();
147 sourceDiagram = loadDiagram(structuralPath, experiment);
148 } catch (DatabaseException e) {
154 public void updateDiagram(ResourceArray structuralPath) {
155 canvasContext = createViewerCanvas();
157 IHintContext hints = new HintContext();
158 hints.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment);
160 System.out.println("using layer '"+layer+"'");
161 hints.setHint(DiagramHints.KEY_FIXED_LAYERS, new String[] { layer });
164 sourceDiagram = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(new NullProgressMonitor(), getResourceInput2().getModel(null), structuralPath.resources[0], null, structuralPath.removeFromBeginning(0), synchronizer, hints));
165 canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, sourceDiagram);
166 } catch (DatabaseException e) {
171 void scheduleZoomToFit() {
172 if (sourceDiagram == null)
173 throw new IllegalStateException("source diagram is null");
175 sourceDiagram.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);
176 sourceDiagram.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE);
179 sourceDiagram.removeHint(Hints.KEY_DISABLE_PAINTING);
180 Boolean zoomToFit = sourceDiagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
181 if (zoomToFit != null && zoomToFit)
182 CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT);
183 canvasContext.getContentContext().setDirty();
186 protected IDiagram loadDiagram(ResourceArray structuralPath, IExperiment experiment) throws DatabaseException {
187 IHintContext hints = new HintContext();
188 if(experiment != null)
189 hints.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment);
191 System.out.println("using layer '"+layer+"'");
192 hints.setHint(DiagramHints.KEY_FIXED_LAYERS, new String[] { layer });
194 IDiagram d = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(new NullProgressMonitor(), getResourceInput2().getModel(null), structuralPath.resources[0], null, structuralPath.removeFromBeginning(0), synchronizer, hints));
195 canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, d);
199 protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) {
201 return sessionContext.getSession().syncRequest(new Read<GraphToDiagramSynchronizer>() {
203 public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException {
204 DiagramResource dr = DiagramResource.getInstance(graph);
205 GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx,
206 ElementClassProviders.mappedProvider(
207 ElementClasses.CONNECTION, DefaultConnectionClassFactory.CLASS.newClassWith(new StaticObjectAdapter(dr.Connection)),
208 ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)
211 sync.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph));
215 } catch (DatabaseException e) {
216 throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e);
220 public ICanvasContext createViewerCanvas()
222 IThreadWorkQueue thread = AWTThread.getThreadAccess();
223 CanvasContext ctx = new CanvasContext(thread);
224 IHintContext h = ctx.getDefaultHintContext();
226 this.synchronizer = createSynchronizer(ctx, sessionContext);
228 canvasContext.add( new PanZoomRotateHandler() ); // Must be before TransformUtil
230 // Support & Util Participants
231 ctx.add( new TransformUtil() );
232 ctx.add( new MouseUtil() );
233 ctx.add( new KeyUtil() );
234 ctx.add( new CanvasGrab() );
235 ctx.add( new SymbolUtil() );
236 ctx.add( new TimeParticipant() );
237 ctx.add( new CanvasBoundsParticipant() );
238 ctx.add( new Notifications() );
240 // ctx.add( new SGFocusParticipant(c) ); // FIXME: Get chassis from somewhere
242 h.setHint(PointerPainter.KEY_PAINT_POINTER, true);
244 ctx.add( new MultitouchPanZoomRotateInteractor() );
245 ctx.add( new ZoomToAreaHandler() );
246 ctx.add( new SimpleElementTransformHandler() );
249 addKeyBindingParticipants(ctx);
251 // Grid & Ruler & Background
253 ctx.add( new GridPainter() );
254 ctx.add( new RulerPainter() );
255 ctx.add( new BackgroundPainter() );
256 ctx.add( new PageBorderParticipant() );
258 h.setHint(Hints.KEY_GRID_COLOR, new Color(0.95f, 0.95f, 0.95f));
259 h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE);
260 h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f));
261 h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK);
263 ////// Diagram Participants //////
264 ctx.add(new PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider(), null));
265 ctx.add(new ElementInteractor());
266 ctx.add(new Selection());
267 ctx.add(new DiagramParticipant());
268 ctx.add(new ElementPainter());
269 ctx.add(new TerminalPainter(true, true, false, true));
270 //ctx.add(new ElementHeartbeater());
271 ctx.add(new ZOrderHandler());
272 ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));
274 /////// D'n'D ///////
275 addDropParticipants(ctx);
277 h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);
279 h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 1000.0);
280 h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0);
282 // Add visual browsing capabilities for structural models
283 // ctx.add(new HeadlessStructuralBrowsingHandler(this, sessionContext, structuralPath));
286 PageDesc pageDesc = PageDesc.DEFAULT.withOrientation(PageOrientation.Landscape);
287 // TODO: load page desc from graph
288 h.setHint(Hints.KEY_PAGE_DESC, pageDesc);
290 ctx.assertParticipantDependencies();
295 private boolean firstFocus = true;
298 public void setFocus() {
300 // This is a workaround for using the symbol viewer in multi-page
301 // editors which causes the first zoom-to-fit scheduling to happen
302 // already before the controls have been laid out properly.
308 protected void firstTimeSetFocus() {
313 public void dispose() {
314 System.out.println("RemoteDiagramViewer.dispose()");
315 if(getSite() != null) {
316 IContextService contextService = (IContextService) getSite().getService(IContextService.class);
317 contextService.deactivateContext(contextActivation);
321 if (activation != null) {
322 activation.deactivate();
326 if(synchronizer != null) {
327 synchronizer.dispose();
331 if(sourceDiagram != null) {
332 sourceDiagram.dispose();
333 sourceDiagram = null;
336 if(support != null) {
344 public void doSave(IProgressMonitor monitor) {
348 public void doSaveAs() {
352 public void init(IEditorSite site, IEditorInput input)
353 throws PartInitException {
354 if (!(input instanceof IResourceEditorInput))
355 throw new PartInitException("Invalid input: must be IResourceEditorInput");
358 support = new ResourceEditorSupport(this);
360 // Set initial part name according to the name given by IEditorInput
361 setPartName(getEditorInput().getName());
365 public boolean isDirty() {
370 public boolean isSaveAsAllowed() {
374 public static ResourceArray[] decodeToResources(Session session, Transferable tr)
377 SerialisationSupport support = session.getService(SerialisationSupport.class);
378 ResourceTransferData data = ResourceTransferUtils.readAwtTransferable(support, tr);
379 if ("property".equals(data.getPurpose()))
380 return data.toResourceArrayArray();
381 } catch (UnsupportedFlavorException e) {
382 throw new RuntimeException(e);
383 } catch (IOException e) {
384 throw new RuntimeException(e);
385 } catch (IllegalArgumentException e) {
386 throw new RuntimeException(e);
387 } catch (DatabaseException e) {
388 throw new RuntimeException(e);
393 @SuppressWarnings("rawtypes")
395 public Object getAdapter(Class adapter) {
396 if (adapter == IContentOutlinePage.class)
397 return new DiagramOutlinePage(sessionContextProvider, getResourceInput2());
398 if (adapter == ILayersViewPage.class)
399 return new DiagramLayersPage(sourceDiagram, canvasContext);
400 if (adapter == ICanvasContext.class)
401 return canvasContext;
402 if (adapter == IDiagram.class)
403 return sourceDiagram;
404 if (adapter == Session.class)
405 return sessionContext.getSession();
406 return super.getAdapter(adapter);
409 public ICanvasContext getCanvasContext() {
410 return canvasContext;
413 protected void onCreated() {
417 public void createPartControl(Composite parent) {
418 // TODO Auto-generated method stub
423 public IResourceEditorInput2 getResourceInput2() {
424 // TODO Auto-generated method stub
429 public IResourceEditorInput getResourceInput() {
430 // TODO Auto-generated method stub