1 /*******************************************************************************
2 * Copyright (c) 2009, 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 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.views
;
15 import org
.eclipse
.linuxtools
.tmf
.event
.TmfEvent
;
16 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
17 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperiment
;
18 import org
.eclipse
.linuxtools
.tmf
.request
.TmfDataRequest
;
19 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentSelectedSignal
;
20 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentUpdatedSignal
;
21 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfRangeSynchSignal
;
22 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
23 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
24 import org
.eclipse
.swt
.SWT
;
25 import org
.eclipse
.swt
.events
.SelectionAdapter
;
26 import org
.eclipse
.swt
.events
.SelectionEvent
;
27 import org
.eclipse
.swt
.layout
.GridData
;
28 import org
.eclipse
.swt
.widgets
.Composite
;
29 import org
.eclipse
.swt
.widgets
.Event
;
30 import org
.eclipse
.swt
.widgets
.Listener
;
31 import org
.eclipse
.swt
.widgets
.Table
;
32 import org
.eclipse
.swt
.widgets
.TableColumn
;
33 import org
.eclipse
.swt
.widgets
.TableItem
;
36 * <b><u>TmfEventsView</u></b>
39 * TODO: Implement me. Please.
40 * TODO: Handle column selection, sort, ... generically (nothing less...)
41 * TODO: Implement hide/display columns
43 public class TmfEventsView
extends TmfView
{
45 public static final String ID
= "org.eclipse.linuxtools.tmf.ui.views.events";
47 private TmfExperiment
<TmfEvent
> fExperiment
;
48 private String fTitlePrefix
;
50 // ------------------------------------------------------------------------
52 // ------------------------------------------------------------------------
57 private final String TIMESTAMP_COLUMN
= "Timestamp";
58 private final String SOURCE_COLUMN
= "Source";
59 private final String TYPE_COLUMN
= "Type";
60 private final String REFERENCE_COLUMN
= "File";
61 private final String CONTENT_COLUMN
= "Content";
62 private final String
[] columnProperties
= new String
[] {
71 private class ColumnData
{
72 public final String header
;
73 public final int width
;
74 public final int alignment
;
76 public ColumnData(String h
, int w
, int a
) {
83 private ColumnData
[] columnData
= new ColumnData
[] {
84 new ColumnData(columnProperties
[0], 100, SWT
.LEFT
),
85 new ColumnData(columnProperties
[1], 100, SWT
.LEFT
),
86 new ColumnData(columnProperties
[2], 100, SWT
.LEFT
),
87 new ColumnData(columnProperties
[3], 100, SWT
.LEFT
),
88 new ColumnData(columnProperties
[4], 100, SWT
.LEFT
)
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
95 private static final int DEFAULT_CACHE_SIZE
= 1000;
96 private final int fCacheSize
;
97 private TmfEvent
[] cache
= new TmfEvent
[1];
98 private int cacheStartIndex
= 0;
99 private int cacheEndIndex
= 0;
101 // ------------------------------------------------------------------------
103 // ------------------------------------------------------------------------
105 public TmfEventsView(int cacheSize
) {
106 super("TmfEventsView");
107 fCacheSize
= cacheSize
;
110 public TmfEventsView() {
111 this(DEFAULT_CACHE_SIZE
);
114 // ------------------------------------------------------------------------
116 // ------------------------------------------------------------------------
118 @SuppressWarnings("unchecked")
120 public void createPartControl(Composite parent
) {
122 // Create a virtual table
123 // TODO: change SINGLE to MULTI line selection and adjust the selection listener
124 final int style
= SWT
.SINGLE
| SWT
.H_SCROLL
| SWT
.V_SCROLL
| SWT
.BORDER
| SWT
.VIRTUAL
;
125 fTable
= new Table(parent
, style
);
127 // Set the table layout
128 GridData layoutData
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
129 fTable
.setLayoutData(layoutData
);
131 // Some cosmetic enhancements
132 fTable
.setHeaderVisible(true);
133 fTable
.setLinesVisible(true);
136 createColumnHeaders(fTable
);
138 // Handle the table item requests
139 fTable
.addSelectionListener(new SelectionAdapter() {
142 public void widgetSelected(SelectionEvent e
) {
143 TmfTimestamp ts
= (TmfTimestamp
) fTable
.getSelection()[0].getData();
144 broadcast(new TmfTimeSynchSignal(fTable
, ts
));
148 // Handle the table item requests
149 fTable
.addListener(SWT
.SetData
, new Listener() {
151 public void handleEvent(Event event
) {
153 final TableItem item
= (TableItem
) event
.item
;
154 final int index
= fTable
.indexOf(item
);
156 // Note: this works because handleEvent() is called once for each row, in sequence
157 if ((index
>= cacheStartIndex
) && (index
< cacheEndIndex
)) {
158 int i
= index
- cacheStartIndex
;
159 item
.setText(extractItemFields(cache
[i
]));
160 item
.setData(new TmfTimestamp(cache
[i
].getTimestamp()));
164 TmfDataRequest
<TmfEvent
> request
= new TmfDataRequest
<TmfEvent
>(TmfEvent
.class, index
, fCacheSize
) {
166 public void handleData() {
167 TmfEvent
[] tmpEvent
= getData();
168 if ((tmpEvent
!= null) && (tmpEvent
.length
> 0)) {
170 cacheStartIndex
= index
;
171 cacheEndIndex
= index
+ tmpEvent
.length
;
172 // System.out.println("TmfTableView: entry#" + index);
176 fExperiment
.sendRequest(request
);
178 request
.waitForCompletion();
179 if (cache
[0] != null && cacheStartIndex
== index
) {
180 item
.setText(extractItemFields(cache
[0]));
181 item
.setData(new TmfTimestamp(cache
[0].getTimestamp()));
183 } catch (InterruptedException e
) {
189 fTable
.setItemCount(0);
190 fTitlePrefix
= getTitle();
192 // If an experiment is already selected, update the table
193 fExperiment
= (TmfExperiment
<TmfEvent
>) TmfExperiment
.getCurrentExperiment();
194 if (fExperiment
!= null) {
195 experimentSelected(new TmfExperimentSelectedSignal
<TmfEvent
>(fTable
, fExperiment
));
202 * FIXME: Add support for column selection
204 protected void createColumnHeaders(Table table
) {
205 for (int i
= 0; i
< columnData
.length
; i
++) {
206 TableColumn column
= new TableColumn(table
, columnData
[i
].alignment
, i
);
207 column
.setText(columnData
[i
].header
);
208 column
.setWidth(columnData
[i
].width
);
216 * FIXME: Add support for column selection
218 protected String
[] extractItemFields(TmfEvent event
) {
219 String
[] fields
= new String
[0];
221 fields
= new String
[] {
222 new Long(event
.getTimestamp().getValue()).toString(),
223 event
.getSource().getSourceId().toString(),
224 event
.getType().getTypeId().toString(),
225 event
.getReference().getReference().toString(),
226 event
.getContent().toString()
233 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
236 public void setFocus() {
240 * @see java.lang.Object#toString()
243 public String
toString() {
244 return "[TmfEventsView]";
247 // ------------------------------------------------------------------------
249 // ------------------------------------------------------------------------
251 @SuppressWarnings("unchecked")
253 public void experimentSelected(TmfExperimentSelectedSignal
<TmfEvent
> signal
) {
254 // Update the trace reference
255 fExperiment
= (TmfExperiment
<TmfEvent
>) signal
.getExperiment();
256 setPartName(fTitlePrefix
+ " - " + fExperiment
.getName());
258 // Perform the updates on the UI thread
259 fTable
.getDisplay().asyncExec(new Runnable() {
261 fTable
.setSelection(0);
263 cacheStartIndex
= cacheEndIndex
= 0; // Clear the cache
269 public void experimentUpdated(TmfExperimentUpdatedSignal signal
) {
270 // Perform the refresh on the UI thread
271 fTable
.getDisplay().asyncExec(new Runnable() {
273 if (!fTable
.isDisposed() && fExperiment
!= null) {
274 int nbEvents
= (int) fExperiment
.getNbEvents();
275 fTable
.setItemCount((nbEvents
> 100) ? nbEvents
: 100);
281 private boolean fRefreshPending
= false;
283 public synchronized void rangeSynched(TmfRangeSynchSignal signal
) {
284 if (!fRefreshPending
) {
285 // Perform the refresh on the UI thread
286 fRefreshPending
= true;
287 fTable
.getDisplay().asyncExec(new Runnable() {
289 fRefreshPending
= false;
290 if (!fTable
.isDisposed() && fExperiment
!= null) {
291 fTable
.setItemCount((int) fExperiment
.getNbEvents());
292 // if (Tracer.INTERNALS) Tracer.trace("TmfEventsView: itemCount=" + fTable.getItemCount());
300 public void currentTimeUpdated(TmfTimeSynchSignal signal
) {
301 if (signal
.getSource() != fTable
&& fExperiment
!= null) {
302 final int index
= (int) fExperiment
.getRank(signal
.getCurrentTime());
303 // Perform the updates on the UI thread
304 fTable
.getDisplay().asyncExec(new Runnable() {
306 fTable
.setSelection(index
);
307 // The timestamp might not correspond to an actual event
308 // and the selection will point to the next experiment event.
309 // But we would like to display both the event before and
310 // after the selected timestamp.
311 // This works fine by default except when the selected event
312 // is the top displayed event. The following ensures that we
313 // always see both events.
314 if ((index
> 0) && (index
== fTable
.getTopIndex())) {
315 fTable
.setTopIndex(index
- 1);