]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionRoutingMenuContribution.java
7f98894edd4b71be512e2e200e3770877ba5f2d9
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / handler / ConnectionRoutingMenuContribution.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.diagram.handler;
13
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;
19
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.datastructures.Callback;
48 import org.simantics.utils.ui.AdaptionUtils;
49 import org.simantics.utils.ui.ExceptionUtils;
50
51 /**
52  * @author Tuukka Lehtonen
53  */
54 public class ConnectionRoutingMenuContribution extends DynamicMenuContribution {
55         
56
57     private static final IContributionItem[] NONE = {};
58
59     @Override
60     protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {
61         ArrayList<IContributionItem> result = new ArrayList<IContributionItem>(4);
62
63         result.addAll(getConnectionRoutingItems(graph, selection));
64         result.addAll(getAttachedConnectionRoutingItems(graph, selection));
65
66         return result.toArray(NONE);
67     }
68
69     public static Collection<IContributionItem> getConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
70         Layer0 l0 = Layer0.getInstance(graph);
71         DiagramResource dr = DiagramResource.getInstance(graph);
72
73         final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
74         if (routings.size() == 0)
75             return Collections.emptyList();
76
77         final List<Resource> connections = new ArrayList<Resource>();
78         for (Object s : selection) {
79             Resource connection = AdaptionUtils.adaptToSingle(s, Resource.class);
80             if (connection == null)
81                 return Collections.emptyList();
82             if (!graph.isInstanceOf(connection, dr.Connection))
83                 return Collections.emptyList();
84             // Route graph connection routing is not selected per-connection, but per-terminal.
85             if (graph.isInstanceOf(connection, dr.RouteGraphConnection))
86                 return Collections.emptyList();
87             connections.add(connection);
88         }
89         if (connections.isEmpty())
90             return Collections.emptyList();
91
92         // See if all connections have a common routing.
93         Resource currentRoute = null;
94         for (Resource connection : connections) {
95             Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);
96             if (currentRouting != null) {
97                 Resource route = currentRouting.getPredicate();
98                 if (currentRoute == null)
99                     currentRoute = route;
100                 else if (!currentRoute.equals(route)) {
101                     currentRoute = null;
102                     break;
103                 }
104             }
105         }
106
107         final List<SetRoutingAction> actions = new ArrayList<SetRoutingAction>();
108         for (Resource routing : routings) {
109             String text = graph.adapt(routing, String.class);
110             SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);
111             if (routing.equals(currentRoute))
112                 action.setChecked(true);
113             actions.add(action);
114         }
115
116
117         sort(actions);
118
119         return Collections.<IContributionItem>singleton(
120                 new ContributionItem() {
121                     @Override
122                     public void fill(Menu menu, int index) {
123                         MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);
124                         openWith.setText("Connection Routing");
125                         Menu subMenu = new Menu(menu);
126                         openWith.setMenu(subMenu);
127
128                         for (SetRoutingAction a : actions) {
129                             MenuItem item = new MenuItem(subMenu, SWT.CHECK);
130                             item.setText(a.getText());
131                             item.addSelectionListener(a);
132                             item.setSelection(a.isChecked());
133                         }
134                     }
135                 }
136         );
137     }
138
139     public static Collection<IContributionItem> getAttachedConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
140         Layer0 l0 = Layer0.getInstance(graph);
141         DiagramResource dr = DiagramResource.getInstance(graph);
142         StructuralResource2 sr = StructuralResource2.getInstance(graph);
143         ModelingResources MOD = ModelingResources.getInstance(graph);
144         // HACK
145         Resource ReferenceProvider = graph.getPossibleResource("http://www.apros.fi/Apros-6.1/ReferenceProvider");
146         // Just continuing to do stupid things as above ;)
147         Resource connectionType = graph.getPossibleResource("http://www.simantics.org/Kcleco-5.0/FlowConnection");
148       
149
150         final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
151         if (routings.size() == 0)
152             return Collections.emptyList();
153
154         final List<Resource> connections = new ArrayList<Resource>();
155
156         // For route graph connections
157         final List<Resource> connectors = new ArrayList<Resource>();
158         boolean directRoutings = false;
159         boolean straightRoutings = false;
160
161         ArrayList<Resource> elements = new ArrayList<Resource>(); 
162         for (Object s : selection) {
163             Resource element = AdaptionUtils.adaptToSingle(s, Resource.class);
164             if (element == null)
165                 return Collections.emptyList();
166             if (!graph.isInstanceOf(element, dr.Element) || graph.isInstanceOf(element, dr.Connection))
167                 return Collections.emptyList();
168
169             elements.add(element);
170             
171             for(Statement stat : graph.getStatements(element, sr.IsConnectedTo)) {
172                 Resource diagramRelation = stat.getPredicate();
173                 Resource connectionRelation = graph.getPossibleObject(diagramRelation, MOD.DiagramConnectionRelationToConnectionRelation);
174                 if(connectionRelation == null)
175                     continue;
176                 // FIXME HACK
177                 if(ReferenceProvider != null && !graph.isInstanceOf(connectionRelation, ReferenceProvider))
178                     continue;
179                 Resource connector = stat.getObject();
180
181                 Resource connection = ConnectionUtil.tryGetConnection(graph, connector);
182                 if (connection != null) {
183                     if (graph.isInstanceOf(connection, dr.RouteGraphConnection)) {
184                         if (connectionType != null && graph.isInstanceOf(connection, connectionType))   
185                             continue;
186                         connectors.add(connector);
187                         boolean direct = Boolean.TRUE.equals( graph.getPossibleRelatedValue2(connector, dr.Connector_straight, Bindings.BOOLEAN) );
188                         directRoutings |= direct;
189                         straightRoutings |= !direct;
190                     } else {
191                         connections.add(connection);
192                     }
193                 }
194             }
195         }
196         if (connectors.isEmpty() && connections.isEmpty())
197             return Collections.emptyList();
198
199         // See if all connections have a common routing.
200         Resource currentRoute = null;
201         for (Resource connection : connections) {
202             Statement currentRouting = graph.getPossibleStatement(connection, dr.Routing);
203             if (currentRouting != null) {
204                 Resource route = currentRouting.getPredicate();
205                 if (currentRoute == null)
206                     currentRoute = route;
207                 else if (!currentRoute.equals(route)) {
208                     currentRoute = null;
209                     break;
210                 }
211             }
212         }
213
214         final List<SelectionListenerAction> actions = new ArrayList<SelectionListenerAction>();
215
216         if (!connections.isEmpty()) {
217             // Handle old style connections and their routing
218             for (Resource routing : routings) {
219                 String text = graph.adapt(routing, String.class);
220                 SetRoutingAction action = new SetRoutingAction(graph.getSession(), connections, routing, text);
221                 if (routing.equals(currentRoute)) {
222                     action.setChecked(true);
223                 }
224                 actions.add(action);
225             }
226         }
227         if (!connectors.isEmpty()) {
228             // Handle route graph connections
229             SelectionListenerAction direct = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, true, "Direct");
230             SelectionListenerAction straight = new SetAttachedRouteGraphRoutingAction(graph.getSession(), elements, false, "Straight-angled");
231             direct.setChecked(directRoutings);
232             straight.setChecked(straightRoutings);
233             actions.add(direct);
234             actions.add(straight);
235         }
236
237         sort(actions);
238
239         return Collections.<IContributionItem>singleton(
240                 new ContributionItem() {
241                     @Override
242                     public void fill(Menu menu, int index) {
243                         MenuItem openWith = new MenuItem(menu, SWT.CASCADE, index);
244                         openWith.setText("Attached Connection Routing");
245                         Menu subMenu = new Menu(menu);
246                         openWith.setMenu(subMenu);
247
248                         for (SelectionListenerAction a : actions) {
249                             MenuItem item = new MenuItem(subMenu, SWT.CHECK);
250                             item.setText(a.getText());
251                             item.addSelectionListener(a);
252                             item.setSelection(a.isChecked());
253                         }
254                     }
255                 }
256         );
257     }
258
259     private static void sort(List<? extends IAction> actions) {
260         // Sort the open with actions in string order.
261         Collections.sort(actions, new Comparator<IAction>() {
262             @Override
263             public int compare(IAction o1, IAction o2) {
264                 return o1.getText().compareToIgnoreCase(o2.getText());
265             }
266         });
267     }
268
269     static abstract class SelectionListenerAction extends Action implements SelectionListener {
270         public SelectionListenerAction(String text) {
271             super(text);
272         }
273     }
274
275     static class SetRoutingAction extends SelectionListenerAction {
276
277         Session session;
278         Collection<Resource> connections;
279         Resource routingTag;
280
281         public SetRoutingAction(Session session, Collection<Resource> connections, Resource routingTag, String text) {
282             super(text);
283             this.session = session;
284             this.connections = connections;
285             this.routingTag = routingTag;
286         }
287
288         @Override
289         public void run() {
290             session.asyncRequest(new WriteRequest() {
291                 @Override
292                 public void perform(WriteGraph graph) throws DatabaseException {
293                     DiagramResource dr = DiagramResource.getInstance(graph);
294                     for (Resource connection : connections) {
295                         graph.deny(connection, dr.Routing);
296                         graph.claim(connection, routingTag, connection);
297                     }
298                 }
299             }, new Callback<DatabaseException>() {
300                 @Override
301                 public void run(DatabaseException parameter) {
302                     if (parameter != null)
303                         ExceptionUtils.logError(parameter);
304                 }
305             });
306         }
307
308         @Override
309         public void widgetDefaultSelected(SelectionEvent e) {
310             widgetSelected(e);
311         }
312
313         @Override
314         public void widgetSelected(SelectionEvent e) {
315             run();
316         }
317
318     }
319
320     static class SetAttachedRouteGraphRoutingAction extends SelectionListenerAction {
321
322         Session session;
323         Collection<Resource> elements;
324         boolean straight;
325
326         public SetAttachedRouteGraphRoutingAction(Session session, Collection<Resource> elements, boolean straight, String text) {
327             super(text);
328             this.session = session;
329             this.elements = elements;
330             this.straight = straight;
331         }
332
333         @Override
334         public void run() {
335             session.asyncRequest(new WriteRequest() {
336                 @Override
337                 public void perform(WriteGraph graph) throws DatabaseException {
338                     Command command = Commands.get(graph, "Simantics/Diagram/setStraightConnectionLines");
339                     for(Resource element : elements)
340                         command.execute(graph,
341                                 graph.syncRequest(new IndexRoot(element)),
342                                 element, straight);
343                     
344                     CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
345                     graph.addMetadata(cm.add("Set routing for an element."));
346                 }
347             }, new Callback<DatabaseException>() {
348                 @Override
349                 public void run(DatabaseException parameter) {
350                     if (parameter != null)
351                         ExceptionUtils.logError(parameter);
352                 }
353             });
354         }
355
356         @Override
357         public void widgetDefaultSelected(SelectionEvent e) {
358             widgetSelected(e);
359         }
360
361         @Override
362         public void widgetSelected(SelectionEvent e) {
363             run();
364         }
365
366     }
367
368 }