aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.ddms/src/com
diff options
context:
space:
mode:
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