1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.modeling.ui.diagramEditor.handlers;
\r
14 import java.awt.Shape;
\r
15 import java.awt.geom.AffineTransform;
\r
16 import java.awt.geom.Rectangle2D;
\r
17 import java.util.Collection;
\r
18 import java.util.HashSet;
\r
19 import java.util.Set;
\r
20 import java.util.function.Consumer;
\r
22 import org.eclipse.ui.IEditorPart;
\r
23 import org.eclipse.ui.IWorkbenchPartSite;
\r
24 import org.eclipse.ui.PartInitException;
\r
25 import org.simantics.db.ReadGraph;
\r
26 import org.simantics.db.Resource;
\r
27 import org.simantics.db.common.ResourceArray;
\r
28 import org.simantics.db.common.request.ReadRequest;
\r
29 import org.simantics.db.common.utils.OrderedSetUtils;
\r
30 import org.simantics.db.exception.DatabaseException;
\r
31 import org.simantics.db.management.ISessionContext;
\r
32 import org.simantics.diagram.stubs.DiagramResource;
\r
33 import org.simantics.g2d.canvas.ICanvasContext;
\r
34 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
\r
35 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
\r
36 import org.simantics.g2d.diagram.DiagramHints;
\r
37 import org.simantics.g2d.diagram.IDiagram;
\r
38 import org.simantics.g2d.diagram.handler.DataElementMap;
\r
39 import org.simantics.g2d.diagram.participant.Selection;
\r
40 import org.simantics.g2d.element.ElementHints;
\r
41 import org.simantics.g2d.element.ElementUtils;
\r
42 import org.simantics.g2d.element.IElement;
\r
43 import org.simantics.g2d.participant.CanvasBoundsParticipant;
\r
44 import org.simantics.g2d.participant.TransformUtil;
\r
45 import org.simantics.g2d.utils.GeometryUtils;
\r
46 import org.simantics.modeling.ModelingResources;
\r
47 import org.simantics.modeling.ui.diagramEditor.DiagramViewer;
\r
48 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
\r
49 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;
\r
50 import org.simantics.structural.stubs.StructuralResource2;
\r
51 import org.simantics.ui.workbench.ResourceEditorInput;
\r
52 import org.simantics.utils.page.MarginUtils;
\r
53 import org.simantics.utils.threads.ThreadUtils;
\r
54 import org.simantics.utils.ui.ErrorLogger;
\r
55 import org.simantics.utils.ui.workbench.WorkbenchUtils;
\r
58 * StructuralBrowsingHandler supports visual browsing into subcomponents through
\r
61 * @author Tuukka Lehtonen
\r
63 public class LinkBrowsingHandler extends AbstractCanvasParticipant {
\r
66 CanvasBoundsParticipant canvasBounds;
\r
68 Selection selection;
\r
70 IWorkbenchPartSite site;
\r
71 DiagramViewer viewer;
\r
72 ISessionContext sessionContext;
\r
74 public LinkBrowsingHandler(IWorkbenchPartSite site, DiagramViewer viewer, ISessionContext context) {
\r
76 assert site != null;
\r
78 // System.out.println("LinkBrowsingHandler " + viewer + " " + viewer.structuralPath);
\r
81 this.viewer = viewer;
\r
82 this.sessionContext = context;
\r
86 public static Runnable editorActivator(final IEditorPart part, final ResourceArray input, final Consumer<IEditorPart> successCallback) {
\r
87 String sourcePartId = part.getSite().getId();
\r
88 return editorActivator(sourcePartId, input, successCallback);
\r
91 public Runnable elementSelectorZoomer(final ICanvasContext canvas, final Collection<Object> elementObjects, final boolean keepZoom) {
\r
92 return new Runnable() {
\r
95 IDiagram diagram = canvas.getHintStack().getHint(DiagramHints.KEY_DIAGRAM);
\r
96 assert diagram != null;
\r
97 if (!zoomToSelection(canvas, diagram, selectElement(canvas, diagram, elementObjects), keepZoom)) {
\r
98 // Reschedule for later.
\r
99 ThreadUtils.asyncExec(canvas.getThreadAccess(), this);
\r
105 public static Set<IElement> selectElement(final ICanvasContext canvas, final IDiagram diagram, final Collection<Object> elementObjects) {
\r
107 Set<IElement> selection = new HashSet<IElement>();
\r
108 DataElementMap dataMap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
\r
109 for (Object obj : elementObjects) {
\r
110 IElement element = dataMap.getElement(diagram, obj);
\r
111 if (element == null) {
\r
112 ErrorLogger.defaultLogWarning("No element to select for object " + obj, new Exception());
\r
114 selection.add(element);
\r
117 for (Selection s : canvas.getItemsByClass(Selection.class)) {
\r
118 s.setSelection(0, selection);
\r
123 public boolean zoomToSelection(final ICanvasContext canvas, final IDiagram diagram, Set<IElement> selection, boolean keepZoom) {
\r
124 TransformUtil util = canvas.getSingleItem(TransformUtil.class);
\r
125 Rectangle2D controlBounds = canvasBounds.getControlBounds();
\r
126 if (controlBounds == null)
\r
129 Shape shp = ElementUtils.getElementBoundsOnDiagram(selection);
\r
133 Rectangle2D diagramRect = shp.getBounds2D();
\r
135 double scaleFactor = GeometryUtils.getScale(util.getTransform());
\r
136 double cwh = controlBounds.getWidth() / (scaleFactor*2);
\r
137 double chh = controlBounds.getHeight() / (scaleFactor*2);
\r
139 AffineTransform view = new AffineTransform();
\r
140 view.scale(scaleFactor, scaleFactor);
\r
141 view.translate(-diagramRect.getCenterX()+cwh, -diagramRect.getCenterY()+chh);
\r
143 util.setTransform(view);
\r
145 MarginUtils.Margin margin = MarginUtils.marginOf(40, 0, 0);
\r
146 MarginUtils.Margins margins = new MarginUtils.Margins(margin, margin, margin, margin);
\r
147 util.fitArea(controlBounds, diagramRect, margins);
\r
152 public static Runnable editorActivator(String editorPartId, ResourceArray input, Consumer<IEditorPart> successCallback) {
\r
153 return new Runnable() {
\r
155 public void run() {
\r
157 // open and activate new editor
\r
158 IEditorPart newPart = WorkbenchUtils.openEditor(editorPartId, new ResourceEditorInput(editorPartId, input));
\r
159 newPart.getSite().getPage().activate(newPart);
\r
160 successCallback.accept(newPart);
\r
161 } catch (PartInitException e) {
\r
162 // TODO: handle properly
\r
163 e.printStackTrace();
\r
169 public static Resource getOwnerList(ReadGraph g, Resource listElement) throws DatabaseException {
\r
170 return OrderedSetUtils.getSingleOwnerList(g, listElement, DiagramResource.getInstance(g).Composite);
\r
173 @EventHandler(priority = 0)
\r
174 public boolean handleDoubleClick(MouseDoubleClickedEvent me) {
\r
176 //System.out.println("LinkBrowsingHandler");
\r
178 if (sessionContext == null)
\r
181 Set<IElement> sel = selection.getSelection(0);
\r
183 if (sel.size() == 1) {
\r
184 IElement e = sel.iterator().next();
\r
185 Object data = e.getHint(ElementHints.KEY_OBJECT);
\r
186 if (data instanceof Resource) {
\r
187 final Resource element = (Resource) data;
\r
188 sessionContext.getSession().asyncRequest(new ReadRequest() {
\r
190 public void run(ReadGraph graph) throws DatabaseException {
\r
192 //System.out.println("LinkBrowsingHandler0");
\r
194 ModelingResources mr = ModelingResources.getInstance(graph);
\r
195 DiagramResource dr = DiagramResource.getInstance(graph);
\r
196 StructuralResource2 sr = StructuralResource2.getInstance(graph);
\r
198 if (graph.isInstanceOf(element, dr.UpwardLink)) {
\r
200 // Resource component = viewer.structuralPath.resources[0];
\r
201 // Resource element = graph.getPossibleObject(component, mr.ComponentToElement);
\r
202 // Resource diagram = getOwnerList(graph, element);
\r
204 // IEditorPart thisEditor = (IEditorPart) site.getPart();
\r
205 // site.getWorkbenchWindow().getShell().getDisplay().asyncExec(
\r
206 // editorActivator(thisEditor, viewer.structuralPath.removeFromBeginning(1).prepended(diagram), new Callback<IEditorPart>() {
\r
208 // public void run(IEditorPart part) {
\r
212 } else if (graph.isInstanceOf(element, dr.Link)) {
\r
214 //System.out.println("LinkBrowsingHandler2");
\r
216 // ContextMap parameters = new ContextMap();
\r
217 // parameters.put(ModelingOperationConstants.WORKBENCH_WINDOW, site.getWorkbenchWindow());
\r
218 // parameters.put(ModelingOperationConstants.WORKBENCH_PART, site.getPart());
\r
219 // parameters.put(IOperation.SUBJECT, element);
\r
221 Resource thisDiagram = getOwnerList(graph, element);
\r
222 if (thisDiagram == null) return;
\r
224 final Resource target = graph.getPossibleObject(element, dr.HasLinkTarget);
\r
225 if (target == null) return;
\r
227 final Resource otherDiagram = getOwnerList(graph, target);
\r
228 if (otherDiagram == null)
\r
231 final Resource component = graph.getPossibleObject(target, mr.ElementToComponent);
\r
232 if (component == null)
\r
235 Resource type = graph.getSingleType(component, sr.Component);
\r
239 Resource definedBy = graph.getPossibleObject(type, sr.IsDefinedBy);
\r
240 if (definedBy == null)
\r
243 final Resource diagram = graph.getPossibleObject(definedBy, mr.CompositeToDiagram);
\r
244 if (diagram == null)
\r
247 // PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
\r
249 // public void run() {
\r
251 // WorkbenchUtils.openEditor(site.getId(), new ResourceEditorInput(site.getId(), parentStructuralPath.prepended(diagram, component)));
\r
252 // } catch (PartInitException e) {
\r
253 // // TODO Auto-generated catch block
\r
254 // e.printStackTrace();
\r
259 // IEditorPart thisEditor = (IEditorPart) site.getPart();
\r
260 // ResourceArray input = viewer.structuralPath.prepended(diagram, component);
\r
261 // System.out.println("Browsing link " + input);
\r
262 // site.getWorkbenchWindow().getShell().getDisplay().asyncExec(
\r
263 // editorActivator(thisEditor, input, new Callback<IEditorPart>() {
\r
265 // public void run(IEditorPart part) {
\r
266 //// final ICanvasContext openedCanvas = (ICanvasContext) part.getAdapter(ICanvasContext.class);
\r
267 //// assert openedCanvas != null;
\r
268 //// IDiagram diagram = (IDiagram) part.getAdapter(IDiagram.class);
\r
269 //// assert diagram != null;
\r
270 // // Disable automatic-zoom-to-fit
\r
271 //// diagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
\r
272 //// ThreadUtils.asyncExec(openedCanvas.getThreadAccess(),
\r
273 //// elementSelectorZoomer(openedCanvas, Collections.singleton((Object) target), false));
\r
279 // System.out.println("LinkBrowsingHandler3");
\r
281 // if (!thisDiagram.equals(otherDiagram)) {
\r
283 // System.out.println("LinkBrowsingHandler4");
\r
285 // // Find the structural path
\r
286 // Resource ownerComposite = graph.getPossibleObject(otherDiagram, mr.DiagramToComposite);
\r
287 // if (ownerComposite == null)
\r
290 // Collection<ResourceArray> inputs = ComponentUtils.formInputs(graph, ownerComposite);
\r
293 // for (final ResourceArray input : inputs) {
\r