1
/*******************************************************************************
2
* Copyright (c) 2009 Red Hat, Inc.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Elliott Baron <ebaron@redhat.com> - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.linuxtools.internal.valgrind.cachegrind;
13
import java.util.Arrays;
15
import org.eclipse.cdt.core.model.CModelException;
16
import org.eclipse.cdt.core.model.ISourceRange;
17
import org.eclipse.cdt.core.model.ISourceReference;
18
import org.eclipse.jface.action.IAction;
19
import org.eclipse.jface.action.IMenuListener;
20
import org.eclipse.jface.action.IMenuManager;
21
import org.eclipse.jface.action.MenuManager;
22
import org.eclipse.jface.text.BadLocationException;
23
import org.eclipse.jface.viewers.DoubleClickEvent;
24
import org.eclipse.jface.viewers.IDoubleClickListener;
25
import org.eclipse.jface.viewers.ITreeContentProvider;
26
import org.eclipse.jface.viewers.ITreeSelection;
27
import org.eclipse.jface.viewers.StructuredSelection;
28
import org.eclipse.jface.viewers.TreeViewer;
29
import org.eclipse.jface.viewers.TreeViewerColumn;
30
import org.eclipse.jface.viewers.Viewer;
31
import org.eclipse.jface.viewers.ViewerComparator;
32
import org.eclipse.linuxtools.internal.valgrind.cachegrind.model.CachegrindFile;
33
import org.eclipse.linuxtools.internal.valgrind.cachegrind.model.CachegrindFunction;
34
import org.eclipse.linuxtools.internal.valgrind.cachegrind.model.CachegrindLine;
35
import org.eclipse.linuxtools.internal.valgrind.cachegrind.model.CachegrindOutput;
36
import org.eclipse.linuxtools.internal.valgrind.cachegrind.model.ICachegrindElement;
37
import org.eclipse.linuxtools.profiling.ui.ProfileUIUtils;
38
import org.eclipse.linuxtools.valgrind.ui.IValgrindToolView;
39
import org.eclipse.swt.SWT;
40
import org.eclipse.swt.events.SelectionAdapter;
41
import org.eclipse.swt.events.SelectionEvent;
42
import org.eclipse.swt.events.SelectionListener;
43
import org.eclipse.swt.layout.GridData;
44
import org.eclipse.swt.layout.GridLayout;
45
import org.eclipse.swt.widgets.Composite;
46
import org.eclipse.swt.widgets.Menu;
47
import org.eclipse.swt.widgets.Tree;
48
import org.eclipse.swt.widgets.TreeColumn;
49
import org.eclipse.ui.PartInitException;
50
import org.eclipse.ui.part.ViewPart;
52
public class CachegrindViewPart extends ViewPart implements IValgrindToolView {
54
protected CachegrindOutput[] outputs;
55
protected TreeViewer viewer;
57
protected static final int COLUMN_SIZE = 75;
58
protected CachegrindLabelProvider labelProvider;
59
protected CachegrindTreeContentProvider contentProvider;
60
protected IDoubleClickListener doubleClickListener;
61
protected ExpandAction expandAction;
62
protected CollapseAction collapseAction;
65
protected static final String IR = "Ir"; //$NON-NLS-1$
66
protected static final String I1MR = "I1mr"; //$NON-NLS-1$
67
protected static final String I2MR = "I2mr"; //$NON-NLS-1$
68
protected static final String DR = "Dr"; //$NON-NLS-1$
69
protected static final String D1MR = "D1mr"; //$NON-NLS-1$
70
protected static final String D2MR = "D2mr"; //$NON-NLS-1$
71
protected static final String DW = "Dw"; //$NON-NLS-1$
72
protected static final String D1MW = "D1mw"; //$NON-NLS-1$
73
protected static final String D2MW = "D2mw"; //$NON-NLS-1$
76
protected static final String BC = "Bc"; //$NON-NLS-1$
77
protected static final String BCM = "Bcm"; //$NON-NLS-1$
78
protected static final String BI = "Bi"; //$NON-NLS-1$
79
protected static final String BIM = "Bim"; //$NON-NLS-1$
82
public void createPartControl(Composite parent) {
83
Composite top = new Composite(parent, SWT.NONE);
84
GridLayout topLayout = new GridLayout();
85
topLayout.marginHeight = topLayout.marginWidth = 0;
86
top.setLayout(topLayout);
87
top.setLayoutData(new GridData(GridData.FILL_BOTH));
89
viewer = new TreeViewer(top, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL
90
| SWT.FULL_SELECTION);
92
labelProvider = new CachegrindLabelProvider();
94
Tree tree = viewer.getTree();
95
tree.setHeaderVisible(true);
96
tree.setLinesVisible(true);
97
tree.setLayoutData(new GridData(GridData.FILL_BOTH));
99
TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.NONE);
100
column.getColumn().setText(Messages.getString("CachegrindViewPart.Location")); //$NON-NLS-1$
101
column.getColumn().setWidth(COLUMN_SIZE * 4);
102
column.getColumn().setResizable(true);
103
column.getColumn().addSelectionListener(getHeaderListener());
104
column.setLabelProvider(labelProvider);
106
contentProvider = new CachegrindTreeContentProvider();
107
viewer.setContentProvider(contentProvider);
108
viewer.setLabelProvider(labelProvider);
109
viewer.setAutoExpandLevel(2);
110
doubleClickListener = new IDoubleClickListener() {
111
public void doubleClick(DoubleClickEvent event) {
112
Object selection = ((StructuredSelection) event.getSelection()).getFirstElement();
115
if (selection instanceof CachegrindFile) {
116
path = ((CachegrindFile) selection).getPath();
118
else if (selection instanceof CachegrindLine) {
119
CachegrindLine element = (CachegrindLine) selection;
120
CachegrindFile file = (CachegrindFile) element.getParent().getParent();
121
path = file.getPath();
122
line = element.getLine();
124
else if (selection instanceof CachegrindFunction) {
125
CachegrindFunction function = (CachegrindFunction) selection;
126
path = ((CachegrindFile) function.getParent()).getPath();
127
if (function.getModel() instanceof ISourceReference) {
128
ISourceReference model = (ISourceReference) function.getModel();
130
ISourceRange sr = model.getSourceRange();
132
line = sr.getStartLine();
134
} catch (CModelException e) {
141
ProfileUIUtils.openEditorAndSelect(path, line);
142
} catch (PartInitException e) {
144
} catch (BadLocationException e) {
150
viewer.addDoubleClickListener(doubleClickListener);
152
expandAction = new ExpandAction(viewer);
153
collapseAction = new CollapseAction(viewer);
155
MenuManager manager = new MenuManager();
156
manager.addMenuListener(new IMenuListener() {
157
public void menuAboutToShow(IMenuManager manager) {
158
ITreeSelection selection = (ITreeSelection) viewer.getSelection();
159
ICachegrindElement element = (ICachegrindElement) selection.getFirstElement();
160
if (contentProvider.hasChildren(element)) {
161
manager.add(expandAction);
162
manager.add(collapseAction);
167
manager.setRemoveAllWhenShown(true);
168
Menu contextMenu = manager.createContextMenu(viewer.getTree());
169
viewer.getControl().setMenu(contextMenu);
173
public void setFocus() {
174
viewer.getTree().setFocus();
177
public IAction[] getToolbarActions() {
181
public void refreshView() {
182
if (outputs != null && outputs.length > 0) {
183
String[] events = outputs[0].getEvents();
184
for (int i = 0; i < events.length; i++) {
185
TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.NONE);
186
column.getColumn().setText(events[i]);
187
column.getColumn().setWidth(COLUMN_SIZE);
188
column.getColumn().setToolTipText(getFullEventName(events[i]));
189
column.getColumn().setResizable(true);
190
column.getColumn().addSelectionListener(getHeaderListener());
191
column.setLabelProvider(labelProvider);
193
viewer.setInput(outputs);
194
viewer.getTree().layout(true);
198
public void setOutputs(CachegrindOutput[] outputs) {
199
this.outputs = outputs;
202
public CachegrindOutput[] getOutputs() {
206
public TreeViewer getViewer() {
210
public IDoubleClickListener getDoubleClickListener() {
211
return doubleClickListener;
214
private SelectionListener getHeaderListener() {
215
return new SelectionAdapter() {
217
public void widgetSelected(SelectionEvent e) {
218
TreeColumn column = (TreeColumn) e.widget;
219
Tree tree = viewer.getTree();
220
if (column.equals(tree.getSortColumn())) {
221
int direction = tree.getSortDirection() == SWT.UP ? SWT.DOWN
223
tree.setSortDirection(direction);
225
tree.setSortDirection(SWT.UP);
227
tree.setSortColumn(column);
228
viewer.setComparator(new ViewerComparator() {
230
public int compare(Viewer viewer, Object e1, Object e2) {
231
Tree tree = ((TreeViewer) viewer).getTree();
232
int direction = tree.getSortDirection();
233
ICachegrindElement o1 = (ICachegrindElement) e1;
234
ICachegrindElement o2 = (ICachegrindElement) e2;
237
int sortIndex = Arrays.asList(tree.getColumns()).indexOf(tree.getSortColumn());
238
if (sortIndex == 0) { // use compareTo
239
result = o1.compareTo(o2);
244
if (o1 instanceof CachegrindFunction && o2 instanceof CachegrindFunction) {
245
v1 = ((CachegrindFunction) o1).getTotals();
246
v2 = ((CachegrindFunction) o2).getTotals();
248
else if (o1 instanceof CachegrindLine && o2 instanceof CachegrindLine) {
249
v1 = ((CachegrindLine) o1).getValues();
250
v2 = ((CachegrindLine) o2).getValues();
252
else if (o1 instanceof CachegrindOutput && o2 instanceof CachegrindOutput) {
253
v1 = ((CachegrindOutput) o1).getSummary();
254
v2 = ((CachegrindOutput) o2).getSummary();
257
if (v1 != null && v2 != null) {
258
result = v1[sortIndex - 1] - v2[sortIndex - 1];
262
// ascending or descending
263
result = direction == SWT.UP ? result : -result;
266
if (result > Integer.MAX_VALUE) {
267
result = Integer.MAX_VALUE;
268
} else if (result < Integer.MIN_VALUE) {
269
result = Integer.MIN_VALUE;
279
private String getFullEventName(String event) {
280
String result = event;
281
if (event.equals(IR)) {
282
result = Messages.getString("CachegrindViewPart.Ir_long"); //$NON-NLS-1$
284
else if (event.equals(I1MR)) {
285
result = Messages.getString("CachegrindViewPart.I1mr_long"); //$NON-NLS-1$
287
else if (event.equals(I2MR)) {
288
result = Messages.getString("CachegrindViewPart.I2mr_long"); //$NON-NLS-1$
290
else if (event.equals(DR)) {
291
result = Messages.getString("CachegrindViewPart.Dr_long"); //$NON-NLS-1$
293
else if (event.equals(D1MR)) {
294
result = Messages.getString("CachegrindViewPart.D1mr_long"); //$NON-NLS-1$
296
else if (event.equals(D2MR)) {
297
result = Messages.getString("CachegrindViewPart.D2mr_long"); //$NON-NLS-1$
299
else if (event.equals(DW)) {
300
result = Messages.getString("CachegrindViewPart.Dw_long"); //$NON-NLS-1$
302
else if (event.equals(D1MW)) {
303
result = Messages.getString("CachegrindViewPart.D1mw_long"); //$NON-NLS-1$
305
else if (event.equals(D2MW)) {
306
result = Messages.getString("CachegrindViewPart.D2mw_long"); //$NON-NLS-1$
308
else if (event.equals(BC)) {
309
result = Messages.getString("CachegrindViewPart.Bc_long"); //$NON-NLS-1$
311
else if (event.equals(BCM)) {
312
result = Messages.getString("CachegrindViewPart.Bcm_long"); //$NON-NLS-1$
314
else if (event.equals(BI)) {
315
result = Messages.getString("CachegrindViewPart.Bi_long"); //$NON-NLS-1$
317
else if (event.equals(BIM)) {
318
result = Messages.getString("CachegrindViewPart.Bim_long"); //$NON-NLS-1$
323
protected class CachegrindTreeContentProvider implements ITreeContentProvider {
325
public Object[] getChildren(Object parentElement) {
326
Object[] result = null;
327
if (parentElement instanceof CachegrindOutput[]) {
328
result = (CachegrindOutput[]) parentElement;
330
else if (parentElement instanceof ICachegrindElement) {
331
result = ((ICachegrindElement) parentElement).getChildren();
336
public Object getParent(Object element) {
337
return ((ICachegrindElement) element).getParent();
340
public boolean hasChildren(Object element) {
341
ICachegrindElement[] children = (ICachegrindElement[]) getChildren(element);
342
return children != null && children.length > 0;
345
public Object[] getElements(Object inputElement) {
346
return getChildren(inputElement);
349
public void dispose() {
352
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {