X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2FdiagramEditor%2FWikiDiagramViewer.java;fp=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2FdiagramEditor%2FWikiDiagramViewer.java;h=8848eb2b2ba4a22e15226d94971f36fe635030ed;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/WikiDiagramViewer.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/WikiDiagramViewer.java new file mode 100644 index 000000000..8848eb2b2 --- /dev/null +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/WikiDiagramViewer.java @@ -0,0 +1,434 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.modeling.ui.diagramEditor; + +import java.awt.Color; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.contexts.IContextActivation; +import org.eclipse.ui.contexts.IContextService; +import org.eclipse.ui.part.EditorPart; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.simantics.db.ReadGraph; +import org.simantics.db.Session; +import org.simantics.db.common.ResourceArray; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.management.ISessionContextProvider; +import org.simantics.db.request.Read; +import org.simantics.db.service.SerialisationSupport; +import org.simantics.diagram.adapter.DefaultConnectionClassFactory; +import org.simantics.diagram.adapter.FlagClassFactory; +import org.simantics.diagram.adapter.GraphToDiagramSynchronizer; +import org.simantics.diagram.handler.SimpleElementTransformHandler; +import org.simantics.diagram.layer.ILayersViewPage; +import org.simantics.diagram.query.DiagramRequests; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.diagram.ui.DiagramModelHints; +import org.simantics.g2d.canvas.Hints; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.canvas.impl.CanvasContext; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.participant.DiagramParticipant; +import org.simantics.g2d.diagram.participant.ElementInteractor; +import org.simantics.g2d.diagram.participant.ElementPainter; +import org.simantics.g2d.diagram.participant.Selection; +import org.simantics.g2d.diagram.participant.TerminalPainter; +import org.simantics.g2d.diagram.participant.ZOrderHandler; +import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor; +import org.simantics.g2d.element.ElementClassProviders; +import org.simantics.g2d.element.ElementClasses; +import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; +import org.simantics.g2d.multileveldiagram.TransitionFunction; +import org.simantics.g2d.multileveldiagram.ZoomTransitionParticipant; +import org.simantics.g2d.participant.BackgroundPainter; +import org.simantics.g2d.participant.CanvasBoundsParticipant; +import org.simantics.g2d.participant.CanvasGrab; +import org.simantics.g2d.participant.GridPainter; +import org.simantics.g2d.participant.KeyToCommand; +import org.simantics.g2d.participant.KeyUtil; +import org.simantics.g2d.participant.MouseUtil; +import org.simantics.g2d.participant.MultitouchPanZoomRotateInteractor; +import org.simantics.g2d.participant.Notifications; +import org.simantics.g2d.participant.PageBorderParticipant; +import org.simantics.g2d.participant.PanZoomRotateHandler; +import org.simantics.g2d.participant.PointerPainter; +import org.simantics.g2d.participant.RulerPainter; +import org.simantics.g2d.participant.SymbolUtil; +import org.simantics.g2d.participant.TimeParticipant; +import org.simantics.g2d.participant.TransformUtil; +import org.simantics.g2d.participant.ZoomToAreaHandler; +import org.simantics.g2d.utils.CanvasUtils; +import org.simantics.layer0.utils.triggers.IActivation; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.mapping.ModelingSynchronizationHints; +import org.simantics.scenegraph.g2d.events.command.CommandKeyBinding; +import org.simantics.scenegraph.g2d.events.command.Commands; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.dnd.ResourceTransferData; +import org.simantics.ui.dnd.ResourceTransferUtils; +import org.simantics.ui.workbench.IResourceEditorInput; +import org.simantics.ui.workbench.IResourceEditorInput2; +import org.simantics.ui.workbench.IResourceEditorPart2; +import org.simantics.ui.workbench.ResourceEditorSupport; +import org.simantics.utils.datastructures.hints.HintContext; +import org.simantics.utils.datastructures.hints.IHintContext; +import org.simantics.utils.page.PageDesc; +import org.simantics.utils.page.PageOrientation; +import org.simantics.utils.threads.AWTThread; +import org.simantics.utils.threads.IThreadWorkQueue; + +/** + * @author J-P Laine + */ +public class WikiDiagramViewer extends EditorPart implements IResourceEditorPart2 { + + protected boolean disposed = false; + protected IDiagram sourceDiagram; + protected ICanvasContext canvasContext; + protected ResourceEditorSupport support; + protected ISessionContextProvider sessionContextProvider; + protected ISessionContext sessionContext; + protected GraphToDiagramSynchronizer synchronizer; + protected IActivation activation; + protected ResourceArray structuralPath = new ResourceArray(); + protected IContextActivation contextActivation; + protected IExperiment experiment; + protected String layer = null; + + public WikiDiagramViewer() { + } + + protected void addDropParticipants(ICanvasContext ctx) { + // FIXME This is a workaround so that this participant can be disabled + // for SymbolViewer + ctx.add(new PopulateElementDropParticipant(synchronizer)); + ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5)); + } + + protected void addKeyBindingParticipants(CanvasContext ctx) { + ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) ); + } + + public void setExperiment(IExperiment experiment) { + sourceDiagram.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment); + } + + public void init(ResourceArray structuralPath, String layer, IExperiment experiment) { + this.experiment = experiment; + this.layer = layer; + this.structuralPath = structuralPath; + + sessionContextProvider = SimanticsUI.getSessionContextProvider(); + sessionContext = sessionContextProvider.getSessionContext(); + + canvasContext = createViewerCanvas(); + + try { + sourceDiagram = loadDiagram(structuralPath, experiment); + } catch (DatabaseException e) { + e.printStackTrace(); + } + onCreated(); + } + + public void updateDiagram(ResourceArray structuralPath) { + canvasContext = createViewerCanvas(); + try { + IHintContext hints = new HintContext(); + hints.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment); + if(layer != null) { + System.out.println("using layer '"+layer+"'"); + hints.setHint(DiagramHints.KEY_FIXED_LAYERS, new String[] { layer }); + } + + sourceDiagram = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(new NullProgressMonitor(), getResourceInput2().getModel(null), structuralPath.resources[0], null, structuralPath.removeFromBeginning(0), synchronizer, hints)); + canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, sourceDiagram); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + void scheduleZoomToFit() { + if (sourceDiagram == null) + throw new IllegalStateException("source diagram is null"); + + sourceDiagram.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE); + sourceDiagram.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE); + + // zoom-to-fit + sourceDiagram.removeHint(Hints.KEY_DISABLE_PAINTING); + Boolean zoomToFit = sourceDiagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT); + if (zoomToFit != null && zoomToFit) + CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT); + canvasContext.getContentContext().setDirty(); + } + + protected IDiagram loadDiagram(ResourceArray structuralPath, IExperiment experiment) throws DatabaseException { + IHintContext hints = new HintContext(); + if(experiment != null) + hints.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment); + if(layer != null) { + System.out.println("using layer '"+layer+"'"); + hints.setHint(DiagramHints.KEY_FIXED_LAYERS, new String[] { layer }); + } + IDiagram d = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(new NullProgressMonitor(), getResourceInput2().getModel(null), structuralPath.resources[0], null, structuralPath.removeFromBeginning(0), synchronizer, hints)); + canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, d); + return d; + } + + protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) { + try { + return sessionContext.getSession().syncRequest(new Read() { + @Override + public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(graph); + GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx, + ElementClassProviders.mappedProvider( + ElementClasses.CONNECTION, DefaultConnectionClassFactory.CLASS.newClassWith(new StaticObjectAdapter(dr.Connection)), + ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal) + ) + ); + sync.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph)); + return sync; + } + }); + } catch (DatabaseException e) { + throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e); + } + } + + public ICanvasContext createViewerCanvas() + { + IThreadWorkQueue thread = AWTThread.getThreadAccess(); + CanvasContext ctx = new CanvasContext(thread); + IHintContext h = ctx.getDefaultHintContext(); + + this.synchronizer = createSynchronizer(ctx, sessionContext); + + canvasContext.add( new PanZoomRotateHandler() ); // Must be before TransformUtil + + // Support & Util Participants + ctx.add( new TransformUtil() ); + ctx.add( new MouseUtil() ); + ctx.add( new KeyUtil() ); + ctx.add( new CanvasGrab() ); + ctx.add( new SymbolUtil() ); + ctx.add( new TimeParticipant() ); + ctx.add( new CanvasBoundsParticipant() ); + ctx.add( new Notifications() ); + +// ctx.add( new SGFocusParticipant(c) ); // FIXME: Get chassis from somewhere + + h.setHint(PointerPainter.KEY_PAINT_POINTER, true); + + ctx.add( new MultitouchPanZoomRotateInteractor() ); + ctx.add( new ZoomToAreaHandler() ); + ctx.add( new SimpleElementTransformHandler() ); + + // Key bindings + addKeyBindingParticipants(ctx); + + // Grid & Ruler & Background + + ctx.add( new GridPainter() ); + ctx.add( new RulerPainter() ); + ctx.add( new BackgroundPainter() ); + ctx.add( new PageBorderParticipant() ); + + h.setHint(Hints.KEY_GRID_COLOR, new Color(0.95f, 0.95f, 0.95f)); + h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE); + h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f)); + h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK); + + ////// Diagram Participants ////// + ctx.add(new PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider(), null)); + ctx.add(new ElementInteractor()); + ctx.add(new Selection()); + ctx.add(new DiagramParticipant()); + ctx.add(new ElementPainter()); + ctx.add(new TerminalPainter(true, true, false, true)); + //ctx.add(new ElementHeartbeater()); + ctx.add(new ZOrderHandler()); + ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID)); + + /////// D'n'D /////// + addDropParticipants(ctx); + + h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL); + + h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 1000.0); + h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0); + + // Add visual browsing capabilities for structural models +// ctx.add(new HeadlessStructuralBrowsingHandler(this, sessionContext, structuralPath)); + + // Page settings + PageDesc pageDesc = PageDesc.DEFAULT.withOrientation(PageOrientation.Landscape); + // TODO: load page desc from graph + h.setHint(Hints.KEY_PAGE_DESC, pageDesc); + + ctx.assertParticipantDependencies(); + + return ctx; + } + + private boolean firstFocus = true; + + @Override + public void setFocus() { + if (firstFocus) { + // This is a workaround for using the symbol viewer in multi-page + // editors which causes the first zoom-to-fit scheduling to happen + // already before the controls have been laid out properly. + firstFocus = false; + firstTimeSetFocus(); + } + } + + protected void firstTimeSetFocus() { + scheduleZoomToFit(); + } + + @Override + public void dispose() { + System.out.println("RemoteDiagramViewer.dispose()"); + if(getSite() != null) { + IContextService contextService = (IContextService) getSite().getService(IContextService.class); + contextService.deactivateContext(contextActivation); + } + + disposed = true; + if (activation != null) { + activation.deactivate(); + activation = null; + } + + if(synchronizer != null) { + synchronizer.dispose(); + synchronizer = null; + } + + if(sourceDiagram != null) { + sourceDiagram.dispose(); + sourceDiagram = null; + } + + if(support != null) { + support.dispose(); + support = null; + } + super.dispose(); + } + + @Override + public void doSave(IProgressMonitor monitor) { + } + + @Override + public void doSaveAs() { + } + + @Override + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + if (!(input instanceof IResourceEditorInput)) + throw new PartInitException("Invalid input: must be IResourceEditorInput"); + setSite(site); + setInput(input); + support = new ResourceEditorSupport(this); + + // Set initial part name according to the name given by IEditorInput + setPartName(getEditorInput().getName()); + } + + @Override + public boolean isDirty() { + return false; + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } + + public static ResourceArray[] decodeToResources(Session session, Transferable tr) + { + try { + SerialisationSupport support = session.getService(SerialisationSupport.class); + ResourceTransferData data = ResourceTransferUtils.readAwtTransferable(support, tr); + if ("property".equals(data.getPurpose())) + return data.toResourceArrayArray(); + } catch (UnsupportedFlavorException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (DatabaseException e) { + throw new RuntimeException(e); + } + return null; + } + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + if (adapter == IContentOutlinePage.class) + return new DiagramOutlinePage(sessionContextProvider, getResourceInput2()); + if (adapter == ILayersViewPage.class) + return new DiagramLayersPage(sourceDiagram, canvasContext); + if (adapter == ICanvasContext.class) + return canvasContext; + if (adapter == IDiagram.class) + return sourceDiagram; + if (adapter == Session.class) + return sessionContext.getSession(); + return super.getAdapter(adapter); + } + + public ICanvasContext getCanvasContext() { + return canvasContext; + } + + protected void onCreated() { + } + + @Override + public void createPartControl(Composite parent) { + // TODO Auto-generated method stub + + } + + @Override + public IResourceEditorInput2 getResourceInput2() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IResourceEditorInput getResourceInput() { + // TODO Auto-generated method stub + return null; + } + +}