2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.ddmuilib;
19 import com.android.ddmlib.Client;
20 import com.android.ddmlib.IStackTraceInfo;
22 import org.eclipse.jface.preference.IPreferenceStore;
23 import org.eclipse.jface.viewers.DoubleClickEvent;
24 import org.eclipse.jface.viewers.IDoubleClickListener;
25 import org.eclipse.jface.viewers.ILabelProviderListener;
26 import org.eclipse.jface.viewers.ISelection;
27 import org.eclipse.jface.viewers.IStructuredContentProvider;
28 import org.eclipse.jface.viewers.IStructuredSelection;
29 import org.eclipse.jface.viewers.ITableLabelProvider;
30 import org.eclipse.jface.viewers.TableViewer;
31 import org.eclipse.jface.viewers.Viewer;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.graphics.Image;
34 import org.eclipse.swt.layout.GridLayout;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.Table;
40 * <p/>This is not a panel in the regular sense. Instead this is just an object around the creation
41 * and management of a Stack Trace display.
42 * <p/>UI creation is done through
43 * {@link #createPanel(Composite, String, String, String, String, String, IPreferenceStore)}.
46 public final class StackTracePanel {
48 private static ISourceRevealer sSourceRevealer;
50 private Table mStackTraceTable;
51 private TableViewer mStackTraceViewer;
53 private Client mCurrentClient;
57 * Content Provider to display the stack trace of a thread.
58 * Expected input is a {@link IStackTraceInfo} object.
60 private static class StackTraceContentProvider implements IStructuredContentProvider {
61 public Object[] getElements(Object inputElement) {
62 if (inputElement instanceof IStackTraceInfo) {
63 // getElement cannot return null, so we return an empty array
64 // if there's no stack trace
65 StackTraceElement trace[] = ((IStackTraceInfo)inputElement).getStackTrace();
74 public void dispose() {
78 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
85 * A Label Provider to use with {@link StackTraceContentProvider}. It expects the elements to be
86 * of type {@link StackTraceElement}.
88 private static class StackTraceLabelProvider implements ITableLabelProvider {
90 public Image getColumnImage(Object element, int columnIndex) {
94 public String getColumnText(Object element, int columnIndex) {
95 if (element instanceof StackTraceElement) {
96 StackTraceElement traceElement = (StackTraceElement)element;
97 switch (columnIndex) {
99 return traceElement.getClassName();
101 return traceElement.getMethodName();
103 return traceElement.getFileName();
105 return Integer.toString(traceElement.getLineNumber());
107 return Boolean.toString(traceElement.isNativeMethod());
114 public void addListener(ILabelProviderListener listener) {
118 public void dispose() {
122 public boolean isLabelProperty(Object element, String property) {
127 public void removeListener(ILabelProviderListener listener) {
133 * Classes which implement this interface provide a method that is able to reveal a method
136 public interface ISourceRevealer {
138 * Sent to reveal a particular line in a source editor
139 * @param applicationName the name of the application running the source.
140 * @param className the fully qualified class name
141 * @param line the line to reveal
143 public void reveal(String applicationName, String className, int line);
148 * Sets the {@link ISourceRevealer} object able to reveal source code in a source editor.
151 public static void setSourceRevealer(ISourceRevealer revealer) {
152 sSourceRevealer = revealer;
156 * Creates the controls for the StrackTrace display.
157 * <p/>This method will set the parent {@link Composite} to use a {@link GridLayout} with
159 * @param parent the parent composite.
160 * @param prefs_stack_col_class
161 * @param prefs_stack_col_method
162 * @param prefs_stack_col_file
163 * @param prefs_stack_col_line
164 * @param prefs_stack_col_native
167 public Table createPanel(Composite parent, String prefs_stack_col_class,
168 String prefs_stack_col_method, String prefs_stack_col_file, String prefs_stack_col_line,
169 String prefs_stack_col_native, IPreferenceStore store) {
171 mStackTraceTable = new Table(parent, SWT.MULTI | SWT.FULL_SELECTION);
172 mStackTraceTable.setHeaderVisible(true);
173 mStackTraceTable.setLinesVisible(true);
175 TableHelper.createTableColumn(
179 "SomeLongClassName", //$NON-NLS-1$
180 prefs_stack_col_class, store);
182 TableHelper.createTableColumn(
186 "someLongMethod", //$NON-NLS-1$
187 prefs_stack_col_method, store);
189 TableHelper.createTableColumn(
193 "android/somepackage/someotherpackage/somefile.class", //$NON-NLS-1$
194 prefs_stack_col_file, store);
196 TableHelper.createTableColumn(
200 "99999", //$NON-NLS-1$
201 prefs_stack_col_line, store);
203 TableHelper.createTableColumn(
207 "Native", //$NON-NLS-1$
208 prefs_stack_col_native, store);
210 mStackTraceViewer = new TableViewer(mStackTraceTable);
211 mStackTraceViewer.setContentProvider(new StackTraceContentProvider());
212 mStackTraceViewer.setLabelProvider(new StackTraceLabelProvider());
214 mStackTraceViewer.addDoubleClickListener(new IDoubleClickListener() {
215 public void doubleClick(DoubleClickEvent event) {
216 if (sSourceRevealer != null && mCurrentClient != null) {
217 // get the selected stack trace element
218 ISelection selection = mStackTraceViewer.getSelection();
220 if (selection instanceof IStructuredSelection) {
221 IStructuredSelection structuredSelection = (IStructuredSelection)selection;
222 Object object = structuredSelection.getFirstElement();
223 if (object instanceof StackTraceElement) {
224 StackTraceElement traceElement = (StackTraceElement)object;
226 if (traceElement.isNativeMethod() == false) {
227 sSourceRevealer.reveal(
228 mCurrentClient.getClientData().getClientDescription(),
229 traceElement.getClassName(),
230 traceElement.getLineNumber());
238 return mStackTraceTable;
242 * Sets the input for the {@link TableViewer}.
243 * @param input the {@link IStackTraceInfo} that will provide the viewer with the list of
244 * {@link StackTraceElement}
246 public void setViewerInput(IStackTraceInfo input) {
247 mStackTraceViewer.setInput(input);
248 mStackTraceViewer.refresh();
252 * Sets the current client running the stack trace.
253 * @param currentClient the {@link Client}.
255 public void setCurrentClient(Client currentClient) {
256 mCurrentClient = currentClient;