1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.modeling.ui.modelBrowser.handlers;
\r
13 import gnu.trove.set.hash.THashSet;
\r
15 import java.util.Collections;
\r
16 import java.util.List;
\r
17 import java.util.Set;
\r
19 import org.eclipse.core.commands.AbstractHandler;
\r
20 import org.eclipse.core.commands.ExecutionEvent;
\r
21 import org.eclipse.core.commands.ExecutionException;
\r
22 import org.eclipse.jface.action.IStatusLineManager;
\r
23 import org.eclipse.jface.viewers.ISelection;
\r
24 import org.eclipse.jface.viewers.StructuredSelection;
\r
25 import org.eclipse.swt.dnd.Clipboard;
\r
26 import org.eclipse.swt.dnd.TextTransfer;
\r
27 import org.eclipse.swt.dnd.Transfer;
\r
28 import org.eclipse.swt.widgets.Control;
\r
29 import org.eclipse.swt.widgets.Display;
\r
30 import org.eclipse.swt.widgets.Shell;
\r
31 import org.eclipse.swt.widgets.Tree;
\r
32 import org.eclipse.swt.widgets.TreeItem;
\r
33 import org.eclipse.ui.PlatformUI;
\r
34 import org.eclipse.ui.handlers.HandlerUtil;
\r
35 import org.simantics.Simantics;
\r
36 import org.simantics.browsing.ui.BuiltinKeys;
\r
37 import org.simantics.browsing.ui.GraphExplorer;
\r
38 import org.simantics.browsing.ui.NodeContext;
\r
39 import org.simantics.db.ReadGraph;
\r
40 import org.simantics.db.Resource;
\r
41 import org.simantics.db.common.request.ReadRequest;
\r
42 import org.simantics.db.common.utils.Logger;
\r
43 import org.simantics.db.exception.DatabaseException;
\r
44 import org.simantics.db.layer0.SelectionHints;
\r
45 import org.simantics.db.layer0.adapter.CopyHandler;
\r
46 import org.simantics.db.layer0.util.ClipboardUtils;
\r
47 import org.simantics.db.layer0.util.SimanticsClipboardImpl;
\r
48 import org.simantics.db.layer0.variable.Variable;
\r
49 import org.simantics.ui.utils.ResourceAdaptionUtils;
\r
50 import org.simantics.utils.datastructures.hints.IHintContext;
\r
51 import org.simantics.utils.ui.ISelectionUtils;
\r
52 import org.simantics.utils.ui.SWTUtils;
\r
53 import org.simantics.utils.ui.SWTUtils.ControlFilter;
\r
54 import org.simantics.utils.ui.workbench.WorkbenchUtils;
\r
56 public class StandardCopyHandler extends AbstractHandler {
\r
58 private static IStatusLineManager status;
\r
60 private static List<Variable> getVariables(ISelection selection) {
\r
61 NodeContext context = ISelectionUtils.getSinglePossibleKey(selection, SelectionHints.KEY_MAIN, NodeContext.class);
\r
62 if(context == null) return Collections.emptyList();
\r
63 Object input = context.getConstant(BuiltinKeys.INPUT);
\r
64 IHintContext hints = input instanceof IHintContext ? (IHintContext) input : null;
\r
65 if(hints == null) return Collections.emptyList();
\r
66 Variable var = hints.getHint(SelectionHints.KEY_SELECTION_PROPERTY);
\r
67 if(var == null) return Collections.emptyList();
\r
68 else return Collections.singletonList(var);
\r
71 private boolean copyText(ISelection selection) {
\r
72 if(selection instanceof StructuredSelection) {
\r
73 StructuredSelection sel = (StructuredSelection)selection;
\r
74 if(sel.size() == 1) {
\r
75 Object element = sel.getFirstElement();
\r
76 if(element instanceof String) {
\r
77 setSystemClipboardText((String) element);
\r
85 public Object execute(ExecutionEvent event) throws ExecutionException {
\r
87 status = WorkbenchUtils.getStatusLine( HandlerUtil.getActiveSite(event) );
\r
88 ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
\r
90 // If the selection is plain text copy it into system clipboard and be happy
\r
91 if(copyText(selection)) return null;
\r
93 formatSelectionToClipboardText(event);
\r
95 final Resource[] rs = ResourceAdaptionUtils.toResources(selection);
\r
96 copyResourcesToClipboard(rs, selection);
\r
100 public static String copyResourcesToClipboard(final Resource[] rs, ISelection selection) {
\r
102 if(rs == null || rs.length == 0) {
\r
103 // This support was added for copying of properties (variables)
\r
104 final List<Variable> variables = getVariables(selection);
\r
105 if(!variables.isEmpty()) {
\r
106 final SimanticsClipboardImpl builder = new SimanticsClipboardImpl();
\r
107 for(Variable var : variables) {
\r
108 builder.addContent(Collections.singleton(ClipboardUtils.createVariable(Simantics.getSession(), var)));
\r
110 Simantics.setClipboard(builder);
\r
111 setCopyMessage(builder.getContents().size(), "variable");
\r
114 setCopyMessage(0, "");
\r
119 final SimanticsClipboardImpl builder = new SimanticsClipboardImpl();
\r
120 Simantics.getSession().syncRequest(new ReadRequest() {
\r
122 public void run(ReadGraph graph) throws DatabaseException {
\r
123 for (Resource r : rs) {
\r
124 CopyHandler handler = graph.adapt(r, CopyHandler.class);
\r
125 handler.copyToClipboard(graph, builder);
\r
129 Simantics.setClipboard(builder);
\r
130 setCopyMessage(builder.getContents().size(), "resource");
\r
131 } catch (DatabaseException e) {
\r
132 Logger.defaultLogError(e);
\r
138 private static void setCopyMessage(int count, String elementName) {
\r
140 setStatus("Copied " + count + " " + elementName + "s to clipboard");
\r
141 else if (count == 1)
\r
142 setStatus("Copied " + elementName + " to clipboard");
\r
144 setStatus("Nothing to copy.");
\r
147 private static void setStatus(String message) {
\r
148 if (status != null)
\r
149 status.setMessage(message);
\r
152 private boolean formatSelectionToClipboardText(ExecutionEvent event) {
\r
153 Shell shell = HandlerUtil.getActiveShell(event);
\r
154 Tree tree = shell == null ? null : tryGetExplorer(shell.getDisplay().getFocusControl());
\r
158 TreeItem[] selection = tree.getSelection();
\r
159 if (selection.length == 0)
\r
162 StringBuilder sb = format(selection, new StringBuilder());
\r
163 if (sb.length() > 0) {
\r
164 setSystemClipboardText(sb.toString());
\r
170 private static StringBuilder format(TreeItem[] selection, StringBuilder sb) {
\r
171 Set<TreeItem> items = new THashSet<TreeItem>(selection.length);
\r
172 for (TreeItem item : selection)
\r
174 for (TreeItem item : selection) {
\r
175 int cc = item.getParent().getColumnCount();
\r
176 int indent = indentLevel(item, items);
\r
177 for (int i = 0; i < indent; ++i)
\r
179 boolean first = true;
\r
180 for (int c = 0; c < cc; ++c) {
\r
181 String ct = item.getText(c);
\r
193 private static int indentLevel(TreeItem item, Set<TreeItem> items) {
\r
194 TreeItem p = item.getParentItem();
\r
195 for (int i = 1; ; p = p.getParentItem()) {
\r
198 if (items.contains(p))
\r
203 private static Tree tryGetExplorer(Control control) {
\r
204 return SWTUtils.tryGetObject(control, new ControlFilter<Tree>() {
\r
206 public Tree accept(Control control) {
\r
207 if (!control.isDisposed()
\r
208 && control instanceof Tree
\r
209 && control.getData(GraphExplorer.KEY_GRAPH_EXPLORER) != null)
\r
210 return (Tree) control;
\r
216 private static void setSystemClipboardText(String text) {
\r
217 Clipboard clipboard = new Clipboard(Display.getCurrent());
\r
218 clipboard.setContents(new Object[]{ text }, new Transfer[] { TextTransfer.getInstance() });
\r
219 clipboard.dispose();
\r