--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.diagram.handler;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.ContributionItem;\r
+import org.eclipse.jface.action.IAction;\r
+import org.eclipse.jface.action.IContributionItem;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.swt.widgets.MenuItem;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.CommentMetadata;\r
+import org.simantics.db.common.request.IndexRoot;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.content.ConnectionUtil;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.scl.commands.Command;\r
+import org.simantics.scl.commands.Commands;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.ui.contribution.DynamicMenuContribution;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ConnectionRoutingMenuContribution extends DynamicMenuContribution {\r
+ \r
+\r
+ private static final IContributionItem[] NONE = {};\r
+\r
+ @Override\r
+ protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {\r
+ ArrayList<IContributionItem> result = new ArrayList<IContributionItem>(4);\r
+\r
+ result.addAll(getConnectionRoutingItems(graph, selection));\r
+ result.addAll(getAttachedConnectionRoutingItems(graph, selection));\r
+\r
+ return result.toArray(NONE);\r
+ }\r
+\r
+ public static Collection<IContributionItem> getConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+\r
+ final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);\r
+ if (routings.size() == 0)\r
+ return Collections.emptyList();\r
+\r
+ final List<Resource> connections = new ArrayList<Resource>();\r
+ for (Object s : selection) {\r
+ Resource connection = AdaptionUtils.adaptToSingle(s, Resource.class);\r
+ if (connection == null)\r
+ return Collections.emptyList();\r
+ if (!graph.isInstanceOf(connection, dr.Connection))\r
+ return Collections.emptyList();\r
+ // Route graph connection routing is not selected per-connection, but per-terminal.\r
+ if (graph.isInstanceOf(connection, dr.RouteGraphConnection))\r
+ return Collections.emptyList();\r
+ connections.add(connection);\r
+ }\r
+ if (connections.isEmpty())\r
+ return Collections.emptyList();\r
+\r
+ // See if all connections have a common routing.\r
+ Resource currentRoute = null;\r
+ for (Resource connection : connections) {\r
+ Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);\r
+ if (currentRouting != null) {\r
+ Resource route = currentRouting.getPredicate();\r
+ if (currentRoute == null)\r
+ currentRoute = route;\r
+ else if (!currentRoute.equals(route)) {\r
+ currentRoute = null;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ final List<SetRoutingAction> actions = new ArrayList<SetRoutingAction>();\r
+ for (Resource routing : routings) {\r
+ String text = graph.adapt(routing, String.class);\r
+ SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);\r
+ if (routing.equals(currentRoute))\r
+ action.setChecked(true);\r
+ actions.add(action);\r
+ }\r
+\r
+\r
+ sort(actions);\r
+\r
+ return Collections.<IContributionItem>singleton(\r
+ new ContributionItem() {\r
+ @Override\r
+ public void fill(Menu menu, int index) {\r
+ MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);\r
+ openWith.setText("Connection Routing");\r
+ Menu subMenu = new Menu(menu);\r
+ openWith.setMenu(subMenu);\r
+\r
+ for (SetRoutingAction a : actions) {\r
+ MenuItem item = new MenuItem(subMenu, SWT.CHECK);\r
+ item.setText(a.getText());\r
+ item.addSelectionListener(a);\r
+ item.setSelection(a.isChecked());\r
+ }\r
+ }\r
+ }\r
+ );\r
+ }\r
+\r
+ public static Collection<IContributionItem> getAttachedConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ StructuralResource2 sr = StructuralResource2.getInstance(graph);\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ // HACK\r
+ Resource ReferenceProvider = graph.getPossibleResource("http://www.apros.fi/Apros-6.1/ReferenceProvider");\r
+ // Just continuing to do stupid things as above ;)\r
+ Resource connectionType = graph.getPossibleResource("http://www.simantics.org/Kcleco-5.0/FlowConnection");\r
+ \r
+\r
+ final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);\r
+ if (routings.size() == 0)\r
+ return Collections.emptyList();\r
+\r
+ final List<Resource> connections = new ArrayList<Resource>();\r
+\r
+ // For route graph connections\r
+ final List<Resource> connectors = new ArrayList<Resource>();\r
+ boolean directRoutings = false;\r
+ boolean straightRoutings = false;\r
+\r
+ ArrayList<Resource> elements = new ArrayList<Resource>(); \r
+ for (Object s : selection) {\r
+ Resource element = AdaptionUtils.adaptToSingle(s, Resource.class);\r
+ if (element == null)\r
+ return Collections.emptyList();\r
+ if (!graph.isInstanceOf(element, dr.Element) || graph.isInstanceOf(element, dr.Connection))\r
+ return Collections.emptyList();\r
+\r
+ elements.add(element);\r
+ \r
+ for(Statement stat : graph.getStatements(element, sr.IsConnectedTo)) {\r
+ Resource diagramRelation = stat.getPredicate();\r
+ Resource connectionRelation = graph.getPossibleObject(diagramRelation, MOD.DiagramConnectionRelationToConnectionRelation);\r
+ if(connectionRelation == null)\r
+ continue;\r
+ // FIXME HACK\r
+ if(ReferenceProvider != null && !graph.isInstanceOf(connectionRelation, ReferenceProvider))\r
+ continue;\r
+ Resource connector = stat.getObject();\r
+\r
+ Resource connection = ConnectionUtil.tryGetConnection(graph, connector);\r
+ if (connection != null) {\r
+ if (graph.isInstanceOf(connection, dr.RouteGraphConnection)) {\r
+ if (connectionType != null && graph.isInstanceOf(connection, connectionType)) \r
+ continue;\r
+ connectors.add(connector);\r
+ boolean direct = Boolean.TRUE.equals( graph.getPossibleRelatedValue2(connector, dr.Connector_straight, Bindings.BOOLEAN) );\r
+ directRoutings |= direct;\r
+ straightRoutings |= !direct;\r
+ } else {\r
+ connections.add(connection);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (connectors.isEmpty() && connections.isEmpty())\r
+ return Collections.emptyList();\r
+\r
+ // See if all connections have a common routing.\r
+ Resource currentRoute = null;\r
+ for (Resource connection : connections) {\r
+ Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);\r
+ if (currentRouting != null) {\r
+ Resource route = currentRouting.getPredicate();\r
+ if (currentRoute == null)\r
+ currentRoute = route;\r
+ else if (!currentRoute.equals(route)) {\r
+ currentRoute = null;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ final List<SelectionListenerAction> actions = new ArrayList<SelectionListenerAction>();\r
+\r
+ if (!connections.isEmpty()) {\r
+ // Handle old style connections and their routing\r
+ for (Resource routing : routings) {\r
+ String text = graph.adapt(routing, String.class);\r
+ SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);\r
+ if (routing.equals(currentRoute)) {\r
+ action.setChecked(true);\r
+ }\r
+ actions.add(action);\r
+ }\r
+ }\r
+ if (!connectors.isEmpty()) {\r
+ // Handle route graph connections\r
+ SelectionListenerAction direct = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, true, "Direct");\r
+ SelectionListenerAction straight = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, false, "Straight-angled");\r
+ direct.setChecked(directRoutings);\r
+ straight.setChecked(straightRoutings);\r
+ actions.add(direct);\r
+ actions.add(straight);\r
+ }\r
+\r
+ sort(actions);\r
+\r
+ return Collections.<IContributionItem>singleton(\r
+ new ContributionItem() {\r
+ @Override\r
+ public void fill(Menu menu, int index) {\r
+ MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);\r
+ openWith.setText("Attached Connection Routing");\r
+ Menu subMenu = new Menu(menu);\r
+ openWith.setMenu(subMenu);\r
+\r
+ for (SelectionListenerAction a : actions) {\r
+ MenuItem item = new MenuItem(subMenu, SWT.CHECK);\r
+ item.setText(a.getText());\r
+ item.addSelectionListener(a);\r
+ item.setSelection(a.isChecked());\r
+ }\r
+ }\r
+ }\r
+ );\r
+ }\r
+\r
+ private static void sort(List<? extends IAction> actions) {\r
+ // Sort the open with actions in string order.\r
+ Collections.sort(actions, new Comparator<IAction>() {\r
+ @Override\r
+ public int compare(IAction o1, IAction o2) {\r
+ return o1.getText().compareToIgnoreCase(o2.getText());\r
+ }\r
+ });\r
+ }\r
+\r
+ static abstract class SelectionListenerAction extends Action implements SelectionListener {\r
+ public SelectionListenerAction(String text) {\r
+ super(text);\r
+ }\r
+ }\r
+\r
+ static class SetRoutingAction extends SelectionListenerAction {\r
+\r
+ Session session;\r
+ Collection<Resource> connections;\r
+ Resource routingTag;\r
+\r
+ public SetRoutingAction(Session session, Collection<Resource> connections, Resource routingTag, String text) {\r
+ super(text);\r
+ this.session = session;\r
+ this.connections = connections;\r
+ this.routingTag = routingTag;\r
+ }\r
+\r
+ @Override\r
+ public void run() {\r
+ session.asyncRequest(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ for (Resource connection : connections) {\r
+ graph.deny(connection, dr.Routing);\r
+ graph.claim(connection, routingTag, connection);\r
+ }\r
+ }\r
+ }, new Callback<DatabaseException>() {\r
+ @Override\r
+ public void run(DatabaseException parameter) {\r
+ if (parameter != null)\r
+ ExceptionUtils.logError(parameter);\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ widgetSelected(e);\r
+ }\r
+\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ run();\r
+ }\r
+\r
+ }\r
+\r
+ static class SetAttachedRouteGraphRoutingAction extends SelectionListenerAction {\r
+\r
+ Session session;\r
+ Collection<Resource> elements;\r
+ boolean straight;\r
+\r
+ public SetAttachedRouteGraphRoutingAction(Session session, Collection<Resource> elements, boolean straight, String text) {\r
+ super(text);\r
+ this.session = session;\r
+ this.elements = elements;\r
+ this.straight = straight;\r
+ }\r
+\r
+ @Override\r
+ public void run() {\r
+ session.asyncRequest(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ Command command = Commands.get(graph, "Simantics/Diagram/setStraightConnectionLines");\r
+ for(Resource element : elements)\r
+ command.execute(graph,\r
+ graph.syncRequest(new IndexRoot(element)),\r
+ element, straight);\r
+ \r
+ CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
+ graph.addMetadata(cm.add("Set routing for an element."));\r
+ }\r
+ }, new Callback<DatabaseException>() {\r
+ @Override\r
+ public void run(DatabaseException parameter) {\r
+ if (parameter != null)\r
+ ExceptionUtils.logError(parameter);\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ widgetSelected(e);\r
+ }\r
+\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ run();\r
+ }\r
+\r
+ }\r
+\r
+}\r