Home | History | Annotate | Download | only in ddmuilib
      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 }
    259