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