]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/handler/ConnectionRoutingMenuContribution.java
Use Consumer interface instead of deprecated Callback interface
[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.ui.AdaptionUtils;
48 import org.simantics.utils.ui.ExceptionUtils;
49
50 /**
51  * @author Tuukka Lehtonen
52  */
53 public class ConnectionRoutingMenuContribution extends DynamicMenuContribution {
54         
55
56     private static final IContributionItem[] NONE = {};
57
58     @Override
59     protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {
60         ArrayList<IContributionItem> result = new ArrayList<IContributionItem>(4);
61
62         result.addAll(getConnectionRoutingItems(graph, selection));
63         result.addAll(getAttachedConnectionRoutingItems(graph, selection));
64
65         return result.toArray(NONE);
66     }
67
68     public static Collection<IContributionItem> getConnectionRoutingItems(ReadGraph graph, Object[] selection) throws DatabaseException {
69         Layer0 l0 = Layer0.getInstance(graph);
70         DiagramResource dr = DiagramResource.getInstance(graph);
71
72         final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
73         if (routings.size() == 0)
74             return Collections.emptyList();
75
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);
87         }
88         if (connections.isEmpty())
89             return Collections.emptyList();
90
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)
98                     currentRoute = route;
99                 else if (!currentRoute.equals(route)) {
100                     currentRoute = null;
101                     break;
102                 }
103             }
104         }
105
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);
112             actions.add(action);
113         }
114
115
116         sort(actions);
117
118         return Collections.<IContributionItem>singleton(
119                 new ContributionItem() {
120                     @Override
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);
126
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());
132                         }
133                     }
134                 }
135         );
136     }
137
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);
143         // HACK
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");
147       
148
149         final Collection<Resource> routings = graph.getObjects(dr.Routing, l0.SuperrelationOf);
150         if (routings.size() == 0)
151             return Collections.emptyList();
152
153         final List<Resource> connections = new ArrayList<Resource>();
154
155         // For route graph connections
156         final List<Resource> connectors = new ArrayList<Resource>();
157         boolean directRoutings = false;
158         boolean straightRoutings = false;
159
160         ArrayList<Resource> elements = new ArrayList<Resource>(); 
161         for (Object s : selection) {
162             Resource element = AdaptionUtils.adaptToSingle(s, Resource.class);
163             if (element == null)
164                 return Collections.emptyList();
165             if (!graph.isInstanceOf(element, dr.Element) || graph.isInstanceOf(element, dr.Connection))
166                 return Collections.emptyList();
167
168             elements.add(element);
169             
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)
174                     continue;
175                 // FIXME HACK
176                 if(ReferenceProvider != null && !graph.isInstanceOf(connectionRelation, ReferenceProvider))
177                     continue;
178                 Resource connector = stat.getObject();
179
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))   
184                             continue;
185                         connectors.add(connector);
186                         boolean direct = Boolean.TRUE.equals( graph.getPossibleRelatedValue2(connector, dr.Connector_straight, Bindings.BOOLEAN) );
187                         directRoutings |= direct;
188                         straightRoutings |= !direct;
189                     } else {
190                         connections.add(connection);
191                     }
192                 }
193             }
194         }
195         if (connectors.isEmpty() && connections.isEmpty())
196             return Collections.emptyList();
197
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)) {
207                     currentRoute = null;
208                     break;
209                 }
210             }
211         }
212
213         final List<SelectionListenerAction> actions = new ArrayList<SelectionListenerAction>();
214
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);
222                 }
223                 actions.add(action);
224             }
225         }
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);
232             actions.add(direct);
233             actions.add(straight);
234         }
235
236         sort(actions);
237
238         return Collections.<IContributionItem>singleton(
239                 new ContributionItem() {
240                     @Override
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);
246
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());
252                         }
253                     }
254                 }
255         );
256     }
257
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>() {
261             @Override
262             public int compare(IAction o1, IAction o2) {
263                 return o1.getText().compareToIgnoreCase(o2.getText());
264             }
265         });
266     }
267
268     static abstract class SelectionListenerAction extends Action implements SelectionListener {
269         public SelectionListenerAction(String text) {
270             super(text);
271         }
272     }
273
274     static class SetRoutingAction extends SelectionListenerAction {
275
276         Session session;
277         Collection<Resource> connections;
278         Resource routingTag;
279
280         public SetRoutingAction(Session session, Collection<Resource> connections, Resource routingTag, String text) {
281             super(text);
282             this.session = session;
283             this.connections = connections;
284             this.routingTag = routingTag;
285         }
286
287         @Override
288         public void run() {
289             session.asyncRequest(new WriteRequest() {
290                 @Override
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);
296                     }
297                 }
298             }, parameter -> {
299                 if (parameter != null)
300                     ExceptionUtils.logError(parameter);
301             });
302         }
303
304         @Override
305         public void widgetDefaultSelected(SelectionEvent e) {
306             widgetSelected(e);
307         }
308
309         @Override
310         public void widgetSelected(SelectionEvent e) {
311             run();
312         }
313
314     }
315
316     static class SetAttachedRouteGraphRoutingAction extends SelectionListenerAction {
317
318         Session session;
319         Collection<Resource> elements;
320         boolean straight;
321
322         public SetAttachedRouteGraphRoutingAction(Session session, Collection<Resource> elements, boolean straight, String text) {
323             super(text);
324             this.session = session;
325             this.elements = elements;
326             this.straight = straight;
327         }
328
329         @Override
330         public void run() {
331             session.asyncRequest(new WriteRequest() {
332                 @Override
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)),
338                                 element, straight);
339                     
340                     CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
341                     graph.addMetadata(cm.add("Set routing for an element."));
342                 }
343             }, parameter -> {
344                 if (parameter != null)
345                     ExceptionUtils.logError(parameter);
346             });
347         }
348
349         @Override
350         public void widgetDefaultSelected(SelectionEvent e) {
351             widgetSelected(e);
352         }
353
354         @Override
355         public void widgetSelected(SelectionEvent e) {
356             run();
357         }
358
359     }
360
361 }