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