1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.handler;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Comparator;
18 import java.util.List;
20 import org.eclipse.jface.action.Action;
21 import org.eclipse.jface.action.ContributionItem;
22 import org.eclipse.jface.action.IAction;
23 import org.eclipse.jface.action.IContributionItem;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.SelectionEvent;
26 import org.eclipse.swt.events.SelectionListener;
27 import org.eclipse.swt.widgets.Menu;
28 import org.eclipse.swt.widgets.MenuItem;
29 import org.simantics.databoard.Bindings;
30 import org.simantics.db.ReadGraph;
31 import org.simantics.db.Resource;
32 import org.simantics.db.Session;
33 import org.simantics.db.Statement;
34 import org.simantics.db.WriteGraph;
35 import org.simantics.db.common.CommentMetadata;
36 import org.simantics.db.common.request.IndexRoot;
37 import org.simantics.db.common.request.WriteRequest;
38 import org.simantics.db.exception.DatabaseException;
39 import org.simantics.diagram.content.ConnectionUtil;
40 import org.simantics.diagram.stubs.DiagramResource;
41 import org.simantics.layer0.Layer0;
42 import org.simantics.modeling.ModelingResources;
43 import org.simantics.scl.commands.Command;
44 import org.simantics.scl.commands.Commands;
45 import org.simantics.structural.stubs.StructuralResource2;
46 import org.simantics.ui.contribution.DynamicMenuContribution;
47 import org.simantics.utils.ui.AdaptionUtils;
48 import org.simantics.utils.ui.ExceptionUtils;
51 * @author Tuukka Lehtonen
53 public class ConnectionRoutingMenuContribution extends DynamicMenuContribution {
56 private static final IContributionItem[] NONE = {};
59 protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {
60 ArrayList<IContributionItem> result = new ArrayList<IContributionItem>(4);
62 result.addAll(getConnectionRoutingItems(graph, selection));
63 result.addAll(getAttachedConnectionRoutingItems(graph, selection));
65 return result.toArray(NONE);
68 public static Collection<IContributionItem> getConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
69 Layer0 l0 = Layer0.getInstance(graph);
70 DiagramResource dr = DiagramResource.getInstance(graph);
72 final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
73 if (routings.size() == 0)
74 return Collections.emptyList();
76 final List<Resource> connections = new ArrayList<Resource>();
77 for (Object s : selection) {
78 Resource connection = AdaptionUtils.adaptToSingle(s, Resource.class);
79 if (connection == null)
80 return Collections.emptyList();
81 if (!graph.isInstanceOf(connection, dr.Connection))
82 return Collections.emptyList();
83 // Route graph connection routing is not selected per-connection, but per-terminal.
84 if (graph.isInstanceOf(connection, dr.RouteGraphConnection))
85 return Collections.emptyList();
86 connections.add(connection);
88 if (connections.isEmpty())
89 return Collections.emptyList();
91 // See if all connections have a common routing.
92 Resource currentRoute = null;
93 for (Resource connection : connections) {
94 Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);
95 if (currentRouting != null) {
96 Resource route = currentRouting.getPredicate();
97 if (currentRoute == null)
99 else if (!currentRoute.equals(route)) {
106 final List<SetRoutingAction> actions = new ArrayList<SetRoutingAction>();
107 for (Resource routing : routings) {
108 String text = graph.adapt(routing, String.class);
109 SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);
110 if (routing.equals(currentRoute))
111 action.setChecked(true);
118 return Collections.<IContributionItem>singleton(
119 new ContributionItem() {
121 public void fill(Menu menu, int index) {
122 MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);
123 openWith.setText("Connection Routing");
124 Menu subMenu = new Menu(menu);
125 openWith.setMenu(subMenu);
127 for (SetRoutingAction a : actions) {
128 MenuItem item = new MenuItem(subMenu, SWT.CHECK);
129 item.setText(a.getText());
130 item.addSelectionListener(a);
131 item.setSelection(a.isChecked());
138 public static Collection<IContributionItem> getAttachedConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
139 Layer0 l0 = Layer0.getInstance(graph);
140 DiagramResource dr = DiagramResource.getInstance(graph);
141 StructuralResource2 sr = StructuralResource2.getInstance(graph);
142 ModelingResources MOD = ModelingResources.getInstance(graph);
144 Resource ReferenceProvider = graph.getPossibleResource("http://www.apros.fi/Apros-6.1/ReferenceProvider");
145 // Just continuing to do stupid things as above ;)
146 Resource connectionType = graph.getPossibleResource("http://www.simantics.org/Kcleco-5.0/FlowConnection");
149 final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
150 if (routings.size() == 0)
151 return Collections.emptyList();
153 final List<Resource> connections = new ArrayList<Resource>();
155 // For route graph connections
156 final List<Resource> connectors = new ArrayList<Resource>();
157 boolean directRoutings = false;
158 boolean straightRoutings = false;
160 ArrayList<Resource> elements = new ArrayList<Resource>();
161 for (Object s : selection) {
162 Resource element = AdaptionUtils.adaptToSingle(s, Resource.class);
164 return Collections.emptyList();
165 if (!graph.isInstanceOf(element, dr.Element) || graph.isInstanceOf(element, dr.Connection))
166 return Collections.emptyList();
168 elements.add(element);
170 for(Statement stat : graph.getStatements(element, sr.IsConnectedTo)) {
171 Resource diagramRelation = stat.getPredicate();
172 Resource connectionRelation = graph.getPossibleObject(diagramRelation, MOD.DiagramConnectionRelationToConnectionRelation);
173 if(connectionRelation == null)
176 if(ReferenceProvider != null && !graph.isInstanceOf(connectionRelation, ReferenceProvider))
178 Resource connector = stat.getObject();
180 Resource connection = ConnectionUtil.tryGetConnection(graph, connector);
181 if (connection != null) {
182 if (graph.isInstanceOf(connection, dr.RouteGraphConnection)) {
183 if (connectionType != null && graph.isInstanceOf(connection, connectionType))
185 connectors.add(connector);
186 boolean direct = Boolean.TRUE.equals( graph.getPossibleRelatedValue2(connector, dr.Connector_straight, Bindings.BOOLEAN) );
187 directRoutings |= direct;
188 straightRoutings |= !direct;
190 connections.add(connection);
195 if (connectors.isEmpty() && connections.isEmpty())
196 return Collections.emptyList();
198 // See if all connections have a common routing.
199 Resource currentRoute = null;
200 for (Resource connection : connections) {
201 Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);
202 if (currentRouting != null) {
203 Resource route = currentRouting.getPredicate();
204 if (currentRoute == null)
205 currentRoute = route;
206 else if (!currentRoute.equals(route)) {
213 final List<SelectionListenerAction> actions = new ArrayList<SelectionListenerAction>();
215 if (!connections.isEmpty()) {
216 // Handle old style connections and their routing
217 for (Resource routing : routings) {
218 String text = graph.adapt(routing, String.class);
219 SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);
220 if (routing.equals(currentRoute)) {
221 action.setChecked(true);
226 if (!connectors.isEmpty()) {
227 // Handle route graph connections
228 SelectionListenerAction direct = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, true, "Direct");
229 SelectionListenerAction straight = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, false, "Straight-angled");
230 direct.setChecked(directRoutings);
231 straight.setChecked(straightRoutings);
233 actions.add(straight);
238 return Collections.<IContributionItem>singleton(
239 new ContributionItem() {
241 public void fill(Menu menu, int index) {
242 MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);
243 openWith.setText("Attached Connection Routing");
244 Menu subMenu = new Menu(menu);
245 openWith.setMenu(subMenu);
247 for (SelectionListenerAction a : actions) {
248 MenuItem item = new MenuItem(subMenu, SWT.CHECK);
249 item.setText(a.getText());
250 item.addSelectionListener(a);
251 item.setSelection(a.isChecked());
258 private static void sort(List<? extends IAction> actions) {
259 // Sort the open with actions in string order.
260 Collections.sort(actions, new Comparator<IAction>() {
262 public int compare(IAction o1, IAction o2) {
263 return o1.getText().compareToIgnoreCase(o2.getText());
268 static abstract class SelectionListenerAction extends Action implements SelectionListener {
269 public SelectionListenerAction(String text) {
274 static class SetRoutingAction extends SelectionListenerAction {
277 Collection<Resource> connections;
280 public SetRoutingAction(Session session, Collection<Resource> connections, Resource routingTag, String text) {
282 this.session = session;
283 this.connections = connections;
284 this.routingTag = routingTag;
289 session.asyncRequest(new WriteRequest() {
291 public void perform(WriteGraph graph) throws DatabaseException {
292 DiagramResource dr = DiagramResource.getInstance(graph);
293 for (Resource connection : connections) {
294 graph.deny(connection, dr.Routing);
295 graph.claim(connection, routingTag, connection);
299 if (parameter != null)
300 ExceptionUtils.logError(parameter);
305 public void widgetDefaultSelected(SelectionEvent e) {
310 public void widgetSelected(SelectionEvent e) {
316 static class SetAttachedRouteGraphRoutingAction extends SelectionListenerAction {
319 Collection<Resource> elements;
322 public SetAttachedRouteGraphRoutingAction(Session session, Collection<Resource> elements, boolean straight, String text) {
324 this.session = session;
325 this.elements = elements;
326 this.straight = straight;
331 session.asyncRequest(new WriteRequest() {
333 public void perform(WriteGraph graph) throws DatabaseException {
334 Command command = Commands.get(graph, "Simantics/Diagram/setStraightConnectionLines");
335 for(Resource element : elements)
336 command.execute(graph,
337 graph.syncRequest(new IndexRoot(element)),
340 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
341 graph.addMetadata(cm.add("Set routing for an element."));
344 if (parameter != null)
345 ExceptionUtils.logError(parameter);
350 public void widgetDefaultSelected(SelectionEvent e) {
355 public void widgetSelected(SelectionEvent e) {