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.diagram.handler;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collection;
\r
16 import java.util.Collections;
\r
17 import java.util.Comparator;
\r
18 import java.util.List;
\r
20 import org.eclipse.jface.action.Action;
\r
21 import org.eclipse.jface.action.ContributionItem;
\r
22 import org.eclipse.jface.action.IAction;
\r
23 import org.eclipse.jface.action.IContributionItem;
\r
24 import org.eclipse.swt.SWT;
\r
25 import org.eclipse.swt.events.SelectionEvent;
\r
26 import org.eclipse.swt.events.SelectionListener;
\r
27 import org.eclipse.swt.widgets.Menu;
\r
28 import org.eclipse.swt.widgets.MenuItem;
\r
29 import org.simantics.databoard.Bindings;
\r
30 import org.simantics.db.ReadGraph;
\r
31 import org.simantics.db.Resource;
\r
32 import org.simantics.db.Session;
\r
33 import org.simantics.db.Statement;
\r
34 import org.simantics.db.WriteGraph;
\r
35 import org.simantics.db.common.CommentMetadata;
\r
36 import org.simantics.db.common.request.IndexRoot;
\r
37 import org.simantics.db.common.request.WriteRequest;
\r
38 import org.simantics.db.exception.DatabaseException;
\r
39 import org.simantics.diagram.content.ConnectionUtil;
\r
40 import org.simantics.diagram.stubs.DiagramResource;
\r
41 import org.simantics.layer0.Layer0;
\r
42 import org.simantics.modeling.ModelingResources;
\r
43 import org.simantics.scl.commands.Command;
\r
44 import org.simantics.scl.commands.Commands;
\r
45 import org.simantics.structural.stubs.StructuralResource2;
\r
46 import org.simantics.ui.contribution.DynamicMenuContribution;
\r
47 import org.simantics.utils.datastructures.Callback;
\r
48 import org.simantics.utils.ui.AdaptionUtils;
\r
49 import org.simantics.utils.ui.ExceptionUtils;
\r
52 * @author Tuukka Lehtonen
\r
54 public class ConnectionRoutingMenuContribution extends DynamicMenuContribution {
\r
57 private static final IContributionItem[] NONE = {};
\r
60 protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {
\r
61 ArrayList<IContributionItem> result = new ArrayList<IContributionItem>(4);
\r
63 result.addAll(getConnectionRoutingItems(graph, selection));
\r
64 result.addAll(getAttachedConnectionRoutingItems(graph, selection));
\r
66 return result.toArray(NONE);
\r
69 public static Collection<IContributionItem> getConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
\r
70 Layer0 l0 = Layer0.getInstance(graph);
\r
71 DiagramResource dr = DiagramResource.getInstance(graph);
\r
73 final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
\r
74 if (routings.size() == 0)
\r
75 return Collections.emptyList();
\r
77 final List<Resource> connections = new ArrayList<Resource>();
\r
78 for (Object s : selection) {
\r
79 Resource connection = AdaptionUtils.adaptToSingle(s, Resource.class);
\r
80 if (connection == null)
\r
81 return Collections.emptyList();
\r
82 if (!graph.isInstanceOf(connection, dr.Connection))
\r
83 return Collections.emptyList();
\r
84 // Route graph connection routing is not selected per-connection, but per-terminal.
\r
85 if (graph.isInstanceOf(connection, dr.RouteGraphConnection))
\r
86 return Collections.emptyList();
\r
87 connections.add(connection);
\r
89 if (connections.isEmpty())
\r
90 return Collections.emptyList();
\r
92 // See if all connections have a common routing.
\r
93 Resource currentRoute = null;
\r
94 for (Resource connection : connections) {
\r
95 Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);
\r
96 if (currentRouting != null) {
\r
97 Resource route = currentRouting.getPredicate();
\r
98 if (currentRoute == null)
\r
99 currentRoute = route;
\r
100 else if (!currentRoute.equals(route)) {
\r
101 currentRoute = null;
\r
107 final List<SetRoutingAction> actions = new ArrayList<SetRoutingAction>();
\r
108 for (Resource routing : routings) {
\r
109 String text = graph.adapt(routing, String.class);
\r
110 SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);
\r
111 if (routing.equals(currentRoute))
\r
112 action.setChecked(true);
\r
113 actions.add(action);
\r
119 return Collections.<IContributionItem>singleton(
\r
120 new ContributionItem() {
\r
122 public void fill(Menu menu, int index) {
\r
123 MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);
\r
124 openWith.setText("Connection Routing");
\r
125 Menu subMenu = new Menu(menu);
\r
126 openWith.setMenu(subMenu);
\r
128 for (SetRoutingAction a : actions) {
\r
129 MenuItem item = new MenuItem(subMenu, SWT.CHECK);
\r
130 item.setText(a.getText());
\r
131 item.addSelectionListener(a);
\r
132 item.setSelection(a.isChecked());
\r
139 public static Collection<IContributionItem> getAttachedConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
\r
140 Layer0 l0 = Layer0.getInstance(graph);
\r
141 DiagramResource dr = DiagramResource.getInstance(graph);
\r
142 StructuralResource2 sr = StructuralResource2.getInstance(graph);
\r
143 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
145 Resource ReferenceProvider = graph.getPossibleResource("http://www.apros.fi/Apros-6.1/ReferenceProvider");
\r
146 // Just continuing to do stupid things as above ;)
\r
147 Resource connectionType = graph.getPossibleResource("http://www.simantics.org/Kcleco-5.0/FlowConnection");
\r
150 final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
\r
151 if (routings.size() == 0)
\r
152 return Collections.emptyList();
\r
154 final List<Resource> connections = new ArrayList<Resource>();
\r
156 // For route graph connections
\r
157 final List<Resource> connectors = new ArrayList<Resource>();
\r
158 boolean directRoutings = false;
\r
159 boolean straightRoutings = false;
\r
161 ArrayList<Resource> elements = new ArrayList<Resource>();
\r
162 for (Object s : selection) {
\r
163 Resource element = AdaptionUtils.adaptToSingle(s, Resource.class);
\r
164 if (element == null)
\r
165 return Collections.emptyList();
\r
166 if (!graph.isInstanceOf(element, dr.Element) || graph.isInstanceOf(element, dr.Connection))
\r
167 return Collections.emptyList();
\r
169 elements.add(element);
\r
171 for(Statement stat : graph.getStatements(element, sr.IsConnectedTo)) {
\r
172 Resource diagramRelation = stat.getPredicate();
\r
173 Resource connectionRelation = graph.getPossibleObject(diagramRelation, MOD.DiagramConnectionRelationToConnectionRelation);
\r
174 if(connectionRelation == null)
\r
177 if(ReferenceProvider != null && !graph.isInstanceOf(connectionRelation, ReferenceProvider))
\r
179 Resource connector = stat.getObject();
\r
181 Resource connection = ConnectionUtil.tryGetConnection(graph, connector);
\r
182 if (connection != null) {
\r
183 if (graph.isInstanceOf(connection, dr.RouteGraphConnection)) {
\r
184 if (connectionType != null && graph.isInstanceOf(connection, connectionType))
\r
186 connectors.add(connector);
\r
187 boolean direct = Boolean.TRUE.equals( graph.getPossibleRelatedValue2(connector, dr.Connector_straight, Bindings.BOOLEAN) );
\r
188 directRoutings |= direct;
\r
189 straightRoutings |= !direct;
\r
191 connections.add(connection);
\r
196 if (connectors.isEmpty() && connections.isEmpty())
\r
197 return Collections.emptyList();
\r
199 // See if all connections have a common routing.
\r
200 Resource currentRoute = null;
\r
201 for (Resource connection : connections) {
\r
202 Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);
\r
203 if (currentRouting != null) {
\r
204 Resource route = currentRouting.getPredicate();
\r
205 if (currentRoute == null)
\r
206 currentRoute = route;
\r
207 else if (!currentRoute.equals(route)) {
\r
208 currentRoute = null;
\r
214 final List<SelectionListenerAction> actions = new ArrayList<SelectionListenerAction>();
\r
216 if (!connections.isEmpty()) {
\r
217 // Handle old style connections and their routing
\r
218 for (Resource routing : routings) {
\r
219 String text = graph.adapt(routing, String.class);
\r
220 SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);
\r
221 if (routing.equals(currentRoute)) {
\r
222 action.setChecked(true);
\r
224 actions.add(action);
\r
227 if (!connectors.isEmpty()) {
\r
228 // Handle route graph connections
\r
229 SelectionListenerAction direct = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, true, "Direct");
\r
230 SelectionListenerAction straight = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, false, "Straight-angled");
\r
231 direct.setChecked(directRoutings);
\r
232 straight.setChecked(straightRoutings);
\r
233 actions.add(direct);
\r
234 actions.add(straight);
\r
239 return Collections.<IContributionItem>singleton(
\r
240 new ContributionItem() {
\r
242 public void fill(Menu menu, int index) {
\r
243 MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);
\r
244 openWith.setText("Attached Connection Routing");
\r
245 Menu subMenu = new Menu(menu);
\r
246 openWith.setMenu(subMenu);
\r
248 for (SelectionListenerAction a : actions) {
\r
249 MenuItem item = new MenuItem(subMenu, SWT.CHECK);
\r
250 item.setText(a.getText());
\r
251 item.addSelectionListener(a);
\r
252 item.setSelection(a.isChecked());
\r
259 private static void sort(List<? extends IAction> actions) {
\r
260 // Sort the open with actions in string order.
\r
261 Collections.sort(actions, new Comparator<IAction>() {
\r
263 public int compare(IAction o1, IAction o2) {
\r
264 return o1.getText().compareToIgnoreCase(o2.getText());
\r
269 static abstract class SelectionListenerAction extends Action implements SelectionListener {
\r
270 public SelectionListenerAction(String text) {
\r
275 static class SetRoutingAction extends SelectionListenerAction {
\r
278 Collection<Resource> connections;
\r
279 Resource routingTag;
\r
281 public SetRoutingAction(Session session, Collection<Resource> connections, Resource routingTag, String text) {
\r
283 this.session = session;
\r
284 this.connections = connections;
\r
285 this.routingTag = routingTag;
\r
289 public void run() {
\r
290 session.asyncRequest(new WriteRequest() {
\r
292 public void perform(WriteGraph graph) throws DatabaseException {
\r
293 DiagramResource dr = DiagramResource.getInstance(graph);
\r
294 for (Resource connection : connections) {
\r
295 graph.deny(connection, dr.Routing);
\r
296 graph.claim(connection, routingTag, connection);
\r
299 }, new Callback<DatabaseException>() {
\r
301 public void run(DatabaseException parameter) {
\r
302 if (parameter != null)
\r
303 ExceptionUtils.logError(parameter);
\r
309 public void widgetDefaultSelected(SelectionEvent e) {
\r
314 public void widgetSelected(SelectionEvent e) {
\r
320 static class SetAttachedRouteGraphRoutingAction extends SelectionListenerAction {
\r
323 Collection<Resource> elements;
\r
326 public SetAttachedRouteGraphRoutingAction(Session session, Collection<Resource> elements, boolean straight, String text) {
\r
328 this.session = session;
\r
329 this.elements = elements;
\r
330 this.straight = straight;
\r
334 public void run() {
\r
335 session.asyncRequest(new WriteRequest() {
\r
337 public void perform(WriteGraph graph) throws DatabaseException {
\r
338 Command command = Commands.get(graph, "Simantics/Diagram/setStraightConnectionLines");
\r
339 for(Resource element : elements)
\r
340 command.execute(graph,
\r
341 graph.syncRequest(new IndexRoot(element)),
\r
342 element, straight);
\r
344 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
\r
345 graph.addMetadata(cm.add("Set routing for an element."));
\r
347 }, new Callback<DatabaseException>() {
\r
349 public void run(DatabaseException parameter) {
\r
350 if (parameter != null)
\r
351 ExceptionUtils.logError(parameter);
\r
357 public void widgetDefaultSelected(SelectionEvent e) {
\r
362 public void widgetSelected(SelectionEvent e) {
\r