X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fhandler%2FConnectionSplitAndJoin.java;h=a5cd5f10911e49ac3339ac8b79890aeb0589966e;hb=1ecae6e1ad40507badb8807fb14bb67b4adf199c;hp=d46c427320c7b06e8c13a6a77112202146a6d50f;hpb=c78854f7886d52b5375e11b3d6d8daacb12c287e;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionSplitAndJoin.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionSplitAndJoin.java index d46c42732..a5cd5f109 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionSplitAndJoin.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionSplitAndJoin.java @@ -1,312 +1,312 @@ -/******************************************************************************* - * 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.diagram.handler; - -import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.ActionContributionItem; -import org.eclipse.jface.action.IContributionItem; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.ui.IWorkbenchPart; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.IndexRoot; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.utils.OrderedSetUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.content.ConnectionUtil; -import org.simantics.diagram.content.EdgeResource; -import org.simantics.diagram.flag.FlagUtil; -import org.simantics.diagram.flag.Splitter; -import org.simantics.diagram.internal.Activator; -import org.simantics.diagram.stubs.DiagramResource; -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.diagram.DiagramHints; -import org.simantics.g2d.diagram.participant.Selection; -import org.simantics.g2d.element.IElement; -import org.simantics.scl.commands.Command; -import org.simantics.scl.commands.Commands; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.ui.contribution.DynamicMenuContribution; -import org.simantics.utils.threads.ThreadUtils; -import org.simantics.utils.ui.AdaptionUtils; -import org.simantics.utils.ui.ExceptionUtils; -import org.simantics.utils.ui.workbench.WorkbenchUtils; - -/** - * @author Tuukka Lehtonen - */ -public class ConnectionSplitAndJoin extends DynamicMenuContribution { - - private static final IContributionItem[] NONE = {}; - - private ICanvasContext canvas; - - @Override - public void fill(Menu menu, int index) { - // Need to grab active part here, we're still in the SWT thread. - IWorkbenchPart activePart = WorkbenchUtils.getActiveWorkbenchPart(); - if (activePart == null) - return; - ICanvasContext ctx = (ICanvasContext) activePart.getAdapter(ICanvasContext.class); - if (ctx == null) - return; - - this.canvas = ctx; - try { - super.fill(menu, index); - } finally { - this.canvas = null; - } - } - - @Override - protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException { - // If selection contains: - // a) only diagram-locally connected flags, that each are connected to something, allow joining of those flag into connections - // b) a single connection edge element, allow splitting into a connected flag pair - - Collection localConnectedFlags = Collections.emptyList(); - Resource routeGraphConnection = null; - EdgeResource edge = null; - if (selection.length == 1) { - routeGraphConnection = getRouteGraphConnection(graph, selection[0]); - if (routeGraphConnection == null) { - edge = getEdge(graph, selection[0]); - if (edge == null) - localConnectedFlags = getLocalConnectedFlags(graph, selection); - } - } else { - localConnectedFlags = getLocalConnectedFlags(graph, selection); - } - - if (!localConnectedFlags.isEmpty()) { - return new IContributionItem[] { - new ActionContributionItem(new Join(graph.getSession(), canvas, localConnectedFlags)) - }; - } else if (edge != null) { - Selection sel = canvas.getAtMostOneItemOfClass(Selection.class); - if (sel == null) - return NONE; - Set elems = sel.getSelection(0); - if (elems.size() != 1) - return NONE; - IElement edgeElement = ConnectionUtil.getSingleEdge(elems.iterator().next()); - if (edgeElement == null) - return NONE; - Point2D canvasPosition = canvas.getHintStack().getHint(DiagramHints.POPUP_MENU_CANVAS_POSITION); - if (canvasPosition == null) - return NONE; - - return new IContributionItem[] { - new ActionContributionItem(new Split(graph.getSession(), canvas, canvasPosition, edgeElement, edge)) - }; - } else if (routeGraphConnection != null) { - Selection sel = canvas.getAtMostOneItemOfClass(Selection.class); - if (sel == null) - return NONE; - Set elems = sel.getSelection(0); - if (elems.size() != 1) - return NONE; - Point2D canvasPosition = canvas.getHintStack().getHint(DiagramHints.POPUP_MENU_CANVAS_POSITION); - if (canvasPosition == null) - return NONE; - - return new IContributionItem[] { - new ActionContributionItem(new SplitRouteGraph(graph.getSession(), canvas, canvasPosition, routeGraphConnection)) - }; - } - return NONE; - } - - private Resource getRouteGraphConnection(ReadGraph graph, Object object) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - Resource connection = AdaptionUtils.adaptToSingle(object, Resource.class); - if (connection != null && graph.isInstanceOf(connection, DIA.RouteGraphConnection)) - return connection; - return null; - } - - private Collection getLocalConnectedFlags(ReadGraph graph, Object[] selection) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - ArrayList result = new ArrayList(4); - for (Object s : selection) { - Resource r = AdaptionUtils.adaptToSingle(s, Resource.class); - if (r == null || !graph.isInstanceOf(r, DIA.Flag)) - return Collections.emptyList(); - if (!isConnectedToSomething(graph, r)) - return Collections.emptyList(); - Collection counterparts = FlagUtil.getCounterparts(graph, r); - if (counterparts.isEmpty()) - return Collections.emptyList(); - Collection flagDiagrams = OrderedSetUtils.getOwnerLists(graph, r, DIA.Diagram); - for (Resource counterpart : counterparts) { - boolean joinedWithinSingleDiagram = !Collections.disjoint(flagDiagrams, - OrderedSetUtils.getOwnerLists(graph, counterpart, DIA.Diagram)); - if (!joinedWithinSingleDiagram) - return Collections.emptyList(); - if (!isConnectedToSomething(graph, counterpart)) - return Collections.emptyList(); - } - result.add(r); - } - return result; - } - - private boolean isConnectedToSomething(ReadGraph graph, Resource flag) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - StructuralResource2 STR = StructuralResource2.getInstance(graph); - for (Resource connector : graph.getObjects(flag, STR.IsConnectedTo)) { - Resource cntr = graph.getPossibleObject(connector, DIA.AreConnected); - Resource conn = ConnectionUtil.getConnection(graph, cntr); - if (cntr == null || conn == null) - return false; - return true; - } - return false; - } - - private EdgeResource getEdge(ReadGraph graph, Object object) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - - Resource connection = null; - EdgeResource edge = AdaptionUtils.adaptToSingle(object, EdgeResource.class); - if (edge != null) - //connection = ConnectionUtil.getConnection(graph, edge); - return edge; - else { - connection = AdaptionUtils.adaptToSingle(object, Resource.class); - } - - if (connection != null && graph.isInstanceOf(connection, DiagramResource.getInstance(graph).Connection)) { - Collection connectors = graph.getObjects(connection, DIA.HasConnector); - Collection branchPoints = graph.getObjects(connection, DIA.HasBranchPoint); - if (branchPoints.isEmpty() && connectors.size() == 2) { - Iterator it = connectors.iterator(); - Resource connector1 = it.next(); - Resource connector2 = it.next(); - return new EdgeResource(connector1, connector2); - } - } - - return null; - } - - public static abstract class Helper extends Action { - - protected final Session session; - protected final ICanvasContext context; - - public Helper(String label, Session session, ICanvasContext context) { - super(label); - this.session = session; - this.context = context; - } - - @Override - public void run() { - try { - session.syncRequest(new WriteRequest() { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - graph.markUndoPoint(); - performAction(graph); - } - }); - ThreadUtils.asyncExec(context.getThreadAccess(), new Runnable() { - @Override - public void run() { - if (context.isDisposed()) - return; - Selection selection = context.getAtMostOneItemOfClass(Selection.class); - if (selection != null) { - // This prevents workbench selection from being left over. - // Also prevents scene graph crap from being left on the screen. - selection.clear(0); - } - } - }); - } catch (DatabaseException e) { - ExceptionUtils.logError(e); - } - } - - /** - * @param graph - */ - protected abstract void performAction(WriteGraph graph) throws DatabaseException; - - } - - public static class Split extends Helper { - private final Point2D splitCanvasPos; - private final IElement edgeElement; - private final EdgeResource edge; - - public Split(Session session, ICanvasContext context, Point2D splitCanvasPos, IElement edgeElement, EdgeResource edge) { - super("Split Connection", session, context); - setImageDescriptor(Activator.LINK_BREAK_ICON); - this.splitCanvasPos = splitCanvasPos; - this.edgeElement = edgeElement; - this.edge = edge; - } - - @Override - protected void performAction(WriteGraph graph) throws DatabaseException { - new Splitter(graph).split(graph, edgeElement, edge, splitCanvasPos); - } - } - - public static class SplitRouteGraph extends Helper { - private final Point2D splitCanvasPos; - private final Resource connection; - - public SplitRouteGraph(Session session, ICanvasContext context, Point2D splitCanvasPos, Resource connection) { - super("Split Connection", session, context); - setImageDescriptor(Activator.LINK_BREAK_ICON); - this.splitCanvasPos = splitCanvasPos; - this.connection = connection; - } - - @Override - protected void performAction(WriteGraph graph) throws DatabaseException { - Command command = Commands.get(graph, "Simantics/Diagram/splitConnection"); - command.execute(graph, graph.syncRequest(new IndexRoot(connection)), - connection, splitCanvasPos.getX(), splitCanvasPos.getY()); - } - } - - public static class Join extends Helper { - private final Collection flags; - - public Join(Session session, ICanvasContext context, Collection flags) { - super("Join Flags", session, context); - setImageDescriptor(Activator.LINK_ICON); - this.flags = flags; - } - - @Override - protected void performAction(WriteGraph graph) throws DatabaseException { - Command command = Commands.get(graph, "Simantics/Diagram/joinFlagsLocal"); - command.execute(graph, graph.syncRequest(new IndexRoot(flags.iterator().next())), flags); - } - } - +/******************************************************************************* + * 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.diagram.handler; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ActionContributionItem; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IWorkbenchPart; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.IndexRoot; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.content.ConnectionUtil; +import org.simantics.diagram.content.EdgeResource; +import org.simantics.diagram.flag.FlagUtil; +import org.simantics.diagram.flag.Splitter; +import org.simantics.diagram.internal.Activator; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.participant.Selection; +import org.simantics.g2d.element.IElement; +import org.simantics.scl.commands.Command; +import org.simantics.scl.commands.Commands; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.ui.contribution.DynamicMenuContribution; +import org.simantics.utils.threads.ThreadUtils; +import org.simantics.utils.ui.AdaptionUtils; +import org.simantics.utils.ui.ExceptionUtils; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + +/** + * @author Tuukka Lehtonen + */ +public class ConnectionSplitAndJoin extends DynamicMenuContribution { + + private static final IContributionItem[] NONE = {}; + + private ICanvasContext canvas; + + @Override + public void fill(Menu menu, int index) { + // Need to grab active part here, we're still in the SWT thread. + IWorkbenchPart activePart = WorkbenchUtils.getActiveWorkbenchPart(); + if (activePart == null) + return; + ICanvasContext ctx = (ICanvasContext) activePart.getAdapter(ICanvasContext.class); + if (ctx == null) + return; + + this.canvas = ctx; + try { + super.fill(menu, index); + } finally { + this.canvas = null; + } + } + + @Override + protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException { + // If selection contains: + // a) only diagram-locally connected flags, that each are connected to something, allow joining of those flag into connections + // b) a single connection edge element, allow splitting into a connected flag pair + + Collection localConnectedFlags = Collections.emptyList(); + Resource routeGraphConnection = null; + EdgeResource edge = null; + if (selection.length == 1) { + routeGraphConnection = getRouteGraphConnection(graph, selection[0]); + if (routeGraphConnection == null) { + edge = getEdge(graph, selection[0]); + if (edge == null) + localConnectedFlags = getLocalConnectedFlags(graph, selection); + } + } else { + localConnectedFlags = getLocalConnectedFlags(graph, selection); + } + + if (!localConnectedFlags.isEmpty()) { + return new IContributionItem[] { + new ActionContributionItem(new Join(graph.getSession(), canvas, localConnectedFlags)) + }; + } else if (edge != null) { + Selection sel = canvas.getAtMostOneItemOfClass(Selection.class); + if (sel == null) + return NONE; + Set elems = sel.getSelection(0); + if (elems.size() != 1) + return NONE; + IElement edgeElement = ConnectionUtil.getSingleEdge(elems.iterator().next()); + if (edgeElement == null) + return NONE; + Point2D canvasPosition = canvas.getHintStack().getHint(DiagramHints.POPUP_MENU_CANVAS_POSITION); + if (canvasPosition == null) + return NONE; + + return new IContributionItem[] { + new ActionContributionItem(new Split(graph.getSession(), canvas, canvasPosition, edgeElement, edge)) + }; + } else if (routeGraphConnection != null) { + Selection sel = canvas.getAtMostOneItemOfClass(Selection.class); + if (sel == null) + return NONE; + Set elems = sel.getSelection(0); + if (elems.size() != 1) + return NONE; + Point2D canvasPosition = canvas.getHintStack().getHint(DiagramHints.POPUP_MENU_CANVAS_POSITION); + if (canvasPosition == null) + return NONE; + + return new IContributionItem[] { + new ActionContributionItem(new SplitRouteGraph(graph.getSession(), canvas, canvasPosition, routeGraphConnection)) + }; + } + return NONE; + } + + private Resource getRouteGraphConnection(ReadGraph graph, Object object) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + Resource connection = AdaptionUtils.adaptToSingle(object, Resource.class); + if (connection != null && graph.isInstanceOf(connection, DIA.RouteGraphConnection)) + return connection; + return null; + } + + private Collection getLocalConnectedFlags(ReadGraph graph, Object[] selection) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + ArrayList result = new ArrayList(4); + for (Object s : selection) { + Resource r = AdaptionUtils.adaptToSingle(s, Resource.class); + if (r == null || !graph.isInstanceOf(r, DIA.Flag)) + return Collections.emptyList(); + if (!isConnectedToSomething(graph, r)) + return Collections.emptyList(); + Collection counterparts = FlagUtil.getCounterparts(graph, r); + if (counterparts.isEmpty()) + return Collections.emptyList(); + Collection flagDiagrams = OrderedSetUtils.getOwnerLists(graph, r, DIA.Diagram); + for (Resource counterpart : counterparts) { + boolean joinedWithinSingleDiagram = !Collections.disjoint(flagDiagrams, + OrderedSetUtils.getOwnerLists(graph, counterpart, DIA.Diagram)); + if (!joinedWithinSingleDiagram) + return Collections.emptyList(); + if (!isConnectedToSomething(graph, counterpart)) + return Collections.emptyList(); + } + result.add(r); + } + return result; + } + + private boolean isConnectedToSomething(ReadGraph graph, Resource flag) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + for (Resource connector : graph.getObjects(flag, STR.IsConnectedTo)) { + Resource cntr = graph.getPossibleObject(connector, DIA.AreConnected); + Resource conn = ConnectionUtil.getConnection(graph, cntr); + if (cntr == null || conn == null) + return false; + return true; + } + return false; + } + + private EdgeResource getEdge(ReadGraph graph, Object object) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + + Resource connection = null; + EdgeResource edge = AdaptionUtils.adaptToSingle(object, EdgeResource.class); + if (edge != null) + //connection = ConnectionUtil.getConnection(graph, edge); + return edge; + else { + connection = AdaptionUtils.adaptToSingle(object, Resource.class); + } + + if (connection != null && graph.isInstanceOf(connection, DiagramResource.getInstance(graph).Connection)) { + Collection connectors = graph.getObjects(connection, DIA.HasConnector); + Collection branchPoints = graph.getObjects(connection, DIA.HasBranchPoint); + if (branchPoints.isEmpty() && connectors.size() == 2) { + Iterator it = connectors.iterator(); + Resource connector1 = it.next(); + Resource connector2 = it.next(); + return new EdgeResource(connector1, connector2); + } + } + + return null; + } + + public static abstract class Helper extends Action { + + protected final Session session; + protected final ICanvasContext context; + + public Helper(String label, Session session, ICanvasContext context) { + super(label); + this.session = session; + this.context = context; + } + + @Override + public void run() { + try { + session.syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.markUndoPoint(); + performAction(graph); + } + }); + ThreadUtils.asyncExec(context.getThreadAccess(), new Runnable() { + @Override + public void run() { + if (context.isDisposed()) + return; + Selection selection = context.getAtMostOneItemOfClass(Selection.class); + if (selection != null) { + // This prevents workbench selection from being left over. + // Also prevents scene graph crap from being left on the screen. + selection.clear(0); + } + } + }); + } catch (DatabaseException e) { + ExceptionUtils.logError(e); + } + } + + /** + * @param graph + */ + protected abstract void performAction(WriteGraph graph) throws DatabaseException; + + } + + public static class Split extends Helper { + private final Point2D splitCanvasPos; + private final IElement edgeElement; + private final EdgeResource edge; + + public Split(Session session, ICanvasContext context, Point2D splitCanvasPos, IElement edgeElement, EdgeResource edge) { + super("Split Connection", session, context); + setImageDescriptor(Activator.LINK_BREAK_ICON); + this.splitCanvasPos = splitCanvasPos; + this.edgeElement = edgeElement; + this.edge = edge; + } + + @Override + protected void performAction(WriteGraph graph) throws DatabaseException { + new Splitter(graph).split(graph, edgeElement, edge, splitCanvasPos); + } + } + + public static class SplitRouteGraph extends Helper { + private final Point2D splitCanvasPos; + private final Resource connection; + + public SplitRouteGraph(Session session, ICanvasContext context, Point2D splitCanvasPos, Resource connection) { + super("Split Connection", session, context); + setImageDescriptor(Activator.LINK_BREAK_ICON); + this.splitCanvasPos = splitCanvasPos; + this.connection = connection; + } + + @Override + protected void performAction(WriteGraph graph) throws DatabaseException { + Command command = Commands.get(graph, "Simantics/Diagram/splitConnection"); + command.execute(graph, graph.syncRequest(new IndexRoot(connection)), + connection, splitCanvasPos.getX(), splitCanvasPos.getY()); + } + } + + public static class Join extends Helper { + private final Collection flags; + + public Join(Session session, ICanvasContext context, Collection flags) { + super("Join Flags", session, context); + setImageDescriptor(Activator.LINK_ICON); + this.flags = flags; + } + + @Override + protected void performAction(WriteGraph graph) throws DatabaseException { + Command command = Commands.get(graph, "Simantics/Diagram/joinFlagsLocal"); + command.execute(graph, graph.syncRequest(new IndexRoot(flags.iterator().next())), flags); + } + } + } \ No newline at end of file