OSDN Git Service

Merge "Add eclipse version to usage stat ping."
[android-x86/sdk.git] / ddms / libs / ddmuilib / src / com / android / ddmuilib / StackTracePanel.java
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 {
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
74         public void dispose() {
75             // pass
76         }
77
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
90         public Image getColumnImage(Object element, int columnIndex) {
91             return null;
92         }
93
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
114         public void addListener(ILabelProviderListener listener) {
115             // pass
116         }
117
118         public void dispose() {
119             // pass
120         }
121
122         public boolean isLabelProperty(Object element, String property) {
123             // pass
124             return false;
125         }
126
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          */
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      */
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      */
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      */
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      */
255     public void setCurrentClient(Client currentClient) {
256         mCurrentClient = currentClient;
257     }
258 }