OSDN Git Service

Added a New Folder action in File Explorer.
authorPierre Zurek <pierrezurek@gmail.com>
Fri, 11 Feb 2011 23:04:48 +0000 (00:04 +0100)
committerPierre Zurek <pierrezurek@gmail.com>
Tue, 22 Mar 2011 01:15:12 +0000 (02:15 +0100)
This action allows the user to create a new folder if the current
selection in the tree is a folder. It executes the "mkdir" command
on the device. If an error occurs during execution, a popup is
displayed.

Change-Id: Id94485502849679ee9c753882b3e46f30e0edd1e

ddms/app/src/com/android/ddms/UIThread.java
ddms/libs/ddmlib/src/com/android/ddmlib/FileListingService.java
ddms/libs/ddmuilib/src/com/android/ddmuilib/explorer/DeviceExplorer.java
eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/FileExplorerView.java

index 2dc1cf0..ee4ea9d 100644 (file)
 package com.android.ddms;
 
 import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
 import com.android.ddmlib.Client;
 import com.android.ddmlib.ClientData;
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.SyncException;
-import com.android.ddmlib.SyncService;
-import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
 import com.android.ddmlib.ClientData.IHprofDumpHandler;
 import com.android.ddmlib.ClientData.MethodProfilingStatus;
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.ILogOutput;
 import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.SyncException;
+import com.android.ddmlib.SyncService;
 import com.android.ddmuilib.AllocationPanel;
 import com.android.ddmuilib.DevicePanel;
+import com.android.ddmuilib.DevicePanel.IUiSelectionListener;
 import com.android.ddmuilib.EmulatorControlPanel;
 import com.android.ddmuilib.HeapPanel;
 import com.android.ddmuilib.ITableFocusListener;
@@ -40,7 +41,6 @@ import com.android.ddmuilib.ScreenShotDialog;
 import com.android.ddmuilib.SysinfoPanel;
 import com.android.ddmuilib.TablePanel;
 import com.android.ddmuilib.ThreadPanel;
-import com.android.ddmuilib.DevicePanel.IUiSelectionListener;
 import com.android.ddmuilib.actions.ToolItemAction;
 import com.android.ddmuilib.explorer.DeviceExplorer;
 import com.android.ddmuilib.handler.BaseFileHandler;
@@ -1508,9 +1508,19 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
                 deleteAction.item.setText("Delete"); //$NON-NLS-1$
             }
 
+            ToolItemAction createNewFolderAction = new ToolItemAction(toolBar, SWT.PUSH);
+            createNewFolderAction.item.setToolTipText("New Folder");
+            image = mDdmUiLibLoader.loadImage("add.png", mDisplay); //$NON-NLS-1$
+            if (image != null) {
+                createNewFolderAction.item.setImage(image);
+            } else {
+                // this is for debugging purpose when the icon is missing
+                createNewFolderAction.item.setText("New Folder"); //$NON-NLS-1$
+            }
+
             // device explorer
             mExplorer = new DeviceExplorer();
-            mExplorer.setActions(pushAction, pullAction, deleteAction);
+            mExplorer.setActions(pushAction, pullAction, deleteAction, createNewFolderAction);
 
             pullAction.item.addSelectionListener(new SelectionAdapter() {
                 @Override
@@ -1536,6 +1546,14 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
             });
             deleteAction.setEnabled(false);
 
+            createNewFolderAction.item.addSelectionListener(new SelectionAdapter() {
+                @Override
+                public void widgetSelected(SelectionEvent e) {
+                    mExplorer.createNewFolderInSelection();
+                }
+            });
+            createNewFolderAction.setEnabled(false);
+
             Composite parent = new Composite(mExplorerShell, SWT.NONE);
             parent.setLayoutData(new GridData(GridData.FILL_BOTH));
 
index 4cf0056..5ef5428 100644 (file)
@@ -389,7 +389,7 @@ public final class FileListingService {
          * Returns an escaped version of the entry name.
          * @param entryName
          */
-        private String escape(String entryName) {
+        public static String escape(String entryName) {
             return sEscapePattern.matcher(entryName).replaceAll("\\\\$1"); //$NON-NLS-1$
         }
     }
index a0febeb..a466be1 100644 (file)
@@ -19,23 +19,28 @@ package com.android.ddmuilib.explorer;
 import com.android.ddmlib.AdbCommandRejectedException;
 import com.android.ddmlib.DdmConstants;
 import com.android.ddmlib.FileListingService;
+import com.android.ddmlib.FileListingService.FileEntry;
 import com.android.ddmlib.IDevice;
 import com.android.ddmlib.IShellOutputReceiver;
 import com.android.ddmlib.ShellCommandUnresponsiveException;
 import com.android.ddmlib.SyncException;
 import com.android.ddmlib.SyncService;
-import com.android.ddmlib.TimeoutException;
-import com.android.ddmlib.FileListingService.FileEntry;
 import com.android.ddmlib.SyncService.ISyncProgressMonitor;
+import com.android.ddmlib.TimeoutException;
 import com.android.ddmuilib.DdmUiPreferences;
 import com.android.ddmuilib.ImageLoader;
 import com.android.ddmuilib.Panel;
 import com.android.ddmuilib.SyncProgressHelper;
-import com.android.ddmuilib.TableHelper;
 import com.android.ddmuilib.SyncProgressHelper.SyncRunnable;
+import com.android.ddmuilib.TableHelper;
 import com.android.ddmuilib.actions.ICommonAction;
 import com.android.ddmuilib.console.DdmConsole;
 
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
@@ -96,6 +101,7 @@ public class DeviceExplorer extends Panel {
     private ICommonAction mPushAction;
     private ICommonAction mPullAction;
     private ICommonAction mDeleteAction;
+    private ICommonAction mCreateNewFolderAction;
 
     private Image mFileImage;
     private Image mFolderImage;
@@ -134,12 +140,14 @@ public class DeviceExplorer extends Panel {
      * @param pushAction
      * @param pullAction
      * @param deleteAction
+     * @param createNewFolderAction
      */
     public void setActions(ICommonAction pushAction, ICommonAction pullAction,
-            ICommonAction deleteAction) {
+            ICommonAction deleteAction, ICommonAction createNewFolderAction) {
         mPushAction = pushAction;
         mPullAction = pullAction;
         mDeleteAction = deleteAction;
+        mCreateNewFolderAction = createNewFolderAction;
     }
 
     /**
@@ -201,6 +209,7 @@ public class DeviceExplorer extends Panel {
                     mPullAction.setEnabled(false);
                     mPushAction.setEnabled(false);
                     mDeleteAction.setEnabled(false);
+                    mCreateNewFolderAction.setEnabled(false);
                     return;
                 }
                 if (sel instanceof IStructuredSelection) {
@@ -212,7 +221,9 @@ public class DeviceExplorer extends Panel {
                         mPullAction.setEnabled(true);
                         mPushAction.setEnabled(selection.size() == 1);
                         if (selection.size() == 1) {
-                            setDeleteEnabledState((FileEntry)element);
+                            FileEntry entry = (FileEntry) element;
+                            setDeleteEnabledState(entry);
+                            mCreateNewFolderAction.setEnabled(entry.isDirectory());
                         } else {
                             mDeleteAction.setEnabled(false);
                         }
@@ -617,6 +628,82 @@ public class DeviceExplorer extends Panel {
 
     }
 
+    public void createNewFolderInSelection() {
+        TreeItem[] items = mTree.getSelection();
+
+        if (items.length != 1) {
+            return;
+        }
+
+        final FileEntry entry = (FileEntry) items[0].getData();
+
+        if (entry.isDirectory()) {
+            InputDialog inputDialog = new InputDialog(mTree.getShell(), "New Folder",
+                    "Please enter the new folder name", "New Folder", new IInputValidator() {
+                        public String isValid(String newText) {
+                            if ((newText != null) && (newText.length() > 0)
+                                    && (newText.trim().length() > 0)
+                                    && (newText.indexOf('/') == -1)
+                                    && (newText.indexOf('\\') == -1)) {
+                                return null;
+                            } else {
+                                return "Invalid name";
+                            }
+                        }
+                    });
+            inputDialog.open();
+            String value = inputDialog.getValue();
+
+            if (value != null) {
+                // create the mkdir command
+                String command = "mkdir " + entry.getFullEscapedPath() //$NON-NLS-1$
+                        + FileListingService.FILE_SEPARATOR + FileEntry.escape(value);
+
+                try {
+                    mCurrentDevice.executeShellCommand(command, new IShellOutputReceiver() {
+
+                        public boolean isCancelled() {
+                            return false;
+                        }
+
+                        public void flush() {
+                            mTreeViewer.refresh(entry);
+                        }
+
+                        public void addOutput(byte[] data, int offset, int length) {
+                            String errorMessage;
+                            if (data != null) {
+                                errorMessage = new String(data);
+                            } else {
+                                errorMessage = "";
+                            }
+                            Status status = new Status(IStatus.ERROR,
+                                    "DeviceExplorer", 0, errorMessage, null); //$NON-NLS-1$
+                            ErrorDialog.openError(mTree.getShell(), "New Folder Error",
+                                    "New Folder Error", status);
+                        }
+                    });
+                } catch (TimeoutException e) {
+                    // adb failed somehow, we do nothing. We should be
+                    // displaying the error from the output of the shell
+                    // command.
+                } catch (AdbCommandRejectedException e) {
+                    // adb failed somehow, we do nothing. We should be
+                    // displaying the error from the output of the shell
+                    // command.
+                } catch (ShellCommandUnresponsiveException e) {
+                    // adb failed somehow, we do nothing. We should be
+                    // displaying the error from the output of the shell
+                    // command.
+                } catch (IOException e) {
+                    // adb failed somehow, we do nothing. We should be
+                    // displaying the error from the output of the shell
+                    // command.
+                }
+            }
+        }
+    }
+
     /**
      * Force a full refresh of the explorer.
      */
index b3e08a2..57e5370 100644 (file)
@@ -110,8 +110,18 @@ public class FileExplorerView extends ViewPart implements ISelectionListener {
         deleteAction.setImageDescriptor(loader.loadDescriptor("delete.png")); //$NON-NLS-1$
         deleteAction.setEnabled(false);
 
+        CommonAction createNewFolderAction = new CommonAction("New Folder") {
+            @Override
+            public void run() {
+                mExplorer.createNewFolderInSelection();
+            }
+        };
+        createNewFolderAction.setToolTipText("New Folder");
+        createNewFolderAction.setImageDescriptor(loader.loadDescriptor("add.png")); //$NON-NLS-1$
+        createNewFolderAction.setEnabled(false);
+
         // set up the actions in the explorer
-        mExplorer.setActions(pushAction, pullAction, deleteAction);
+        mExplorer.setActions(pushAction, pullAction, deleteAction, createNewFolderAction);
 
         // and in the ui
         IActionBars actionBars = getViewSite().getActionBars();
@@ -122,11 +132,15 @@ public class FileExplorerView extends ViewPart implements ISelectionListener {
         menuManager.add(pushAction);
         menuManager.add(new Separator());
         menuManager.add(deleteAction);
+        menuManager.add(new Separator());
+        menuManager.add(createNewFolderAction);
 
         toolBarManager.add(pullAction);
         toolBarManager.add(pushAction);
         toolBarManager.add(new Separator());
         toolBarManager.add(deleteAction);
+        toolBarManager.add(new Separator());
+        toolBarManager.add(createNewFolderAction);
 
         mExplorer.createPanel(parent);