1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.analysis
.os
.linux
.ui
.views
.cpuusage
;
15 import org
.eclipse
.jface
.viewers
.ISelection
;
16 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
17 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
18 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
19 import org
.eclipse
.swt
.SWT
;
20 import org
.eclipse
.swt
.custom
.SashForm
;
21 import org
.eclipse
.swt
.events
.ControlAdapter
;
22 import org
.eclipse
.swt
.events
.ControlEvent
;
23 import org
.eclipse
.swt
.events
.PaintEvent
;
24 import org
.eclipse
.swt
.events
.PaintListener
;
25 import org
.eclipse
.swt
.layout
.GridData
;
26 import org
.eclipse
.swt
.layout
.GridLayout
;
27 import org
.eclipse
.swt
.widgets
.Composite
;
28 import org
.eclipse
.swt
.widgets
.Control
;
29 import org
.eclipse
.swt
.widgets
.Event
;
30 import org
.eclipse
.swt
.widgets
.Listener
;
31 import org
.eclipse
.swt
.widgets
.Sash
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
36 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
37 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentSignal
;
38 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
39 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
42 * CPU usage view. It contains 2 viewers: one tree viewer showing all the
43 * threads who were on the CPU in the time range, and one XY chart viewer
44 * plotting the total time spent on CPU and the time of the threads selected in
47 * @author Geneviève Bastien
49 public class CpuUsageView
extends TmfView
implements ITmfTimeAligned
{
52 public static final String ID
= "org.eclipse.tracecompass.analysis.os.linux.views.cpuusage"; //$NON-NLS-1$
54 private static final int[] DEFAULT_WEIGHTS
= {1, 3};
56 private CpuUsageComposite fTreeViewer
= null;
57 private CpuUsageXYViewer fXYViewer
= null;
59 private SashForm fSashForm
;
60 private Listener fSashDragListener
;
61 /** A composite that allows us to add margins */
62 private Composite fXYViewerContainer
;
67 public CpuUsageView() {
68 super(Messages
.CpuUsageView_Title
);
72 public void createPartControl(Composite parent
) {
73 super.createPartControl(parent
);
75 fSashForm
= new SashForm(parent
, SWT
.NONE
);
77 fTreeViewer
= new CpuUsageComposite(fSashForm
);
79 fXYViewerContainer
= new Composite(fSashForm
, SWT
.NONE
);
80 GridLayout layout
= new GridLayout();
81 layout
.marginHeight
= 0;
82 layout
.marginWidth
= 0;
83 fXYViewerContainer
.setLayout(layout
);
85 /* Build the XY chart part of the view */
86 fXYViewer
= new CpuUsageXYViewer(fXYViewerContainer
);
87 fXYViewer
.setSendTimeAlignSignals(true);
88 fXYViewer
.getControl().setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
90 /* Add selection listener to tree viewer */
91 fTreeViewer
.addSelectionChangeListener(new ISelectionChangedListener() {
93 public void selectionChanged(SelectionChangedEvent event
) {
94 ISelection selection
= event
.getSelection();
95 if (selection
instanceof IStructuredSelection
) {
96 Object structSelection
= ((IStructuredSelection
) selection
).getFirstElement();
97 if (structSelection
instanceof CpuUsageEntry
) {
98 CpuUsageEntry entry
= (CpuUsageEntry
) structSelection
;
99 fTreeViewer
.setSelectedThread(entry
.getTid());
100 fXYViewer
.setSelectedThread(Long
.valueOf(entry
.getTid()));
106 /* Initialize the viewers with the currently selected trace */
107 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
109 TmfTraceSelectedSignal signal
= new TmfTraceSelectedSignal(this, trace
);
110 fTreeViewer
.traceSelected(signal
);
111 fXYViewer
.traceSelected(signal
);
113 fTreeViewer
.getControl().addControlListener(new ControlAdapter() {
115 public void controlResized(ControlEvent e
) {
116 super.controlResized(e
);
120 fXYViewer
.getControl().addPaintListener(new PaintListener() {
122 public void paintControl(PaintEvent e
) {
123 // Sashes in a SashForm are being created on layout so add the
124 // drag listener here
125 if (fSashDragListener
== null) {
126 for (Control control
: fSashForm
.getChildren()) {
127 if (control
instanceof Sash
) {
128 fSashDragListener
= new Listener() {
131 public void handleEvent(Event event
) {
132 TmfSignalManager
.dispatchSignal(new TmfTimeViewAlignmentSignal(fSashForm
, getTimeViewAlignmentInfo()));
135 control
.removePaintListener(this);
136 control
.addListener(SWT
.Selection
, fSashDragListener
);
137 // There should be only one sash
145 fSashForm
.setWeights(DEFAULT_WEIGHTS
);
149 public void setFocus() {
150 fXYViewer
.getControl().setFocus();
154 public void dispose() {
156 if (fTreeViewer
!= null) {
157 fTreeViewer
.dispose();
159 if (fXYViewer
!= null) {
168 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
169 if (fSashForm
== null) {
173 return new TmfTimeViewAlignmentInfo(fSashForm
.getShell(), fSashForm
.toDisplay(0, 0), getTimeAxisOffset());
176 private int getTimeAxisOffset() {
177 return fTreeViewer
.getControl().getSize().x
+ fSashForm
.getSashWidth() + fXYViewer
.getPointAreaOffset();
184 public int getAvailableWidth(int requestedOffset
) {
185 int pointAreaWidth
= fXYViewer
.getPointAreaWidth();
186 int curTimeAxisOffset
= getTimeAxisOffset();
187 if (pointAreaWidth
<= 0) {
188 pointAreaWidth
= fSashForm
.getBounds().width
- curTimeAxisOffset
;
190 // TODO this is just an approximation that assumes that the end will be at the same position but that can change for a different data range/scaling
191 int endOffset
= curTimeAxisOffset
+ pointAreaWidth
;
192 GridLayout layout
= (GridLayout
) fXYViewerContainer
.getLayout();
193 int endOffsetWithoutMargin
= endOffset
+ layout
.marginRight
;
194 int availableWidth
= endOffsetWithoutMargin
- requestedOffset
;
195 availableWidth
= Math
.min(fSashForm
.getBounds().width
, Math
.max(0, availableWidth
));
196 return availableWidth
;
203 public void performAlign(int offset
, int width
) {
204 int total
= fSashForm
.getBounds().width
;
205 int plotAreaOffset
= fXYViewer
.getPointAreaOffset();
206 int width1
= Math
.max(0, offset
- plotAreaOffset
- fSashForm
.getSashWidth());
207 int width2
= Math
.max(0, total
- width1
- fSashForm
.getSashWidth());
208 fSashForm
.setWeights(new int[] { width1
, width2
});
211 Composite composite
= fXYViewerContainer
;
212 GridLayout layout
= (GridLayout
) composite
.getLayout();
213 int timeAxisWidth
= getAvailableWidth(offset
);
214 int marginSize
= timeAxisWidth
- width
;
215 layout
.marginRight
= Math
.max(0, marginSize
);