]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionRoutingMenuContribution.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / handler / ConnectionRoutingMenuContribution.java
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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.diagram.handler;\r
13 \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
19 \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
50 \r
51 /**\r
52  * @author Tuukka Lehtonen\r
53  */\r
54 public class ConnectionRoutingMenuContribution extends DynamicMenuContribution {\r
55         \r
56 \r
57     private static final IContributionItem[] NONE = {};\r
58 \r
59     @Override\r
60     protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {\r
61         ArrayList<IContributionItem> result = new ArrayList<IContributionItem>(4);\r
62 \r
63         result.addAll(getConnectionRoutingItems(graph, selection));\r
64         result.addAll(getAttachedConnectionRoutingItems(graph, selection));\r
65 \r
66         return result.toArray(NONE);\r
67     }\r
68 \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
72 \r
73         final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);\r
74         if (routings.size() == 0)\r
75             return Collections.emptyList();\r
76 \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
88         }\r
89         if (connections.isEmpty())\r
90             return Collections.emptyList();\r
91 \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
102                     break;\r
103                 }\r
104             }\r
105         }\r
106 \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
114         }\r
115 \r
116 \r
117         sort(actions);\r
118 \r
119         return Collections.<IContributionItem>singleton(\r
120                 new ContributionItem() {\r
121                     @Override\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
127 \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
133                         }\r
134                     }\r
135                 }\r
136         );\r
137     }\r
138 \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
144         // HACK\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
148       \r
149 \r
150         final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);\r
151         if (routings.size() == 0)\r
152             return Collections.emptyList();\r
153 \r
154         final List<Resource> connections = new ArrayList<Resource>();\r
155 \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
160 \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
168 \r
169             elements.add(element);\r
170             \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
175                     continue;\r
176                 // FIXME HACK\r
177                 if(ReferenceProvider != null && !graph.isInstanceOf(connectionRelation, ReferenceProvider))\r
178                     continue;\r
179                 Resource connector = stat.getObject();\r
180 \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
185                             continue;\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
190                     } else {\r
191                         connections.add(connection);\r
192                     }\r
193                 }\r
194             }\r
195         }\r
196         if (connectors.isEmpty() && connections.isEmpty())\r
197             return Collections.emptyList();\r
198 \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
209                     break;\r
210                 }\r
211             }\r
212         }\r
213 \r
214         final List<SelectionListenerAction> actions = new ArrayList<SelectionListenerAction>();\r
215 \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
223                 }\r
224                 actions.add(action);\r
225             }\r
226         }\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
235         }\r
236 \r
237         sort(actions);\r
238 \r
239         return Collections.<IContributionItem>singleton(\r
240                 new ContributionItem() {\r
241                     @Override\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
247 \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
253                         }\r
254                     }\r
255                 }\r
256         );\r
257     }\r
258 \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
262             @Override\r
263             public int compare(IAction o1, IAction o2) {\r
264                 return o1.getText().compareToIgnoreCase(o2.getText());\r
265             }\r
266         });\r
267     }\r
268 \r
269     static abstract class SelectionListenerAction extends Action implements SelectionListener {\r
270         public SelectionListenerAction(String text) {\r
271             super(text);\r
272         }\r
273     }\r
274 \r
275     static class SetRoutingAction extends SelectionListenerAction {\r
276 \r
277         Session session;\r
278         Collection<Resource> connections;\r
279         Resource routingTag;\r
280 \r
281         public SetRoutingAction(Session session, Collection<Resource> connections, Resource routingTag, String text) {\r
282             super(text);\r
283             this.session = session;\r
284             this.connections = connections;\r
285             this.routingTag = routingTag;\r
286         }\r
287 \r
288         @Override\r
289         public void run() {\r
290             session.asyncRequest(new WriteRequest() {\r
291                 @Override\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
297                     }\r
298                 }\r
299             }, new Callback<DatabaseException>() {\r
300                 @Override\r
301                 public void run(DatabaseException parameter) {\r
302                     if (parameter != null)\r
303                         ExceptionUtils.logError(parameter);\r
304                 }\r
305             });\r
306         }\r
307 \r
308         @Override\r
309         public void widgetDefaultSelected(SelectionEvent e) {\r
310             widgetSelected(e);\r
311         }\r
312 \r
313         @Override\r
314         public void widgetSelected(SelectionEvent e) {\r
315             run();\r
316         }\r
317 \r
318     }\r
319 \r
320     static class SetAttachedRouteGraphRoutingAction extends SelectionListenerAction {\r
321 \r
322         Session session;\r
323         Collection<Resource> elements;\r
324         boolean straight;\r
325 \r
326         public SetAttachedRouteGraphRoutingAction(Session session, Collection<Resource> elements, boolean straight, String text) {\r
327             super(text);\r
328             this.session = session;\r
329             this.elements = elements;\r
330             this.straight = straight;\r
331         }\r
332 \r
333         @Override\r
334         public void run() {\r
335             session.asyncRequest(new WriteRequest() {\r
336                 @Override\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
343                     \r
344                     CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
345                     graph.addMetadata(cm.add("Set routing for an element."));\r
346                 }\r
347             }, new Callback<DatabaseException>() {\r
348                 @Override\r
349                 public void run(DatabaseException parameter) {\r
350                     if (parameter != null)\r
351                         ExceptionUtils.logError(parameter);\r
352                 }\r
353             });\r
354         }\r
355 \r
356         @Override\r
357         public void widgetDefaultSelected(SelectionEvent e) {\r
358             widgetSelected(e);\r
359         }\r
360 \r
361         @Override\r
362         public void widgetSelected(SelectionEvent e) {\r
363             run();\r
364         }\r
365 \r
366     }\r
367 \r
368 }\r