1 /*******************************************************************************
2 * Copyright (c) 2007, 2017 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 * Semantum Oy - JSON plain text input support, #7313
12 *******************************************************************************/
13 package org.simantics.charts.editor;
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;
32 import org.eclipse.jface.viewers.ISelection;
33 import org.simantics.Simantics;
34 import org.simantics.charts.internal.JsonUtils;
35 import org.simantics.charts.internal.VariableUtils;
36 import org.simantics.charts.query.AddChartItem;
37 import org.simantics.charts.query.ChartItemDescriptor;
38 import org.simantics.charts.ui.AddVariableToChartAction;
39 import org.simantics.charts.ui.ChartDropActionFactory;
40 import org.simantics.charts.ui.ChartVariable;
41 import org.simantics.databoard.util.ObjectUtils;
42 import org.simantics.db.ReadGraph;
43 import org.simantics.db.Resource;
44 import org.simantics.db.Session;
45 import org.simantics.db.common.request.UnaryRead;
46 import org.simantics.db.common.request.UniqueRead;
47 import org.simantics.db.exception.DatabaseException;
48 import org.simantics.db.layer0.SelectionHints;
49 import org.simantics.db.layer0.request.PossibleModel;
50 import org.simantics.db.layer0.variable.RVI;
51 import org.simantics.db.layer0.variable.Variable;
52 import org.simantics.db.layer0.variable.VariableReference;
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;
71 * @author Tuukka Lehtonen
73 public class SubscriptionDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant {
75 private static class SubscriptionItemDragItem extends DragItem<ChartItemDescriptor> {
76 public SubscriptionItemDragItem(ChartItemDescriptor obj) {
81 private static class VariableReferenceDragItem extends DragItem<VariableReference> {
82 public VariableReferenceDragItem(VariableReference obj) {
90 public SubscriptionDropParticipant(Resource container) {
91 this.container = container;
93 model = Simantics.getSession().sync( new PossibleModel( container ) );
94 } catch (DatabaseException e) {
99 public void dragEnter(DropTargetDragEvent dtde, IDnDContext dp) {
100 // The source cannot link, too bad
101 if ((dtde.getSourceActions() & DnDConstants.ACTION_LINK) == 0) {
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);
116 private void dragEnterLocalObject(DropTargetDragEvent dtde, IDnDContext dp) {
118 Object data = dtde.getTransferable().getTransferData(LocalObjectTransferable.FLAVOR);
119 data = LocalObjectTransfer.getTransfer().getObject();
121 List<IDragItem> items = new ArrayList<>();
122 Session session = Simantics.getSession();
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>>() {
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) ) );
147 if(data instanceof RVI) {
149 VariableReferenceDragItem vrdi = new VariableReferenceDragItem(session.sync(new UnaryRead<RVI, VariableReference>((RVI)data) {
151 public VariableReference perform(ReadGraph graph) throws DatabaseException {
152 return new VariableReference(parameter, VariableUtils.getDatatype(graph, model, parameter), null);
158 // Variable/PropertyVariable are mutually exclusive
159 List<IDragItem> varItems = null;
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>>() {
166 public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
167 return toDragItems( graph.syncRequest(VariableReferences.variablesToReferences(model, vars2)) );
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>>() {
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)) );
184 if (varItems != null)
185 items.addAll(varItems);
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>>() {
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);
202 return toDragItems( graph.syncRequest(VariableReferences.variablesToReferences(model, wsevars)) );
209 if (items.isEmpty()) {
212 // Accept, make sure it is Link
213 for (IDragItem i : items)
215 dtde.acceptDrag( DnDConstants.ACTION_LINK );
217 } catch (UnsupportedFlavorException e) {
218 throw new RuntimeException(e);
219 } catch (IOException e) {
220 ErrorLogger.defaultLogError(e);
222 } catch (DatabaseException e) {
223 ErrorLogger.defaultLogError(e);
228 private void dragEnterPlainText(DropTargetDragEvent dtde, IDnDContext dp) {
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));
236 List<IDragItem> items = new ArrayList<>();
237 Session session = Simantics.getSession();
238 Optional<Variable> v = JsonUtils.tryParseJsonPropertyVariable(session, data);
240 items.addAll( toDragItems( session.syncRequest(VariableReferences.variablesToReferences(model, Collections.singletonList(v.get()))) ) );
243 if (items.isEmpty()) {
246 // Accept, make sure it is Link
247 for (IDragItem i : items)
249 dtde.acceptDrag( DnDConstants.ACTION_LINK );
251 } catch (UnsupportedFlavorException e) {
252 throw new RuntimeException(e);
253 } catch (IOException e) {
254 ErrorLogger.defaultLogError(e);
256 } catch (DatabaseException e) {
257 ErrorLogger.defaultLogError(e);
263 public void dragExit(DropTargetEvent dte, IDnDContext dp) {
264 for (IDragItem i : dp.getItemsByClass(SubscriptionItemDragItem.class))
266 for (IDragItem i : dp.getItemsByClass(VariableReferenceDragItem.class))
271 public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) {
275 public void drop(DropTargetDropEvent dtde, IDnDContext dp) {
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);
286 // Variable Reference
287 Collection<VariableReferenceDragItem> vrdis = dp.getItemsByClass(VariableReferenceDragItem.class);
288 if (!vrdis.isEmpty()) {
290 new AddVariableToChartAction( container, null,
291 vrdis.stream().map(DragItem::getObject).collect(Collectors.toList()) )
293 dtde.dropComplete(true);
294 } catch (DatabaseException e) {
295 ShowMessage.showError(e.getClass().getName(), e.getMessage());
296 dtde.dropComplete(true);
305 public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) {
306 dtde.acceptDrag( DnDConstants.ACTION_LINK );
310 public int getAllowedOps() {
311 return DnDConstants.ACTION_LINK;
314 private static List<IDragItem> toDragItems(Collection<VariableReference> references) {
315 return references.stream().map(VariableReferenceDragItem::new).collect(Collectors.toList());
319 public double getPriority() {