]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser/handlers/StandardCopyHandler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / modelBrowser / handlers / StandardCopyHandler.java
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
7  *\r
8  * Contributors:\r
9  *     VTT Technical Research Centre of Finland - initial API and implementation\r
10  *******************************************************************************/\r
11 package org.simantics.modeling.ui.modelBrowser.handlers;\r
12 \r
13 import gnu.trove.set.hash.THashSet;\r
14 \r
15 import java.util.Collections;\r
16 import java.util.List;\r
17 import java.util.Set;\r
18 \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
55 \r
56 public class StandardCopyHandler extends AbstractHandler {\r
57 \r
58     private static IStatusLineManager status;\r
59 \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
69     }\r
70 \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
78                         }\r
79                 }\r
80         }\r
81         return false;\r
82     }\r
83     \r
84     @Override\r
85     public Object execute(ExecutionEvent event) throws ExecutionException {\r
86         \r
87         status = WorkbenchUtils.getStatusLine( HandlerUtil.getActiveSite(event) );\r
88         ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();\r
89         \r
90         // If the selection is plain text copy it into system clipboard and be happy\r
91         if(copyText(selection)) return null;\r
92 \r
93         formatSelectionToClipboardText(event);\r
94 \r
95         final Resource[] rs = ResourceAdaptionUtils.toResources(selection);\r
96         copyResourcesToClipboard(rs, selection);\r
97         return null;\r
98     }\r
99     \r
100     public static String copyResourcesToClipboard(final Resource[] rs, ISelection selection) {\r
101         \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
109                 }\r
110                 Simantics.setClipboard(builder);\r
111                 setCopyMessage(builder.getContents().size(), "variable");\r
112                 return null;\r
113             }\r
114             setCopyMessage(0, "");\r
115             return null;\r
116         }\r
117 \r
118         try {\r
119             final SimanticsClipboardImpl builder = new SimanticsClipboardImpl();\r
120             Simantics.getSession().syncRequest(new ReadRequest() {\r
121                 @Override\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
126                     }\r
127                 }\r
128             });\r
129             Simantics.setClipboard(builder);\r
130             setCopyMessage(builder.getContents().size(), "resource");\r
131         } catch (DatabaseException e) {\r
132             Logger.defaultLogError(e);\r
133         }\r
134 \r
135         return null;\r
136     }\r
137 \r
138     private static void setCopyMessage(int count, String elementName) {\r
139         if (count > 1)\r
140             setStatus("Copied " + count + " " + elementName + "s to clipboard");\r
141         else if (count == 1)\r
142             setStatus("Copied " + elementName + " to clipboard");\r
143         else\r
144             setStatus("Nothing to copy.");\r
145     }\r
146 \r
147     private static void setStatus(String message) {\r
148         if (status != null)\r
149             status.setMessage(message);\r
150     }\r
151 \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
155         if (tree == null)\r
156             return false;\r
157 \r
158         TreeItem[] selection = tree.getSelection();\r
159         if (selection.length == 0)\r
160             return false;\r
161 \r
162         StringBuilder sb = format(selection, new StringBuilder());\r
163         if (sb.length() > 0) {\r
164             setSystemClipboardText(sb.toString());\r
165             return true;\r
166         }\r
167         return false;\r
168     }\r
169 \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
173             items.add(item);\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
178                 sb.append('\t');\r
179             boolean first = true;\r
180             for (int c = 0; c < cc; ++c) {\r
181                 String ct = item.getText(c);\r
182                 if (!first) {\r
183                     sb.append('\t');\r
184                 }\r
185                 first = false;\r
186                 sb.append(ct);\r
187             }\r
188             sb.append('\n');\r
189         }\r
190         return sb;\r
191     }\r
192 \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
196             if (p == null)\r
197                 return 0;\r
198             if (items.contains(p))\r
199                 return i;\r
200         }\r
201     }\r
202 \r
203     private static Tree tryGetExplorer(Control control) {\r
204         return SWTUtils.tryGetObject(control, new ControlFilter<Tree>() {\r
205             @Override\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
211                 return null;\r
212             }\r
213         });\r
214     }\r
215 \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
220     }\r
221 \r
222 }\r