package org.simantics.district.network.ui.contributions; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.List; import javax.inject.Named; import org.eclipse.core.commands.ParameterizedCommand; import org.eclipse.e4.core.di.annotations.CanExecute; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.services.IServiceConstants; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IEditorPart; import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.SelectionHints; import org.simantics.db.layer0.util.RemoverUtil; import org.simantics.db.request.Read; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.district.network.ModelledCRS; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.district.network.ui.DistrictDiagramEditor; import org.simantics.district.network.ui.NetworkDrawingParticipant; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.participant.MouseUtil; import org.simantics.g2d.participant.MouseUtil.MouseInfo; import org.simantics.ui.workbench.e4.E4WorkbenchUtils; import org.simantics.utils.ui.ISelectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ChangeVertexToRoutePointHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ChangeVertexToRoutePointHandler.class); static List elements; static boolean cut = true; @CanExecute public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) { List elements = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_MAIN, Resource.class); if (elements.size() != 1) return false; try { return Simantics.getSession().syncRequest(new Read() { @Override public Boolean perform(ReadGraph graph) throws DatabaseException { DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); for (Resource selection : elements) { if (graph.isInstanceOf(selection, DN.Vertex)) { Collection startingEdge = graph.getObjects(selection, DN.HasStartVertex_Inverse); Collection endingEdge = graph.getObjects(selection, DN.HasEndVertex_Inverse); return startingEdge.size() == 1 && endingEdge.size() == 1; } } return false; } }); } catch (DatabaseException e) { LOGGER.error("Could not evaluate if mapping can be changed for selection {}", elements, e); return false; } } @Execute public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart mActiveEditorPart, @Named(IServiceConstants.ACTIVE_SELECTION) Object selection, ParameterizedCommand command) { final List elements = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_MAIN, Resource.class); Resource vertex = elements.get(0); try { Point2D mouseClicked = mouseClickedOnEditor(mActiveEditorPart); if (mouseClicked != null) { IEditorPart activeEditorPart = E4WorkbenchUtils.getActiveIEditorPart(mActiveEditorPart); if (activeEditorPart == null) return; if (!(activeEditorPart instanceof DistrictDiagramEditor)) return; Simantics.getSession().asyncRequest(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); DiagramResource DIA = DiagramResource.getInstance(graph); // we support only single start & end edge Resource startingEdge = graph.getSingleObject(vertex, DN.HasEndVertex_Inverse); Resource endingEdge = graph.getSingleObject(vertex, DN.HasStartVertex_Inverse); double[] startingDetailed = graph.getPossibleRelatedValue(startingEdge, DN.Edge_HasGeometry); double[] endingDetailed = graph.getPossibleRelatedValue(endingEdge, DN.Edge_HasGeometry); Resource endingVertex = graph.getSingleObject(endingEdge, DN.HasEndVertex); int length = startingDetailed.length + 2 + endingDetailed.length; double[] newDetailed = new double[length]; for (int i = 0; i < startingDetailed.length; i++) { double d = startingDetailed[i]; newDetailed[i] = d; } double[] coords = graph.getRelatedValue2(vertex, DIA.HasLocation); int currentVertexIndex = startingDetailed.length; newDetailed[currentVertexIndex] = coords[0]; newDetailed[currentVertexIndex + 1] = coords[1]; int f = startingDetailed.length + 2; for (int i = 0; i < endingDetailed.length; i++) { double d = endingDetailed[i]; newDetailed[f + i] = d; } graph.deny(startingEdge, DN.Edge_HasGeometry); graph.claimLiteral(startingEdge, DN.Edge_HasGeometry, newDetailed, Bindings.DOUBLE_ARRAY); graph.deny(startingEdge, DN.HasEndVertex); graph.claim(startingEdge, DN.HasEndVertex, endingVertex); RemoverUtil.remove(graph, vertex); } }); } else { LOGGER.warn("No mouseClicked for editor {}", mActiveEditorPart); } } catch (InvocationTargetException e) { LOGGER.error("Could not change route point to vertex", e); } } private static Point2D mouseClickedOnEditor(MPart mActiveEditorPart) throws InvocationTargetException { IEditorPart activeEditorPart = E4WorkbenchUtils.getActiveIEditorPart(mActiveEditorPart); if (activeEditorPart == null) return null; if (!(activeEditorPart instanceof DistrictDiagramEditor)) return null; DistrictDiagramEditor editor = (DistrictDiagramEditor) activeEditorPart; ICanvasContext ctx = editor.getAdapter(ICanvasContext.class); NetworkDrawingParticipant drawingParticipant = ctx.getAtMostOneItemOfClass(NetworkDrawingParticipant.class); AffineTransform drawingTransform = drawingParticipant.getTransform(); MouseUtil util = ctx.getAtMostOneItemOfClass(MouseUtil.class); MouseInfo mouseInfo = util.getMousePressedInfo(0); if (mouseInfo == null) { return null; } Point2D canvasPosition = mouseInfo.canvasPosition; Point2D transformed = null; try { transformed = drawingTransform.inverseTransform(canvasPosition, new Point2D.Double()); } catch (NoninvertibleTransformException e) { LOGGER.error("Could not create inverse transform of {}", drawingTransform, e); throw new InvocationTargetException(e); } double x = ModelledCRS.xToLongitude(transformed.getX()); double y = ModelledCRS.yToLatitude(-transformed.getY()); return new Point2D.Double(x, y); } }