diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views')
14 files changed, 2152 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/AllocTrackerView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/AllocTrackerView.java new file mode 100644 index 000000000..e8b73ff51 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/AllocTrackerView.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.AllocationPanel; + +import org.eclipse.swt.widgets.Composite; + +public class AllocTrackerView extends TableView { + + public static final String ID = "com.android.ide.eclipse.ddms.views.AllocTrackerView"; //$NON-NLS-1$ + private AllocationPanel mPanel; + + public AllocTrackerView() { + } + + @Override + public void createPartControl(Composite parent) { + mPanel = new AllocationPanel(); + 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/DeviceView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java new file mode 100644 index 000000000..c70c38803 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java @@ -0,0 +1,877 @@ +/* + * 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.AndroidDebugBridge; +import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; +import com.android.ddmlib.Client; +import com.android.ddmlib.ClientData; +import com.android.ddmlib.ClientData.IHprofDumpHandler; +import com.android.ddmlib.ClientData.MethodProfilingStatus; +import com.android.ddmlib.CollectingOutputReceiver; +import com.android.ddmlib.DdmPreferences; +import com.android.ddmlib.IDevice; +import com.android.ddmlib.SyncException; +import com.android.ddmlib.SyncService; +import com.android.ddmlib.SyncService.ISyncProgressMonitor; +import com.android.ddmlib.TimeoutException; +import com.android.ddmuilib.DevicePanel; +import com.android.ddmuilib.DevicePanel.IUiSelectionListener; +import com.android.ddmuilib.ImageLoader; +import com.android.ddmuilib.ScreenShotDialog; +import com.android.ddmuilib.SyncProgressHelper; +import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; +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.IClientAction; +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.ide.eclipse.ddms.systrace.ISystraceOptions; +import com.android.ide.eclipse.ddms.systrace.ISystraceOptionsDialog; +import com.android.ide.eclipse.ddms.systrace.SystraceOptionsDialogV1; +import com.android.ide.eclipse.ddms.systrace.SystraceOptionsDialogV2; +import com.android.ide.eclipse.ddms.systrace.SystraceOutputParser; +import com.android.ide.eclipse.ddms.systrace.SystraceTask; +import com.android.ide.eclipse.ddms.systrace.SystraceVersionDetector; +import com.android.uiautomator.UiAutomatorHelper; +import com.android.uiautomator.UiAutomatorHelper.UiAutomatorException; +import com.android.uiautomator.UiAutomatorHelper.UiAutomatorResult; +import com.google.common.io.Files; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +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; +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.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.ViewPart; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class DeviceView extends ViewPart implements IUiSelectionListener, IClientChangeListener { + + 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 static DeviceView sThis; + + private Shell mParentShell; + private DevicePanel mDeviceList; + + private Action mResetAdbAction; + private Action mCaptureAction; + private Action mViewUiAutomatorHierarchyAction; + private Action mSystraceAction; + private Action mUpdateThreadAction; + private Action mUpdateHeapAction; + private Action mGcAction; + private Action mKillAppAction; + private Action mDebugAction; + private Action mHprofAction; + private Action mTracingAction; + + private ImageDescriptor mTracingStartImage; + private ImageDescriptor mTracingStopImage; + + public class HProfHandler extends BaseFileHandler implements IHprofDumpHandler { + public final static String ACTION_SAVE = "hprof.save"; //$NON-NLS-1$ + public final static String ACTION_OPEN = "hprof.open"; //$NON-NLS-1$ + + public final static String DOT_HPROF = ".hprof"; //$NON-NLS-1$ + + HProfHandler(Shell parentShell) { + super(parentShell); + } + + @Override + protected String getDialogTitle() { + return Messages.DeviceView_HPROF_Error; + } + + @Override + public void onEndFailure(final Client client, final String message) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + try { + displayErrorFromUiThread( + Messages.DeviceView_Unable_Create_HPROF_For_Application, + client.getClientData().getClientDescription(), + message != null ? message + "\n\n" : ""); //$NON-NLS-1$ //$NON-NLS-2$ + } finally { + // this will make sure the dump hprof button is + // re-enabled for the + // current selection. as the client is finished dumping + // an hprof file + doSelectionChanged(mDeviceList.getSelectedClient()); + } + } + }); + } + + @Override + public void onSuccess(final String remoteFilePath, final Client client) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + final IDevice device = client.getDevice(); + try { + // get the sync service to pull the HPROF file + final SyncService sync = client.getDevice().getSyncService(); + if (sync != null) { + // get from the preference what action to take + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION); + + if (ACTION_OPEN.equals(value)) { + File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$ + final String tempPath = temp.getAbsolutePath(); + SyncProgressHelper.run(new SyncRunnable() { + + @Override + public void run(ISyncProgressMonitor monitor) + throws SyncException, IOException, + TimeoutException { + sync.pullFile(remoteFilePath, tempPath, monitor); + } + + @Override + public void close() { + sync.close(); + } + }, + String.format(Messages.DeviceView_Pulling_From_Device, + remoteFilePath), + mParentShell); + + open(tempPath); + } else { + // default action is ACTION_SAVE + promptAndPull(sync, + client.getClientData().getClientDescription() + DOT_HPROF, + remoteFilePath, Messages.DeviceView_Save_HPROF_File); + + } + } else { + displayErrorFromUiThread( + Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_First_Message, + device.getSerialNumber()); + } + } catch (SyncException e) { + if (e.wasCanceled() == false) { + displayErrorFromUiThread( + Messages.DeviceView_Unable_Download_HPROF_From_Device_Two_Param, + device.getSerialNumber(), e.getMessage()); + } + } catch (Exception e) { + displayErrorFromUiThread( + Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_Second_Message, + device.getSerialNumber()); + + } finally { + // this will make sure the dump hprof button is + // re-enabled for the + // current selection. as the client is finished dumping + // an hprof file + doSelectionChanged(mDeviceList.getSelectedClient()); + } + } + }); + } + + @Override + public void onSuccess(final byte[] data, final Client client) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + // get from the preference what action to take + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION); + + if (ACTION_OPEN.equals(value)) { + try { + // no need to give an extension since we're going to + // convert the + // file anyway after. + File tempFile = saveTempFile(data, null /* extension */); + open(tempFile.getAbsolutePath()); + } catch (Exception e) { + String errorMsg = e.getMessage(); + displayErrorFromUiThread( + Messages.DeviceView_Failed_To_Save_HPROF_Data, + errorMsg != null ? ":\n" + errorMsg : "."); //$NON-NLS-1$ //$NON-NLS-2$ + } + } else { + // default action is ACTION_SAVE + promptAndSave(client.getClientData().getClientDescription() + DOT_HPROF, + data, Messages.DeviceView_Save_HPROF_File); + } + } + }); + } + + private void open(String path) throws IOException, InterruptedException, PartInitException { + // make a temp file to convert the hprof into something + // readable by normal tools + File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$ + String tempPath = temp.getAbsolutePath(); + + String[] command = new String[3]; + command[0] = DdmsPlugin.getHprofConverter(); + command[1] = path; + command[2] = tempPath; + + Process p = Runtime.getRuntime().exec(command); + p.waitFor(); + + IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(tempPath)); + if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) { + // before we open the file in an editor window, we make sure the + // current + // workbench page has an editor area (typically the ddms + // perspective doesn't). + IWorkbench workbench = PlatformUI.getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IWorkbenchPage page = window.getActivePage(); + if (page == null) { + return; + } + + if (page.isEditorAreaVisible() == false) { + IAdaptable input; + input = page.getInput(); + try { + workbench.showPerspective("org.eclipse.debug.ui.DebugPerspective", //$NON-NLS-1$ + window, input); + } catch (WorkbenchException e) { + } + } + + IDE.openEditorOnFileStore(page, fileStore); + } + } + } + + public DeviceView() { + // the view is declared with allowMultiple="false" so we + // can safely do this. + sThis = this; + } + + public static DeviceView getInstance() { + return sThis; + } + + @Override + public void createPartControl(Composite parent) { + mParentShell = parent.getShell(); + + ImageLoader loader = ImageLoader.getDdmUiLibLoader(); + + mDeviceList = new DevicePanel(USE_SELECTED_DEBUG_PORT); + mDeviceList.createPanel(parent); + mDeviceList.addSelectionListener(this); + + DdmsPlugin plugin = DdmsPlugin.getDefault(); + mDeviceList.addSelectionListener(plugin); + plugin.setListeningState(true); + + mCaptureAction = new Action(Messages.DeviceView_Screen_Capture) { + @Override + public void run() { + ScreenShotDialog dlg = new ScreenShotDialog( + DdmsPlugin.getDisplay().getActiveShell()); + dlg.open(mDeviceList.getSelectedDevice()); + } + }; + 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$ + + mSystraceAction = new Action("Capture System Wide Trace") { + @Override + public void run() { + launchSystrace(mDeviceList.getSelectedDevice(), + DdmsPlugin.getDisplay().getActiveShell()); + } + }; + mSystraceAction.setToolTipText("Capture system wide trace using Android systrace"); + mSystraceAction.setImageDescriptor( + DdmsPlugin.getImageDescriptor("icons/systrace.png")); //$NON-NLS-1$ + mSystraceAction.setEnabled(true); + + mResetAdbAction = new Action(Messages.DeviceView_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() { + @Override + public void run() { + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, Messages.DeviceView_ADB_Error, + Messages.DeviceView_ADB_Failed_Restart); + } + }); + } + } + } + }; + mResetAdbAction.setToolTipText(Messages.DeviceView_Reset_ADB_Host_Deamon); + mResetAdbAction.setImageDescriptor(PlatformUI.getWorkbench() + .getSharedImages().getImageDescriptor( + ISharedImages.IMG_OBJS_WARN_TSK)); + + mKillAppAction = new Action() { + @Override + public void run() { + mDeviceList.killSelectedClient(); + } + }; + + mKillAppAction.setText(Messages.DeviceView_Stop_Process); + mKillAppAction.setToolTipText(Messages.DeviceView_Stop_Process_Tooltip); + mKillAppAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HALT)); + + mGcAction = new Action() { + @Override + public void run() { + mDeviceList.forceGcOnSelectedClient(); + } + }; + + mGcAction.setText(Messages.DeviceView_Cause_GC); + mGcAction.setToolTipText(Messages.DeviceView_Cause_GC_Tooltip); + mGcAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_GC)); + + mHprofAction = new Action() { + @Override + public void run() { + mDeviceList.dumpHprof(); + doSelectionChanged(mDeviceList.getSelectedClient()); + } + }; + mHprofAction.setText(Messages.DeviceView_Dump_HPROF_File); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File_Tooltip); + mHprofAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HPROF)); + + mUpdateHeapAction = new Action(Messages.DeviceView_Update_Heap, IAction.AS_CHECK_BOX) { + @Override + public void run() { + boolean enable = mUpdateHeapAction.isChecked(); + mDeviceList.setEnabledHeapOnSelectedClient(enable); + } + }; + mUpdateHeapAction.setToolTipText(Messages.DeviceView_Update_Heap_Tooltip); + mUpdateHeapAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HEAP)); + + mUpdateThreadAction = new Action(Messages.DeviceView_Threads, IAction.AS_CHECK_BOX) { + @Override + public void run() { + boolean enable = mUpdateThreadAction.isChecked(); + mDeviceList.setEnabledThreadOnSelectedClient(enable); + } + }; + mUpdateThreadAction.setToolTipText(Messages.DeviceView_Threads_Tooltip); + mUpdateThreadAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_THREAD)); + + mTracingAction = new Action() { + @Override + public void run() { + mDeviceList.toggleMethodProfiling(); + } + }; + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); + mTracingStartImage = loader.loadDescriptor(DevicePanel.ICON_TRACING_START); + mTracingStopImage = loader.loadDescriptor(DevicePanel.ICON_TRACING_STOP); + mTracingAction.setImageDescriptor(mTracingStartImage); + + mDebugAction = new Action(Messages.DeviceView_Debug_Process) { + @Override + public void run() { + if (DdmsPlugin.getDefault().hasDebuggerConnectors()) { + Client currentClient = mDeviceList.getSelectedClient(); + if (currentClient != null) { + ClientData clientData = currentClient.getClientData(); + + // make sure the client can be debugged + switch (clientData.getDebuggerConnectionStatus()) { + case ERROR: { + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, + Messages.DeviceView_Debug_Process_Title, + Messages.DeviceView_Process_Debug_Already_In_Use); + return; + } + case ATTACHED: { + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, + Messages.DeviceView_Debug_Process_Title, + Messages.DeviceView_Process_Already_Being_Debugged); + return; + } + } + + // get the name of the client + String packageName = clientData.getClientDescription(); + if (packageName != null) { + + // try all connectors till one returns true. + IDebuggerConnector[] connectors = + DdmsPlugin.getDefault().getDebuggerConnectors(); + + if (connectors != null) { + for (IDebuggerConnector connector : connectors) { + try { + if (connector.connectDebugger(packageName, + currentClient.getDebuggerListenPort(), + DdmPreferences.getSelectedDebugPort())) { + return; + } + } catch (Throwable t) { + // ignore, we'll just not use this + // implementation + } + } + } + + // 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, Messages.DeviceView_Debug_Process_Title, + String.format( + Messages.DeviceView_Debug_Session_Failed, + packageName)); + } + } + } + } + }; + mDebugAction.setToolTipText(Messages.DeviceView_Debug_Process_Tooltip); + mDebugAction.setImageDescriptor(loader.loadDescriptor("debug-attach.png")); //$NON-NLS-1$ + mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors()); + + placeActions(); + + // disabling all action buttons + selectionChanged(null, null); + + ClientData.setHprofDumpHandler(new HProfHandler(mParentShell)); + AndroidDebugBridge.addClientChangeListener(this); + ClientData.setMethodProfilingHandler(new MethodProfilingHandler(mParentShell) { + @Override + protected void open(String tempPath) { + if (DdmsPlugin.getDefault().launchTraceview(tempPath) == false) { + super.open(tempPath); + } + } + }); + } + + 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) { + Throwable t = e; + if (e instanceof InvocationTargetException) { + t = ((InvocationTargetException) e).getTargetException(); + } + Status s = new Status(IStatus.ERROR, DdmsPlugin.PLUGIN_ID, + "Error obtaining UI hierarchy", t); + ErrorDialog.openError(shell, "UI Automator", + "Unexpected error while obtaining UI hierarchy", s); + } + }; + + private void launchSystrace(final IDevice device, final Shell parentShell) { + final File systraceAssets = new File(DdmsPlugin.getPlatformToolsFolder(), "systrace"); //$NON-NLS-1$ + if (!systraceAssets.isDirectory()) { + MessageDialog.openError(parentShell, "Systrace", + "Updated version of platform-tools (18.0.1 or greater) is required.\n" + + "Please update your platform-tools using SDK Manager."); + return; + } + + SystraceVersionDetector detector = new SystraceVersionDetector(device); + try { + new ProgressMonitorDialog(parentShell).run(true, false, detector); + } catch (InvocationTargetException e) { + MessageDialog.openError(parentShell, + "Systrace", + "Unexpected error while detecting atrace version: " + e); + return; + } catch (InterruptedException e) { + return; + } + + final ISystraceOptionsDialog dlg; + if (detector.getVersion() == SystraceVersionDetector.SYSTRACE_V1) { + dlg = new SystraceOptionsDialogV1(parentShell); + } else { + Client[] clients = device.getClients(); + List<String> apps = new ArrayList<String>(clients.length); + for (int i = 0; i < clients.length; i++) { + String name = clients[i].getClientData().getClientDescription(); + if (name != null && !name.isEmpty()) { + apps.add(name); + } + } + dlg = new SystraceOptionsDialogV2(parentShell, detector.getTags(), apps); + } + + if (dlg.open() != SystraceOptionsDialogV1.OK) { + return; + } + + final ISystraceOptions options = dlg.getSystraceOptions(); + + // set trace tag if necessary: + // adb shell setprop debug.atrace.tags.enableflags <tag> + String tag = options.getTags(); + if (tag != null) { + CountDownLatch setTagLatch = new CountDownLatch(1); + CollectingOutputReceiver receiver = new CollectingOutputReceiver(setTagLatch); + try { + String cmd = "setprop debug.atrace.tags.enableflags " + tag; + device.executeShellCommand(cmd, receiver); + setTagLatch.await(5, TimeUnit.SECONDS); + } catch (Exception e) { + MessageDialog.openError(parentShell, + "Systrace", + "Unexpected error while setting trace tags: " + e); + return; + } + + String shellOutput = receiver.getOutput(); + if (shellOutput.contains("Error type")) { //$NON-NLS-1$ + throw new RuntimeException(receiver.getOutput()); + } + } + + // obtain the output of "adb shell atrace <trace-options>" and generate the html file + ProgressMonitorDialog d = new ProgressMonitorDialog(parentShell); + try { + d.run(true, true, new IRunnableWithProgress() { + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, + InterruptedException { + boolean COMPRESS_DATA = true; + + monitor.setTaskName("Collecting Trace Information"); + final String atraceOptions = options.getOptions() + + (COMPRESS_DATA ? " -z" : ""); + SystraceTask task = new SystraceTask(device, atraceOptions); + Thread t = new Thread(task, "Systrace Output Receiver"); + t.start(); + + // check if the user has cancelled tracing every so often + while (true) { + t.join(1000); + + if (t.isAlive()) { + if (monitor.isCanceled()) { + task.cancel(); + return; + } + } else { + break; + } + } + + if (task.getError() != null) { + throw new RuntimeException(task.getError()); + } + + monitor.setTaskName("Saving trace information"); + SystraceOutputParser parser = new SystraceOutputParser( + COMPRESS_DATA, + SystraceOutputParser.getJs(systraceAssets), + SystraceOutputParser.getCss(systraceAssets), + SystraceOutputParser.getHtmlPrefix(systraceAssets), + SystraceOutputParser.getHtmlSuffix(systraceAssets)); + + parser.parse(task.getAtraceOutput()); + + String html = parser.getSystraceHtml(); + try { + Files.write(html.getBytes(), new File(dlg.getTraceFilePath())); + } catch (IOException e) { + throw new InvocationTargetException(e); + } + } + }); + } catch (InvocationTargetException e) { + ErrorDialog.openError(parentShell, "Systrace", + "Unable to collect system trace.", + new Status(Status.ERROR, + DdmsPlugin.PLUGIN_ID, + "Unexpected error while collecting system trace.", + e.getCause())); + } catch (InterruptedException ignore) { + } + } + + @Override + public void setFocus() { + mDeviceList.setFocus(); + } + + /** + * Sent when a new {@link IDevice} 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. + */ + @Override + public void selectionChanged(IDevice 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(DdmsPlugin.getDefault().hasDebuggerConnectors()); + mKillAppAction.setEnabled(true); + mGcAction.setEnabled(true); + + mUpdateHeapAction.setEnabled(true); + mUpdateHeapAction.setChecked(selectedClient.isHeapUpdateEnabled()); + + mUpdateThreadAction.setEnabled(true); + mUpdateThreadAction.setChecked(selectedClient.isThreadUpdateEnabled()); + + ClientData data = selectedClient.getClientData(); + + if (data.hasFeature(ClientData.FEATURE_HPROF)) { + mHprofAction.setEnabled(data.hasPendingHprofDump() == false); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File); + } else { + mHprofAction.setEnabled(false); + mHprofAction + .setToolTipText(Messages.DeviceView_Dump_HPROF_File_Not_Supported_By_VM); + } + + if (data.hasFeature(ClientData.FEATURE_PROFILING)) { + mTracingAction.setEnabled(true); + if (data.getMethodProfilingStatus() == MethodProfilingStatus.TRACER_ON + || data.getMethodProfilingStatus() == MethodProfilingStatus.SAMPLER_ON) { + mTracingAction + .setToolTipText(Messages.DeviceView_Stop_Method_Profiling_Tooltip); + mTracingAction.setText(Messages.DeviceView_Stop_Method_Profiling); + mTracingAction.setImageDescriptor(mTracingStopImage); + } else { + mTracingAction + .setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); + mTracingAction.setImageDescriptor(mTracingStartImage); + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + } + } else { + mTracingAction.setEnabled(false); + mTracingAction.setImageDescriptor(mTracingStartImage); + mTracingAction + .setToolTipText(Messages.DeviceView_Start_Method_Profiling_Not_Suported_By_Vm); + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + } + } 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); + mHprofAction.setEnabled(false); + + mHprofAction.setEnabled(false); + mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File); + + mTracingAction.setEnabled(false); + mTracingAction.setImageDescriptor(mTracingStartImage); + mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip); + mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling); + } + + for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { + a.selectedClientChanged(selectedClient); + } + } + + private void doSelectionChanged(IDevice selectedDevice) { + boolean validDevice = selectedDevice != null; + + mCaptureAction.setEnabled(validDevice); + mViewUiAutomatorHierarchyAction.setEnabled(validDevice); + mSystraceAction.setEnabled(validDevice); + } + + /** + * Place the actions in the ui. + */ + private final void placeActions() { + IActionBars actionBars = getViewSite().getActionBars(); + + // first in the menu + IMenuManager menuManager = actionBars.getMenuManager(); + menuManager.removeAll(); + menuManager.add(mDebugAction); + menuManager.add(new Separator()); + menuManager.add(mUpdateHeapAction); + menuManager.add(mHprofAction); + menuManager.add(mGcAction); + menuManager.add(new Separator()); + menuManager.add(mUpdateThreadAction); + menuManager.add(mTracingAction); + menuManager.add(new Separator()); + menuManager.add(mKillAppAction); + menuManager.add(new Separator()); + menuManager.add(mCaptureAction); + menuManager.add(new Separator()); + menuManager.add(mViewUiAutomatorHierarchyAction); + menuManager.add(new Separator()); + menuManager.add(mSystraceAction); + menuManager.add(new Separator()); + menuManager.add(mResetAdbAction); + for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { + menuManager.add(a.getAction()); + } + + // and then in the toolbar + IToolBarManager toolBarManager = actionBars.getToolBarManager(); + toolBarManager.removeAll(); + toolBarManager.add(mDebugAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mUpdateHeapAction); + toolBarManager.add(mHprofAction); + toolBarManager.add(mGcAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mUpdateThreadAction); + toolBarManager.add(mTracingAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mKillAppAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mCaptureAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mViewUiAutomatorHierarchyAction); + toolBarManager.add(new Separator()); + toolBarManager.add(mSystraceAction); + for (IClientAction a : DdmsPlugin.getDefault().getClientSpecificActions()) { + toolBarManager.add(a.getAction()); + } + } + + @Override + public void clientChanged(final Client client, int changeMask) { + if ((changeMask & Client.CHANGE_METHOD_PROFILING_STATUS) == Client.CHANGE_METHOD_PROFILING_STATUS) { + if (mDeviceList.getSelectedClient() == client) { + mParentShell.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + // force refresh of the button enabled state. + doSelectionChanged(client); + } + }); + } + } + } +} 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 000000000..0dda7ef61 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EmulatorControlView.java @@ -0,0 +1,42 @@ +/* + * 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 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(); + 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 000000000..653f17f43 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/EventLogView.java @@ -0,0 +1,111 @@ +/* + * 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.ImageLoader; +import com.android.ddmuilib.log.event.EventLogPanel; +import com.android.ide.eclipse.ddms.CommonAction; +import com.android.ide.eclipse.ddms.i18n.Messages; + +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 = ImageLoader.getDdmUiLibLoader(); + + // create the external actions + CommonAction optionsAction = new CommonAction(Messages.EventLogView_Options); + optionsAction.setToolTipText(Messages.EventLogView_Opens_Options_Panel); + optionsAction.setImageDescriptor(loader.loadDescriptor("edit.png")); //$NON-NLS-1$ + + CommonAction clearLogAction = new CommonAction(Messages.EventLogView_Clear_Log); + clearLogAction.setToolTipText(Messages.EventLogView_Clears_Event_Log); + clearLogAction.setImageDescriptor(loader.loadDescriptor("clear.png")); //$NON-NLS-1$ + + CommonAction saveAction = new CommonAction(Messages.EventLogView_Save_Log); + saveAction.setToolTipText(Messages.EventLogView_Saves_Event_Log); + saveAction.setImageDescriptor(loader.loadDescriptor("save.png")); //$NON-NLS-1$ + + CommonAction loadAction = new CommonAction(Messages.EventLogView_Load_Log); + loadAction.setToolTipText(Messages.EventLogView_Loads_Event_Log); + loadAction.setImageDescriptor(loader.loadDescriptor("load.png")); //$NON-NLS-1$ + + CommonAction importBugAction = new CommonAction(Messages.EventLogView_Import_Bug_Report_Log); + importBugAction.setToolTipText(Messages.EventLogView_Imports_Bug_Report); + importBugAction.setImageDescriptor(loader.loadDescriptor("importBug.png")); //$NON-NLS-1$ + + placeActions(optionsAction, clearLogAction, saveAction, loadAction, importBugAction); + + mLogPanel = new EventLogPanel(); + 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 000000000..41796dcfd --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/FileExplorerView.java @@ -0,0 +1,181 @@ +/* + * 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.IDevice; +import com.android.ddmuilib.ImageLoader; +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 com.android.ide.eclipse.ddms.i18n.Messages; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.graphics.Device; +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) { + ImageLoader loader = ImageLoader.getDdmUiLibLoader(); + + 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.setCustomImages( + PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE), + PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER), + null /* apk image */, + PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT) + ); + + // creates the actions + CommonAction pushAction = new CommonAction(Messages.FileExplorerView_Push_File) { + @Override + public void run() { + mExplorer.pushIntoSelection(); + } + }; + pushAction.setToolTipText(Messages.FileExplorerView_Push_File_Onto_Device); + pushAction.setImageDescriptor(loader.loadDescriptor("push.png")); //$NON-NLS-1$ + pushAction.setEnabled(false); + + CommonAction pullAction = new CommonAction(Messages.FileExplorerView_Pull_File) { + @Override + public void run() { + mExplorer.pullSelection(); + } + }; + pullAction.setToolTipText(Messages.FileExplorerView_Pull_File_From_File); + pullAction.setImageDescriptor(loader.loadDescriptor("pull.png")); //$NON-NLS-1$ + pullAction.setEnabled(false); + + CommonAction deleteAction = new CommonAction(Messages.FileExplorerView_Delete) { + @Override + public void run() { + mExplorer.deleteSelection(); + } + }; + deleteAction.setToolTipText(Messages.FileExplorerView_Delete_The_Selection); + deleteAction.setImageDescriptor(loader.loadDescriptor("delete.png")); //$NON-NLS-1$ + deleteAction.setEnabled(false); + + CommonAction createNewFolderAction = new CommonAction("New Folder") { + @Override + public void run() { + mExplorer.createNewFolderInSelection(); + } + }; + createNewFolderAction.setToolTipText("New Folder"); + createNewFolderAction.setImageDescriptor(loader.loadDescriptor("add.png")); //$NON-NLS-1$ + createNewFolderAction.setEnabled(false); + + // set up the actions in the explorer + mExplorer.setActions(pushAction, pullAction, deleteAction, createNewFolderAction); + + // 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); + menuManager.add(new Separator()); + menuManager.add(createNewFolderAction); + + toolBarManager.add(pullAction); + toolBarManager.add(pushAction); + toolBarManager.add(new Separator()); + toolBarManager.add(deleteAction); + toolBarManager.add(new Separator()); + toolBarManager.add(createNewFolderAction); + + mExplorer.createPanel(parent); + + DdmsPlugin.getDefault().addSelectionListener(this); + } + + @Override + public void setFocus() { + mExplorer.setFocus(); + } + + /** + * Sent when a new {@link Client} is selected. + * + * @param selectedClient The selected client. + */ + @Override + public void selectionChanged(Client selectedClient) { + // pass + } + + /** + * Sent when a new {@link Device} is selected. + * + * @param selectedDevice the selected device. + */ + @Override + public void selectionChanged(IDevice 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 000000000..5745e8efc --- /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 000000000..9f78c4aa1 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2011 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.logcat.LogCatMessage; +import com.android.ddmuilib.logcat.ILogCatMessageSelectionListener; +import com.android.ddmuilib.logcat.LogCatPanel; +import com.android.ddmuilib.logcat.LogCatStackTraceParser; +import com.android.ide.eclipse.ddms.DdmsPlugin; +import com.android.ide.eclipse.ddms.JavaSourceRevealer; +import com.android.ide.eclipse.ddms.i18n.Messages; +import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.actions.ActionFactory; + +public class LogCatView extends SelectionDependentViewPart { + /** LogCatView ID as defined in plugin.xml. */ + public static final String ID = "com.android.ide.eclipse.ddms.views.LogCatView"; //$NON-NLS-1$ + + /** Switch perspective when a Java file is opened from logcat view. */ + public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true; + + /** Target perspective to open when a Java file is opened from logcat view. */ + public static final String DEFAULT_PERSPECTIVE_ID = + "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$ + + private LogCatPanel mLogCatPanel; + private LogCatStackTraceParser mStackTraceParser = new LogCatStackTraceParser(); + + private Clipboard mClipboard; + + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new FillLayout()); + + IPreferenceStore prefStore = DdmsPlugin.getDefault().getPreferenceStore(); + mLogCatPanel = new LogCatPanel(prefStore); + mLogCatPanel.createPanel(parent); + setSelectionDependentPanel(mLogCatPanel); + + mLogCatPanel.addLogCatMessageSelectionListener(new ILogCatMessageSelectionListener() { + @Override + public void messageDoubleClicked(LogCatMessage m) { + onDoubleClick(m); + } + }); + + mClipboard = new Clipboard(parent.getDisplay()); + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), + new Action(Messages.LogCatView_Copy) { + @Override + public void run() { + mLogCatPanel.copySelectionToClipboard(mClipboard); + } + }); + + actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), + new Action(Messages.LogCatView_Select_All) { + @Override + public void run() { + mLogCatPanel.selectAll(); + } + }); + + actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(), + new Action("Find") { + @Override + public void run() { + mLogCatPanel.showFindDialog(); + } + }); + } + + @Override + public void setFocus() { + } + + private void onDoubleClick(LogCatMessage m) { + String msg = m.getMessage(); + if (!mStackTraceParser.isValidExceptionTrace(msg)) { + return; + } + + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + String perspectiveId = null; + if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) { + perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID); + } + + + String fileName = mStackTraceParser.getFileName(msg); + int lineNumber = mStackTraceParser.getLineNumber(msg); + String methodName = mStackTraceParser.getMethodName(msg); + JavaSourceRevealer.revealMethod(methodName, fileName, lineNumber, perspectiveId); + } + + public void selectTransientAppFilter(String appName) { + mLogCatPanel.selectTransientAppFilter(appName); + } +} 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 000000000..91c8022b7 --- /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/NetworkStatisticsView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NetworkStatisticsView.java new file mode 100644 index 000000000..f90189c6d --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NetworkStatisticsView.java @@ -0,0 +1,47 @@ +/* + * 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.views; + +import com.android.ddmuilib.net.NetworkPanel; + +import org.eclipse.swt.widgets.Composite; + +public class NetworkStatisticsView extends TableView { + public static final String ID = "com.android.ide.eclipse.ddms.views.NetworkStatsView"; + + private NetworkPanel mPanel; + + public NetworkStatisticsView() { + } + + @Override + public void createPartControl(Composite parent) { + mPanel = new NetworkPanel(); + 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/OldLogCatView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/OldLogCatView.java new file mode 100644 index 000000000..d0b1fb442 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/OldLogCatView.java @@ -0,0 +1,385 @@ +/* + * 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.Log.LogLevel; +import com.android.ddmuilib.ImageLoader; +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 com.android.ddmuilib.logcat.LogPanel.LogCatViewInterface; +import com.android.ide.eclipse.ddms.CommonAction; +import com.android.ide.eclipse.ddms.DdmsPlugin; +import com.android.ide.eclipse.ddms.i18n.Messages; +import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +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.preference.IPreferenceStore; +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.IPerspectiveRegistry; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.ide.IDE; + +import java.util.ArrayList; + +/** + * The log cat view displays log output from the current device selection. + */ +public final class OldLogCatView extends SelectionDependentViewPart implements LogCatViewInterface { + + public static final String ID = "com.android.ide.eclipse.ddms.views.OldLogCatView"; //$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$ + + public static final String CHOICE_METHOD_DECLARATION = + DdmsPlugin.PLUGIN_ID + ".logcat.MethodDeclaration"; //$NON-NLS-1$ + public static final String CHOICE_ERROR_LINE = + DdmsPlugin.PLUGIN_ID + ".logcat.ErrorLine"; //$NON-NLS-1$ + + /* Default values for the switch of perspective. */ + public static final boolean DEFAULT_SWITCH_PERSPECTIVE = true; + public static final String DEFAULT_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; //$NON-NLS-1$ + private static OldLogCatView 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 { + + @Override + 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()]); + } + + @Override + 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()); + } + + @Override + public boolean requiresDefaultFilter() { + return true; + } + } + + public OldLogCatView() { + 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 OldLogCatView 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 = ImageLoader.getDdmUiLibLoader(); + + 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(Messages.LogCatView_Create_Filter) { + @Override + public void run() { + mLogPanel.addFilter(); + } + }; + mCreateFilterAction.setToolTipText(Messages.LogCatView_Create_Filter_Tooltip); + mCreateFilterAction.setImageDescriptor(loader.loadDescriptor("add.png")); //$NON-NLS-1$ + + mEditFilterAction = new CommonAction(Messages.LogCatView_Edit_Filter) { + @Override + public void run() { + mLogPanel.editFilter(); + } + }; + mEditFilterAction.setToolTipText(Messages.LogCatView_Edit_Filter_Tooltip); + mEditFilterAction.setImageDescriptor(loader.loadDescriptor("edit.png")); //$NON-NLS-1$ + + mDeleteFilterAction = new CommonAction(Messages.LogCatView_Delete_Filter) { + @Override + public void run() { + mLogPanel.deleteFilter(); + } + }; + mDeleteFilterAction.setToolTipText(Messages.LogCatView_Delete_Filter_Tooltip); + mDeleteFilterAction.setImageDescriptor(loader.loadDescriptor("delete.png")); //$NON-NLS-1$ + + mExportAction = new CommonAction(Messages.LogCatView_Export_Selection_As_Text) { + @Override + public void run() { + mLogPanel.save(); + } + }; + mExportAction.setToolTipText(Messages.LogCatView_Export_Selection_As_Text_Tooltip); + 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 j = 0; j < mLogLevelActions.length; j++) { + Action a = mLogLevelActions[j]; + if (a == this) { + a.setChecked(true); + + // set the log level + mLogPanel.setCurrentFilterLogLevel(j + 2); + } else { + a.setChecked(false); + } + } + } + }; + + mLogLevelActions[i].setToolTipText(name); + mLogLevelActions[i].setImageDescriptor(loader.loadDescriptor(mLogLevelIcons[i])); + } + + mClearAction = new Action(Messages.LogCatView_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(colors, new FilterStorage(), LogPanel.FILTER_MANUAL); + mLogPanel.setLogCatViewInterface(this); + 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( + Messages.LogCatView_Copy) { + @Override + public void run() { + mLogPanel.copy(mClipboard); + } + }); + + // setup the select all action + actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), + new Action(Messages.LogCatView_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); + } + + void openFile(IFile file, IMarker marker) { + try { + IWorkbenchPage page = getViewSite().getWorkbenchWindow() + .getActivePage(); + if (page != null) { + IDE.openEditor(page, marker); + marker.delete(); + } + } catch (CoreException e) { + Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e); + DdmsPlugin.getDefault().getLog().log(s); + } + } + + void switchPerspective() { + IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore(); + if (store.getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE)) { + IWorkbench workbench = PlatformUI.getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IPerspectiveRegistry perspectiveRegistry = workbench.getPerspectiveRegistry(); + String perspectiveId = store.getString(PreferenceInitializer.ATTR_PERSPECTIVE_ID); + if (perspectiveId != null + && perspectiveId.length() > 0 + && perspectiveRegistry.findPerspectiveWithId(perspectiveId) != null) { + try { + workbench.showPerspective(perspectiveId, window); + } catch (WorkbenchException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public void onDoubleClick() { + } +} 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 000000000..3326d0138 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SelectionDependentViewPart.java @@ -0,0 +1,71 @@ +/* + * 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.IDevice; +import com.android.ddmuilib.SelectionDependentPanel; +import com.android.ide.eclipse.ddms.DdmsPlugin; +import com.android.ide.eclipse.ddms.DdmsPlugin.ISelectionListener; + +import org.eclipse.swt.graphics.Device; +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 + */ + @Override + public final void selectionChanged(Client selectedClient) { + mPanel.clientSelected(selectedClient); + } + + /** + * Sent when a new {@link Device} is selected. + * @param selectedDevice the selected device. + * + * @see ISelectionListener + */ + @Override + public final void selectionChanged(IDevice selectedDevice) { + mPanel.deviceSelected(selectedDevice); + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SysInfoView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SysInfoView.java new file mode 100644 index 000000000..e4939250e --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/SysInfoView.java @@ -0,0 +1,29 @@ +package com.android.ide.eclipse.ddms.views; + +import com.android.ddmuilib.SysinfoPanel; + +import org.eclipse.swt.widgets.Composite; + +public class SysInfoView extends SelectionDependentViewPart { + public static final String ID = "com.android.ide.eclipse.ddms.views.SysInfoView"; //$NON-NLS-1$ + + private SysinfoPanel mSysInfoPanel; + + @Override + public void createPartControl(Composite parent) { + mSysInfoPanel = new SysinfoPanel(); + mSysInfoPanel.createPanel(parent); + setSelectionDependentPanel(mSysInfoPanel); + } + + @Override + public void setFocus() { + mSysInfoPanel.setFocus(); + } + + @Override + public void dispose() { + mSysInfoPanel.dispose(); + super.dispose(); + } +} 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 000000000..1f9f0db53 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/TableView.java @@ -0,0 +1,101 @@ +/* + * 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.ITableFocusListener.IFocusedTableActivator; +import com.android.ddmuilib.TablePanel; +import com.android.ide.eclipse.ddms.i18n.Messages; + +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() { + @Override + public void focusGained(IFocusedTableActivator activator) { + mActivator = activator; + mCopyAction.setEnabled(true); + mSelectAllAction.setEnabled(true); + } + + @Override + 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(Messages.TableView_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(Messages.TableView_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 000000000..9d4eeb74a --- /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(); + } +} |