1 /*******************************************************************************
2 * Copyright (c) 2010 Ericsson
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 * Francois Chouinard - Initial API and implementation
11 * Patrick Tasse - Factored out from events view
12 * Francois Chouinard - Replaced Table by TmfVirtualTable
13 *******************************************************************************/
15 package org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.events
;
17 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
18 import org
.eclipse
.core
.runtime
.IStatus
;
19 import org
.eclipse
.core
.runtime
.Status
;
20 import org
.eclipse
.core
.runtime
.jobs
.Job
;
21 import org
.eclipse
.linuxtools
.tmf
.component
.ITmfDataProvider
;
22 import org
.eclipse
.linuxtools
.tmf
.component
.TmfComponent
;
23 import org
.eclipse
.linuxtools
.tmf
.event
.TmfEvent
;
24 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
25 import org
.eclipse
.linuxtools
.tmf
.request
.TmfDataRequest
;
26 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentUpdatedSignal
;
27 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfRangeSynchSignal
;
28 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
29 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
30 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTraceUpdatedSignal
;
31 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfTrace
;
32 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.ColumnData
;
33 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.TmfVirtualTable
;
34 import org
.eclipse
.swt
.SWT
;
35 import org
.eclipse
.swt
.events
.SelectionAdapter
;
36 import org
.eclipse
.swt
.events
.SelectionEvent
;
37 import org
.eclipse
.swt
.layout
.GridData
;
38 import org
.eclipse
.swt
.widgets
.Composite
;
39 import org
.eclipse
.swt
.widgets
.Event
;
40 import org
.eclipse
.swt
.widgets
.Listener
;
41 import org
.eclipse
.swt
.widgets
.TableColumn
;
42 import org
.eclipse
.swt
.widgets
.TableItem
;
45 * <b><u>TmfEventsTable</u></b>
47 public class TmfEventsTable
extends TmfComponent
{
49 // private Shell fShell;
51 // ------------------------------------------------------------------------
53 // ------------------------------------------------------------------------
55 protected TmfVirtualTable fTable
;
56 protected ITmfTrace fTrace
;
57 protected boolean fPackDone
= false;
60 static private final String TIMESTAMP_COLUMN
= "Timestamp";
61 static private final String SOURCE_COLUMN
= "Source";
62 static private final String TYPE_COLUMN
= "Type";
63 static private final String REFERENCE_COLUMN
= "File";
64 static private final String CONTENT_COLUMN
= "Content";
65 static private final String
[] COLUMN_NAMES
= new String
[] {
73 static private ColumnData
[] COLUMN_DATA
= new ColumnData
[] {
74 new ColumnData(COLUMN_NAMES
[0], 100, SWT
.LEFT
),
75 new ColumnData(COLUMN_NAMES
[1], 100, SWT
.LEFT
),
76 new ColumnData(COLUMN_NAMES
[2], 100, SWT
.LEFT
),
77 new ColumnData(COLUMN_NAMES
[3], 100, SWT
.LEFT
),
78 new ColumnData(COLUMN_NAMES
[4], 100, SWT
.LEFT
)
81 // ------------------------------------------------------------------------
83 // ------------------------------------------------------------------------
85 private final int fCacheSize
;
86 private TmfEvent
[] fCache
;
87 private int fCacheStartIndex
= 0;
88 private int fCacheEndIndex
= 0;
90 private boolean fDisposeOnClose
;
92 // ------------------------------------------------------------------------
94 // ------------------------------------------------------------------------
96 public TmfEventsTable(Composite parent
, int cacheSize
) {
97 this(parent
, cacheSize
, COLUMN_DATA
);
100 public TmfEventsTable(Composite parent
, int cacheSize
, ColumnData
[] columnData
) {
101 super("TmfEventsTable");
103 fCacheSize
= cacheSize
;
104 fCache
= new TmfEvent
[fCacheSize
];
106 // Create a virtual table
107 final int style
= SWT
.SINGLE
| SWT
.FULL_SELECTION
| SWT
.BORDER
;
108 fTable
= new TmfVirtualTable(parent
, style
);
110 // Set the table layout
111 GridData layoutData
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
112 fTable
.setLayoutData(layoutData
);
114 // Some cosmetic enhancements
115 fTable
.setHeaderVisible(true);
116 fTable
.setLinesVisible(true);
119 setColumnHeaders(columnData
);
121 // Handle the table item requests
122 fTable
.addSelectionListener(new SelectionAdapter() {
124 public void widgetSelected(SelectionEvent e
) {
125 TmfTimestamp ts
= (TmfTimestamp
) fTable
.getSelection()[0].getData();
126 broadcast(new TmfTimeSynchSignal(fTable
, ts
));
130 // Handle the table item requests
131 fTable
.addListener(SWT
.SetData
, new Listener() {
133 @SuppressWarnings("unchecked")
134 public void handleEvent(Event event
) {
136 final TableItem item
= (TableItem
) event
.item
;
137 final int index
= fTable
.indexOf(item
);
139 // Note: this works because handleEvent() is called once for each row, in sequence
140 if ((index
>= fCacheStartIndex
) && (index
< fCacheEndIndex
)) {
141 int i
= index
- fCacheStartIndex
;
142 item
.setText(extractItemFields(fCache
[i
]));
143 item
.setData(new TmfTimestamp(fCache
[i
].getTimestamp()));
147 fCacheStartIndex
= index
;
148 fCacheEndIndex
= index
;
150 TmfDataRequest
<TmfEvent
> request
= new TmfDataRequest
<TmfEvent
>(TmfEvent
.class, index
, fCacheSize
) {
152 // public void handleData() {
153 // TmfEvent[] tmpEvent = getData();
154 // if ((tmpEvent != null) && (tmpEvent.length > 0)) {
155 // fCache = tmpEvent;
156 // fCacheStartIndex = index;
157 // fCacheEndIndex = index + tmpEvent.length;
161 private int count
= 0;
164 public void handleData(TmfEvent event
) {
165 super.handleData(event
);
167 fCache
[count
++] = event
.clone();
174 ((ITmfDataProvider
<TmfEvent
>) fTrace
).sendRequest(request
);
176 request
.waitForCompletion();
177 } catch (InterruptedException e
) {
181 if (fCache
[0] != null && fCacheStartIndex
== index
) {
182 item
.setText(extractItemFields(fCache
[0]));
183 item
.setData(new TmfTimestamp(fCache
[0].getTimestamp()));
190 fTable
.setItemCount(0);
194 public void dispose() {
196 if (fTrace
!= null && fDisposeOnClose
) {
202 public TmfVirtualTable
getTable() {
209 * FIXME: Add support for column selection
211 protected void setColumnHeaders(ColumnData
[] columnData
) {
212 fTable
.setColumnHeaders(columnData
);
215 protected void packColumns() {
216 if (fPackDone
) return;
217 for (TableColumn column
: fTable
.getColumns()) {
218 int headerWidth
= column
.getWidth();
220 if (column
.getWidth() < headerWidth
) {
221 column
.setWidth(headerWidth
);
231 * FIXME: Add support for column selection
233 protected String
[] extractItemFields(TmfEvent event
) {
234 String
[] fields
= new String
[0];
236 fields
= new String
[] {
237 new Long(event
.getTimestamp().getValue()).toString(),
238 event
.getSource().getSourceId().toString(),
239 event
.getType().getTypeId().toString(),
240 event
.getReference().getReference().toString(),
241 event
.getContent().toString()
247 public void setFocus() {
253 * @param disposeOnClose true if the trace should be disposed when the table is disposed
255 public void setTrace(ITmfTrace trace
, boolean disposeOnClose
) {
256 if (fTrace
!= null && fDisposeOnClose
) {
260 fDisposeOnClose
= disposeOnClose
;
262 // Perform the updates on the UI thread
263 fTable
.getDisplay().syncExec(new Runnable() {
265 //fTable.setSelection(0);
267 fCacheStartIndex
= fCacheEndIndex
= 0; // Clear the cache
269 if (!fTable
.isDisposed() && fTrace
!= null) {
270 //int nbEvents = (int) fTrace.getNbEvents();
271 //fTable.setItemCount((nbEvents > 100) ? nbEvents : 100);
272 fTable
.setItemCount((int) fTrace
.getNbEvents());
278 // ------------------------------------------------------------------------
280 // ------------------------------------------------------------------------
283 public void experimentUpdated(TmfExperimentUpdatedSignal signal
) {
284 if (signal
.getExperiment() != fTrace
) return;
285 // Perform the refresh on the UI thread
286 fTable
.getDisplay().asyncExec(new Runnable() {
288 if (!fTable
.isDisposed() && fTrace
!= null) {
289 fTable
.setItemCount((int) fTrace
.getNbEvents());
297 public void traceUpdated(TmfTraceUpdatedSignal signal
) {
298 if (signal
.getTrace() != fTrace
) return;
299 // Perform the refresh on the UI thread
300 fTable
.getDisplay().asyncExec(new Runnable() {
302 if (!fTable
.isDisposed() && fTrace
!= null) {
303 //int nbEvents = (int) fTrace.getNbEvents();
304 //fTable.setItemCount((nbEvents > 100) ? nbEvents : 100);
305 fTable
.setItemCount((int) fTrace
.getNbEvents());
311 private boolean fRefreshPending
= false;
313 public synchronized void rangeSynched(TmfRangeSynchSignal signal
) {
314 if (!fRefreshPending
) {
315 // Perform the refresh on the UI thread
316 fRefreshPending
= true;
317 fTable
.getDisplay().asyncExec(new Runnable() {
319 fRefreshPending
= false;
320 if (!fTable
.isDisposed() && fTrace
!= null) {
321 fTable
.setItemCount((int) fTrace
.getNbEvents());
329 public void currentTimeUpdated(final TmfTimeSynchSignal signal
) {
330 if (signal
.getSource() != fTable
&& fTrace
!= null) {
331 Job job
= new Job("seeking...") {
333 protected IStatus
run(IProgressMonitor monitor
) {
334 final int index
= (int) fTrace
.getRank(signal
.getCurrentTime());
335 // Perform the updates on the UI thread
336 fTable
.getDisplay().asyncExec(new Runnable() {
338 fTable
.setSelection(index
);
339 // The timestamp might not correspond to an actual event
340 // and the selection will point to the next experiment event.
341 // But we would like to display both the event before and
342 // after the selected timestamp.
343 // This works fine by default except when the selected event
344 // is the top displayed event. The following ensures that we
345 // always see both events.
346 if ((index
> 0) && (index
== fTable
.getTopIndex())) {
347 fTable
.setTopIndex(index
- 1);
351 return Status
.OK_STATUS
;