/******************************************************************************* * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.modeling.ui.modelBrowser.handlers; import gnu.trove.set.hash.THashSet; import java.util.Collections; import java.util.List; import java.util.Set; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.HandlerUtil; import org.simantics.Simantics; import org.simantics.browsing.ui.BuiltinKeys; import org.simantics.browsing.ui.GraphExplorer; import org.simantics.browsing.ui.NodeContext; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.SelectionHints; import org.simantics.db.layer0.adapter.CopyHandler; import org.simantics.db.layer0.util.ClipboardUtils; import org.simantics.db.layer0.util.SimanticsClipboardImpl; import org.simantics.db.layer0.variable.Variable; import org.simantics.ui.utils.ResourceAdaptionUtils; import org.simantics.utils.datastructures.hints.IHintContext; import org.simantics.utils.ui.ISelectionUtils; import org.simantics.utils.ui.SWTUtils; import org.simantics.utils.ui.SWTUtils.ControlFilter; import org.simantics.utils.ui.workbench.WorkbenchUtils; public class StandardCopyHandler extends AbstractHandler { private static IStatusLineManager status; private static List getVariables(ISelection selection) { NodeContext context = ISelectionUtils.getSinglePossibleKey(selection, SelectionHints.KEY_MAIN, NodeContext.class); if(context == null) return Collections.emptyList(); Object input = context.getConstant(BuiltinKeys.INPUT); IHintContext hints = input instanceof IHintContext ? (IHintContext) input : null; if(hints == null) return Collections.emptyList(); Variable var = hints.getHint(SelectionHints.KEY_SELECTION_PROPERTY); if(var == null) return Collections.emptyList(); else return Collections.singletonList(var); } private boolean copyText(ISelection selection) { if(selection instanceof StructuredSelection) { StructuredSelection sel = (StructuredSelection)selection; if(sel.size() == 1) { Object element = sel.getFirstElement(); if(element instanceof String) { setSystemClipboardText((String) element); } } } return false; } @Override public Object execute(ExecutionEvent event) throws ExecutionException { status = WorkbenchUtils.getStatusLine( HandlerUtil.getActiveSite(event) ); ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); // If the selection is plain text copy it into system clipboard and be happy if(copyText(selection)) return null; formatSelectionToClipboardText(event); final Resource[] rs = ResourceAdaptionUtils.toResources(selection); copyResourcesToClipboard(rs, selection); return null; } public static String copyResourcesToClipboard(final Resource[] rs, ISelection selection) { if(rs == null || rs.length == 0) { // This support was added for copying of properties (variables) final List variables = getVariables(selection); if(!variables.isEmpty()) { final SimanticsClipboardImpl builder = new SimanticsClipboardImpl(); for(Variable var : variables) { builder.addContent(Collections.singleton(ClipboardUtils.createVariable(Simantics.getSession(), var))); } Simantics.setClipboard(builder); setCopyMessage(builder.getContents().size(), "variable"); return null; } setCopyMessage(0, ""); return null; } try { final SimanticsClipboardImpl builder = new SimanticsClipboardImpl(); Simantics.getSession().syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { for (Resource r : rs) { CopyHandler handler = graph.adapt(r, CopyHandler.class); handler.copyToClipboard(graph, builder); } } }); Simantics.setClipboard(builder); setCopyMessage(builder.getContents().size(), "resource"); } catch (DatabaseException e) { Logger.defaultLogError(e); } return null; } private static void setCopyMessage(int count, String elementName) { if (count > 1) setStatus("Copied " + count + " " + elementName + "s to clipboard"); else if (count == 1) setStatus("Copied " + elementName + " to clipboard"); else setStatus("Nothing to copy."); } private static void setStatus(String message) { if (status != null) status.setMessage(message); } private boolean formatSelectionToClipboardText(ExecutionEvent event) { Shell shell = HandlerUtil.getActiveShell(event); Tree tree = shell == null ? null : tryGetExplorer(shell.getDisplay().getFocusControl()); if (tree == null) return false; TreeItem[] selection = tree.getSelection(); if (selection.length == 0) return false; StringBuilder sb = format(selection, new StringBuilder()); if (sb.length() > 0) { setSystemClipboardText(sb.toString()); return true; } return false; } private static StringBuilder format(TreeItem[] selection, StringBuilder sb) { Set items = new THashSet(selection.length); for (TreeItem item : selection) items.add(item); for (TreeItem item : selection) { int cc = item.getParent().getColumnCount(); int indent = indentLevel(item, items); for (int i = 0; i < indent; ++i) sb.append('\t'); boolean first = true; for (int c = 0; c < cc; ++c) { String ct = item.getText(c); if (!first) { sb.append('\t'); } first = false; sb.append(ct); } sb.append('\n'); } return sb; } private static int indentLevel(TreeItem item, Set items) { TreeItem p = item.getParentItem(); for (int i = 1; ; p = p.getParentItem()) { if (p == null) return 0; if (items.contains(p)) return i; } } private static Tree tryGetExplorer(Control control) { return SWTUtils.tryGetObject(control, new ControlFilter() { @Override public Tree accept(Control control) { if (!control.isDisposed() && control instanceof Tree && control.getData(GraphExplorer.KEY_GRAPH_EXPLORER) != null) return (Tree) control; return null; } }); } private static void setSystemClipboardText(String text) { Clipboard clipboard = new Clipboard(Display.getCurrent()); clipboard.setContents(new Object[]{ text }, new Transfer[] { TextTransfer.getInstance() }); clipboard.dispose(); } }