• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 package com.android.ddmuilib;
18 
19 import com.android.ddmlib.Client;
20 import com.android.ddmlib.IStackTraceInfo;
21 
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;
37 
38 /**
39  * Stack Trace Panel.
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)}.
44  *
45  */
46 public final class StackTracePanel {
47 
48     private static ISourceRevealer sSourceRevealer;
49 
50     private Table mStackTraceTable;
51     private TableViewer mStackTraceViewer;
52 
53     private Client mCurrentClient;
54 
55 
56     /**
57      * Content Provider to display the stack trace of a thread.
58      * Expected input is a {@link IStackTraceInfo} object.
59      */
60     private static class StackTraceContentProvider implements IStructuredContentProvider {
getElements(Object inputElement)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();
66                 if (trace != null) {
67                     return trace;
68                 }
69             }
70 
71             return new Object[0];
72         }
73 
dispose()74         public void dispose() {
75             // pass
76         }
77 
inputChanged(Viewer viewer, Object oldInput, Object newInput)78         public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
79             // pass
80         }
81     }
82 
83 
84     /**
85      * A Label Provider to use with {@link StackTraceContentProvider}. It expects the elements to be
86      * of type {@link StackTraceElement}.
87      */
88     private static class StackTraceLabelProvider implements ITableLabelProvider {
89 
getColumnImage(Object element, int columnIndex)90         public Image getColumnImage(Object element, int columnIndex) {
91             return null;
92         }
93 
getColumnText(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) {
98                     case 0:
99                         return traceElement.getClassName();
100                     case 1:
101                         return traceElement.getMethodName();
102                     case 2:
103                         return traceElement.getFileName();
104                     case 3:
105                         return Integer.toString(traceElement.getLineNumber());
106                     case 4:
107                         return Boolean.toString(traceElement.isNativeMethod());
108                 }
109             }
110 
111             return null;
112         }
113 
addListener(ILabelProviderListener listener)114         public void addListener(ILabelProviderListener listener) {
115             // pass
116         }
117 
dispose()118         public void dispose() {
119             // pass
120         }
121 
isLabelProperty(Object element, String property)122         public boolean isLabelProperty(Object element, String property) {
123             // pass
124             return false;
125         }
126 
removeListener(ILabelProviderListener listener)127         public void removeListener(ILabelProviderListener listener) {
128             // pass
129         }
130     }
131 
132     /**
133      * Classes which implement this interface provide a method that is able to reveal a method
134      * in a source editor
135      */
136     public interface ISourceRevealer {
137         /**
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
142          */
reveal(String applicationName, String className, int line)143         public void reveal(String applicationName, String className, int line);
144     }
145 
146 
147     /**
148      * Sets the {@link ISourceRevealer} object able to reveal source code in a source editor.
149      * @param revealer
150      */
setSourceRevealer(ISourceRevealer revealer)151     public static void setSourceRevealer(ISourceRevealer revealer) {
152         sSourceRevealer = revealer;
153     }
154 
155     /**
156      * Creates the controls for the StrackTrace display.
157      * <p/>This method will set the parent {@link Composite} to use a {@link GridLayout} with
158      * 2 columns.
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
165      * @param store
166      */
createPanel(Composite parent, String prefs_stack_col_class, String prefs_stack_col_method, String prefs_stack_col_file, String prefs_stack_col_line, String prefs_stack_col_native, IPreferenceStore store)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) {
170 
171         mStackTraceTable = new Table(parent, SWT.MULTI | SWT.FULL_SELECTION);
172         mStackTraceTable.setHeaderVisible(true);
173         mStackTraceTable.setLinesVisible(true);
174 
175         TableHelper.createTableColumn(
176                 mStackTraceTable,
177                 "Class",
178                 SWT.LEFT,
179                 "SomeLongClassName", //$NON-NLS-1$
180                 prefs_stack_col_class, store);
181 
182         TableHelper.createTableColumn(
183                 mStackTraceTable,
184                 "Method",
185                 SWT.LEFT,
186                 "someLongMethod", //$NON-NLS-1$
187                 prefs_stack_col_method, store);
188 
189         TableHelper.createTableColumn(
190                 mStackTraceTable,
191                 "File",
192                 SWT.LEFT,
193                 "android/somepackage/someotherpackage/somefile.class", //$NON-NLS-1$
194                 prefs_stack_col_file, store);
195 
196         TableHelper.createTableColumn(
197                 mStackTraceTable,
198                 "Line",
199                 SWT.RIGHT,
200                 "99999", //$NON-NLS-1$
201                 prefs_stack_col_line, store);
202 
203         TableHelper.createTableColumn(
204                 mStackTraceTable,
205                 "Native",
206                 SWT.LEFT,
207                 "Native", //$NON-NLS-1$
208                 prefs_stack_col_native, store);
209 
210         mStackTraceViewer = new TableViewer(mStackTraceTable);
211         mStackTraceViewer.setContentProvider(new StackTraceContentProvider());
212         mStackTraceViewer.setLabelProvider(new StackTraceLabelProvider());
213 
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();
219 
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;
225 
226                             if (traceElement.isNativeMethod() == false) {
227                                 sSourceRevealer.reveal(
228                                         mCurrentClient.getClientData().getClientDescription(),
229                                         traceElement.getClassName(),
230                                         traceElement.getLineNumber());
231                             }
232                         }
233                     }
234                 }
235             }
236         });
237 
238         return mStackTraceTable;
239     }
240 
241     /**
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}
245      */
setViewerInput(IStackTraceInfo input)246     public void setViewerInput(IStackTraceInfo input) {
247         mStackTraceViewer.setInput(input);
248         mStackTraceViewer.refresh();
249     }
250 
251     /**
252      * Sets the current client running the stack trace.
253      * @param currentClient the {@link Client}.
254      */
setCurrentClient(Client currentClient)255     public void setCurrentClient(Client currentClient) {
256         mCurrentClient = currentClient;
257     }
258 }
259