aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.ddms/src/com
diff options
context:
space:
mode:
authorSiva Velusamy <vsiva@google.com>2012-08-08 17:22:04 -0700
committerSiva Velusamy <vsiva@google.com>2012-08-14 10:47:16 -0700
commit07750e98d91da6a1a906c73e2a2b92e46aedf4cf (patch)
tree50e8077a6beebc71ed0e6f2e36610ae36c19f13e /eclipse/plugins/com.android.ide.eclipse.ddms/src/com
parent2528d6f1dd7074f6a3e3b2e4d31ccc76c62558a8 (diff)
downloadsdk-07750e98d91da6a1a906c73e2a2b92e46aedf4cf.tar.gz
Integrate uiautomatorviewer into Eclipse
This CL integrates uiautomatorviewer into Eclipse. There are two components to this: 1. Take UI Hierarchy Dump from a device: This is added as an action to the device view in the DDMS perspective. 2. Viewing the resulting UI hierarchy: This is added as an editor, associated with the .uix extension. The editor simply wraps a UiAutomatorView. The UiAutomatorView is modified slightly to allow for opening just the hierarchy file without the associated screenshot. This is to enable opening the .uix file via standard Eclipse Open File Dialog. When opened this way, the canvas displaying the screenshot is replaced with a button that allows the user to specify the actual screenshot to be displayed. Change-Id: I0f31fe95b2728123ff6f0f748478c18c0c2f1b48
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.ddms/src/com')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/editors/UiAutomatorViewer.java172
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java66
3 files changed, 239 insertions, 5 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
index a24f1222d..71639ec16 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
@@ -43,6 +43,7 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWTException;
@@ -816,4 +817,9 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL
mLogCatMonitor.monitorDevice(device);
}
+
+ /** Returns an image descriptor for the image file at the given plug-in relative path */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/editors/UiAutomatorViewer.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/editors/UiAutomatorViewer.java
new file mode 100644
index 000000000..0843018aa
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/editors/UiAutomatorViewer.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.ddms.editors;
+
+import com.android.ide.eclipse.base.InstallDetails;
+import com.android.uiautomator.UiAutomatorHelper.UiAutomatorResult;
+import com.android.uiautomator.UiAutomatorModel;
+import com.android.uiautomator.UiAutomatorView;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IURIEditorInput;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.EditorPart;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class UiAutomatorViewer extends EditorPart {
+ private String mFilePath;
+ private UiAutomatorView mView;
+
+ @Override
+ public void doSave(IProgressMonitor arg0) {
+ }
+
+ @Override
+ public void doSaveAs() {
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return false;
+ }
+
+ @Override
+ public boolean isDirty() {
+ return false;
+ }
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ // we use a IURIEditorInput to allow opening files not within the workspace
+ if (!(input instanceof IURIEditorInput)) {
+ throw new PartInitException("UI Automator Hierarchy View: unsupported input type.");
+ }
+
+ setSite(site);
+ setInput(input);
+ mFilePath = ((IURIEditorInput) input).getURI().getPath();
+
+ // set the editor part name to be the name of the file.
+ File f = new File(mFilePath);
+ setPartName(f.getName());
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ Composite c = new Composite(parent, SWT.NONE);
+ c.setLayout(new GridLayout(1, false));
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ c.setLayoutData(gd);
+
+ mView = new UiAutomatorView(c, SWT.BORDER);
+ mView.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ if (mFilePath == null) {
+ return;
+ }
+
+ UiAutomatorModel model = null;
+ File modelFile = new File(mFilePath);
+ try {
+ model = new UiAutomatorModel(modelFile);
+ } catch (Exception e) {
+ MessageDialog.openError(parent.getShell(), "Error opening " + mFilePath,
+ "Unexpected error while parsing input: " + e.getMessage());
+ return;
+ }
+
+ mView.setModel(model, modelFile, null);
+ }
+
+ @Override
+ public void setFocus() {
+ }
+
+ public static boolean openEditor(final UiAutomatorResult r) {
+ final IFileStore fileStore = EFS.getLocalFileSystem().getStore(
+ new Path(r.uiHierarchy.getAbsolutePath()));
+ if (!fileStore.fetchInfo().exists()) {
+ return false;
+ }
+
+ final AtomicBoolean status = new AtomicBoolean(false);
+
+ final IWorkbench workbench = PlatformUI.getWorkbench();
+ workbench.getDisplay().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ if (window == null) {
+ return;
+ }
+
+ IWorkbenchPage page = window.getActivePage();
+ if (page == null) {
+ return;
+ }
+
+ // try to switch perspectives if possible
+ if (page.isEditorAreaVisible() == false && InstallDetails.isAdtInstalled()) {
+ try {
+ workbench.showPerspective("org.eclipse.jdt.ui.JavaPerspective", window); //$NON-NLS-1$
+ } catch (WorkbenchException e) {
+ }
+ }
+
+ IEditorPart editor = null;
+ try {
+ editor = IDE.openEditorOnFileStore(page, fileStore);
+ } catch (PartInitException e) {
+ return;
+ }
+
+ if (!(editor instanceof UiAutomatorViewer)) {
+ return;
+ }
+
+ ((UiAutomatorViewer) editor).setModel(r.model, r.uiHierarchy, r.screenshot);
+ status.set(true);
+ }
+ });
+
+ return status.get();
+ }
+
+ protected void setModel(UiAutomatorModel model, File modelFile, Image screenshot) {
+ mView.setModel(model, modelFile, screenshot);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
index 31ae3b856..17670e49e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
@@ -38,20 +38,29 @@ import com.android.ddmuilib.handler.BaseFileHandler;
import com.android.ddmuilib.handler.MethodProfilingHandler;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.ide.eclipse.ddms.IDebuggerConnector;
+import com.android.ide.eclipse.ddms.editors.UiAutomatorViewer;
import com.android.ide.eclipse.ddms.i18n.Messages;
import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
+import com.android.uiautomator.UiAutomatorHelper;
+import com.android.uiautomator.UiAutomatorHelper.UiAutomatorException;
+import com.android.uiautomator.UiAutomatorHelper.UiAutomatorResult;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Composite;
@@ -70,6 +79,7 @@ import org.eclipse.ui.part.ViewPart;
import java.io.File;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
public class DeviceView extends ViewPart implements IUiSelectionListener, IClientChangeListener {
@@ -84,6 +94,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
private Action mResetAdbAction;
private Action mCaptureAction;
+ private Action mViewUiAutomatorHierarchyAction;
private Action mUpdateThreadAction;
private Action mUpdateHeapAction;
private Action mGcAction;
@@ -255,12 +266,13 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
IWorkbenchPage page = window.getActivePage();
+ if (page == null) {
+ return;
+ }
+
if (page.isEditorAreaVisible() == false) {
IAdaptable input;
- if (page != null)
- input = page.getInput();
- else
- input = ResourcesPlugin.getWorkspace().getRoot();
+ input = page.getInput();
try {
workbench.showPerspective("org.eclipse.debug.ui.DebugPerspective", //$NON-NLS-1$
window, input);
@@ -308,6 +320,17 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
mCaptureAction.setToolTipText(Messages.DeviceView_Screen_Capture_Tooltip);
mCaptureAction.setImageDescriptor(loader.loadDescriptor("capture.png")); //$NON-NLS-1$
+ mViewUiAutomatorHierarchyAction = new Action("Dump View Hierarchy for UI Automator") {
+ @Override
+ public void run() {
+ takeUiAutomatorSnapshot(mDeviceList.getSelectedDevice(),
+ DdmsPlugin.getDisplay().getActiveShell());
+ }
+ };
+ mViewUiAutomatorHierarchyAction.setToolTipText("Dump View Hierarchy for UI Automator");
+ mViewUiAutomatorHierarchyAction.setImageDescriptor(
+ DdmsPlugin.getImageDescriptor("icons/uiautomator.png")); //$NON-NLS-1$
+
mResetAdbAction = new Action(Messages.DeviceView_Reset_ADB) {
@Override
public void run() {
@@ -486,6 +509,34 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
});
}
+ private void takeUiAutomatorSnapshot(final IDevice device, final Shell shell) {
+ ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
+ try {
+ dialog.run(true, false, new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException,
+ InterruptedException {
+ UiAutomatorResult result = null;
+ try {
+ result = UiAutomatorHelper.takeSnapshot(device, monitor);
+ } catch (UiAutomatorException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+
+ UiAutomatorViewer.openEditor(result);
+ }
+ });
+ } catch (Exception e) {
+ Status s = new Status(IStatus.ERROR, DdmsPlugin.PLUGIN_ID,
+ "Error obtaining UI hierarchy", e);
+ ErrorDialog.openError(shell, "UI Automator",
+ "Unexpected error while obtaining UI hierarchy", s);
+ }
+ };
+
+
@Override
public void setFocus() {
mDeviceList.setFocus();
@@ -585,6 +636,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
private void doSelectionChanged(IDevice selectedDevice) {
mCaptureAction.setEnabled(selectedDevice != null);
+ mViewUiAutomatorHierarchyAction.setEnabled(selectedDevice != null);
}
/**
@@ -609,6 +661,8 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
menuManager.add(new Separator());
menuManager.add(mCaptureAction);
menuManager.add(new Separator());
+ menuManager.add(mViewUiAutomatorHierarchyAction);
+ menuManager.add(new Separator());
menuManager.add(mResetAdbAction);
// and then in the toolbar
@@ -626,6 +680,8 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien
toolBarManager.add(mKillAppAction);
toolBarManager.add(new Separator());
toolBarManager.add(mCaptureAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(mViewUiAutomatorHierarchyAction);
}
@Override