2010-10-26 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug309042
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / events / TmfEventsTable.java
CommitLineData
abfad0aa
FC
1/*******************************************************************************\r
2 * Copyright (c) 2010 Ericsson\r
3 * \r
4 * All rights reserved. This program and the accompanying materials are\r
5 * made available under the terms of the Eclipse Public License v1.0 which\r
6 * accompanies this distribution, and is available at\r
7 * http://www.eclipse.org/legal/epl-v10.html\r
8 * \r
9 * Contributors:\r
10 * Francois Chouinard - Initial API and implementation\r
11 * Patrick Tasse - Factored out from events view\r
9ccc6d01 12 * Francois Chouinard - Replaced Table by TmfVirtualTable\r
abfad0aa
FC
13 *******************************************************************************/\r
14\r
15package org.eclipse.linuxtools.tmf.ui.viewers.events;\r
16\r
529ee6a9
FC
17import org.eclipse.core.runtime.IProgressMonitor;\r
18import org.eclipse.core.runtime.IStatus;\r
19import org.eclipse.core.runtime.Status;\r
20import org.eclipse.core.runtime.jobs.Job;\r
abfad0aa
FC
21import org.eclipse.linuxtools.tmf.component.ITmfDataProvider;\r
22import org.eclipse.linuxtools.tmf.component.TmfComponent;\r
23import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
24import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
25import org.eclipse.linuxtools.tmf.request.TmfDataRequest;\r
26import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal;\r
27import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;\r
28import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;\r
29import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;\r
30import org.eclipse.linuxtools.tmf.signal.TmfTraceUpdatedSignal;\r
31import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
9ccc6d01
FC
32import org.eclipse.linuxtools.tmf.ui.widgets.ColumnData;\r
33import org.eclipse.linuxtools.tmf.ui.widgets.TmfVirtualTable;\r
abfad0aa
FC
34import org.eclipse.swt.SWT;\r
35import org.eclipse.swt.events.SelectionAdapter;\r
36import org.eclipse.swt.events.SelectionEvent;\r
37import org.eclipse.swt.layout.GridData;\r
38import org.eclipse.swt.widgets.Composite;\r
39import org.eclipse.swt.widgets.Event;\r
40import org.eclipse.swt.widgets.Listener;\r
abfad0aa
FC
41import org.eclipse.swt.widgets.TableColumn;\r
42import org.eclipse.swt.widgets.TableItem;\r
43\r
44/**\r
45 * <b><u>TmfEventsTable</u></b>\r
46 */\r
47public class TmfEventsTable extends TmfComponent {\r
48\r
abfad0aa
FC
49 // ------------------------------------------------------------------------\r
50 // Table data\r
51 // ------------------------------------------------------------------------\r
52\r
9ccc6d01 53 protected TmfVirtualTable fTable;\r
abfad0aa
FC
54 protected ITmfTrace fTrace;\r
55 protected boolean fPackDone = false;\r
56\r
57 // Table column names\r
529ee6a9
FC
58 static private final String TIMESTAMP_COLUMN = "Timestamp";\r
59 static private final String SOURCE_COLUMN = "Source";\r
60 static private final String TYPE_COLUMN = "Type";\r
61 static private final String REFERENCE_COLUMN = "File";\r
62 static private final String CONTENT_COLUMN = "Content";\r
63 static private final String[] COLUMN_NAMES = new String[] {\r
abfad0aa
FC
64 TIMESTAMP_COLUMN,\r
65 SOURCE_COLUMN,\r
66 TYPE_COLUMN,\r
67 REFERENCE_COLUMN,\r
68 CONTENT_COLUMN\r
69 };\r
70\r
529ee6a9
FC
71 static private ColumnData[] COLUMN_DATA = new ColumnData[] {\r
72 new ColumnData(COLUMN_NAMES[0], 100, SWT.LEFT),\r
73 new ColumnData(COLUMN_NAMES[1], 100, SWT.LEFT),\r
74 new ColumnData(COLUMN_NAMES[2], 100, SWT.LEFT),\r
75 new ColumnData(COLUMN_NAMES[3], 100, SWT.LEFT),\r
76 new ColumnData(COLUMN_NAMES[4], 100, SWT.LEFT)\r
abfad0aa
FC
77 };\r
78\r
79 // ------------------------------------------------------------------------\r
80 // Event cache\r
81 // ------------------------------------------------------------------------\r
82\r
9ccc6d01
FC
83 private final int fCacheSize;\r
84 private TmfEvent[] fCache;\r
85 private int fCacheStartIndex = 0;\r
86 private int fCacheEndIndex = 0;\r
87\r
529ee6a9 88 private boolean fDisposeOnClose;\r
abfad0aa
FC
89\r
90 // ------------------------------------------------------------------------\r
91 // Constructor\r
92 // ------------------------------------------------------------------------\r
93\r
94 public TmfEventsTable(Composite parent, int cacheSize) {\r
9ccc6d01
FC
95 this(parent, cacheSize, COLUMN_DATA);\r
96 }\r
97\r
98 public TmfEventsTable(Composite parent, int cacheSize, ColumnData[] columnData) {\r
abfad0aa
FC
99 super("TmfEventsTable");\r
100 \r
101 fCacheSize = cacheSize;\r
9ccc6d01 102 fCache = new TmfEvent[fCacheSize];\r
abfad0aa
FC
103 \r
104 // Create a virtual table\r
9ccc6d01
FC
105 final int style = SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER;\r
106 fTable = new TmfVirtualTable(parent, style);\r
abfad0aa
FC
107\r
108 // Set the table layout\r
109 GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);\r
110 fTable.setLayoutData(layoutData);\r
111\r
112 // Some cosmetic enhancements\r
113 fTable.setHeaderVisible(true);\r
114 fTable.setLinesVisible(true);\r
115\r
116 // Set the columns\r
9ccc6d01 117 setColumnHeaders(columnData);\r
abfad0aa
FC
118\r
119 // Handle the table item requests \r
120 fTable.addSelectionListener(new SelectionAdapter() {\r
abfad0aa
FC
121 @Override\r
122 public void widgetSelected(SelectionEvent e) {\r
123 TmfTimestamp ts = (TmfTimestamp) fTable.getSelection()[0].getData();\r
124 broadcast(new TmfTimeSynchSignal(fTable, ts));\r
125 }\r
126 });\r
127\r
128 // Handle the table item requests \r
129 fTable.addListener(SWT.SetData, new Listener() {\r
130\r
d4011df2
FC
131 @Override\r
132 @SuppressWarnings("unchecked")\r
abfad0aa
FC
133 public void handleEvent(Event event) {\r
134\r
135 final TableItem item = (TableItem) event.item;\r
136 final int index = fTable.indexOf(item);\r
137\r
138 // Note: this works because handleEvent() is called once for each row, in sequence \r
9ccc6d01
FC
139 if ((index >= fCacheStartIndex) && (index < fCacheEndIndex)) {\r
140 int i = index - fCacheStartIndex;\r
141 item.setText(extractItemFields(fCache[i]));\r
142 item.setData(new TmfTimestamp(fCache[i].getTimestamp()));\r
abfad0aa
FC
143 return;\r
144 }\r
145\r
f9673903
FC
146 fCacheStartIndex = index;\r
147 fCacheEndIndex = index;\r
148\r
abfad0aa 149 TmfDataRequest<TmfEvent> request = new TmfDataRequest<TmfEvent>(TmfEvent.class, index, fCacheSize) {\r
f9673903
FC
150 private int count = 0;\r
151\r
152 @Override\r
153 public void handleData(TmfEvent event) {\r
154 super.handleData(event);\r
155 if (event != null) {\r
156 fCache[count++] = event.clone();\r
157 fCacheEndIndex++;\r
abfad0aa
FC
158 }\r
159 }\r
f9673903 160\r
abfad0aa 161 };\r
f9673903 162\r
abfad0aa
FC
163 ((ITmfDataProvider<TmfEvent>) fTrace).sendRequest(request);\r
164 try {\r
165 request.waitForCompletion();\r
166 } catch (InterruptedException e) {\r
167 e.printStackTrace();\r
168 }\r
169 \r
9ccc6d01
FC
170 if (fCache[0] != null && fCacheStartIndex == index) {\r
171 item.setText(extractItemFields(fCache[0]));\r
172 item.setData(new TmfTimestamp(fCache[0].getTimestamp()));\r
173 packColumns();\r
abfad0aa
FC
174 }\r
175 \r
176 }\r
177 });\r
178\r
179 fTable.setItemCount(0);\r
180 }\r
181\r
9ccc6d01
FC
182 @Override\r
183 public void dispose() {\r
abfad0aa 184 fTable.dispose();\r
529ee6a9 185 if (fTrace != null && fDisposeOnClose) {\r
abfad0aa
FC
186 fTrace.dispose();\r
187 }\r
188 super.dispose();\r
189 }\r
190\r
9ccc6d01 191 public TmfVirtualTable getTable() {\r
abfad0aa
FC
192 return fTable;\r
193 }\r
194 \r
195 /**\r
196 * @param table\r
197 * \r
198 * FIXME: Add support for column selection\r
199 */\r
9ccc6d01
FC
200 protected void setColumnHeaders(ColumnData[] columnData) {\r
201 fTable.setColumnHeaders(columnData);\r
abfad0aa
FC
202 }\r
203\r
9ccc6d01 204 protected void packColumns() {\r
abfad0aa
FC
205 if (fPackDone) return;\r
206 for (TableColumn column : fTable.getColumns()) {\r
207 int headerWidth = column.getWidth();\r
208 column.pack();\r
209 if (column.getWidth() < headerWidth) {\r
210 column.setWidth(headerWidth);\r
211 }\r
212 }\r
213 fPackDone = true;\r
214 }\r
215 \r
216 /**\r
217 * @param event\r
218 * @return\r
219 * \r
220 * FIXME: Add support for column selection\r
221 */\r
78c0de16 222 protected String[] extractItemFields(TmfEvent event) {\r
abfad0aa
FC
223 String[] fields = new String[0];\r
224 if (event != null) {\r
225 fields = new String[] {\r
226 new Long(event.getTimestamp().getValue()).toString(), \r
227 event.getSource().getSourceId().toString(),\r
228 event.getType().getTypeId().toString(),\r
229 event.getReference().getReference().toString(),\r
230 event.getContent().toString()\r
231 };\r
232 }\r
233 return fields;\r
234 }\r
235\r
236 public void setFocus() {\r
237 fTable.setFocus();\r
238 }\r
239\r
529ee6a9
FC
240 /**\r
241 * @param trace\r
242 * @param disposeOnClose true if the trace should be disposed when the table is disposed\r
243 */\r
244 public void setTrace(ITmfTrace trace, boolean disposeOnClose) {\r
245 if (fTrace != null && fDisposeOnClose) {\r
246 fTrace.dispose();\r
247 }\r
abfad0aa 248 fTrace = trace;\r
529ee6a9 249 fDisposeOnClose = disposeOnClose;\r
abfad0aa
FC
250 \r
251 // Perform the updates on the UI thread\r
252 fTable.getDisplay().syncExec(new Runnable() {\r
d4011df2
FC
253 @Override\r
254 public void run() {\r
529ee6a9 255 //fTable.setSelection(0);\r
abfad0aa 256 fTable.removeAll();\r
9ccc6d01 257 fCacheStartIndex = fCacheEndIndex = 0; // Clear the cache\r
abfad0aa
FC
258 \r
259 if (!fTable.isDisposed() && fTrace != null) {\r
260 //int nbEvents = (int) fTrace.getNbEvents();\r
261 //fTable.setItemCount((nbEvents > 100) ? nbEvents : 100);\r
262 fTable.setItemCount((int) fTrace.getNbEvents());\r
263 }\r
264 }\r
265 });\r
abfad0aa
FC
266 }\r
267\r
268 // ------------------------------------------------------------------------\r
269 // Signal handlers\r
270 // ------------------------------------------------------------------------\r
271 \r
272 @TmfSignalHandler\r
273 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {\r
db1ea19b 274 if ((signal.getExperiment() != fTrace) || fTable.isDisposed()) return;\r
abfad0aa
FC
275 // Perform the refresh on the UI thread\r
276 fTable.getDisplay().asyncExec(new Runnable() {\r
d4011df2
FC
277 @Override\r
278 public void run() {\r
abfad0aa
FC
279 if (!fTable.isDisposed() && fTrace != null) {\r
280 fTable.setItemCount((int) fTrace.getNbEvents());\r
9ccc6d01 281 fTable.refresh();\r
abfad0aa
FC
282 }\r
283 }\r
284 });\r
285 }\r
286 \r
287 @TmfSignalHandler\r
288 public void traceUpdated(TmfTraceUpdatedSignal signal) {\r
db1ea19b 289 if ((signal.getTrace() != fTrace ) || fTable.isDisposed()) return;\r
abfad0aa
FC
290 // Perform the refresh on the UI thread\r
291 fTable.getDisplay().asyncExec(new Runnable() {\r
d4011df2
FC
292 @Override\r
293 public void run() {\r
abfad0aa
FC
294 if (!fTable.isDisposed() && fTrace != null) {\r
295 //int nbEvents = (int) fTrace.getNbEvents();\r
296 //fTable.setItemCount((nbEvents > 100) ? nbEvents : 100);\r
297 fTable.setItemCount((int) fTrace.getNbEvents());\r
298 }\r
299 }\r
300 });\r
301 }\r
302\r
303 private boolean fRefreshPending = false;\r
304 @TmfSignalHandler\r
305 public synchronized void rangeSynched(TmfRangeSynchSignal signal) {\r
db1ea19b 306 if (!fRefreshPending && !fTable.isDisposed()) {\r
abfad0aa
FC
307 // Perform the refresh on the UI thread\r
308 fRefreshPending = true;\r
309 fTable.getDisplay().asyncExec(new Runnable() {\r
d4011df2
FC
310 @Override\r
311 public void run() {\r
abfad0aa
FC
312 fRefreshPending = false;\r
313 if (!fTable.isDisposed() && fTrace != null) {\r
314 fTable.setItemCount((int) fTrace.getNbEvents());\r
315 }\r
316 }\r
317 });\r
318 }\r
319 }\r
320 \r
321 @TmfSignalHandler\r
529ee6a9 322 public void currentTimeUpdated(final TmfTimeSynchSignal signal) {\r
db1ea19b 323 if (signal.getSource() != fTable && fTrace != null && !fTable.isDisposed()) {\r
529ee6a9
FC
324 Job job = new Job("seeking...") {\r
325 @Override\r
326 protected IStatus run(IProgressMonitor monitor) {\r
327 final int index = (int) fTrace.getRank(signal.getCurrentTime());\r
328 // Perform the updates on the UI thread\r
329 fTable.getDisplay().asyncExec(new Runnable() {\r
d4011df2
FC
330 @Override\r
331 public void run() {\r
db1ea19b
FC
332 // Return if table is disposed\r
333 if (fTable.isDisposed()) return;\r
334 \r
529ee6a9
FC
335 fTable.setSelection(index);\r
336 // The timestamp might not correspond to an actual event\r
337 // and the selection will point to the next experiment event.\r
338 // But we would like to display both the event before and\r
339 // after the selected timestamp.\r
340 // This works fine by default except when the selected event\r
341 // is the top displayed event. The following ensures that we\r
342 // always see both events.\r
343 if ((index > 0) && (index == fTable.getTopIndex())) {\r
344 fTable.setTopIndex(index - 1);\r
345 }\r
346 }\r
347 });\r
348 return Status.OK_STATUS;\r
349 }};\r
350 job.schedule();\r
abfad0aa
FC
351 }\r
352 }\r
353}\r
This page took 0.043884 seconds and 5 git commands to generate.