OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / sdk / eclipse / plugins / com.android.ide.eclipse.ddms / src / com / android / ide / eclipse / ddms / views / LogCatView.java
1 /*
2  * Copyright (C) 2007 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.ide.eclipse.ddms.views;
18
19 import com.android.ddmlib.Log.LogLevel;
20 import com.android.ddmuilib.ImageLoader;
21 import com.android.ddmuilib.logcat.LogColors;
22 import com.android.ddmuilib.logcat.LogFilter;
23 import com.android.ddmuilib.logcat.LogPanel;
24 import com.android.ddmuilib.logcat.LogPanel.ILogFilterStorageManager;
25 import com.android.ide.eclipse.ddms.CommonAction;
26 import com.android.ide.eclipse.ddms.DdmsPlugin;
27 import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
28
29 import org.eclipse.core.resources.IFile;
30 import org.eclipse.core.resources.IMarker;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.NullProgressMonitor;
33 import org.eclipse.core.runtime.Status;
34 import org.eclipse.jdt.core.search.IJavaSearchConstants;
35 import org.eclipse.jdt.core.search.SearchEngine;
36 import org.eclipse.jdt.core.search.SearchMatch;
37 import org.eclipse.jdt.core.search.SearchParticipant;
38 import org.eclipse.jdt.core.search.SearchPattern;
39 import org.eclipse.jdt.core.search.SearchRequestor;
40 import org.eclipse.jface.action.Action;
41 import org.eclipse.jface.action.IAction;
42 import org.eclipse.jface.action.IMenuManager;
43 import org.eclipse.jface.action.IToolBarManager;
44 import org.eclipse.jface.action.Separator;
45 import org.eclipse.swt.dnd.Clipboard;
46 import org.eclipse.swt.graphics.Color;
47 import org.eclipse.swt.graphics.Font;
48 import org.eclipse.swt.graphics.FontData;
49 import org.eclipse.swt.widgets.Composite;
50 import org.eclipse.swt.widgets.Display;
51 import org.eclipse.ui.IActionBars;
52 import org.eclipse.ui.IPerspectiveRegistry;
53 import org.eclipse.ui.IWorkbenchPage;
54 import org.eclipse.ui.IWorkbenchWindow;
55 import org.eclipse.ui.actions.ActionFactory;
56 import org.eclipse.ui.ide.IDE;
57 import org.eclipse.ui.internal.WorkbenchPlugin;
58 import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
59
60 import java.util.ArrayList;
61 import java.util.HashMap;
62 import java.util.regex.Matcher;
63 import java.util.regex.Pattern;
64
65 /**
66  * The log cat view displays log output from the current device selection.
67  *
68  */
69 public final class LogCatView extends SelectionDependentViewPart {
70
71     public static final String ID =
72         "com.android.ide.eclipse.ddms.views.LogCatView"; // $NON-NLS-1$
73
74     private static final String PREFS_COL_TIME =
75         DdmsPlugin.PLUGIN_ID + ".logcat.time"; // $NON-NLS-1$
76     private static final String PREFS_COL_LEVEL =
77         DdmsPlugin.PLUGIN_ID + ".logcat.level"; // $NON-NLS-1$
78     private static final String PREFS_COL_PID =
79         DdmsPlugin.PLUGIN_ID + ".logcat.pid"; // $NON-NLS-1$
80     private static final String PREFS_COL_TAG =
81         DdmsPlugin.PLUGIN_ID + ".logcat.tag"; // $NON-NLS-1$
82     private static final String PREFS_COL_MESSAGE =
83         DdmsPlugin.PLUGIN_ID + ".logcat.message"; // $NON-NLS-1$
84
85     private static final String PREFS_FILTERS =
86         DdmsPlugin.PLUGIN_ID + ".logcat.filters"; // $NON-NLS-1$
87
88     private static LogCatView sThis;
89     private LogPanel mLogPanel;
90
91     private CommonAction mCreateFilterAction;
92     private CommonAction mDeleteFilterAction;
93     private CommonAction mEditFilterAction;
94     private CommonAction mExportAction;
95     private CommonAction gotoLineAction;
96
97     private CommonAction[] mLogLevelActions;
98     private String[] mLogLevelIcons = {
99             "v.png", //$NON-NLS-1S
100             "d.png", //$NON-NLS-1S
101             "i.png", //$NON-NLS-1S
102             "w.png", //$NON-NLS-1S
103             "e.png", //$NON-NLS-1S
104     };
105
106     private Action mClearAction;
107
108     private Clipboard mClipboard;
109
110     /**
111      * An implementation of {@link ILogFilterStorageManager} to bridge to the eclipse preference
112      * store, and saves the log filters.
113      */
114     private final class FilterStorage implements ILogFilterStorageManager {
115
116         public LogFilter[] getFilterFromStore() {
117             String filterPrefs = DdmsPlugin.getDefault().getPreferenceStore().getString(
118                     PREFS_FILTERS);
119
120             // split in a string per filter
121             String[] filters = filterPrefs.split("\\|"); // $NON-NLS-1$
122
123             ArrayList<LogFilter> list =
124                 new ArrayList<LogFilter>(filters.length);
125
126             for (String f : filters) {
127                 if (f.length() > 0) {
128                     LogFilter logFilter = new LogFilter();
129                     if (logFilter.loadFromString(f)) {
130                         list.add(logFilter);
131                     }
132                 }
133             }
134
135             return list.toArray(new LogFilter[list.size()]);
136         }
137
138         public void saveFilters(LogFilter[] filters) {
139             StringBuilder sb = new StringBuilder();
140             for (LogFilter f : filters) {
141                 String filterString = f.toString();
142                 sb.append(filterString);
143                 sb.append('|');
144             }
145
146             DdmsPlugin.getDefault().getPreferenceStore().setValue(PREFS_FILTERS, sb.toString());
147         }
148
149         public boolean requiresDefaultFilter() {
150             return true;
151         }
152     }
153
154     public LogCatView() {
155         sThis = this;
156         LogPanel.PREFS_TIME = PREFS_COL_TIME;
157         LogPanel.PREFS_LEVEL = PREFS_COL_LEVEL;
158         LogPanel.PREFS_PID = PREFS_COL_PID;
159         LogPanel.PREFS_TAG = PREFS_COL_TAG;
160         LogPanel.PREFS_MESSAGE = PREFS_COL_MESSAGE;
161     }
162
163     /**
164      * Returns the singleton instance.
165      */
166     public static LogCatView getInstance() {
167         return sThis;
168     }
169
170     /**
171      * Sets the display font.
172      * @param font The font.
173      */
174     public static void setFont(Font font) {
175         if (sThis != null && sThis.mLogPanel != null) {
176             sThis.mLogPanel.setFont(font);
177         }
178     }
179
180     @Override
181     public void createPartControl(Composite parent) {
182         Display d = parent.getDisplay();
183         LogColors colors = new LogColors();
184
185         ImageLoader loader = ImageLoader.getDdmUiLibLoader();
186
187         colors.infoColor = new Color(d, 0, 127, 0);
188         colors.debugColor = new Color(d, 0, 0, 127);
189         colors.errorColor = new Color(d, 255, 0, 0);
190         colors.warningColor = new Color(d, 255, 127, 0);
191         colors.verboseColor = new Color(d, 0, 0, 0);
192
193         mCreateFilterAction = new CommonAction("Create Filter") {
194             @Override
195             public void run() {
196                 mLogPanel.addFilter();
197             }
198         };
199         mCreateFilterAction.setToolTipText("Create Filter");
200         mCreateFilterAction.setImageDescriptor(loader.loadDescriptor("add.png"));
201
202         mEditFilterAction = new CommonAction("Edit Filter") {
203             @Override
204             public void run() {
205                 mLogPanel.editFilter();
206             }
207         };
208         mEditFilterAction.setToolTipText("Edit Filter");
209         mEditFilterAction.setImageDescriptor(loader.loadDescriptor("edit.png")); // $NON-NLS-1$
210
211         mDeleteFilterAction = new CommonAction("Delete Filter") {
212             @Override
213             public void run() {
214                 mLogPanel.deleteFilter();
215             }
216         };
217         mDeleteFilterAction.setToolTipText("Delete Filter");
218         mDeleteFilterAction.setImageDescriptor(loader.loadDescriptor("delete.png")); // $NON-NLS-1$
219
220         mExportAction = new CommonAction("Export Selection As Text...") {
221             @Override
222             public void run() {
223                 mLogPanel.save();
224             }
225         };
226         mExportAction.setToolTipText("Export Selection As Text...");
227         mExportAction.setImageDescriptor(loader.loadDescriptor("save.png")); // $NON-NLS-1$
228
229         gotoLineAction = new CommonAction("Go to Problem") {
230             @Override
231             public void run() {
232                 goToErrorLine();
233             }
234         };
235
236         LogLevel[] levels = LogLevel.values();
237         mLogLevelActions = new CommonAction[mLogLevelIcons.length];
238         for (int i = 0 ; i < mLogLevelActions.length; i++) {
239             String name = levels[i].getStringValue();
240             mLogLevelActions[i] = new CommonAction(name, IAction.AS_CHECK_BOX) {
241                 @Override
242                 public void run() {
243                     // disable the other actions and record current index
244                     for (int i = 0 ; i < mLogLevelActions.length; i++) {
245                         Action a = mLogLevelActions[i];
246                         if (a == this) {
247                             a.setChecked(true);
248
249                             // set the log level
250                             mLogPanel.setCurrentFilterLogLevel(i+2);
251                         } else {
252                             a.setChecked(false);
253                         }
254                     }
255                 }
256             };
257
258             mLogLevelActions[i].setToolTipText(name);
259             mLogLevelActions[i].setImageDescriptor(loader.loadDescriptor(mLogLevelIcons[i]));
260         }
261
262         mClearAction = new Action("Clear Log") {
263             @Override
264             public void run() {
265                 mLogPanel.clear();
266             }
267         };
268         mClearAction.setImageDescriptor(loader.loadDescriptor("clear.png")); // $NON-NLS-1$
269
270
271         // now create the log view
272         mLogPanel = new LogPanel(colors, new FilterStorage(), LogPanel.FILTER_MANUAL);
273         mLogPanel.setActions(mDeleteFilterAction, mEditFilterAction, mLogLevelActions);
274
275         // get the font
276         String fontStr = DdmsPlugin.getDefault().getPreferenceStore().getString(
277                 PreferenceInitializer.ATTR_LOGCAT_FONT);
278         if (fontStr != null) {
279             FontData data = new FontData(fontStr);
280
281             if (fontStr != null) {
282                 mLogPanel.setFont(new Font(parent.getDisplay(), data));
283             }
284         }
285
286         mLogPanel.createPanel(parent);
287         setSelectionDependentPanel(mLogPanel);
288
289         // place the actions.
290         placeActions();
291
292         // setup the copy action
293         mClipboard = new Clipboard(d);
294         IActionBars actionBars = getViewSite().getActionBars();
295         actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action("Copy") {
296             @Override
297             public void run() {
298                 mLogPanel.copy(mClipboard);
299             }
300         });
301
302         // setup the select all action
303         actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
304                 new Action("Select All") {
305             @Override
306             public void run() {
307                 mLogPanel.selectAll();
308             }
309         });
310     }
311
312     @Override
313     public void dispose() {
314         mLogPanel.stopLogCat(true);
315         mClipboard.dispose();
316     }
317
318     @Override
319     public void setFocus() {
320         mLogPanel.setFocus();
321     }
322
323     /**
324      * Place the actions in the ui.
325      */
326     private void placeActions() {
327         IActionBars actionBars = getViewSite().getActionBars();
328
329         // first in the menu
330         IMenuManager menuManager = actionBars.getMenuManager();
331         menuManager.add(mCreateFilterAction);
332         menuManager.add(mEditFilterAction);
333         menuManager.add(mDeleteFilterAction);
334         menuManager.add(new Separator());
335         menuManager.add(mClearAction);
336         menuManager.add(new Separator());
337         menuManager.add(mExportAction);
338         menuManager.add(gotoLineAction);
339
340         // and then in the toolbar
341         IToolBarManager toolBarManager = actionBars.getToolBarManager();
342         for (CommonAction a : mLogLevelActions) {
343             toolBarManager.add(a);
344         }
345         toolBarManager.add(new Separator());
346         toolBarManager.add(mCreateFilterAction);
347         toolBarManager.add(mEditFilterAction);
348         toolBarManager.add(mDeleteFilterAction);
349         toolBarManager.add(new Separator());
350         toolBarManager.add(mClearAction);
351     }
352
353     IMarker createMarkerFromSearchMatch(IFile file, SearchMatch match) {
354         HashMap<String, Object> map = new HashMap<String, Object>();
355         map.put(IMarker.CHAR_START, new Integer(match.getOffset()));
356         map.put(IMarker.CHAR_END, new Integer(match.getOffset()
357                 + match.getLength()));
358         IMarker marker = null;
359         try {
360             marker = file.createMarker(IMarker.TEXT);
361             marker.setAttributes(map);
362         } catch (CoreException e) {
363             Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
364             DdmsPlugin.getDefault().getLog().log(s);
365         }
366         return marker;
367     }
368
369     void openFile(IFile file, IMarker marker) {
370         try {
371             IWorkbenchPage page = getViewSite().getWorkbenchWindow()
372                     .getActivePage();
373             if (page != null) {
374                 IDE.openEditor(page, marker);
375                 marker.delete();
376             }
377         } catch (CoreException e) {
378             Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
379             DdmsPlugin.getDefault().getLog().log(s);
380         }
381     }
382
383     void switchPerspective() {
384
385         IWorkbenchWindow window = getViewSite().getWorkbenchWindow()
386                 .getWorkbench().getActiveWorkbenchWindow();
387         String rtPerspectiveId = "org.eclipse.jdt.ui.JavaPerspective";
388         IPerspectiveRegistry reg = WorkbenchPlugin.getDefault()
389                 .getPerspectiveRegistry();
390         PerspectiveDescriptor rtPerspectiveDesc = (PerspectiveDescriptor) reg
391                 .findPerspectiveWithId(rtPerspectiveId);
392         if (window != null) {
393             IWorkbenchPage page = window.getActivePage();
394             page.setPerspective(rtPerspectiveDesc);
395         }
396     }
397
398     void goToErrorLine() {
399         try {
400             String msg = mLogPanel.getSelectedErrorLineMessage();
401             if (msg != null) {
402                 String error_line_matcher_string = "\\s*at\\ (.*)\\((.*\\.java)\\:(\\d+)\\)";
403                 Matcher error_line_matcher = Pattern.compile(
404                         error_line_matcher_string).matcher(msg);
405
406                 if (error_line_matcher.find()) {
407                     String class_name = error_line_matcher.group(1);
408
409                     // TODO: Search currently only matches the class declaration (using
410                     // IJavaSearchConstants.DECLARATIONS). We may want to jump to the
411                     // "reference" of the class instead (IJavaSearchConstants.REFERENCES)
412                     // using the filename and line number to disambiguate the search results.
413 //                  String filename = error_line_matcher.group(2);
414 //                  int line_number = Integer.parseInt(error_line_matcher.group(3));
415
416                     SearchEngine se = new SearchEngine();
417                     se.search(SearchPattern.createPattern(class_name,
418                             IJavaSearchConstants.METHOD,
419                             IJavaSearchConstants.DECLARATIONS,
420                             SearchPattern.R_EXACT_MATCH
421                                     | SearchPattern.R_CASE_SENSITIVE),
422                             new SearchParticipant[] { SearchEngine
423                                     .getDefaultSearchParticipant() },
424                             SearchEngine.createWorkspaceScope(),
425                             new SearchRequestor() {
426                                 boolean found_first_match = false;
427
428                                 @Override
429                                 public void acceptSearchMatch(
430                                         SearchMatch match)
431                                         throws CoreException {
432
433                                     if (match.getResource() instanceof IFile
434                                             && !found_first_match) {
435                                         found_first_match = true;
436
437                                         IFile matched_file = (IFile) match
438                                                 .getResource();
439                                         IMarker marker = createMarkerFromSearchMatch(
440                                                 matched_file, match);
441
442                                         // There should only be one exact match,
443                                         // so we go immediately to that one.
444                                         switchPerspective();
445                                         openFile(matched_file, marker);
446                                     }
447                                 }
448                             }, new NullProgressMonitor());
449
450                 }
451             }
452         } catch (Exception e) {
453             Status s = new Status(Status.ERROR, DdmsPlugin.PLUGIN_ID, e.getMessage(), e);
454             DdmsPlugin.getDefault().getLog().log(s);
455         }
456     }
457  }
458