Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java409
1 files changed, 409 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java
new file mode 100644
index 000000000..2a3d832de
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java
@@ -0,0 +1,409 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 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.dnd;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tcf.te.runtime.callback.Callback;
+import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation;
+import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IRuntimeModel;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCopy;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpMove;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefresh;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload;
+import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager;
+import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode;
+import org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager;
+import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin;
+import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts;
+import org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers.MoveCopyCallback;
+import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor;
+import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages;
+import org.eclipse.ui.PlatformUI;
+/**
+ * Common DnD operations shared by File Explorer and Target Explorer.
+ */
+public class CommonDnD implements IConfirmCallback {
+
+ /**
+ * If the current selection is draggable.
+ *
+ * @param selection The currently selected nodes.
+ * @return true if it is draggable.
+ */
+ public boolean isDraggable(IStructuredSelection selection) {
+ if (selection.isEmpty()) {
+ return false;
+ }
+ Object[] objects = selection.toArray();
+ for (Object object : objects) {
+ if (!isDraggableObject(object)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * If the specified object is a draggable element.
+ *
+ * @param object The object to be dragged.
+ * @return true if it is draggable.
+ */
+ private boolean isDraggableObject(Object object) {
+ if (object instanceof FSTreeNode) {
+ FSTreeNode node = (FSTreeNode) object;
+ return !node.isRoot() && (node.isWindowsNode() && !node.isReadOnly() || !node.isWindowsNode() && node.isWritable());
+ }
+ return false;
+ }
+
+ /**
+ * Perform the drop operation over dragged files to the specified target folder.
+ *
+ * @param viewer the tree viewer to be refreshed after dragging.
+ * @param files The files being dropped.
+ * @param operations the current dnd operations.
+ * @param target the target folder the files to be dropped to.
+ * @return true if the dropping is successful.
+ */
+ public boolean dropFiles(TreeViewer viewer, String[] files, int operations, FSTreeNode target) {
+ IOpExecutor executor = null;
+ if ((operations & DND.DROP_MOVE) != 0) {
+ String question;
+ if (files.length == 1) {
+ question = NLS.bind(Messages.FSDropTargetListener_MovingWarningSingle, files[0]);
+ }
+ else {
+ question = NLS.bind(Messages.FSDropTargetListener_MovingWarningMultiple, Integer.valueOf(files.length));
+ }
+ Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ if (MessageDialog.openQuestion(parent, Messages.FSDropTargetListener_ConfirmMoveTitle, question)) {
+ ICallback callback = getMoveCallback(viewer, files, target);
+ executor = new UiExecutor(callback);
+ }
+ }
+ else if ((operations & DND.DROP_COPY) != 0) {
+ ICallback callback = getCopyCallback(viewer, files, target);
+ executor = new UiExecutor(callback);
+ }
+ if (executor != null) {
+ IStatus status = executor.execute(new OpUpload(files, target, this));
+ return status != null && status.isOK();
+ }
+ return false;
+ }
+
+ /**
+ * Get the callback that refresh and select the files being dragged when the dragging gesture is
+ * copying.
+ *
+ * @param viewer the tree viewer to be refreshed after dragging.
+ * @param files The files being dragged.
+ * @param target The target folder to drag the files to.
+ * @return callback that handles refreshing and selection.
+ */
+ private ICallback getCopyCallback(final TreeViewer viewer, final String[] files, final FSTreeNode target) {
+ return new Callback() {
+ @Override
+ protected void internalDone(Object caller, IStatus status) {
+ if (status.isOK()) {
+ IOpExecutor executor = new JobExecutor(getSelectionCallback(viewer, files, target));
+ executor.execute(new OpRefresh(target));
+ }
+ }
+ };
+ }
+
+ /**
+ * Get the callback that delete the dragged source files, refresh and select the files being
+ * dragged when the dragging gesture is moving.
+ *
+ * @param viewer the tree viewer to be refreshed after dragging.
+ * @param files The files being dragged.
+ * @param target The target folder to drag the files to.
+ * @return callback that handles deletion, refreshing and selection.
+ */
+ private ICallback getMoveCallback(final TreeViewer viewer, final String[] files, final FSTreeNode target) {
+ return new Callback() {
+ @Override
+ protected void internalDone(Object caller, IStatus status) {
+ if (status.isOK()) {
+ boolean successful = true;
+ for (String path : files) {
+ File file = new File(path);
+ successful &= file.delete();
+ }
+ if (successful) {
+ IRuntimeModel model = ModelManager.getRuntimeModel(target.peerNode);
+ IOpExecutor executor = new JobExecutor(getSelectionCallback(viewer, files, target));
+ executor.execute(new OpRefresh(model.getRoot()));
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * Get the callback that refresh the files being dragged after moving or copying.
+ *
+ * @param viewer the tree viewer to be refreshed after dragging.
+ * @param paths The paths of the files being dragged.
+ * @param target The target folder to drag the files to.
+ * @return callback that handles refreshing and selection.
+ */
+ ICallback getSelectionCallback(final TreeViewer viewer, final String[] paths, final FSTreeNode target) {
+ return new Callback() {
+ @Override
+ protected void internalDone(Object caller, IStatus status) {
+ if(status.isOK()) {
+ List<FSTreeNode> nodes = new ArrayList<FSTreeNode>();
+ List<FSTreeNode> children = target.getChildren();
+ for (String path : paths) {
+ File file = new File(path);
+ String name = file.getName();
+ for (FSTreeNode child : children) {
+ if (name.equals(child.name)) {
+ nodes.add(child);
+ break;
+ }
+ }
+ }
+ if (viewer != null) {
+ updateViewer(viewer, target, nodes);
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * Update the tree viewer after DnD and select the nodes that being dropped.
+ *
+ * @param viewer The tree viewer in which the DnD takes place.
+ * @param target The target node that the drop operation happens.
+ * @param nodes The nodes that are being dropped.
+ */
+ protected void updateViewer(final TreeViewer viewer, final FSTreeNode target, final List<FSTreeNode> nodes) {
+ if (Display.getCurrent() != null) {
+ viewer.refresh(target);
+ IStructuredSelection selection = new StructuredSelection(nodes.toArray());
+ viewer.setSelection(selection, true);
+ }
+ else {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable(){
+ @Override
+ public void run() {
+ updateViewer(viewer, target, nodes);
+ }});
+ }
+ }
+
+ /**
+ * Perform the drop operation over dragged selection.
+ *
+ * @param aTarget the target Object to be moved to.
+ * @param operations the current dnd operations.
+ * @param selection The local selection being dropped.
+ * @return true if the dropping is successful.
+ */
+ public boolean dropLocalSelection(FSTreeNode target, int operations, IStructuredSelection selection) {
+ List<FSTreeNode> nodes = selection.toList();
+ IOpExecutor executor = null;
+ IOperation operation = null;
+ if ((operations & DND.DROP_MOVE) != 0) {
+ operation = new OpMove(nodes, target, new MoveCopyCallback());
+ executor = new UiExecutor(new Callback(){
+ @Override
+ protected void internalDone(Object caller, IStatus status) {
+ UIPlugin.getClipboard().clear();
+ }
+ });
+ }
+ else if ((operations & DND.DROP_COPY) != 0) {
+ FSTreeNode dest = getCopyDestination(target, nodes);
+ boolean cpPerm = UIPlugin.isCopyPermission();
+ boolean cpOwn = UIPlugin.isCopyOwnership();
+ operation = new OpCopy(nodes, dest, cpPerm, cpOwn, new MoveCopyCallback());
+ executor = new UiExecutor();
+ }
+ if (operation != null && executor != null) {
+ IStatus status = executor.execute(operation);
+ return status != null && status.isOK();
+ }
+ return false;
+ }
+
+ /**
+ * Return an appropriate destination directory for copying according to the specified hovered
+ * node. If the hovered node is a file, then return its parent directory. If the hovered node is
+ * a directory, then return its self if it is not a node being copied. Return its parent
+ * directory if it is a node being copied.
+ *
+ * @param hovered
+ * @param nodes
+ * @return
+ */
+ private FSTreeNode getCopyDestination(FSTreeNode hovered, List<FSTreeNode> nodes) {
+ if (hovered.isFile()) {
+ return hovered.getParent();
+ }
+ else if (hovered.isDirectory()) {
+ for (FSTreeNode node : nodes) {
+ if (node == hovered) {
+ return hovered.getParent();
+ }
+ }
+ }
+ return hovered;
+ }
+
+ /**
+ * Validate dropping when the elements being dragged are files.
+ *
+ * @param target The target object.
+ * @param operation The DnD operation.
+ * @param transferType The transfered data simulator.
+ * @return true if it is valid for dropping.
+ */
+ public boolean validateFilesDrop(Object target, int operation, TransferData transferType) {
+ FileTransfer transfer = FileTransfer.getInstance();
+ String[] elements = (String[]) transfer.nativeToJava(transferType);
+ if (elements.length > 0) {
+ boolean moving = (operation & DND.DROP_MOVE) != 0;
+ boolean copying = (operation & DND.DROP_COPY) != 0;
+ FSTreeNode hovered = (FSTreeNode) target;
+ if (hovered.isFile() && copying) {
+ hovered = hovered.getParent();
+ }
+ return hovered.isDirectory() && hovered.isWritable() && (moving || copying);
+ }
+ return false;
+ }
+
+ /**
+ * Validate dropping when the elements being dragged are local selection.
+ *
+ * @param target The target object.
+ * @param operation The DnD operation.
+ * @param transferType The transfered data simulator.
+ * @return true if it is valid for dropping.
+ */
+ public boolean validateLocalSelectionDrop(Object target, int operation, TransferData transferType) {
+ FSTreeNode hovered = (FSTreeNode) target;
+ LocalSelectionTransfer transfer = LocalSelectionTransfer.getTransfer();
+ IStructuredSelection selection = (IStructuredSelection) transfer.getSelection();
+ List<FSTreeNode> nodes = selection.toList();
+ boolean moving = (operation & DND.DROP_MOVE) != 0;
+ boolean copying = (operation & DND.DROP_COPY) != 0;
+ if (hovered.isDirectory() && hovered.isWritable() && (moving || copying)) {
+ FSTreeNode head = nodes.get(0);
+ String hid = head.peerNode.getPeerId();
+ String tid = hovered.peerNode.getPeerId();
+ if (hid.equals(tid)) {
+ for (FSTreeNode node : nodes) {
+ if (moving && node == hovered || node.isAncestorOf(hovered)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ else if (hovered.isFile() && copying) {
+ hovered = hovered.getParent();
+ return validateLocalSelectionDrop(hovered, operation, transferType);
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.filesystem.interfaces.IConfirmCallback#requires(java.lang.Object)
+ */
+ @Override
+ public boolean requires(Object object) {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.tcf.te.tcf.filesystem.interfaces.IConfirmCallback#confirms(java.lang.Object)
+ */
+ @Override
+ public int confirms(Object object) {
+ final int[] results = new int[1];
+ final File file = (File) object;
+ Display display = PlatformUI.getWorkbench().getDisplay();
+ display.syncExec(new Runnable() {
+ @Override
+ public void run() {
+ Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ String title = Messages.FSUpload_OverwriteTitle;
+ String message = NLS.bind(Messages.FSUpload_OverwriteConfirmation, file.getName());
+ final Image titleImage = UIPlugin.getImage(ImageConsts.DELETE_READONLY_CONFIRM);
+ MessageDialog qDialog = new MessageDialog(parent, title, null, message,
+ MessageDialog.QUESTION, new String[] {Messages.FSUpload_Yes,
+ Messages.FSUpload_YesToAll, Messages.FSUpload_No, Messages.FSUpload_Cancel}, 0) {
+ @Override
+ public Image getQuestionImage() {
+ return titleImage;
+ }
+ };
+ results[0] = qDialog.open();
+ }
+ });
+ return results[0];
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent)
+ */
+ public boolean setDragData(DragSourceEvent anEvent) {
+ if (LocalSelectionTransfer.getTransfer().isSupportedType(anEvent.dataType)) {
+ anEvent.data = LocalSelectionTransfer.getTransfer().getSelection();
+ return true;
+ }
+ else if (FileTransfer.getInstance().isSupportedType(anEvent.dataType)) {
+ IStructuredSelection selection = (IStructuredSelection) LocalSelectionTransfer.getTransfer().getSelection();
+ List<FSTreeNode> nodes = selection.toList();
+ List<String> paths = new ArrayList<String>();
+ for(FSTreeNode node : nodes) {
+ File file = CacheManager.getCacheFile(node);
+ if(file.exists()) {
+ paths.add(file.getAbsolutePath());
+ }
+ }
+ if (!paths.isEmpty()) anEvent.data = paths.toArray(new String[paths.size()]);
+ return !paths.isEmpty();
+ }
+ return false;
+ }
+}

Back to the top