/******************************************************************************* * Copyright (c) 2007, 2014 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 * Semantum Oy - support SHIFT+left double click browsing outside of model configuration *******************************************************************************/ package org.simantics.modeling.ui.diagramEditor.handlers; import java.util.Set; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.PossibleIndexRoot; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.RVI; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.db.management.ISessionContext; import org.simantics.diagram.flag.FlagUtil; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.diagram.ui.DiagramModelHints; import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; import org.simantics.g2d.diagram.participant.Selection; import org.simantics.g2d.element.ElementHints; import org.simantics.g2d.element.IElement; import org.simantics.layer0.utils.operations.IOperation; import org.simantics.modeling.ModelingOperationConstants; import org.simantics.modeling.ModelingResources; import org.simantics.modeling.actions.NavigateToTarget; import org.simantics.modeling.ui.Activator; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.ui.workbench.IResourceEditorInput2; import org.simantics.ui.workbench.ResourceEditorInput2; import org.simantics.utils.datastructures.persistent.ContextMap; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.workbench.WorkbenchUtils; /** * StructuralBrowsingHandler supports visual browsing into subcomponents through * mouse events. * * @author Tuukka Lehtonen */ public class StructuralBrowsingHandler extends AbstractDiagramParticipant { @Dependency Selection selection; IWorkbenchPartSite site; ISessionContext sessionContext; IResourceEditorInput2 input; public StructuralBrowsingHandler(IWorkbenchPartSite site, ISessionContext sessionContext, IResourceEditorInput2 input) { assert site != null; this.site = site; this.sessionContext = sessionContext; this.input = input; } @EventHandler(priority = 0) public boolean handleDoubleClick(MouseDoubleClickedEvent me) { if (sessionContext == null || diagram == null) return false; Set sel = selection.getSelection(0); if (sel.size() == 1) { IElement e = sel.iterator().next(); Object data = e.getHint(ElementHints.KEY_OBJECT); final Resource runtime = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE); if (data instanceof Resource) { final Resource element = (Resource) data; final int stateMask = me.stateMask; try { return sessionContext.getSession().syncRequest(new UniqueRead() { @Override public Boolean perform(ReadGraph graph) throws DatabaseException { return browse(graph, element, runtime, stateMask); } }); } catch (DatabaseException e1) { ErrorLogger.defaultLogError(e1); } } } return false; } private boolean browse(ReadGraph graph, Resource element, Resource runtimeDiagram, int stateMask) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(graph); ModelingResources mr = ModelingResources.getInstance(graph); DiagramResource dr = DiagramResource.getInstance(graph); StructuralResource2 sr = StructuralResource2.getInstance(graph); if (graph.isInstanceOf(element, dr.Flag)) { ContextMap parameters = new ContextMap(); parameters.put(ModelingOperationConstants.WORKBENCH_WINDOW, site.getWorkbenchWindow()); parameters.put(ModelingOperationConstants.WORKBENCH_PART, site.getPart()); parameters.put(IOperation.SUBJECT, element); new NavigateToTarget().exec(graph.getSession(), parameters); // Return true only if the flag is joined somewhere and navigation is possible. return FlagUtil.isJoined(graph, element); } if((stateMask & MouseDoubleClickedEvent.SHIFT_MASK) == 0) return false; if(runtimeDiagram == null || !graph.isInstanceOf(runtimeDiagram, DIA.RuntimeDiagram)) return false; final Resource component = graph.getPossibleObject(element, mr.ElementToComponent); if (component == null) return false; Resource type = graph.getPossibleType(component, sr.Component); if (type == null) return false; if(graph.hasStatement(type, sr.ComponentType_Locked)) return false; Resource definedBy = graph.getPossibleObject(type, sr.IsDefinedBy); if (definedBy == null) return false; final Resource diagram = graph.getPossibleObject(definedBy, mr.CompositeToDiagram); if (diagram == null) return false; Resource model = input.getModel(graph); RVI subprocessRVI = null; String rvis = (String) graph.getPossibleRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasRVI); if (rvis != null) { RVI rvi = RVI.fromResourceFormat(graph, rvis); Variable base = Variables.getConfigurationContext(graph, model); Variable current = rvi.resolve(graph, base); Variable subprocess = current.browse(graph, component); subprocessRVI = subprocess.getRVI(graph); } else { // Not in a model configuration context. // Probably in a component type configuration. // Use the index root of the diagram to be opened as model[0] // and leave subprocessRVI[0] as null. model = graph.syncRequest(new PossibleIndexRoot(definedBy)); } PlatformUI.getWorkbench().getDisplay().asyncExec(navigateToSubstructure(diagram, model, subprocessRVI)); return true; } private Runnable navigateToSubstructure(final Resource diagram, final Resource model, final RVI subprocessRVI) { return new Runnable() { @Override public void run() { try { WorkbenchUtils.openEditor(site.getId(), new ResourceEditorInput2(site.getId(), diagram, model, subprocessRVI)); } catch (PartInitException e) { Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to open editor, see exception for details.", e)); } } }; } }