]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.charts/src/org/simantics/charts/editor/SubscriptionDropParticipant.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.charts / src / org / simantics / charts / editor / SubscriptionDropParticipant.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2016 Association for Decentralized Information Management in
3  * 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  *     Semantum Oy - JSON plain text input support
12  *******************************************************************************/
13 package org.simantics.charts.editor;
14
15 import java.awt.datatransfer.DataFlavor;
16 import java.awt.datatransfer.Transferable;
17 import java.awt.datatransfer.UnsupportedFlavorException;
18 import java.awt.dnd.DnDConstants;
19 import java.awt.dnd.DropTargetDragEvent;
20 import java.awt.dnd.DropTargetDropEvent;
21 import java.awt.dnd.DropTargetEvent;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.nio.charset.Charset;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Optional;
30 import java.util.stream.Collectors;
31
32 import org.eclipse.jface.viewers.ISelection;
33 import org.simantics.Simantics;
34 import org.simantics.charts.internal.JsonUtils;
35 import org.simantics.charts.query.AddChartItem;
36 import org.simantics.charts.query.ChartItemDescriptor;
37 import org.simantics.charts.ui.AddVariableToChartAction;
38 import org.simantics.charts.ui.ChartDropActionFactory;
39 import org.simantics.charts.ui.ChartVariable;
40 import org.simantics.databoard.util.ObjectUtils;
41 import org.simantics.db.ReadGraph;
42 import org.simantics.db.Resource;
43 import org.simantics.db.Session;
44 import org.simantics.db.common.request.UnaryRead;
45 import org.simantics.db.common.request.UniqueRead;
46 import org.simantics.db.exception.DatabaseException;
47 import org.simantics.db.layer0.SelectionHints;
48 import org.simantics.db.layer0.request.PossibleModel;
49 import org.simantics.db.layer0.variable.RVI;
50 import org.simantics.db.layer0.variable.Variable;
51 import org.simantics.db.layer0.variable.VariableReference;
52 import org.simantics.db.layer0.variable.Variables;
53 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
54 import org.simantics.g2d.dnd.DragItem;
55 import org.simantics.g2d.dnd.IDnDContext;
56 import org.simantics.g2d.dnd.IDragItem;
57 import org.simantics.g2d.dnd.IDropTargetParticipant;
58 import org.simantics.modeling.ModelingResources;
59 import org.simantics.modeling.PropertyVariables;
60 import org.simantics.modeling.PropertyVariablesImpl;
61 import org.simantics.modeling.utils.VariableReferences;
62 import org.simantics.ui.dnd.LocalObjectTransfer;
63 import org.simantics.ui.dnd.LocalObjectTransferable;
64 import org.simantics.ui.selection.WorkbenchSelectionElement;
65 import org.simantics.utils.FileUtils;
66 import org.simantics.utils.ui.ErrorLogger;
67 import org.simantics.utils.ui.ISelectionUtils;
68 import org.simantics.utils.ui.dialogs.ShowMessage;
69
70 /**
71  * @author Tuukka Lehtonen
72  */
73 public class SubscriptionDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant { 
74
75     private static class SubscriptionItemDragItem extends DragItem<ChartItemDescriptor> {
76         public SubscriptionItemDragItem(ChartItemDescriptor obj) {
77             super(obj);
78         }
79     }
80
81     private static class VariableReferenceDragItem extends DragItem<VariableReference> {
82         public VariableReferenceDragItem(VariableReference obj) {
83             super(obj);
84         }
85     }
86     
87     Resource container;
88     Resource model;
89
90     public SubscriptionDropParticipant(Resource container) {
91         this.container = container;
92         try {
93                         model = Simantics.getSession().sync( new PossibleModel( container ) );
94                 } catch (DatabaseException e) {
95                 }
96     }
97
98     @Override
99     public void dragEnter(DropTargetDragEvent dtde, IDnDContext dp) {
100         // The source cannot link, too bad
101         if ((dtde.getSourceActions() & DnDConstants.ACTION_LINK) == 0) {
102             dtde.rejectDrag();
103             return;
104         }
105
106         // Ensure the content is usable
107         if (dtde.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {
108             dragEnterLocalObject(dtde, dp);
109         } else if (dtde.isDataFlavorSupported(DataFlavor.getTextPlainUnicodeFlavor())) {
110             dragEnterPlainText(dtde, dp);
111         } else {
112             dtde.rejectDrag();
113         }
114     }
115
116     private void dragEnterLocalObject(DropTargetDragEvent dtde, IDnDContext dp) {
117         try {
118             Object data = dtde.getTransferable().getTransferData(LocalObjectTransferable.FLAVOR);
119             data = LocalObjectTransfer.getTransfer().getObject();
120
121             List<IDragItem> items = new ArrayList<>();
122             Session session = Simantics.getSession();
123
124             final List<Resource> resources = ISelectionUtils.getPossibleKeys(data, SelectionHints.KEY_MAIN, Resource.class);
125             if (!resources.isEmpty()) {
126                 // Support SubscriptionItem drags
127                 items.addAll( session.syncRequest(new UniqueRead<List<IDragItem>>() {
128                     @Override
129                     public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
130                         List<IDragItem> result = new ArrayList<>();
131                         ModelingResources MOD = ModelingResources.getInstance(graph);
132                         Resource targetModel = graph.syncRequest(new PossibleModel(container));
133                         if (targetModel != null) {
134                             for (Resource r : resources) {
135                                 if (graph.isInstanceOf(r, MOD.Subscription_Item)) {
136                                     Resource model = graph.syncRequest(new PossibleModel(r));
137                                     if (ObjectUtils.objectEquals(targetModel, model))
138                                         result.add( new SubscriptionItemDragItem( AddChartItem.createDescriptor(graph, r) ) );
139                                 }
140                             }
141                         }
142                         return result;
143                     }
144                 }) );
145             }
146
147             if(data instanceof RVI) {
148
149                 VariableReferenceDragItem vrdi = new VariableReferenceDragItem(session.sync(new UnaryRead<RVI, VariableReference>((RVI)data) {
150                     @Override
151                     public VariableReference perform(ReadGraph graph) throws DatabaseException {
152                         return new VariableReference(parameter, Variables.getDatatype(graph, model, parameter), null);
153                     }
154                 }));
155                 items.add( vrdi );
156
157             } else {
158                 // Variable/PropertyVariable are mutually exclusive
159                 List<IDragItem> varItems = null;
160
161                 // 1st try Variable
162                 final List<Variable> vars2 = ISelectionUtils.getPossibleKeys(data, SelectionHints.KEY_MAIN, Variable.class);
163                 if (!vars2.isEmpty()) {
164                     varItems = session.syncRequest( new UniqueRead<List<IDragItem>>() {
165                         @Override
166                         public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
167                             return toDragItems( graph.syncRequest(VariableReferences.variablesToReferences(model, vars2)) );
168                         }
169                     } );
170                 }
171                 if (varItems == null || varItems.isEmpty()) {
172                     // Try legacy PropertyVariables
173                     final List<PropertyVariables> vars = ISelectionUtils.getPossibleKeys(data, SelectionHints.KEY_MAIN, PropertyVariables.class);
174                     if (!vars.isEmpty()) {
175                         varItems = session.syncRequest( new UniqueRead<List<IDragItem>>() {
176                             @Override
177                             public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
178                                 List<PropertyVariables> vars2 = PropertyVariablesImpl.resolve(graph, vars);
179                                 return toDragItems( graph.syncRequest(VariableReferences.toReferences(model, vars2)) );
180                             }
181                         } );
182                     }
183                 }
184                 if (varItems != null)
185                     items.addAll(varItems);
186
187                 // Try WorkbenchSelectionElement
188                 if (data instanceof ISelection) {
189                     final List<WorkbenchSelectionElement> wses = ISelectionUtils.filterSelection((ISelection)data, WorkbenchSelectionElement.class);
190                     if (!wses.isEmpty()) {
191                         items.addAll( session.syncRequest( new UniqueRead<List<IDragItem>>() {
192                             @Override
193                             public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
194                                 List<Variable> wsevars = new ArrayList<>();
195                                 ChartVariable av = new ChartVariable(graph);
196                                 for(WorkbenchSelectionElement wse : wses) {
197                                     Variable v = wse.getContent(av);
198                                     if(v != null) {
199                                         wsevars.add(v);
200                                     }
201                                 }
202                                 return toDragItems( graph.syncRequest(VariableReferences.variablesToReferences(model, wsevars)) );
203                             }
204                         } ) );
205                     }
206                 }
207             }
208
209             if (items.isEmpty()) {
210                 dtde.rejectDrag();
211             } else {
212                 // Accept, make sure it is Link
213                 for (IDragItem i : items)
214                     dp.add(i);
215                 dtde.acceptDrag( DnDConstants.ACTION_LINK );
216             }
217         } catch (UnsupportedFlavorException e) {
218             throw new RuntimeException(e);
219         } catch (IOException e) {
220             ErrorLogger.defaultLogError(e);
221             dtde.rejectDrag();
222         } catch (DatabaseException e) {
223             ErrorLogger.defaultLogError(e);
224             dtde.rejectDrag();
225         }
226     }
227
228     private void dragEnterPlainText(DropTargetDragEvent dtde, IDnDContext dp) {
229         try {
230             DataFlavor flavor = DataFlavor.getTextPlainUnicodeFlavor();
231             String flavorCharset = flavor.getParameter("charset");
232             Transferable t = dtde.getTransferable();
233             InputStream in = (InputStream) t.getTransferData(flavor);
234             String data = FileUtils.getContents(in, Charset.forName(flavorCharset));
235
236             List<IDragItem> items = new ArrayList<>();
237             Session session = Simantics.getSession();
238             Optional<Variable> v = JsonUtils.tryParseJsonPropertyVariable(session, data);
239             if (v.isPresent()) {
240                 items.addAll( toDragItems( session.syncRequest(VariableReferences.variablesToReferences(model, Collections.singletonList(v.get()))) ) );
241             }
242
243             if (items.isEmpty()) {
244                 dtde.rejectDrag();
245             } else {
246                 // Accept, make sure it is Link
247                 for (IDragItem i : items)
248                     dp.add(i);
249                 dtde.acceptDrag( DnDConstants.ACTION_LINK );
250             }
251         } catch (UnsupportedFlavorException e) {
252             throw new RuntimeException(e);
253         } catch (IOException e) {
254             ErrorLogger.defaultLogError(e);
255             dtde.rejectDrag();
256         } catch (DatabaseException e) {
257             ErrorLogger.defaultLogError(e);
258             dtde.rejectDrag();
259         }
260     }
261
262     @Override
263     public void dragExit(DropTargetEvent dte, IDnDContext dp) {
264         for (IDragItem i : dp.getItemsByClass(SubscriptionItemDragItem.class))
265             dp.remove(i);
266         for (IDragItem i : dp.getItemsByClass(VariableReferenceDragItem.class))
267             dp.remove(i);
268     }
269
270     @Override
271     public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) {
272     }
273
274     @Override
275     public void drop(DropTargetDropEvent dtde, IDnDContext dp) {
276         // Subscription Item
277         Collection<SubscriptionItemDragItem> subs = dp.getItemsByClass(SubscriptionItemDragItem.class);
278         if (!subs.isEmpty()) {
279             ChartDropActionFactory.addPlots(container,
280                     subs.stream().map(DragItem::getObject).collect(Collectors.toList()),
281                     Collections.<Resource>emptySet()).run();
282             dtde.dropComplete(true);
283             return;
284         }
285
286         // Variable Reference
287         Collection<VariableReferenceDragItem> vrdis = dp.getItemsByClass(VariableReferenceDragItem.class);
288         if (!vrdis.isEmpty()) {
289             try {
290                 new AddVariableToChartAction( container, null,
291                         vrdis.stream().map(DragItem::getObject).collect(Collectors.toList()) )
292                 .init().run();
293                     dtde.dropComplete(true);
294                         } catch (DatabaseException e) {
295                                 ShowMessage.showError(e.getClass().getName(), e.getMessage());
296                     dtde.dropComplete(true);
297                         }
298             return;
299         }
300
301         dtde.rejectDrop();
302     }
303
304     @Override
305     public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) {
306         dtde.acceptDrag( DnDConstants.ACTION_LINK );
307     }
308
309     @Override
310     public int getAllowedOps() {
311         return DnDConstants.ACTION_LINK;
312     }
313
314     private static List<IDragItem> toDragItems(Collection<VariableReference> references) {
315         return references.stream().map(VariableReferenceDragItem::new).collect(Collectors.toList());
316     }
317
318     @Override
319     public double getPriority() {
320         return 10.0;
321     }
322
323 }