1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2016 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 * Semantum Oy - JSON plain text input support
\r
12 *******************************************************************************/
\r
13 package org.simantics.charts.editor;
\r
15 import java.awt.datatransfer.DataFlavor;
\r
16 import java.awt.datatransfer.Transferable;
\r
17 import java.awt.datatransfer.UnsupportedFlavorException;
\r
18 import java.awt.dnd.DnDConstants;
\r
19 import java.awt.dnd.DropTargetDragEvent;
\r
20 import java.awt.dnd.DropTargetDropEvent;
\r
21 import java.awt.dnd.DropTargetEvent;
\r
22 import java.io.IOException;
\r
23 import java.io.InputStream;
\r
24 import java.nio.charset.Charset;
\r
25 import java.util.ArrayList;
\r
26 import java.util.Collection;
\r
27 import java.util.Collections;
\r
28 import java.util.List;
\r
29 import java.util.Optional;
\r
30 import java.util.stream.Collectors;
\r
32 import org.eclipse.jface.viewers.ISelection;
\r
33 import org.simantics.Simantics;
\r
34 import org.simantics.charts.internal.JsonUtils;
\r
35 import org.simantics.charts.query.AddChartItem;
\r
36 import org.simantics.charts.query.ChartItemDescriptor;
\r
37 import org.simantics.charts.ui.AddVariableToChartAction;
\r
38 import org.simantics.charts.ui.ChartDropActionFactory;
\r
39 import org.simantics.charts.ui.ChartVariable;
\r
40 import org.simantics.databoard.util.ObjectUtils;
\r
41 import org.simantics.db.ReadGraph;
\r
42 import org.simantics.db.Resource;
\r
43 import org.simantics.db.Session;
\r
44 import org.simantics.db.common.request.UnaryRead;
\r
45 import org.simantics.db.common.request.UniqueRead;
\r
46 import org.simantics.db.exception.DatabaseException;
\r
47 import org.simantics.db.layer0.SelectionHints;
\r
48 import org.simantics.db.layer0.request.PossibleModel;
\r
49 import org.simantics.db.layer0.variable.RVI;
\r
50 import org.simantics.db.layer0.variable.Variable;
\r
51 import org.simantics.db.layer0.variable.VariableReference;
\r
52 import org.simantics.db.layer0.variable.Variables;
\r
53 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
\r
54 import org.simantics.g2d.dnd.DragItem;
\r
55 import org.simantics.g2d.dnd.IDnDContext;
\r
56 import org.simantics.g2d.dnd.IDragItem;
\r
57 import org.simantics.g2d.dnd.IDropTargetParticipant;
\r
58 import org.simantics.modeling.ModelingResources;
\r
59 import org.simantics.modeling.PropertyVariables;
\r
60 import org.simantics.modeling.PropertyVariablesImpl;
\r
61 import org.simantics.modeling.utils.VariableReferences;
\r
62 import org.simantics.ui.dnd.LocalObjectTransfer;
\r
63 import org.simantics.ui.dnd.LocalObjectTransferable;
\r
64 import org.simantics.ui.selection.WorkbenchSelectionElement;
\r
65 import org.simantics.utils.FileUtils;
\r
66 import org.simantics.utils.ui.ErrorLogger;
\r
67 import org.simantics.utils.ui.ISelectionUtils;
\r
68 import org.simantics.utils.ui.dialogs.ShowMessage;
\r
71 * @author Tuukka Lehtonen
\r
73 public class SubscriptionDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant {
\r
75 private static class SubscriptionItemDragItem extends DragItem<ChartItemDescriptor> {
\r
76 public SubscriptionItemDragItem(ChartItemDescriptor obj) {
\r
81 private static class VariableReferenceDragItem extends DragItem<VariableReference> {
\r
82 public VariableReferenceDragItem(VariableReference obj) {
\r
90 public SubscriptionDropParticipant(Resource container) {
\r
91 this.container = container;
\r
93 model = Simantics.getSession().sync( new PossibleModel( container ) );
\r
94 } catch (DatabaseException e) {
\r
99 public void dragEnter(DropTargetDragEvent dtde, IDnDContext dp) {
\r
100 // The source cannot link, too bad
\r
101 if ((dtde.getSourceActions() & DnDConstants.ACTION_LINK) == 0) {
\r
106 // Ensure the content is usable
\r
107 if (dtde.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {
\r
108 dragEnterLocalObject(dtde, dp);
\r
109 } else if (dtde.isDataFlavorSupported(DataFlavor.getTextPlainUnicodeFlavor())) {
\r
110 dragEnterPlainText(dtde, dp);
\r
116 private void dragEnterLocalObject(DropTargetDragEvent dtde, IDnDContext dp) {
\r
118 Object data = dtde.getTransferable().getTransferData(LocalObjectTransferable.FLAVOR);
\r
119 data = LocalObjectTransfer.getTransfer().getObject();
\r
121 List<IDragItem> items = new ArrayList<>();
\r
122 Session session = Simantics.getSession();
\r
124 final List<Resource> resources = ISelectionUtils.getPossibleKeys(data, SelectionHints.KEY_MAIN, Resource.class);
\r
125 if (!resources.isEmpty()) {
\r
126 // Support SubscriptionItem drags
\r
127 items.addAll( session.syncRequest(new UniqueRead<List<IDragItem>>() {
\r
129 public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
\r
130 List<IDragItem> result = new ArrayList<>();
\r
131 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
132 Resource targetModel = graph.syncRequest(new PossibleModel(container));
\r
133 if (targetModel != null) {
\r
134 for (Resource r : resources) {
\r
135 if (graph.isInstanceOf(r, MOD.Subscription_Item)) {
\r
136 Resource model = graph.syncRequest(new PossibleModel(r));
\r
137 if (ObjectUtils.objectEquals(targetModel, model))
\r
138 result.add( new SubscriptionItemDragItem( AddChartItem.createDescriptor(graph, r) ) );
\r
147 if(data instanceof RVI) {
\r
149 VariableReferenceDragItem vrdi = new VariableReferenceDragItem(session.sync(new UnaryRead<RVI, VariableReference>((RVI)data) {
\r
151 public VariableReference perform(ReadGraph graph) throws DatabaseException {
\r
152 return new VariableReference(parameter, Variables.getDatatype(graph, model, parameter), null);
\r
158 // Variable/PropertyVariable are mutually exclusive
\r
159 List<IDragItem> varItems = null;
\r
161 // 1st try Variable
\r
162 final List<Variable> vars2 = ISelectionUtils.getPossibleKeys(data, SelectionHints.KEY_MAIN, Variable.class);
\r
163 if (!vars2.isEmpty()) {
\r
164 varItems = session.syncRequest( new UniqueRead<List<IDragItem>>() {
\r
166 public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
\r
167 return toDragItems( graph.syncRequest(VariableReferences.variablesToReferences(model, vars2)) );
\r
171 if (varItems == null || varItems.isEmpty()) {
\r
172 // Try legacy PropertyVariables
\r
173 final List<PropertyVariables> vars = ISelectionUtils.getPossibleKeys(data, SelectionHints.KEY_MAIN, PropertyVariables.class);
\r
174 if (!vars.isEmpty()) {
\r
175 varItems = session.syncRequest( new UniqueRead<List<IDragItem>>() {
\r
177 public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
\r
178 List<PropertyVariables> vars2 = PropertyVariablesImpl.resolve(graph, vars);
\r
179 return toDragItems( graph.syncRequest(VariableReferences.toReferences(model, vars2)) );
\r
184 if (varItems != null)
\r
185 items.addAll(varItems);
\r
187 // Try WorkbenchSelectionElement
\r
188 if (data instanceof ISelection) {
\r
189 final List<WorkbenchSelectionElement> wses = ISelectionUtils.filterSelection((ISelection)data, WorkbenchSelectionElement.class);
\r
190 if (!wses.isEmpty()) {
\r
191 items.addAll( session.syncRequest( new UniqueRead<List<IDragItem>>() {
\r
193 public List<IDragItem> perform(ReadGraph graph) throws DatabaseException {
\r
194 List<Variable> wsevars = new ArrayList<>();
\r
195 ChartVariable av = new ChartVariable(graph);
\r
196 for(WorkbenchSelectionElement wse : wses) {
\r
197 Variable v = wse.getContent(av);
\r
202 return toDragItems( graph.syncRequest(VariableReferences.variablesToReferences(model, wsevars)) );
\r
209 if (items.isEmpty()) {
\r
212 // Accept, make sure it is Link
\r
213 for (IDragItem i : items)
\r
215 dtde.acceptDrag( DnDConstants.ACTION_LINK );
\r
217 } catch (UnsupportedFlavorException e) {
\r
218 throw new RuntimeException(e);
\r
219 } catch (IOException e) {
\r
220 ErrorLogger.defaultLogError(e);
\r
222 } catch (DatabaseException e) {
\r
223 ErrorLogger.defaultLogError(e);
\r
228 private void dragEnterPlainText(DropTargetDragEvent dtde, IDnDContext dp) {
\r
230 DataFlavor flavor = DataFlavor.getTextPlainUnicodeFlavor();
\r
231 String flavorCharset = flavor.getParameter("charset");
\r
232 Transferable t = dtde.getTransferable();
\r
233 InputStream in = (InputStream) t.getTransferData(flavor);
\r
234 String data = FileUtils.getContents(in, Charset.forName(flavorCharset));
\r
236 List<IDragItem> items = new ArrayList<>();
\r
237 Session session = Simantics.getSession();
\r
238 Optional<Variable> v = JsonUtils.tryParseJsonPropertyVariable(session, data);
\r
239 if (v.isPresent()) {
\r
240 items.addAll( toDragItems( session.syncRequest(VariableReferences.variablesToReferences(model, Collections.singletonList(v.get()))) ) );
\r
243 if (items.isEmpty()) {
\r
246 // Accept, make sure it is Link
\r
247 for (IDragItem i : items)
\r
249 dtde.acceptDrag( DnDConstants.ACTION_LINK );
\r
251 } catch (UnsupportedFlavorException e) {
\r
252 throw new RuntimeException(e);
\r
253 } catch (IOException e) {
\r
254 ErrorLogger.defaultLogError(e);
\r
256 } catch (DatabaseException e) {
\r
257 ErrorLogger.defaultLogError(e);
\r
263 public void dragExit(DropTargetEvent dte, IDnDContext dp) {
\r
264 for (IDragItem i : dp.getItemsByClass(SubscriptionItemDragItem.class))
\r
266 for (IDragItem i : dp.getItemsByClass(VariableReferenceDragItem.class))
\r
271 public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) {
\r
275 public void drop(DropTargetDropEvent dtde, IDnDContext dp) {
\r
276 // Subscription Item
\r
277 Collection<SubscriptionItemDragItem> subs = dp.getItemsByClass(SubscriptionItemDragItem.class);
\r
278 if (!subs.isEmpty()) {
\r
279 ChartDropActionFactory.addPlots(container,
\r
280 subs.stream().map(DragItem::getObject).collect(Collectors.toList()),
\r
281 Collections.<Resource>emptySet()).run();
\r
282 dtde.dropComplete(true);
\r
286 // Variable Reference
\r
287 Collection<VariableReferenceDragItem> vrdis = dp.getItemsByClass(VariableReferenceDragItem.class);
\r
288 if (!vrdis.isEmpty()) {
\r
290 new AddVariableToChartAction( container, null,
\r
291 vrdis.stream().map(DragItem::getObject).collect(Collectors.toList()) )
\r
293 dtde.dropComplete(true);
\r
294 } catch (DatabaseException e) {
\r
295 ShowMessage.showError(e.getClass().getName(), e.getMessage());
\r
296 dtde.dropComplete(true);
\r
305 public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) {
\r
306 dtde.acceptDrag( DnDConstants.ACTION_LINK );
\r
310 public int getAllowedOps() {
\r
311 return DnDConstants.ACTION_LINK;
\r
314 private static List<IDragItem> toDragItems(Collection<VariableReference> references) {
\r
315 return references.stream().map(VariableReferenceDragItem::new).collect(Collectors.toList());
\r
319 public double getPriority() {
\r