1 /*******************************************************************************
2 * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
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
8 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.internal
.provisional
.analysis
.lami
.ui
.views
;
12 import java
.util
.HashSet
;
13 import java
.util
.LinkedHashSet
;
16 import org
.eclipse
.jface
.window
.Window
;
17 import org
.eclipse
.swt
.widgets
.Composite
;
18 import org
.eclipse
.swt
.widgets
.Shell
;
19 import org
.eclipse
.tracecompass
.internal
.provisional
.analysis
.lami
.core
.module
.LamiResultTable
;
20 import org
.eclipse
.tracecompass
.internal
.provisional
.analysis
.lami
.core
.module
.LamiTableEntry
;
21 import org
.eclipse
.tracecompass
.internal
.provisional
.analysis
.lami
.core
.types
.LamiTimeRange
;
22 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.chart
.core
.chart
.ChartData
;
23 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.chart
.core
.chart
.ChartModel
;
24 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.chart
.core
.signal
.ChartSelectionUpdateSignal
;
25 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.chart
.ui
.dialog
.ChartMakerDialog
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.component
.TmfComponent
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
35 import com
.google
.common
.collect
.Iterables
;
38 * Sub-view of a {@link LamiReportView} that shows the contents of one table of
39 * the analysis report. While it is not a View object directly, its
40 * responsibilities are the same.
42 * @author Alexandre Montplaisir
43 * @author Jonathan Rajotte-Julien
44 * @author Gabriel-Andrew Pollo-Guilbert
47 public final class LamiReportViewTabPage
extends TmfComponent
{
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
53 private final LamiResultTable fResultTable
;
54 private final LamiViewerControl fTableViewerControl
;
55 private final Set
<LamiViewerControl
> fCustomGraphViewerControls
= new LinkedHashSet
<>();
56 private final Composite fControl
;
58 private Set
<Object
> fSelection
;
60 // ------------------------------------------------------------------------
62 // ------------------------------------------------------------------------
70 * The result table to display in this tab
72 public LamiReportViewTabPage(Composite parent
, LamiResultTable table
) {
73 super(table
.getTableClass().getTableTitle());
79 /* Map the current trace selection to our lami entry */
80 fSelection
= getEntriesIntersectingTimerange(fResultTable
, TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange());
82 /* Prepare the table viewer, which is always present */
83 LamiViewerControl tableViewerControl
= new LamiViewerControl(fControl
, this);
84 fTableViewerControl
= tableViewerControl
;
86 /* Automatically open the table viewer initially */
87 fTableViewerControl
.getToggleAction().run();
89 /* Simulate a new external signal to the default viewer */
90 ChartSelectionUpdateSignal chartSignal
= new ChartSelectionUpdateSignal(this, fResultTable
, fSelection
);
91 TmfSignalManager
.dispatchSignal(chartSignal
);
93 /* Dispose this class's resource */
94 fControl
.addDisposeListener(e
-> {
95 fTableViewerControl
.dispose();
96 clearAllCustomViewers();
101 // ------------------------------------------------------------------------
103 // ------------------------------------------------------------------------
106 public void dispose() {
107 /* fControl's listner will dispose other resources */
111 // ------------------------------------------------------------------------
113 // ------------------------------------------------------------------------
116 * This method is used for creating a chart from the result table of the
117 * analyse. It uses the custom charts plugin to configure and create the
120 public void createNewCustomChart() {
121 Shell shell
= this.getControl().getShell();
126 /* Open the chart maker dialog */
127 ChartMakerDialog dialog
= new ChartMakerDialog(shell
, fResultTable
);
128 if (dialog
.open() != Window
.OK
) {
132 /* Make sure the data for making a chart was generated */
133 ChartData data
= dialog
.getDataSeries();
134 ChartModel model
= dialog
.getChartModel();
135 if (data
== null || model
== null) {
139 /* Make a chart with the factory constructor */
140 LamiViewerControl viewerControl
= new LamiViewerControl(fControl
, data
, model
);
141 fCustomGraphViewerControls
.add(viewerControl
);
142 viewerControl
.getToggleAction().run();
143 /* Signal the current selection to the newly created graph */
144 ChartSelectionUpdateSignal signal
= new ChartSelectionUpdateSignal(LamiReportViewTabPage
.this,
145 fResultTable
, fSelection
);
146 TmfSignalManager
.dispatchSignal(signal
);
152 * Clear all the custom graph viewers in this tab.
154 public void clearAllCustomViewers() {
155 fCustomGraphViewerControls
.forEach(LamiViewerControl
::dispose
);
156 fCustomGraphViewerControls
.clear();
160 * Toggle the display of the table viewer in this tab. This shows it if it
161 * is currently hidden, and vice versa.
163 public void toggleTableViewer() {
164 fTableViewerControl
.getToggleAction().run();
167 // ------------------------------------------------------------------------
169 // ------------------------------------------------------------------------
172 * Get the SWT control associated with this tab page.
174 * @return The SWT control
176 public Composite
getControl() {
181 * Get the result table shown in this tab.
183 * @return The report result table
185 public LamiResultTable
getResultTable() {
189 // ------------------------------------------------------------------------
191 // ------------------------------------------------------------------------
193 // Custom chart signals
195 * Signal handler for a chart selection update. It will try to propagate a
196 * {@link TmfSelectionRangeUpdatedSignal} if possible.
199 * The selection update signal
202 public void updateSelection(ChartSelectionUpdateSignal signal
) {
204 /* Make sure we are not sending a signal to ourself */
205 if (signal
.getSource() == this) {
209 /* Make sure the signal comes from the data provider's scope */
210 if (fResultTable
.hashCode() != signal
.getDataProvider().hashCode()) {
214 /* Find which index row has been selected */
215 Set
<Object
> entries
= signal
.getSelectedObject();
217 /* Update the selection */
218 fSelection
= entries
;
220 /* Only propagate to all TraceCompass if there is a single selection */
221 if (entries
.size() == 1) {
222 LamiTableEntry entry
= (LamiTableEntry
) Iterables
.getOnlyElement(entries
);
224 /* Make sure the selection represent a time range */
225 LamiTimeRange timeRange
= entry
.getCorrespondingTimeRange();
226 if (timeRange
== null) {
230 /* Get the timestamps from the time range */
232 * TODO: Consider low and high limits of timestamps here.
234 Number tsBeginValueNumber
= timeRange
.getBegin().getValue();
235 Number tsEndValueNumber
= timeRange
.getEnd().getValue();
236 if(tsBeginValueNumber
== null || tsEndValueNumber
== null) {
240 /* Send Range update to other views */
241 ITmfTimestamp start
= TmfTimestamp
.fromNanos(tsBeginValueNumber
.longValue());
242 ITmfTimestamp end
= TmfTimestamp
.fromNanos(tsEndValueNumber
.longValue());
243 TmfSignalManager
.dispatchSignal(new TmfSelectionRangeUpdatedSignal(this, start
, end
));
249 * Signal handler for a trace selection range update signal. It will try to
250 * map the external selection to our lami table entry.
253 * The received signal
256 public void externalUpdateSelectionCustomCharts(TmfSelectionRangeUpdatedSignal signal
) {
257 /* Make sure we are not sending a signal to ourself */
258 if (signal
.getSource() == this) {
262 TmfTimeRange range
= new TmfTimeRange(signal
.getBeginTime(), signal
.getEndTime());
264 // Custom chart signal
265 /* Find which lami table entry intersects the signal */
266 Set
<Object
> selection
= getEntriesIntersectingTimerange(fResultTable
, range
);
268 /* Update all LamiViewer */
269 ChartSelectionUpdateSignal updateSignal
= new ChartSelectionUpdateSignal(this, fResultTable
, selection
);
270 TmfSignalManager
.dispatchSignal(updateSignal
);
273 // ------------------------------------------------------------------------
275 // ------------------------------------------------------------------------
278 * Util method that returns {@link LamiTableEntry} that intersects a
279 * {@link TmfTimeRange}.
282 * The result table to search for entries
284 * The time range itself
285 * @return The set of entries that intersect with the time range
287 private static Set
<Object
> getEntriesIntersectingTimerange(LamiResultTable table
, TmfTimeRange range
) {
288 Set
<Object
> entries
= new HashSet
<>();
289 for (LamiTableEntry entry
: table
.getEntries()) {
290 LamiTimeRange lamiTimeRange
= entry
.getCorrespondingTimeRange();
292 /* Make sure the table has time ranges */
293 if (lamiTimeRange
== null) {
297 /* Get the timestamps from the time range */
299 * TODO: Consider low and high limits of timestamps here.
301 Number tsBeginValueNumber
= lamiTimeRange
.getBegin().getValue();
302 Number tsEndValueNumber
= lamiTimeRange
.getEnd().getValue();
303 if(tsBeginValueNumber
== null || tsEndValueNumber
== null) {
307 /* Convert the timestamps into TMF timestamps */
308 ITmfTimestamp start
= TmfTimestamp
.fromNanos(tsBeginValueNumber
.longValue());
309 ITmfTimestamp end
= TmfTimestamp
.fromNanos(tsEndValueNumber
.longValue());
311 /* Add iff the time range intersects the the signal */
312 TmfTimeRange tempTimeRange
= new TmfTimeRange(start
, end
);
313 if (tempTimeRange
.getIntersection(range
) != null) {