aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins/com.android.ide.eclipse.ddms
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.ddms')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/.classpath10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/.project28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/MODULE_LICENSE_APACHE20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/build.properties10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/icons/android.pngbin0 -> 3609 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/icons/capture.pngbin0 -> 696 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml102
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/CommonAction.java69
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java565
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ImageLoader.java67
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java80
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java74
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java102
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java82
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java329
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EmulatorControlView.java43
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EventLogView.java114
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/FileExplorerView.java165
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/HeapView.java47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java328
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NativeHeapView.java47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SelectionDependentViewPart.java68
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/TableView.java96
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/ThreadView.java47
25 files changed, 2496 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/.classpath b/eclipse/plugins/com.android.ide.eclipse.ddms/.classpath
new file mode 100644
index 0000000..280621c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="lib" path="libs/jfreechart-1.0.9.jar"/>
+ <classpathentry kind="lib" path="libs/jcommon-1.0.12.jar"/>
+ <classpathentry kind="lib" path="libs/jfreechart-1.0.9-swt.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/.project b/eclipse/plugins/com.android.ide.eclipse.ddms/.project
new file mode 100644
index 0000000..2e9f996
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ddms-plugin</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..09b8085
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Dalvik Debug Monitor Service
+Bundle-SymbolicName: com.android.ide.eclipse.ddms;singleton:=true
+Bundle-Version: 0.9.0.qualifier
+Bundle-Activator: com.android.ide.eclipse.ddms.DdmsPlugin
+Bundle-Vendor: The Android Open Source Project
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.console
+Eclipse-LazyStart: true
+Export-Package: com.android.ddmlib,
+ com.android.ddmlib.log,
+ com.android.ddmlib.testrunner,
+ com.android.ddmuilib,
+ com.android.ddmuilib.console,
+ com.android.ide.eclipse.ddms,
+ com.android.ide.eclipse.ddms.views
+Bundle-ClassPath: libs/jcommon-1.0.12.jar,
+ libs/jfreechart-1.0.9.jar,
+ libs/jfreechart-1.0.9-swt.jar,
+ .
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/MODULE_LICENSE_APACHE2 b/eclipse/plugins/com.android.ide.eclipse.ddms/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/MODULE_LICENSE_APACHE2
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/build.properties b/eclipse/plugins/com.android.ide.eclipse.ddms/build.properties
new file mode 100644
index 0000000..1c4c896
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/build.properties
@@ -0,0 +1,10 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ icons/,\
+ plugin.xml,\
+ ., \
+ libs/jcommon-1.0.12.jar,\
+ libs/jfreechart-1.0.9-swt.jar,\
+ libs/jfreechart-1.0.9.jar
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/icons/android.png b/eclipse/plugins/com.android.ide.eclipse.ddms/icons/android.png
new file mode 100644
index 0000000..3779d4d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/icons/android.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/icons/capture.png b/eclipse/plugins/com.android.ide.eclipse.ddms/icons/capture.png
new file mode 100644
index 0000000..d75e7a9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/icons/capture.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml
new file mode 100644
index 0000000..27fadf2
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.views">
+ <category
+ name="Android"
+ id="com.android.ide.eclipse.ddms.views.category">
+ </category>
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.DeviceView"
+ icon="icons/device.png"
+ id="com.android.ide.eclipse.ddms.views.DeviceView"
+ name="Devices">
+ </view>
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.LogCatView"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.ddms.views.LogCatView"
+ name="LogCat"/>
+ <!-- Disabled for now due to AWT/SWT bridge issue on Leopard.
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.EventLogView"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.ddms.views.EventLogView"
+ name="Event Log"/> -->
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.ThreadView"
+ icon="icons/thread.png"
+ id="com.android.ide.eclipse.ddms.views.ThreadView"
+ name="Threads"/>
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.HeapView"
+ icon="icons/heap.png"
+ id="com.android.ide.eclipse.ddms.views.HeapView"
+ name="Heap"/>
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.FileExplorerView"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.ddms.views.FileExplorerView"
+ name="File Explorer"/>
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.EmulatorControlView"
+ icon="icons/emulator.png"
+ id="com.android.ide.eclipse.ddms.views.EmulatorControlView"
+ name="Emulator Control"/>
+ </extension>
+ <extension
+ point="org.eclipse.ui.perspectives">
+ <perspective
+ class="com.android.ide.eclipse.ddms.Perspective"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.ddms.Perspective"
+ name="DDMS"/>
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer class="com.android.ide.eclipse.ddms.preferences.PreferenceInitializer"/>
+ </extension>
+ <extension
+ point="org.eclipse.ui.perspectiveExtensions">
+ <perspectiveExtension targetID="org.eclipse.jdt.ui.JavaPerspective">
+ <perspectiveShortcut id="com.android.ide.eclipse.ddms.Perspective"/>
+ </perspectiveExtension>
+ <perspectiveExtension targetID="org.eclipse.ui.resourcePerspective">
+ <perspectiveShortcut id="com.android.ide.eclipse.ddms.Perspective"/>
+ </perspectiveExtension>
+ <perspectiveExtension targetID="org.eclipse.debug.ui.DebugPerspective">
+ <perspectiveShortcut id="com.android.ide.eclipse.ddms.Perspective"/>
+ <view id="com.android.ide.eclipse.ddms.views.LogCatView"
+ relative="org.eclipse.ui.views.ProblemView"
+ relationship="stack" />
+ </perspectiveExtension>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="com.android.ide.eclipse.preferences.main"
+ class="com.android.ide.eclipse.ddms.preferences.PreferencePage"
+ id="com.android.ide.eclipse.ddms.preferences.PreferencePage"
+ name="DDMS"/>
+ <page
+ category="com.android.ide.eclipse.preferences.main"
+ class="com.android.ide.eclipse.ddms.preferences.LogCatPreferencePage"
+ id="com.android.ide.eclipse.ddms.preferences.LogCatPreferencePage"
+ name="LogCat"/>
+ </extension>
+</plugin>
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/CommonAction.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/CommonAction.java
new file mode 100644
index 0000000..30ca4cb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/CommonAction.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.android.ddmuilib.actions.ICommonAction;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ * Basic action extending the jFace Action class in order to implement
+ * ICommonAction.
+ */
+public class CommonAction extends Action implements ICommonAction {
+
+ private Runnable mRunnable;
+
+ public CommonAction() {
+ super();
+ }
+
+ public CommonAction(String text) {
+ super(text);
+ }
+
+ /**
+ * @param text
+ * @param image
+ */
+ public CommonAction(String text, ImageDescriptor image) {
+ super(text, image);
+ }
+
+ /**
+ * @param text
+ * @param style
+ */
+ public CommonAction(String text, int style) {
+ super(text, style);
+ }
+
+ @Override
+ public void run() {
+ if (mRunnable != null) {
+ mRunnable.run();
+ }
+ }
+
+ /**
+ * Sets the {@link Runnable}.
+ * @see ICommonAction#setRunnable(Runnable)
+ */
+ public void setRunnable(Runnable runnable) {
+ mRunnable = runnable;
+ }
+}
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
new file mode 100644
index 0000000..ccadce6
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.Client;
+import com.android.ddmlib.DdmPreferences;
+import com.android.ddmlib.Device;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
+import com.android.ddmlib.Log.ILogOutput;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmuilib.DdmUiPreferences;
+import com.android.ddmuilib.DevicePanel.IUiSelectionListener;
+import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
+import com.android.ide.eclipse.ddms.views.DeviceView;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
+import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.MessageConsole;
+import org.eclipse.ui.console.MessageConsoleStream;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeListener,
+ IUiSelectionListener {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "com.android.ide.eclipse.ddms"; // $NON-NLS-1$
+
+ private static final String ADB_LOCATION = PLUGIN_ID + ".adb"; // $NON-NLS-1$
+
+ /** The singleton instance */
+ private static DdmsPlugin sPlugin;
+
+ /** Location of the adb command line executable */
+ private static String sAdbLocation;
+
+ /**
+ * Debug Launcher for already running apps
+ */
+ private static IDebugLauncher sRunningAppDebugLauncher;
+
+ /** Console for DDMS log message */
+ private MessageConsole mDdmsConsole;
+
+ /** Image loader object */
+ private ImageLoader mLoader;
+
+ private Device mCurrentDevice;
+ private Client mCurrentClient;
+ private boolean mListeningToUiSelection = false;
+
+ private final ArrayList<ISelectionListener> mListeners = new ArrayList<ISelectionListener>();
+
+ private Color mRed;
+
+ private boolean mDdmlibInitialized;
+
+ /**
+ * Interface to provide debugger launcher for running apps.
+ */
+ public interface IDebugLauncher {
+ public boolean debug(String packageName, int port);
+ }
+
+ /**
+ * Classes which implement this interface provide methods that deals
+ * with {@link Device} and {@link Client} selectionchanges.
+ */
+ public interface ISelectionListener {
+
+ /**
+ * Sent when a new {@link Client} is selected.
+ * @param selectedClient The selected client. If null, no clients are selected.
+ */
+ public void selectionChanged(Client selectedClient);
+
+ /**
+ * Sent when a new {@link Device} is selected.
+ * @param selectedDevice the selected device. If null, no devices are selected.
+ */
+ public void selectionChanged(Device selectedDevice);
+ }
+
+ /**
+ * The constructor
+ */
+ public DdmsPlugin() {
+ sPlugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+
+ final Display display = getDisplay();
+
+ // get the eclipse store
+ final IPreferenceStore eclipseStore = getPreferenceStore();
+
+ AndroidDebugBridge.addDeviceChangeListener(this);
+
+ DdmUiPreferences.setStore(eclipseStore);
+
+ //DdmUiPreferences.displayCharts();
+
+ // set the consoles.
+ mDdmsConsole = new MessageConsole("DDMS", null); // $NON-NLS-1$
+ ConsolePlugin.getDefault().getConsoleManager().addConsoles(
+ new IConsole[] {
+ mDdmsConsole
+ });
+
+ final MessageConsoleStream consoleStream = mDdmsConsole.newMessageStream();
+ final MessageConsoleStream errorConsoleStream = mDdmsConsole.newMessageStream();
+ mRed = new Color(display, 0xFF, 0x00, 0x00);
+
+ // because this can be run, in some cases, by a non UI thread, and because
+ // changing the console properties update the UI, we need to make this change
+ // in the UI thread.
+ display.asyncExec(new Runnable() {
+ public void run() {
+ errorConsoleStream.setColor(mRed);
+ }
+ });
+
+ // set up the ddms log to use the ddms console.
+ Log.setLogOutput(new ILogOutput() {
+ public void printLog(LogLevel logLevel, String tag, String message) {
+ if (logLevel.getPriority() >= LogLevel.ERROR.getPriority()) {
+ printToStream(errorConsoleStream, tag, message);
+ ConsolePlugin.getDefault().getConsoleManager().showConsoleView(mDdmsConsole);
+ } else {
+ printToStream(consoleStream, tag, message);
+ }
+ }
+
+ public void printAndPromptLog(final LogLevel logLevel, final String tag,
+ final String message) {
+ printLog(logLevel, tag, message);
+ // dialog box only run in UI thread..
+ display.asyncExec(new Runnable() {
+ public void run() {
+ Shell shell = display.getActiveShell();
+ if (logLevel == LogLevel.ERROR) {
+ MessageDialog.openError(shell, tag, message);
+ } else {
+ MessageDialog.openWarning(shell, tag, message);
+ }
+ }
+ });
+ }
+
+ });
+
+ // create the loader that's able to load the images
+ mLoader = new ImageLoader(this);
+
+ // set the listener for the preference change
+ Preferences prefs = getPluginPreferences();
+ prefs.addPropertyChangeListener(new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ // get the name of the property that changed.
+ String property = event.getProperty();
+
+ if (PreferenceInitializer.ATTR_DEBUG_PORT_BASE.equals(property)) {
+ DdmPreferences.setDebugPortBase(
+ eclipseStore.getInt(PreferenceInitializer.ATTR_DEBUG_PORT_BASE));
+ } else if (PreferenceInitializer.ATTR_SELECTED_DEBUG_PORT.equals(property)) {
+ DdmPreferences.setSelectedDebugPort(
+ eclipseStore.getInt(PreferenceInitializer.ATTR_SELECTED_DEBUG_PORT));
+ } else if (PreferenceInitializer.ATTR_THREAD_INTERVAL.equals(property)) {
+ DdmUiPreferences.setThreadRefreshInterval(
+ eclipseStore.getInt(PreferenceInitializer.ATTR_THREAD_INTERVAL));
+ } else if (PreferenceInitializer.ATTR_LOG_LEVEL.equals(property)) {
+ DdmPreferences.setLogLevel(
+ eclipseStore.getString(PreferenceInitializer.ATTR_LOG_LEVEL));
+ }
+ }
+ });
+
+ // read the adb location from the prefs to attempt to start it properly without
+ // having to wait for ADT to start
+ sAdbLocation = eclipseStore.getString(ADB_LOCATION);
+
+ // start it in a thread to return from start() asap.
+ new Thread() {
+ @Override
+ public void run() {
+ // init ddmlib if needed
+ getDefault().initDdmlib();
+
+ // create and start the first bridge
+ AndroidDebugBridge.createBridge(sAdbLocation, true /* forceNewBridge */);
+ }
+ }.start();
+ }
+
+ public static Display getDisplay() {
+ IWorkbench bench = sPlugin.getWorkbench();
+ if (bench != null) {
+ return bench.getDisplay();
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ AndroidDebugBridge.removeDeviceChangeListener(this);
+
+ AndroidDebugBridge.terminate();
+
+ mRed.dispose();
+
+ sPlugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static DdmsPlugin getDefault() {
+ return sPlugin;
+ }
+
+ /** Return the image loader for the plugin */
+ public static ImageLoader getImageLoader() {
+ if (sPlugin != null) {
+ return sPlugin.mLoader;
+ }
+ return null;
+ }
+
+ public static String getAdb() {
+ return sAdbLocation;
+ }
+
+ /**
+ * Set the location of the adb executable and optionally starts adb
+ * @param adb location of adb
+ * @param startAdb flag to start adb
+ */
+ public static void setAdb(String adb, boolean startAdb) {
+ sAdbLocation = adb;
+
+ // store the location for future ddms only start.
+ sPlugin.getPreferenceStore().setValue(ADB_LOCATION, sAdbLocation);
+
+ // starts the server in a thread in case this is blocking.
+ if (startAdb) {
+ new Thread() {
+ @Override
+ public void run() {
+ // init ddmlib if needed
+ getDefault().initDdmlib();
+
+ // create and start the bridge
+ AndroidDebugBridge.createBridge(sAdbLocation, false /* forceNewBridge */);
+ }
+ }.start();
+ }
+ }
+
+ private synchronized void initDdmlib() {
+ if (mDdmlibInitialized == false) {
+ // set the preferences.
+ PreferenceInitializer.setupPreferences();
+
+ // init the lib
+ AndroidDebugBridge.init(true /* debugger support */);
+
+ mDdmlibInitialized = true;
+ }
+ }
+
+ /**
+ * Sets the launcher responsible for connecting the debugger to running applications.
+ * @param launcher The launcher.
+ */
+ public static void setRunningAppDebugLauncher(IDebugLauncher launcher) {
+ sRunningAppDebugLauncher = launcher;
+
+ // if the process view is already running, give it the launcher.
+ // This method could be called from a non ui thread, so we make sure to do that
+ // in the ui thread.
+ Display display = getDisplay();
+ if (display != null && display.isDisposed() == false) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ DeviceView dv = DeviceView.getInstance();
+ if (dv != null) {
+ dv.setDebugLauncher(sRunningAppDebugLauncher);
+ }
+ }
+ });
+ }
+ }
+
+ public static IDebugLauncher getRunningAppDebugLauncher() {
+ return sRunningAppDebugLauncher;
+ }
+
+ public synchronized void addSelectionListener(ISelectionListener listener) {
+ mListeners.add(listener);
+
+ // notify the new listener of the current selection
+ listener.selectionChanged(mCurrentDevice);
+ listener.selectionChanged(mCurrentClient);
+ }
+
+ public synchronized void removeSelectionListener(ISelectionListener listener) {
+ mListeners.remove(listener);
+ }
+
+ public synchronized void setListeningState(boolean state) {
+ mListeningToUiSelection = state;
+ }
+
+ /**
+ * Sent when the a device is connected to the {@link AndroidDebugBridge}.
+ * <p/>
+ * This is sent from a non UI thread.
+ * @param device the new device.
+ *
+ * @see IDeviceChangeListener#deviceConnected(Device)
+ */
+ public void deviceConnected(Device device) {
+ // if we are listening to selection coming from the ui, then we do nothing, as
+ // any change in the devices/clients, will be handled by the UI, and we'll receive
+ // selection notification through our implementation of IUiSelectionListener.
+ if (mListeningToUiSelection == false) {
+ if (mCurrentDevice == null) {
+ handleDefaultSelection(device);
+ }
+ }
+ }
+
+ /**
+ * Sent when the a device is disconnected to the {@link AndroidDebugBridge}.
+ * <p/>
+ * This is sent from a non UI thread.
+ * @param device the new device.
+ *
+ * @see IDeviceChangeListener#deviceDisconnected(Device)
+ */
+ public void deviceDisconnected(Device device) {
+ // if we are listening to selection coming from the ui, then we do nothing, as
+ // any change in the devices/clients, will be handled by the UI, and we'll receive
+ // selection notification through our implementation of IUiSelectionListener.
+ if (mListeningToUiSelection == false) {
+ // test if the disconnected device was the default selection.
+ if (mCurrentDevice == device) {
+ // try to find a new device
+ AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
+ if (bridge != null) {
+ // get the device list
+ Device[] devices = bridge.getDevices();
+
+ // check if we still have devices
+ if (devices.length == 0) {
+ handleDefaultSelection((Device)null);
+ } else {
+ handleDefaultSelection(devices[0]);
+ }
+ } else {
+ handleDefaultSelection((Device)null);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sent when a device data changed, or when clients are started/terminated on the device.
+ * <p/>
+ * This is sent from a non UI thread.
+ * @param device the device that was updated.
+ * @param changeMask the mask indicating what changed.
+ *
+ * @see IDeviceChangeListener#deviceChanged(Device)
+ */
+ public void deviceChanged(Device device, int changeMask) {
+ // if we are listening to selection coming from the ui, then we do nothing, as
+ // any change in the devices/clients, will be handled by the UI, and we'll receive
+ // selection notification through our implementation of IUiSelectionListener.
+ if (mListeningToUiSelection == false) {
+
+ // check if this is our device
+ if (device == mCurrentDevice) {
+ if (mCurrentClient == null) {
+ handleDefaultSelection(device);
+ } else {
+ // get the clients and make sure ours is still in there.
+ Client[] clients = device.getClients();
+ boolean foundClient = false;
+ for (Client client : clients) {
+ if (client == mCurrentClient) {
+ foundClient = true;
+ break;
+ }
+ }
+
+ // if we haven't found our client, lets look for a new one
+ if (foundClient == false) {
+ mCurrentClient = null;
+ handleDefaultSelection(device);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sent when a new {@link Device} and {@link Client} are selected.
+ * @param selectedDevice the selected device. If null, no devices are selected.
+ * @param selectedClient The selected client. If null, no clients are selected.
+ */
+ public synchronized void selectionChanged(Device selectedDevice, Client selectedClient) {
+ if (mCurrentDevice != selectedDevice) {
+ mCurrentDevice = selectedDevice;
+
+ // notify of the new default device
+ for (ISelectionListener listener : mListeners) {
+ listener.selectionChanged(mCurrentDevice);
+ }
+ }
+
+ if (mCurrentClient != selectedClient) {
+ mCurrentClient = selectedClient;
+
+ // notify of the new default client
+ for (ISelectionListener listener : mListeners) {
+ listener.selectionChanged(mCurrentClient);
+ }
+ }
+ }
+
+ /**
+ * Handles a default selection of a {@link Device} and {@link Client}.
+ * @param device the selected device
+ */
+ private void handleDefaultSelection(final Device device) {
+ // because the listener expect to receive this from the UI thread, and this is called
+ // from the AndroidDebugBridge notifications, we need to run this in the UI thread.
+ try {
+ Display display = getDisplay();
+
+ display.asyncExec(new Runnable() {
+ public void run() {
+ // set the new device if different.
+ boolean newDevice = false;
+ if (mCurrentDevice != device) {
+ mCurrentDevice = device;
+ newDevice = true;
+
+ // notify of the new default device
+ for (ISelectionListener listener : mListeners) {
+ listener.selectionChanged(mCurrentDevice);
+ }
+ }
+
+ if (device != null) {
+ // if this is a device switch or the same device but we didn't find a valid
+ // client the last time, we go look for a client to use again.
+ if (newDevice || mCurrentClient == null) {
+ // now get the new client
+ Client[] clients = device.getClients();
+ if (clients.length > 0) {
+ handleDefaultSelection(clients[0]);
+ } else {
+ handleDefaultSelection((Client)null);
+ }
+ }
+ } else {
+ handleDefaultSelection((Client)null);
+ }
+ }
+ });
+ } catch (SWTException e) {
+ // display is disposed. Do nothing since we're quitting anyway.
+ }
+ }
+
+ private void handleDefaultSelection(Client client) {
+ mCurrentClient = client;
+
+ // notify of the new default client
+ for (ISelectionListener listener : mListeners) {
+ listener.selectionChanged(mCurrentClient);
+ }
+ }
+
+ /**
+ * Prints a message, associated with a project to the specified stream
+ * @param stream The stream to write to
+ * @param tag The tag associated to the message. Can be null
+ * @param message The message to print.
+ */
+ private static synchronized void printToStream(MessageConsoleStream stream, String tag,
+ String message) {
+ String dateTag = getMessageTag(tag);
+
+ stream.print(dateTag);
+ stream.println(message);
+ }
+
+ /**
+ * Creates a string containing the current date/time, and the tag
+ * @param tag The tag associated to the message. Can be null
+ * @return The dateTag
+ */
+ private static String getMessageTag(String tag) {
+ Calendar c = Calendar.getInstance();
+
+ if (tag == null) {
+ return String.format("[%1$tF %1$tT]", c);
+ }
+
+ return String.format("[%1$tF %1$tT - %2$s]", c, tag);
+ }
+
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ImageLoader.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ImageLoader.java
new file mode 100644
index 0000000..a70405d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ImageLoader.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.android.ddmuilib.IImageLoader;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Implementation of the IImageLoader interface for the eclipse plugin.
+ */
+public class ImageLoader implements IImageLoader {
+
+ private URL mBaseUrl;
+
+ public ImageLoader(Plugin plugin) {
+ mBaseUrl = plugin.getBundle().getEntry("/"); // $NON-NLS-1$
+ }
+
+ /**
+ * default method. only need a filename. the 2 interface methods call this one.
+ * @param filename the filename of the image to load. The filename is searched for under /icons.
+ * @return
+ */
+ public ImageDescriptor loadDescriptor(String filename) {
+ try {
+ URL newUrl = new URL(mBaseUrl, "/icons/" + filename); // $NON-NLS-1$
+ return ImageDescriptor.createFromURL(newUrl);
+ } catch (MalformedURLException e) {
+ // we'll just return null;
+ }
+ return null;
+ }
+
+ public ImageDescriptor loadDescriptor(String filename, Display display) {
+ return loadDescriptor(filename);
+ }
+
+
+ public Image loadImage(String filename, Display display) {
+ ImageDescriptor descriptor = loadDescriptor(filename);
+ if (descriptor !=null) {
+ return descriptor.createImage();
+ }
+ return null;
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java
new file mode 100644
index 0000000..4c01e9b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.android.ide.eclipse.ddms.views.DeviceView;
+import com.android.ide.eclipse.ddms.views.EmulatorControlView;
+import com.android.ide.eclipse.ddms.views.FileExplorerView;
+import com.android.ide.eclipse.ddms.views.HeapView;
+import com.android.ide.eclipse.ddms.views.LogCatView;
+import com.android.ide.eclipse.ddms.views.ThreadView;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+public class Perspective implements IPerspectiveFactory {
+
+ public void createInitialLayout(IPageLayout layout) {
+ // create a default layout that looks like the stand alone DDMS.
+
+ // no editor window
+ layout.setEditorAreaVisible(false);
+
+ String editorArea = layout.getEditorArea();
+ IFolderLayout folder;
+
+ folder = layout.createFolder("logcat", IPageLayout.BOTTOM, 0.8f, //$NON-NLS-1$
+ editorArea);
+ folder.addPlaceholder(LogCatView.ID + ":*"); //$NON-NLS-1$
+ folder.addView(LogCatView.ID);
+
+ folder = layout.createFolder("devices", IPageLayout.LEFT, 0.3f, //$NON-NLS-1$
+ editorArea);
+ folder.addPlaceholder(DeviceView.ID + ":*"); //$NON-NLS-1$
+ folder.addView(DeviceView.ID);
+
+ folder = layout.createFolder("emulator", IPageLayout.BOTTOM, 0.5f, //$NON-NLS-1$
+ "devices");
+ folder.addPlaceholder(EmulatorControlView.ID + ":*"); //$NON-NLS-1$
+ folder.addView(EmulatorControlView.ID);
+
+ folder = layout.createFolder("ddms-detail", IPageLayout.RIGHT, 0.5f, //$NON-NLS-1$
+ editorArea);
+ folder.addPlaceholder(ThreadView.ID + ":*"); //$NON-NLS-1$
+ folder.addView(ThreadView.ID);
+ folder.addView(HeapView.ID);
+ folder.addView(FileExplorerView.ID);
+
+ layout.addPerspectiveShortcut("org.eclipse.ui.resourcePerspective"); //$NON-NLS-1$
+ layout.addPerspectiveShortcut("org.eclipse.debug.ui.DebugPerspective"); //$NON-NLS-1$
+ layout.addPerspectiveShortcut("org.eclipse.jdt.ui.JavaPerspective"); //$NON-NLS-1$
+
+ layout.addShowViewShortcut(DeviceView.ID);
+ layout.addShowViewShortcut(FileExplorerView.ID);
+ layout.addShowViewShortcut(HeapView.ID);
+ layout.addShowViewShortcut(LogCatView.ID);
+ layout.addShowViewShortcut(ThreadView.ID);
+
+ layout.addShowViewShortcut(IPageLayout.ID_RES_NAV);
+ layout.addShowViewShortcut(IPageLayout.ID_BOOKMARKS);
+ layout.addShowViewShortcut(IPageLayout.ID_OUTLINE);
+ layout.addShowViewShortcut(IPageLayout.ID_PROP_SHEET);
+ layout.addShowViewShortcut(IPageLayout.ID_PROBLEM_VIEW);
+ layout.addShowViewShortcut(IPageLayout.ID_PROGRESS_VIEW);
+ layout.addShowViewShortcut(IPageLayout.ID_TASK_LIST);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java
new file mode 100644
index 0000000..909207d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.preferences;
+
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.views.LogCatView;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
+import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.FontFieldEditor;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/**
+ * Preference Pane for LogCat.
+ */
+public class LogCatPreferencePage extends FieldEditorPreferencePage implements
+ IWorkbenchPreferencePage {
+
+ public LogCatPreferencePage() {
+ super(GRID);
+ setPreferenceStore(DdmsPlugin.getDefault().getPreferenceStore());
+ }
+
+ @Override
+ protected void createFieldEditors() {
+ FontFieldEditor ffe = new FontFieldEditor(PreferenceInitializer.ATTR_LOGCAT_FONT,
+ "Display Font:", getFieldEditorParent());
+ addField(ffe);
+
+ Preferences prefs = DdmsPlugin.getDefault().getPluginPreferences();
+ prefs.addPropertyChangeListener(new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ // get the name of the property that changed.
+ String property = event.getProperty();
+
+ if (PreferenceInitializer.ATTR_LOGCAT_FONT.equals(property)) {
+ try {
+ FontData fdat = new FontData((String)event.getNewValue());
+ LogCatView.setFont(new Font(getFieldEditorParent().getDisplay(), fdat));
+ } catch (IllegalArgumentException e) {
+ // Looks like the data from the store is not valid.
+ // We do nothing (default font will be used).
+ } catch (SWTError e2) {
+ // Looks like the Font() constructor failed.
+ // We do nothing in this case, the logcat view will use the default font.
+ }
+ }
+ }
+ });
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
new file mode 100644
index 0000000..b53d85c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 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.preferences;
+
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ddmlib.DdmPreferences;
+import com.android.ddmuilib.DdmUiPreferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontData;
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+ public final static String ATTR_LOG_LEVEL =
+ DdmsPlugin.PLUGIN_ID + ".logLevel"; //$NON-NLS-1$
+
+ public final static String ATTR_DEBUG_PORT_BASE =
+ DdmsPlugin.PLUGIN_ID + ".adbDebugBasePort"; //$NON-NLS-1$
+
+ public final static String ATTR_SELECTED_DEBUG_PORT =
+ DdmsPlugin.PLUGIN_ID + ".debugSelectedPort"; //$NON-NLS-1$
+
+ public final static String ATTR_DEFAULT_THREAD_UPDATE =
+ DdmsPlugin.PLUGIN_ID + ".defaultThreadUpdateEnabled"; //$NON-NLS-1$
+
+ public final static String ATTR_DEFAULT_HEAP_UPDATE =
+ DdmsPlugin.PLUGIN_ID + ".defaultHeapUpdateEnabled"; //$NON-NLS-1$
+
+ public final static String ATTR_THREAD_INTERVAL =
+ DdmsPlugin.PLUGIN_ID + ".threadStatusInterval"; //$NON-NLS-1$
+
+ public final static String ATTR_IMAGE_SAVE_DIR =
+ DdmsPlugin.PLUGIN_ID + ".imageSaveDir"; //$NON-NLS-1$
+
+ public final static String ATTR_LAST_IMAGE_SAVE_DIR =
+ DdmsPlugin.PLUGIN_ID + ".lastImageSaveDir"; //$NON-NLS-1$
+
+ public final static String ATTR_LOGCAT_FONT =
+ DdmsPlugin.PLUGIN_ID + ".logcatFont"; //$NON-NLS-1$
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer
+ * #initializeDefaultPreferences()
+ */
+ @Override
+ public void initializeDefaultPreferences() {
+ IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
+
+ store.setDefault(ATTR_DEBUG_PORT_BASE, DdmPreferences.DEFAULT_DEBUG_PORT_BASE);
+
+ store.setDefault(ATTR_SELECTED_DEBUG_PORT, DdmPreferences.DEFAULT_SELECTED_DEBUG_PORT);
+
+ store.setDefault(ATTR_DEFAULT_THREAD_UPDATE, DdmPreferences.DEFAULT_INITIAL_THREAD_UPDATE);
+ store.setDefault(ATTR_DEFAULT_HEAP_UPDATE,
+ DdmPreferences.DEFAULT_INITIAL_HEAP_UPDATE);
+
+ store.setDefault(ATTR_THREAD_INTERVAL, DdmUiPreferences.DEFAULT_THREAD_REFRESH_INTERVAL);
+
+ String homeDir = System.getProperty("user.home"); //$NON-NLS-1$
+ store.setDefault(ATTR_IMAGE_SAVE_DIR, homeDir);
+
+ store.setDefault(ATTR_LOG_LEVEL, DdmPreferences.DEFAULT_LOG_LEVEL.getStringValue());
+
+ store.setDefault(ATTR_LOGCAT_FONT,
+ new FontData("Courier", 10, SWT.NORMAL).toString()); //$NON-NLS-1$
+ }
+
+ /**
+ * Initializes the preferences of ddmlib and ddmuilib with values from the eclipse store.
+ */
+ public synchronized static void setupPreferences() {
+ IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
+
+ DdmPreferences.setDebugPortBase(store.getInt(ATTR_DEBUG_PORT_BASE));
+ DdmPreferences.setSelectedDebugPort(store.getInt(ATTR_SELECTED_DEBUG_PORT));
+ DdmPreferences.setLogLevel(store.getString(ATTR_LOG_LEVEL));
+ DdmPreferences.setInitialThreadUpdate(store.getBoolean(ATTR_DEFAULT_THREAD_UPDATE));
+ DdmPreferences.setInitialHeapUpdate(store.getBoolean(ATTR_DEFAULT_HEAP_UPDATE));
+ DdmUiPreferences.setThreadRefreshInterval(store.getInt(ATTR_THREAD_INTERVAL));
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java
new file mode 100644
index 0000000..86e87c7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 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.preferences;
+
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmuilib.PortFieldEditor;
+
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.IntegerFieldEditor;
+import org.eclipse.jface.preference.RadioGroupFieldEditor;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class PreferencePage extends FieldEditorPreferencePage implements
+ IWorkbenchPreferencePage {
+
+ public PreferencePage() {
+ super(GRID);
+ setPreferenceStore(DdmsPlugin.getDefault().getPreferenceStore());
+ }
+
+ /**
+ * Creates the field editors. Field editors are abstractions of the common
+ * GUI blocks needed to manipulate various types of preferences. Each field
+ * editor knows how to save and restore itself.
+ */
+ @Override
+ public void createFieldEditors() {
+ IntegerFieldEditor ife;
+
+ ife = new PortFieldEditor(PreferenceInitializer.ATTR_DEBUG_PORT_BASE,
+ "ADB debugger base port:", getFieldEditorParent());
+ addField(ife);
+
+ BooleanFieldEditor bfe;
+
+ bfe = new BooleanFieldEditor(PreferenceInitializer.ATTR_DEFAULT_THREAD_UPDATE,
+ "Thread updates enabled by default", getFieldEditorParent());
+ addField(bfe);
+
+ bfe = new BooleanFieldEditor(PreferenceInitializer.ATTR_DEFAULT_HEAP_UPDATE,
+ "Heap updates enabled by default", getFieldEditorParent());
+ addField(bfe);
+
+ ife = new IntegerFieldEditor(PreferenceInitializer.ATTR_THREAD_INTERVAL,
+ "Thread status refresh interval (seconds):", getFieldEditorParent());
+ ife.setValidRange(1, 60);
+ addField(ife);
+
+ RadioGroupFieldEditor rgfe = new RadioGroupFieldEditor(PreferenceInitializer.ATTR_LOG_LEVEL,
+ "Logging Level", 1, new String[][] {
+ { "Verbose", LogLevel.VERBOSE.getStringValue() },
+ { "Debug", LogLevel.DEBUG.getStringValue() },
+ { "Info", LogLevel.INFO.getStringValue() },
+ { "Warning", LogLevel.WARN.getStringValue() },
+ { "Error", LogLevel.ERROR.getStringValue() },
+ { "Assert", LogLevel.ASSERT.getStringValue() }
+ },
+ getFieldEditorParent(), true);
+ addField(rgfe);
+
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+}
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
new file mode 100644
index 0000000..62a528a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2008 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.views;
+
+import com.android.ddmlib.Client;
+import com.android.ddmlib.ClientData;
+import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.Device;
+import com.android.ddmuilib.DevicePanel;
+import com.android.ddmuilib.ScreenShotDialog;
+import com.android.ddmuilib.DevicePanel.IUiSelectionListener;
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.DdmsPlugin.IDebugLauncher;
+
+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.MessageDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+
+public class DeviceView extends ViewPart implements IUiSelectionListener {
+
+ private final static boolean USE_SELECTED_DEBUG_PORT = true;
+
+ public static final String ID =
+ "com.android.ide.eclipse.ddms.views.DeviceView"; //$NON-NLS-1$
+
+ private DevicePanel mDeviceList;
+ private Action mResetAdbAction;
+ private Action mCaptureAction;
+ private Action mUpdateThreadAction;
+ private Action mUpdateHeapAction;
+ private Action mGcAction;
+ private Action mKillAppAction;
+ private Action mDebugAction;
+ private IDebugLauncher mDebugLauncher;
+
+ private static DeviceView sThis;
+
+ public DeviceView() {
+ // the view is declared with allowMultiple="false" so we
+ // can safely do this.
+ sThis = this;
+ }
+
+ public static DeviceView getInstance() {
+ return sThis;
+ }
+
+ /**
+ * Sets the {@link IDebugLauncher}.
+ * @param debugLauncher
+ */
+ public void setDebugLauncher(DdmsPlugin.IDebugLauncher debugLauncher) {
+ mDebugLauncher = debugLauncher;
+ if (mDebugAction != null && mDeviceList != null) {
+ Client currentClient = mDeviceList.getSelectedClient();
+ if (currentClient != null) {
+ mDebugAction.setEnabled(true);
+ }
+ }
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ mDeviceList = new DevicePanel(DdmsPlugin.getImageLoader(), USE_SELECTED_DEBUG_PORT);
+ mDeviceList.createPanel(parent);
+ mDeviceList.addSelectionListener(this);
+
+ DdmsPlugin plugin = DdmsPlugin.getDefault();
+ mDeviceList.addSelectionListener(plugin);
+ plugin.setListeningState(true);
+
+ mCaptureAction = new Action("Screen Capture") {
+ @Override
+ public void run() {
+ ScreenShotDialog dlg = new ScreenShotDialog(
+ DdmsPlugin.getDisplay().getActiveShell());
+ dlg.open(mDeviceList.getSelectedDevice());
+ }
+ };
+ mCaptureAction.setToolTipText("Screen Capture");
+ mCaptureAction.setImageDescriptor(
+ DdmsPlugin.getImageLoader().loadDescriptor("capture.png")); //$NON-NLS-1$
+
+ mResetAdbAction = new Action("Reset adb") {
+ @Override
+ public void run() {
+ AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
+ if (bridge != null) {
+ if (bridge.restart() == false) {
+ // get the current Display
+ final Display display = DdmsPlugin.getDisplay();
+
+ // dialog box only run in ui thread..
+ display.asyncExec(new Runnable() {
+ public void run() {
+ Shell shell = display.getActiveShell();
+ MessageDialog.openError(shell, "Adb Error",
+ "Adb failed to restart!\n\nMake sure the plugin is properly configured.");
+ }
+ });
+ }
+ }
+ }
+ };
+ mResetAdbAction.setToolTipText("Reset the adb host daemon");
+ mResetAdbAction.setImageDescriptor(PlatformUI.getWorkbench()
+ .getSharedImages().getImageDescriptor(
+ ISharedImages.IMG_OBJS_WARN_TSK));
+
+ mKillAppAction = new Action() {
+ @Override
+ public void run() {
+ mDeviceList.killSelectedClient();
+ }
+ };
+
+ mKillAppAction.setText("Stop Process");
+ mKillAppAction.setToolTipText("Stop Process");
+ mKillAppAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor(DevicePanel.ICON_HALT));
+
+ mGcAction = new Action() {
+ @Override
+ public void run() {
+ mDeviceList.forceGcOnSelectedClient();
+ }
+ };
+
+ mGcAction.setText("Cause GC");
+ mGcAction.setToolTipText("Cause GC");
+ mGcAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor(DevicePanel.ICON_GC));
+
+ mUpdateHeapAction = new Action("Update Heap", IAction.AS_CHECK_BOX) {
+ @Override
+ public void run() {
+ boolean enable = mUpdateHeapAction.isChecked();
+ mDeviceList.setEnabledHeapOnSelectedClient(enable);
+ }
+ };
+ mUpdateHeapAction.setToolTipText("Update Heap");
+ mUpdateHeapAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor(DevicePanel.ICON_HEAP));
+
+ mUpdateThreadAction = new Action("Update Threads", IAction.AS_CHECK_BOX) {
+ @Override
+ public void run() {
+ boolean enable = mUpdateThreadAction.isChecked();
+ mDeviceList.setEnabledThreadOnSelectedClient(enable);
+ }
+ };
+ mUpdateThreadAction.setToolTipText("Update Threads");
+ mUpdateThreadAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor(DevicePanel.ICON_THREAD));
+
+ // check if there's already a debug launcher set up in the plugin class
+ mDebugLauncher = DdmsPlugin.getRunningAppDebugLauncher();
+
+ mDebugAction = new Action("Debug Process") {
+ @Override
+ public void run() {
+ if (mDebugLauncher != null) {
+ Client currentClient = mDeviceList.getSelectedClient();
+ if (currentClient != null) {
+ ClientData clientData = currentClient.getClientData();
+
+ // make sure the client can be debugged
+ switch (clientData.getDebuggerConnectionStatus()) {
+ case ClientData.DEBUGGER_ERROR: {
+ Display display = DdmsPlugin.getDisplay();
+ Shell shell = display.getActiveShell();
+ MessageDialog.openError(shell, "Process Debug",
+ "The process debug port is already in use!");
+ return;
+ }
+ case ClientData.DEBUGGER_ATTACHED: {
+ Display display = DdmsPlugin.getDisplay();
+ Shell shell = display.getActiveShell();
+ MessageDialog.openError(shell, "Process Debug",
+ "The process is already being debugged!");
+ return;
+ }
+ }
+
+ // get the name of the client
+ String packageName = clientData.getClientDescription();
+ if (packageName != null) {
+ if (mDebugLauncher.debug(packageName,
+ currentClient.getDebuggerListenPort()) == false) {
+
+ // if we get to this point, then we failed to find a project
+ // that matched the application to debug
+ Display display = DdmsPlugin.getDisplay();
+ Shell shell = display.getActiveShell();
+ MessageDialog.openError(shell, "Process Debug",
+ String.format(
+ "No opened project found for %1$s. Debug session failed!",
+ packageName));
+ }
+ }
+ }
+ }
+ }
+ };
+ mDebugAction.setToolTipText("Debug the selected process, provided its source project is present and opened in the workspace.");
+ mDebugAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor("debug-attach.png")); //$NON-NLS-1$
+ if (mDebugLauncher == null) {
+ mDebugAction.setEnabled(false);
+ }
+
+ placeActions();
+ }
+
+ @Override
+ public void setFocus() {
+ mDeviceList.setFocus();
+ }
+
+ /**
+ * Sent when a new {@link Device} and {@link Client} are selected.
+ * @param selectedDevice the selected device. If null, no devices are selected.
+ * @param selectedClient The selected client. If null, no clients are selected.
+ */
+ public void selectionChanged(Device selectedDevice, Client selectedClient) {
+ // update the buttons
+ doSelectionChanged(selectedClient);
+ doSelectionChanged(selectedDevice);
+ }
+
+ private void doSelectionChanged(Client selectedClient) {
+ // update the buttons
+ if (selectedClient != null) {
+ if (USE_SELECTED_DEBUG_PORT) {
+ // set the client as the debug client
+ selectedClient.setAsSelectedClient();
+ }
+
+ mDebugAction.setEnabled(mDebugLauncher != null);
+ mKillAppAction.setEnabled(true);
+ mGcAction.setEnabled(true);
+
+ mUpdateHeapAction.setEnabled(true);
+ mUpdateHeapAction.setChecked(selectedClient.isHeapUpdateEnabled());
+
+ mUpdateThreadAction.setEnabled(true);
+ mUpdateThreadAction.setChecked(selectedClient.isThreadUpdateEnabled());
+ } else {
+ if (USE_SELECTED_DEBUG_PORT) {
+ // set the client as the debug client
+ AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
+ if (bridge != null) {
+ bridge.setSelectedClient(null);
+ }
+ }
+
+ mDebugAction.setEnabled(false);
+ mKillAppAction.setEnabled(false);
+ mGcAction.setEnabled(false);
+ mUpdateHeapAction.setChecked(false);
+ mUpdateHeapAction.setEnabled(false);
+ mUpdateThreadAction.setEnabled(false);
+ mUpdateThreadAction.setChecked(false);
+ }
+ }
+
+ private void doSelectionChanged(Device selectedDevice) {
+ mCaptureAction.setEnabled(selectedDevice != null);
+ }
+
+ /**
+ * Place the actions in the ui.
+ */
+ private final void placeActions() {
+ IActionBars actionBars = getViewSite().getActionBars();
+
+ // first in the menu
+ IMenuManager menuManager = actionBars.getMenuManager();
+ menuManager.add(mDebugAction);
+ menuManager.add(new Separator());
+ menuManager.add(mUpdateThreadAction);
+ menuManager.add(mUpdateHeapAction);
+ menuManager.add(new Separator());
+ menuManager.add(mGcAction);
+ menuManager.add(new Separator());
+ menuManager.add(mKillAppAction);
+ menuManager.add(new Separator());
+ menuManager.add(mCaptureAction);
+ menuManager.add(new Separator());
+ menuManager.add(mResetAdbAction);
+
+ // and then in the toolbar
+ IToolBarManager toolBarManager = actionBars.getToolBarManager();
+ toolBarManager.add(mDebugAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(mUpdateThreadAction);
+ toolBarManager.add(mUpdateHeapAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(mKillAppAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(mCaptureAction);
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EmulatorControlView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EmulatorControlView.java
new file mode 100644
index 0000000..ca9a691
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EmulatorControlView.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ddmuilib.EmulatorControlPanel;
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class EmulatorControlView extends SelectionDependentViewPart {
+
+ public static final String ID =
+ "com.android.ide.eclipse.ddms.views.EmulatorControlView"; //$NON-NLS-1$
+
+ private EmulatorControlPanel mPanel;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ mPanel = new EmulatorControlPanel(DdmsPlugin.getImageLoader());
+ mPanel.createPanel(parent);
+ setSelectionDependentPanel(mPanel);
+ }
+
+ @Override
+ public void setFocus() {
+ mPanel.setFocus();
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EventLogView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EventLogView.java
new file mode 100644
index 0000000..3a74e42
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EventLogView.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2008 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.views;
+
+import com.android.ddmuilib.log.event.EventLogPanel;
+import com.android.ide.eclipse.ddms.CommonAction;
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.ImageLoader;
+
+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.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+
+public class EventLogView extends SelectionDependentViewPart {
+
+ private EventLogPanel mLogPanel;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ ImageLoader loader = DdmsPlugin.getImageLoader();
+
+ // create the external actions
+ CommonAction optionsAction = new CommonAction("Options...");
+ optionsAction.setToolTipText("Opens the options panel");
+ optionsAction.setImageDescriptor(loader
+ .loadDescriptor("edit.png")); // $NON-NLS-1$
+
+ CommonAction clearLogAction = new CommonAction("Clear Log");
+ clearLogAction.setToolTipText("Clears the event log");
+ clearLogAction.setImageDescriptor(loader
+ .loadDescriptor("clear.png")); // $NON-NLS-1$
+
+ CommonAction saveAction = new CommonAction("Save Log");
+ saveAction.setToolTipText("Saves the event log");
+ saveAction.setImageDescriptor(loader
+ .loadDescriptor("save.png")); // $NON-NLS-1$
+
+ CommonAction loadAction = new CommonAction("Load Log");
+ loadAction.setToolTipText("Loads an event log");
+ loadAction.setImageDescriptor(loader
+ .loadDescriptor("load.png")); // $NON-NLS-1$
+
+ CommonAction importBugAction = new CommonAction("Import Bug Report Log");
+ importBugAction.setToolTipText("Imports a bug report.");
+ importBugAction.setImageDescriptor(loader
+ .loadDescriptor("importBug.png")); // $NON-NLS-1$
+
+ placeActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction);
+
+ mLogPanel = new EventLogPanel(DdmsPlugin.getImageLoader());
+ mLogPanel.setActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction);
+ mLogPanel.createPanel(parent);
+ setSelectionDependentPanel(mLogPanel);
+ }
+
+ @Override
+ public void setFocus() {
+ mLogPanel.setFocus();
+ }
+
+ @Override
+ public void dispose() {
+ if (mLogPanel != null) {
+ mLogPanel.stopEventLog(true);
+ }
+ }
+
+ /**
+ * Places the actions in the toolbar and in the menu.
+ * @param importBugAction
+ */
+ private void placeActions(IAction optionAction, IAction clearAction, IAction saveAction,
+ IAction loadAction, CommonAction importBugAction) {
+ IActionBars actionBars = getViewSite().getActionBars();
+
+ // first in the menu
+ IMenuManager menuManager = actionBars.getMenuManager();
+ menuManager.add(clearAction);
+ menuManager.add(new Separator());
+ menuManager.add(saveAction);
+ menuManager.add(loadAction);
+ menuManager.add(importBugAction);
+ menuManager.add(new Separator());
+ menuManager.add(optionAction);
+
+ // and then in the toolbar
+ IToolBarManager toolBarManager = actionBars.getToolBarManager();
+ toolBarManager.add(clearAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(saveAction);
+ toolBarManager.add(loadAction);
+ toolBarManager.add(importBugAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(optionAction);
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/FileExplorerView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/FileExplorerView.java
new file mode 100644
index 0000000..4f0dd2e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/FileExplorerView.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ddmlib.Client;
+import com.android.ddmlib.Device;
+import com.android.ddmuilib.explorer.DeviceExplorer;
+import com.android.ide.eclipse.ddms.CommonAction;
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.DdmsPlugin.ISelectionListener;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+
+public class FileExplorerView extends ViewPart implements ISelectionListener {
+
+ public static final String ID =
+ "com.android.ide.eclipse.ddms.views.FileExplorerView"; //$NON-NLS-1$
+
+ private final static String COLUMN_NAME =
+ DdmsPlugin.PLUGIN_ID + ".explorer.name"; //$NON-NLS-1S
+ private final static String COLUMN_SIZE =
+ DdmsPlugin.PLUGIN_ID + ".explorer.size"; //$NON-NLS-1S
+ private final static String COLUMN_DATE =
+ DdmsPlugin.PLUGIN_ID + ".explorer.data"; //$NON-NLS-1S
+ private final static String COLUMN_TIME =
+ DdmsPlugin.PLUGIN_ID + ".explorer.time"; //$NON-NLS-1S
+ private final static String COLUMN_PERMISSIONS =
+ DdmsPlugin.PLUGIN_ID +".explorer.permissions"; //$NON-NLS-1S
+ private final static String COLUMN_INFO =
+ DdmsPlugin.PLUGIN_ID + ".explorer.info"; //$NON-NLS-1$
+
+ private DeviceExplorer mExplorer;
+
+ public FileExplorerView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ DeviceExplorer.COLUMN_NAME = COLUMN_NAME;
+ DeviceExplorer.COLUMN_SIZE = COLUMN_SIZE;
+ DeviceExplorer.COLUMN_DATE = COLUMN_DATE;
+ DeviceExplorer.COLUMN_TIME = COLUMN_TIME;
+ DeviceExplorer.COLUMN_PERMISSIONS = COLUMN_PERMISSIONS;
+ DeviceExplorer.COLUMN_INFO = COLUMN_INFO;
+
+ // device explorer
+ mExplorer = new DeviceExplorer();
+
+
+ mExplorer.setImages(PlatformUI.getWorkbench()
+ .getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE),
+ PlatformUI.getWorkbench() .getSharedImages().getImage(
+ ISharedImages.IMG_OBJ_FOLDER),
+ DdmsPlugin.getImageLoader().loadDescriptor("android.png") //$NON-NLS-1$
+ .createImage(),
+ PlatformUI.getWorkbench() .getSharedImages().getImage(
+ ISharedImages.IMG_OBJ_ELEMENT));
+
+ // creates the actions
+ CommonAction pushAction = new CommonAction("Push File...") {
+ @Override
+ public void run() {
+ mExplorer.pushIntoSelection();
+ }
+ };
+ pushAction.setToolTipText("Push a file onto the device");
+ pushAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor("push.png")); //$NON-NLS-1$
+ pushAction.setEnabled(false);
+
+ CommonAction pullAction = new CommonAction("Pull File...") {
+ @Override
+ public void run() {
+ mExplorer.pullSelection();
+ }
+ };
+ pullAction.setToolTipText("Pull a file from the device");
+ pullAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor("pull.png")); //$NON-NLS-1$
+ pullAction.setEnabled(false);
+
+ CommonAction deleteAction = new CommonAction("Delete") {
+ @Override
+ public void run() {
+ mExplorer.deleteSelection();
+ }
+ };
+ deleteAction.setToolTipText("Delete the selection");
+ deleteAction.setImageDescriptor(DdmsPlugin.getImageLoader()
+ .loadDescriptor("delete.png")); //$NON-NLS-1$
+ deleteAction.setEnabled(false);
+
+ // set up the actions in the explorer
+ mExplorer.setActions(pushAction, pullAction, deleteAction);
+
+ // and in the ui
+ IActionBars actionBars = getViewSite().getActionBars();
+ IMenuManager menuManager = actionBars.getMenuManager();
+ IToolBarManager toolBarManager = actionBars.getToolBarManager();
+
+ menuManager.add(pullAction);
+ menuManager.add(pushAction);
+ menuManager.add(new Separator());
+ menuManager.add(deleteAction);
+
+ toolBarManager.add(pullAction);
+ toolBarManager.add(pushAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(deleteAction);
+
+ mExplorer.createPanel(parent);
+
+ DdmsPlugin.getDefault().addSelectionListener(this);
+ }
+
+ @Override
+ public void setFocus() {
+ mExplorer.setFocus();
+ }
+
+ /**
+ * Sent when a new {@link Client} is selected.
+ * @param selectedClient The selected client.
+ */
+ public void selectionChanged(Client selectedClient) {
+ // pass
+ }
+
+ /**
+ * Sent when a new {@link Device} is selected.
+ * @param selectedDevice the selected device.
+ */
+ public void selectionChanged(Device selectedDevice) {
+ mExplorer.switchDevice(selectedDevice);
+ }
+
+ /**
+ * Sent when there is no current selection.
+ */
+ public void selectionRemoved() {
+
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/HeapView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/HeapView.java
new file mode 100644
index 0000000..5745e8e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/HeapView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ddmuilib.HeapPanel;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class HeapView extends TableView {
+
+ public static final String ID = "com.android.ide.eclipse.ddms.views.HeapView"; //$NON-NLS-1$
+ private HeapPanel mPanel;
+
+ public HeapView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ mPanel = new HeapPanel();
+ mPanel.createPanel(parent);
+
+ setSelectionDependentPanel(mPanel);
+
+ // listen to focus changes for table(s) of the panel.
+ setupTableFocusListener(mPanel, parent);
+ }
+
+ @Override
+ public void setFocus() {
+ mPanel.setFocus();
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
new file mode 100644
index 0000000..d3053f1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ide.eclipse.ddms.CommonAction;
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.ImageLoader;
+import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmuilib.logcat.LogColors;
+import com.android.ddmuilib.logcat.LogFilter;
+import com.android.ddmuilib.logcat.LogPanel;
+import com.android.ddmuilib.logcat.LogPanel.ILogFilterStorageManager;
+
+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.swt.dnd.Clipboard;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.actions.ActionFactory;
+
+import java.util.ArrayList;
+
+/**
+ * The log cat view displays log output from the current device selection.
+ *
+ */
+public final class LogCatView extends SelectionDependentViewPart {
+
+ public static final String ID =
+ "com.android.ide.eclipse.ddms.views.LogCatView"; // $NON-NLS-1$
+
+ private static final String PREFS_COL_TIME =
+ DdmsPlugin.PLUGIN_ID + ".logcat.time"; // $NON-NLS-1$
+ private static final String PREFS_COL_LEVEL =
+ DdmsPlugin.PLUGIN_ID + ".logcat.level"; // $NON-NLS-1$
+ private static final String PREFS_COL_PID =
+ DdmsPlugin.PLUGIN_ID + ".logcat.pid"; // $NON-NLS-1$
+ private static final String PREFS_COL_TAG =
+ DdmsPlugin.PLUGIN_ID + ".logcat.tag"; // $NON-NLS-1$
+ private static final String PREFS_COL_MESSAGE =
+ DdmsPlugin.PLUGIN_ID + ".logcat.message"; // $NON-NLS-1$
+
+ private static final String PREFS_FILTERS =
+ DdmsPlugin.PLUGIN_ID + ".logcat.filters"; // $NON-NLS-1$
+
+ private static LogCatView sThis;
+ private LogPanel mLogPanel;
+
+ private CommonAction mCreateFilterAction;
+ private CommonAction mDeleteFilterAction;
+ private CommonAction mEditFilterAction;
+ private CommonAction mExportAction;
+
+ private CommonAction[] mLogLevelActions;
+ private String[] mLogLevelIcons = {
+ "v.png", //$NON-NLS-1S
+ "d.png", //$NON-NLS-1S
+ "i.png", //$NON-NLS-1S
+ "w.png", //$NON-NLS-1S
+ "e.png", //$NON-NLS-1S
+ };
+
+ private Action mClearAction;
+
+ private Clipboard mClipboard;
+
+ /**
+ * An implementation of {@link ILogFilterStorageManager} to bridge to the eclipse preference
+ * store, and saves the log filters.
+ */
+ private final class FilterStorage implements ILogFilterStorageManager {
+
+ public LogFilter[] getFilterFromStore() {
+ String filterPrefs = DdmsPlugin.getDefault().getPreferenceStore().getString(
+ PREFS_FILTERS);
+
+ // split in a string per filter
+ String[] filters = filterPrefs.split("\\|"); // $NON-NLS-1$
+
+ ArrayList<LogFilter> list =
+ new ArrayList<LogFilter>(filters.length);
+
+ for (String f : filters) {
+ if (f.length() > 0) {
+ LogFilter logFilter = new LogFilter();
+ if (logFilter.loadFromString(f)) {
+ list.add(logFilter);
+ }
+ }
+ }
+
+ return list.toArray(new LogFilter[list.size()]);
+ }
+
+ public void saveFilters(LogFilter[] filters) {
+ StringBuilder sb = new StringBuilder();
+ for (LogFilter f : filters) {
+ String filterString = f.toString();
+ sb.append(filterString);
+ sb.append('|');
+ }
+
+ DdmsPlugin.getDefault().getPreferenceStore().setValue(PREFS_FILTERS, sb.toString());
+ }
+
+ public boolean requiresDefaultFilter() {
+ return true;
+ }
+ }
+
+ public LogCatView() {
+ sThis = this;
+ LogPanel.PREFS_TIME = PREFS_COL_TIME;
+ LogPanel.PREFS_LEVEL = PREFS_COL_LEVEL;
+ LogPanel.PREFS_PID = PREFS_COL_PID;
+ LogPanel.PREFS_TAG = PREFS_COL_TAG;
+ LogPanel.PREFS_MESSAGE = PREFS_COL_MESSAGE;
+ }
+
+ /**
+ * Returns the singleton instance.
+ */
+ public static LogCatView getInstance() {
+ return sThis;
+ }
+
+ /**
+ * Sets the display font.
+ * @param font The font.
+ */
+ public static void setFont(Font font) {
+ if (sThis != null && sThis.mLogPanel != null) {
+ sThis.mLogPanel.setFont(font);
+ }
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ Display d = parent.getDisplay();
+ LogColors colors = new LogColors();
+
+ ImageLoader loader = DdmsPlugin.getImageLoader();
+
+ colors.infoColor = new Color(d, 0, 127, 0);
+ colors.debugColor = new Color(d, 0, 0, 127);
+ colors.errorColor = new Color(d, 255, 0, 0);
+ colors.warningColor = new Color(d, 255, 127, 0);
+ colors.verboseColor = new Color(d, 0, 0, 0);
+
+ mCreateFilterAction = new CommonAction("Create Filter") {
+ @Override
+ public void run() {
+ mLogPanel.addFilter();
+ }
+ };
+ mCreateFilterAction.setToolTipText("Create Filter");
+ mCreateFilterAction.setImageDescriptor(loader
+ .loadDescriptor("add.png")); // $NON-NLS-1$
+
+ mEditFilterAction = new CommonAction("Edit Filter") {
+ @Override
+ public void run() {
+ mLogPanel.editFilter();
+ }
+ };
+ mEditFilterAction.setToolTipText("Edit Filter");
+ mEditFilterAction.setImageDescriptor(loader
+ .loadDescriptor("edit.png")); // $NON-NLS-1$
+
+ mDeleteFilterAction = new CommonAction("Delete Filter") {
+ @Override
+ public void run() {
+ mLogPanel.deleteFilter();
+ }
+ };
+ mDeleteFilterAction.setToolTipText("Delete Filter");
+ mDeleteFilterAction.setImageDescriptor(loader
+ .loadDescriptor("delete.png")); // $NON-NLS-1$
+
+ mExportAction = new CommonAction("Export Selection As Text...") {
+ @Override
+ public void run() {
+ mLogPanel.save();
+ }
+ };
+ mExportAction.setToolTipText("Export Selection As Text...");
+ mExportAction.setImageDescriptor(loader.loadDescriptor("save.png")); // $NON-NLS-1$
+
+ LogLevel[] levels = LogLevel.values();
+ mLogLevelActions = new CommonAction[mLogLevelIcons.length];
+ for (int i = 0 ; i < mLogLevelActions.length; i++) {
+ String name = levels[i].getStringValue();
+ mLogLevelActions[i] = new CommonAction(name, IAction.AS_CHECK_BOX) {
+ @Override
+ public void run() {
+ // disable the other actions and record current index
+ for (int i = 0 ; i < mLogLevelActions.length; i++) {
+ Action a = mLogLevelActions[i];
+ if (a == this) {
+ a.setChecked(true);
+
+ // set the log level
+ mLogPanel.setCurrentFilterLogLevel(i+2);
+ } else {
+ a.setChecked(false);
+ }
+ }
+ }
+ };
+
+ mLogLevelActions[i].setToolTipText(name);
+ mLogLevelActions[i].setImageDescriptor(loader.loadDescriptor(mLogLevelIcons[i]));
+ }
+
+ mClearAction = new Action("Clear Log") {
+ @Override
+ public void run() {
+ mLogPanel.clear();
+ }
+ };
+ mClearAction.setImageDescriptor(loader
+ .loadDescriptor("clear.png")); // $NON-NLS-1$
+
+
+ // now create the log view
+ mLogPanel = new LogPanel(loader, colors, new FilterStorage(), LogPanel.FILTER_MANUAL);
+ mLogPanel.setActions(mDeleteFilterAction, mEditFilterAction, mLogLevelActions);
+
+ // get the font
+ String fontStr = DdmsPlugin.getDefault().getPreferenceStore().getString(
+ PreferenceInitializer.ATTR_LOGCAT_FONT);
+ if (fontStr != null) {
+ FontData data = new FontData(fontStr);
+
+ if (fontStr != null) {
+ mLogPanel.setFont(new Font(parent.getDisplay(), data));
+ }
+ }
+
+ mLogPanel.createPanel(parent);
+ setSelectionDependentPanel(mLogPanel);
+
+ // place the actions.
+ placeActions();
+
+ // setup the copy action
+ mClipboard = new Clipboard(d);
+ IActionBars actionBars = getViewSite().getActionBars();
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action("Copy") {
+ @Override
+ public void run() {
+ mLogPanel.copy(mClipboard);
+ }
+ });
+
+ // setup the select all action
+ actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
+ new Action("Select All") {
+ @Override
+ public void run() {
+ mLogPanel.selectAll();
+ }
+ });
+ }
+
+ @Override
+ public void dispose() {
+ mLogPanel.stopLogCat(true);
+ mClipboard.dispose();
+ }
+
+ @Override
+ public void setFocus() {
+ mLogPanel.setFocus();
+ }
+
+ /**
+ * Place the actions in the ui.
+ */
+ private void placeActions() {
+ IActionBars actionBars = getViewSite().getActionBars();
+
+ // first in the menu
+ IMenuManager menuManager = actionBars.getMenuManager();
+ menuManager.add(mCreateFilterAction);
+ menuManager.add(mEditFilterAction);
+ menuManager.add(mDeleteFilterAction);
+ menuManager.add(new Separator());
+ menuManager.add(mClearAction);
+ menuManager.add(new Separator());
+ menuManager.add(mExportAction);
+
+ // and then in the toolbar
+ IToolBarManager toolBarManager = actionBars.getToolBarManager();
+ for (CommonAction a : mLogLevelActions) {
+ toolBarManager.add(a);
+ }
+ toolBarManager.add(new Separator());
+ toolBarManager.add(mCreateFilterAction);
+ toolBarManager.add(mEditFilterAction);
+ toolBarManager.add(mDeleteFilterAction);
+ toolBarManager.add(new Separator());
+ toolBarManager.add(mClearAction);
+ }
+ }
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NativeHeapView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NativeHeapView.java
new file mode 100644
index 0000000..ed5aacb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NativeHeapView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ddmuilib.NativeHeapPanel;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class NativeHeapView extends TableView {
+
+ public static final String ID =
+ "com.android.ide.eclipse.ddms.views.NativeHeapView"; // $NON-NLS-1$
+ private NativeHeapPanel mPanel;
+
+ public NativeHeapView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ mPanel = new NativeHeapPanel();
+ mPanel.createPanel(parent);
+
+ setSelectionDependentPanel(mPanel);
+
+ // listen to focus changes for table(s) of the panel.
+ setupTableFocusListener(mPanel, parent);
+ }
+
+ @Override
+ public void setFocus() {
+ mPanel.setFocus();
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SelectionDependentViewPart.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SelectionDependentViewPart.java
new file mode 100644
index 0000000..48b2689
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SelectionDependentViewPart.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.DdmsPlugin.ISelectionListener;
+import com.android.ddmlib.Client;
+import com.android.ddmlib.Device;
+import com.android.ddmuilib.SelectionDependentPanel;
+
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * A Workbench {@link ViewPart} that requires {@link Device}/{@link Client} selection notifications
+ * from {@link DdmsPlugin} through the {@link ISelectionListener} interface.
+ */
+public abstract class SelectionDependentViewPart extends ViewPart implements ISelectionListener {
+
+ private SelectionDependentPanel mPanel;
+
+ protected final void setSelectionDependentPanel(SelectionDependentPanel panel) {
+ // remember the panel
+ mPanel = panel;
+
+ // and add ourself as listener of selection events.
+ DdmsPlugin.getDefault().addSelectionListener(this);
+ }
+
+ @Override
+ public void dispose() {
+ DdmsPlugin.getDefault().removeSelectionListener(this);
+ super.dispose();
+ }
+
+ /**
+ * Sent when a new {@link Client} is selected.
+ * @param selectedClient The selected client.
+ *
+ * @see ISelectionListener
+ */
+ public final void selectionChanged(Client selectedClient) {
+ mPanel.clientSelected(selectedClient);
+ }
+
+ /**
+ * Sent when a new {@link Device} is selected.
+ * @param selectedDevice the selected device.
+ *
+ * @see ISelectionListener
+ */
+ public final void selectionChanged(Device selectedDevice) {
+ mPanel.deviceSelected(selectedDevice);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/TableView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/TableView.java
new file mode 100644
index 0000000..0fda35d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/TableView.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ddmuilib.ITableFocusListener;
+import com.android.ddmuilib.TablePanel;
+import com.android.ddmuilib.ITableFocusListener.IFocusedTableActivator;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.actions.ActionFactory;
+
+/**
+ * Base class for view containing Table that needs to support copy, and select all.
+ */
+public abstract class TableView extends SelectionDependentViewPart {
+
+ /** Activator for the current Table that has the focus */
+ IFocusedTableActivator mActivator = null;
+
+ private Clipboard mClipboard;
+
+ private Action mCopyAction;
+ private Action mSelectAllAction;
+
+ /**
+ * Setup the listener for the Table objects of <code>Panel</code>, and setup
+ * the copy and select all actions.
+ * @param panel The panel to setup
+ * @param parent The parent composite of the Panel's content.
+ */
+ void setupTableFocusListener(TablePanel panel, Composite parent) {
+ panel.setTableFocusListener(new ITableFocusListener() {
+ public void focusGained(IFocusedTableActivator activator) {
+ mActivator = activator;
+ mCopyAction.setEnabled(true);
+ mSelectAllAction.setEnabled(true);
+ }
+
+ public void focusLost(IFocusedTableActivator activator) {
+ if (activator == mActivator) {
+ mActivator = null;
+ mCopyAction.setEnabled(false);
+ mSelectAllAction.setEnabled(false);
+ }
+ }
+ });
+
+ // setup the copy action
+ mClipboard = new Clipboard(parent.getDisplay());
+ IActionBars actionBars = getViewSite().getActionBars();
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(),
+ mCopyAction = new Action("Copy") {
+ @Override
+ public void run() {
+ if (mActivator != null) {
+ mActivator.copy(mClipboard);
+ }
+ }
+ });
+
+ // setup the select all action
+ actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
+ mSelectAllAction = new Action("Select All") {
+ @Override
+ public void run() {
+ if (mActivator != null) {
+ mActivator.selectAll();
+ }
+ }
+ });
+
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ mClipboard.dispose();
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/ThreadView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/ThreadView.java
new file mode 100644
index 0000000..cd24458
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/ThreadView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.views;
+
+import com.android.ddmuilib.ThreadPanel;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class ThreadView extends TableView {
+
+ public static final String ID =
+ "com.android.ide.eclipse.ddms.views.ThreadView"; // $NON-NLS-1$
+ private ThreadPanel mPanel;
+
+ public ThreadView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ mPanel = new ThreadPanel();
+ mPanel.createPanel(parent);
+
+ setSelectionDependentPanel(mPanel);
+
+ // listen to focus changes for table(s) of the panel.
+ setupTableFocusListener(mPanel, parent);
+ }
+
+ @Override
+ public void setFocus() {
+ mPanel.setFocus();
+ }
+}