diff options
author | Uwe Stieber | 2015-06-25 07:46:08 +0000 |
---|---|---|
committer | Uwe Stieber | 2015-06-25 07:46:08 +0000 |
commit | f1f8ca416937b26507c799791727cb07cf132f3a (patch) | |
tree | ae768a838e00ebbc314d156d76f5da95d2240281 | |
parent | 4c5d3ab5fa55ddec1c5584ef56171f9e849b9e80 (diff) | |
download | org.eclipse.tcf-f1f8ca416937b26507c799791727cb07cf132f3a.tar.gz org.eclipse.tcf-f1f8ca416937b26507c799791727cb07cf132f3a.tar.xz org.eclipse.tcf-f1f8ca416937b26507c799791727cb07cf132f3a.zip |
Target Explorer: Fix file system explorer clipboard handling
4 files changed, 258 insertions, 57 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java index d2b186a04..e7145bdcb 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java @@ -11,66 +11,145 @@ package org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations; import java.beans.PropertyChangeEvent; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.core.runtime.Assert; import org.eclipse.swt.SWTException; import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Display; import org.eclipse.tcf.te.core.utils.PropertyChangeProvider; import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IFSTreeNode; +import org.eclipse.tcf.te.ui.swt.DisplayUtil; import org.eclipse.ui.PlatformUI; /** * The clip board to which copy or cut files/folders. */ public class FsClipboard extends PropertyChangeProvider { - // The constants to define the current operation type of the clip board. - private static final int NONE = -1; - private static final int CUT = 0; - private static final int COPY = 1; - // The operation type, CUT, COPY or NONE. - private int operation; - // The currently selected files/folders. - private List<IFSTreeNode> files; - private Clipboard clipboard; + /* default */ static class FsClipboardContent { + // The constants to define the current operation type of the clip board. + public static final int CUT = 0; + public static final int COPY = 1; + + // The operation type, CUT, COPY or NONE. + public final int operation; + // The currently selected files/folders. + public final List<IFSTreeNode> files; + + /** + * Constructor + */ + public FsClipboardContent(int operation, List<IFSTreeNode> files) { + Assert.isTrue(operation == CUT || operation == COPY); + this.operation = operation; + Assert.isNotNull(files); + this.files = files; + } + } + + /* default */ final Clipboard clipboard; /** * Create a clip board instance. */ public FsClipboard() { clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay()); - operation = NONE; } public boolean isCutOp() { - return operation == CUT; + final AtomicReference<Object> object = new AtomicReference<Object>(); + + Runnable runnable = new Runnable() { + @Override + public void run() { + object.set(clipboard.getContents(FsClipboardTransfer.getInstance())); + } + }; + + exec(runnable); + + FsClipboardContent content = (FsClipboardContent) object.get(); + + return content != null && content.operation == FsClipboardContent.CUT; } public boolean isCopyOp() { - return operation == COPY; + final AtomicReference<Object> object = new AtomicReference<Object>(); + + Runnable runnable = new Runnable() { + @Override + public void run() { + object.set(clipboard.getContents(FsClipboardTransfer.getInstance())); + } + }; + + exec(runnable); + + FsClipboardContent content = (FsClipboardContent) object.get(); + + return content != null && content.operation == FsClipboardContent.COPY; } public boolean isEmpty() { - return operation == NONE && (files == null || files.isEmpty()); + final AtomicReference<Object> object = new AtomicReference<Object>(); + + Runnable runnable = new Runnable() { + @Override + public void run() { + object.set(clipboard.getContents(FsClipboardTransfer.getInstance())); + } + }; + + exec(runnable); + + FsClipboardContent content = (FsClipboardContent) object.get(); + + return content == null || content.files.isEmpty(); } /** * Get the currently selected files/folders to operated. */ public List<IFSTreeNode> getFiles() { - return files; + final AtomicReference<Object> object = new AtomicReference<Object>(); + + Runnable runnable = new Runnable() { + @Override + public void run() { + object.set(clipboard.getContents(FsClipboardTransfer.getInstance())); + } + }; + + exec(runnable); + + FsClipboardContent content = (FsClipboardContent) object.get(); + + return content.files; } /** * Cut the specified files/folders to the clip board. */ public void cutFiles(List<IFSTreeNode> files) { - operation = CUT; - this.files = files; - PropertyChangeEvent event = new PropertyChangeEvent(this, "cut", null, null); //$NON-NLS-1$ - firePropertyChange(event); + Assert.isNotNull(files); + + final FsClipboardContent content = new FsClipboardContent(FsClipboardContent.CUT, files); + final FsClipboardTransfer transfer = FsClipboardTransfer.getInstance(); + transfer.setContent(content); + + Runnable runnable = new Runnable() { + @Override + public void run() { + clipboard.setContents(new Object[] { content }, new Transfer[] { transfer }); + + PropertyChangeEvent event = new PropertyChangeEvent(this, "cut", null, null); //$NON-NLS-1$ + firePropertyChange(event); + } + }; - clearSystemClipboard(); + exec(runnable); } /** @@ -79,70 +158,79 @@ public class FsClipboard extends PropertyChangeProvider { * @param files The file/folder nodes. */ public void copyFiles(List<IFSTreeNode> files) { - operation = COPY; - this.files = files; - PropertyChangeEvent event = new PropertyChangeEvent(this, "copy", null, null); //$NON-NLS-1$ - firePropertyChange(event); + Assert.isNotNull(files); + + final FsClipboardContent content = new FsClipboardContent(FsClipboardContent.COPY, files); + final FsClipboardTransfer transfer = FsClipboardTransfer.getInstance(); + transfer.setContent(content); + + Runnable runnable = new Runnable() { + @Override + public void run() { + clipboard.setContents(new Object[] { content }, new Transfer[] { transfer }); + + PropertyChangeEvent event = new PropertyChangeEvent(this, "copy", null, null); //$NON-NLS-1$ + firePropertyChange(event); + } + }; - clearSystemClipboard(); + exec(runnable); } /** * Clear the clip board. */ public void clear() { - operation = NONE; - this.files = null; - PropertyChangeEvent event = new PropertyChangeEvent(this, "clear", null, null); //$NON-NLS-1$ - firePropertyChange(event); + Runnable runnable = new Runnable() { + @Override + public void run() { + clipboard.clearContents(); - clearSystemClipboard(); + PropertyChangeEvent event = new PropertyChangeEvent(this, "clear", null, null); //$NON-NLS-1$ + firePropertyChange(event); + } + }; + + exec(runnable); } /** - * Make sure the system clip board is cleared in a UI thread. + * Executes the given runnable in the UI thread synchronously. + * + * @param runnable The runnable. Must not be <code>null</code>. */ - void clearSystemClipboard() { + private void exec(Runnable runnable) { + Assert.isNotNull(runnable); + if (Display.getCurrent() != null) { - clipboard.clearContents(); - } - else { - PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable(){ - @Override - public void run() { - clearSystemClipboard(); - }}); + runnable.run(); + } else { + DisplayUtil.safeSyncExec(runnable); } } /** - * Dispose the clipboard. + * Dispose the clip board. */ public void dispose() { - if(Display.getCurrent() != null) { - if (!clipboard.isDisposed()) { - try { - clipboard.dispose(); - } - catch (SWTException e) { + Runnable runnable = new Runnable() { + @Override + public void run() { + if (!clipboard.isDisposed()) { + try { clipboard.dispose(); } catch (SWTException e) {} } } - } - else { - PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable(){ - @Override - public void run() { - dispose(); - }}); - } + }; + + exec(runnable); } /** - * Get the system clipboard. + * Get the system clip board. * - * @return The system clipboard. + * @return The system clip board. */ - public Clipboard getSystemClipboard() { + public final Clipboard getSystemClipboard() { return clipboard; } } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboardTransfer.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboardTransfer.java new file mode 100644 index 000000000..799c06a43 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboardTransfer.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2015 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.swt.dnd.ByteArrayTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * Internal clip board transfer implementation used by the file system clip board. + */ +/* default */ class FsClipboardTransfer extends ByteArrayTransfer { + + private static final String TYPE_NAME= "fs-clipboard-transfer-format" + Long.toString(System.currentTimeMillis()); //$NON-NLS-1$; + private static final int TYPEID= registerType(TYPE_NAME); + + private FsClipboard.FsClipboardContent content; + + private static class LazyInstance { + public static FsClipboardTransfer instance = new FsClipboardTransfer(); + } + + /** + * Constructor + */ + /* default */ FsClipboardTransfer() { + } + + /** + * Returns the singleton. + */ + public static FsClipboardTransfer getInstance() { + return LazyInstance.instance; + } + + /** + * Returns the transfer data. + * + * @return The transfer data or <code>null</code>. + */ + public FsClipboard.FsClipboardContent getContent() { + return content; + } + + /** + * Sets the transfer data. + * + * @param content The transfer data or <code>null</code>. + */ + public void setContent(FsClipboard.FsClipboardContent content) { + this.content = content; + } + + /* (non-Javadoc) + * @see org.eclipse.swt.dnd.Transfer#getTypeIds() + */ + @Override + protected int[] getTypeIds() { + return new int[] {TYPEID}; + } + + /* (non-Javadoc) + * @see org.eclipse.swt.dnd.Transfer#getTypeNames() + */ + @Override + protected String[] getTypeNames() { + return new String[] {TYPE_NAME}; + } + + /* (non-Javadoc) + * @see org.eclipse.swt.dnd.Transfer#javaToNative(java.lang.Object, org.eclipse.swt.dnd.TransferData) + */ + @Override + protected void javaToNative(Object object, TransferData transferData) { + byte[] check= TYPE_NAME.getBytes(); + super.javaToNative(check, transferData); + } + + /* (non-Javadoc) + * @see org.eclipse.swt.dnd.Transfer#nativeToJava(org.eclipse.swt.dnd.TransferData) + */ + @Override + protected Object nativeToJava(TransferData transferData) { + Object result= super.nativeToJava(transferData); + if (isInvalidNativeType(result)) { + UIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), Messages.FsClipboardTransfer_errorMessage)); + } + return content; + } + /** + * Tests whether native drop data matches this transfer type. + * + * @param result result of converting the native drop data to Java + * @return true if the native drop data does not match this transfer type. + * false otherwise. + */ + private boolean isInvalidNativeType(Object result) { + return !(result instanceof byte[]) || !TYPE_NAME.equals(new String((byte[])result)); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.java index 9250f3c5c..464b24eb7 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.java @@ -254,4 +254,5 @@ public class Messages extends NLS { public static String ContentProvider_notConnected; public static String UiExecutor_errorRunningOperation; + public static String FsClipboardTransfer_errorMessage; } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.properties index 07046839b..b3feec316 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.properties +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/nls/Messages.properties @@ -175,3 +175,5 @@ TreeViewerSearchDialog_BtnPreciseText=Precise matching ContentProvider_notConnected=Please connect to see the file system on the target. UiExecutor_errorRunningOperation=Operation completed with errors + +FsClipboardTransfer_errorMessage=Received wrong transfer data |