Commit | Line | Data |
---|---|---|
b0d3496e | 1 | /******************************************************************************* |
e31e01e8 | 2 | * Copyright (c) 2009, 2010 Ericsson |
b0d3496e ASL |
3 | * |
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 | |
8 | * | |
9 | * Contributors: | |
10 | * Francois Chouinard - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.tmf.ui.views; | |
14 | ||
15 | import org.eclipse.linuxtools.tmf.event.TmfEvent; | |
16 | import org.eclipse.linuxtools.tmf.event.TmfTimestamp; | |
e31e01e8 | 17 | import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; |
b0d3496e | 18 | import org.eclipse.linuxtools.tmf.request.TmfDataRequest; |
ff4ed569 FC |
19 | import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; |
20 | import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal; | |
550d787e | 21 | import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; |
b0d3496e ASL |
22 | import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; |
23 | import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; | |
24 | import org.eclipse.swt.SWT; | |
e31e01e8 | 25 | import org.eclipse.swt.events.SelectionAdapter; |
b0d3496e ASL |
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; | |
34 | ||
35 | /** | |
36 | * <b><u>TmfEventsView</u></b> | |
37 | * <p> | |
38 | * | |
39 | * TODO: Implement me. Please. | |
40 | * TODO: Handle column selection, sort, ... generically (nothing less...) | |
41 | * TODO: Implement hide/display columns | |
42 | */ | |
79a3a76e | 43 | public class TmfEventsView extends TmfView { |
b0d3496e | 44 | |
e31e01e8 | 45 | public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.events"; |
b0d3496e | 46 | |
e31e01e8 | 47 | private TmfExperiment<TmfEvent> fExperiment; |
62d1696a | 48 | private String fTitlePrefix; |
b0d3496e | 49 | |
e31e01e8 | 50 | // ------------------------------------------------------------------------ |
b0d3496e | 51 | // Table data |
e31e01e8 | 52 | // ------------------------------------------------------------------------ |
b0d3496e ASL |
53 | |
54 | private Table fTable; | |
55 | ||
56 | // Table column names | |
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[] { | |
e31e01e8 | 63 | TIMESTAMP_COLUMN, |
b0d3496e ASL |
64 | SOURCE_COLUMN, |
65 | TYPE_COLUMN, | |
66 | REFERENCE_COLUMN, | |
67 | CONTENT_COLUMN | |
68 | }; | |
69 | ||
70 | // Column data | |
71 | private class ColumnData { | |
72 | public final String header; | |
73 | public final int width; | |
74 | public final int alignment; | |
75 | ||
76 | public ColumnData(String h, int w, int a) { | |
77 | header = h; | |
78 | width = w; | |
79 | alignment = a; | |
80 | } | |
81 | }; | |
82 | ||
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) | |
89 | }; | |
90 | ||
e31e01e8 FC |
91 | // ------------------------------------------------------------------------ |
92 | // Event cache | |
93 | // ------------------------------------------------------------------------ | |
94 | ||
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; | |
100 | ||
101 | // ------------------------------------------------------------------------ | |
b0d3496e | 102 | // Constructor |
e31e01e8 | 103 | // ------------------------------------------------------------------------ |
b0d3496e | 104 | |
e31e01e8 | 105 | public TmfEventsView(int cacheSize) { |
fc6ccf6f | 106 | super("TmfEventsView"); |
e31e01e8 | 107 | fCacheSize = cacheSize; |
b0d3496e ASL |
108 | } |
109 | ||
e31e01e8 FC |
110 | public TmfEventsView() { |
111 | this(DEFAULT_CACHE_SIZE); | |
112 | } | |
113 | ||
114 | // ------------------------------------------------------------------------ | |
115 | // ViewPart | |
116 | // ------------------------------------------------------------------------ | |
117 | ||
118 | @SuppressWarnings("unchecked") | |
119 | @Override | |
b0d3496e ASL |
120 | public void createPartControl(Composite parent) { |
121 | ||
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); | |
126 | ||
127 | // Set the table layout | |
128 | GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); | |
129 | fTable.setLayoutData(layoutData); | |
130 | ||
131 | // Some cosmetic enhancements | |
132 | fTable.setHeaderVisible(true); | |
133 | fTable.setLinesVisible(true); | |
134 | ||
135 | // Set the columns | |
e31e01e8 | 136 | createColumnHeaders(fTable); |
b0d3496e ASL |
137 | |
138 | // Handle the table item requests | |
e31e01e8 | 139 | fTable.addSelectionListener(new SelectionAdapter() { |
3231fbd9 | 140 | |
b9fb2d51 FC |
141 | @Override |
142 | public void widgetSelected(SelectionEvent e) { | |
e31e01e8 FC |
143 | TmfTimestamp ts = (TmfTimestamp) fTable.getSelection()[0].getData(); |
144 | broadcast(new TmfTimeSynchSignal(fTable, ts)); | |
b0d3496e ASL |
145 | } |
146 | }); | |
147 | ||
148 | // Handle the table item requests | |
149 | fTable.addListener(SWT.SetData, new Listener() { | |
e31e01e8 | 150 | |
b0d3496e | 151 | public void handleEvent(Event event) { |
e31e01e8 FC |
152 | |
153 | TableItem item = (TableItem) event.item; | |
98029bc9 | 154 | final int index = fTable.indexOf(item); |
e31e01e8 | 155 | |
98029bc9 FC |
156 | // Note: this works because handleEvent() is called once for each row, in sequence |
157 | if ((index >= cacheStartIndex ) && (index < cacheEndIndex)) { | |
e31e01e8 FC |
158 | int i = index - cacheStartIndex; |
159 | item.setText(extractItemFields(cache[i])); | |
160 | item.setData(new TmfTimestamp(cache[i].getTimestamp())); | |
98029bc9 FC |
161 | return; |
162 | } | |
e31e01e8 FC |
163 | |
164 | TmfDataRequest<TmfEvent> request = new TmfDataRequest<TmfEvent>(TmfEvent.class, index, fCacheSize) { | |
b0d3496e ASL |
165 | @Override |
166 | public void handleData() { | |
28b94d61 | 167 | TmfEvent[] tmpEvent = getData(); |
54d55ced | 168 | if ((tmpEvent != null) && (tmpEvent.length > 0)) { |
28b94d61 | 169 | cache = tmpEvent; |
e31e01e8 | 170 | cacheStartIndex = index; |
85fb0e54 | 171 | cacheEndIndex = index + tmpEvent.length; |
550d787e | 172 | // System.out.println("TmfTableView: entry#" + index); |
28b94d61 | 173 | } |
b0d3496e ASL |
174 | } |
175 | }; | |
951d134a | 176 | fExperiment.sendRequest(request); |
2fb2eb37 FC |
177 | try { |
178 | request.waitForCompletion(); | |
179 | } catch (InterruptedException e) { | |
180 | e.printStackTrace(); | |
181 | } | |
28b94d61 | 182 | |
e31e01e8 | 183 | if (cache[0] != null && cacheStartIndex == index) { |
28b94d61 | 184 | item.setText(extractItemFields(cache[0])); |
e31e01e8 | 185 | item.setData(new TmfTimestamp(cache[0].getTimestamp())); |
28b94d61 FC |
186 | } |
187 | ||
b0d3496e ASL |
188 | } |
189 | }); | |
190 | ||
191 | fTable.setItemCount(0); | |
62d1696a | 192 | fTitlePrefix = getTitle(); |
8d2e2848 FC |
193 | |
194 | // If an experiment is already selected, update the table | |
e31e01e8 | 195 | fExperiment = (TmfExperiment<TmfEvent>) TmfExperiment.getCurrentExperiment(); |
8d2e2848 | 196 | if (fExperiment != null) { |
951d134a | 197 | experimentSelected(new TmfExperimentSelectedSignal<TmfEvent>(fTable, fExperiment)); |
8d2e2848 FC |
198 | } |
199 | } | |
200 | ||
b0d3496e ASL |
201 | /** |
202 | * @param table | |
203 | * | |
204 | * FIXME: Add support for column selection | |
205 | */ | |
e31e01e8 | 206 | protected void createColumnHeaders(Table table) { |
b0d3496e ASL |
207 | for (int i = 0; i < columnData.length; i++) { |
208 | TableColumn column = new TableColumn(table, columnData[i].alignment, i); | |
209 | column.setText(columnData[i].header); | |
210 | column.setWidth(columnData[i].width); | |
211 | } | |
212 | } | |
213 | ||
214 | /** | |
215 | * @param event | |
216 | * @return | |
217 | * | |
218 | * FIXME: Add support for column selection | |
219 | */ | |
220 | protected String[] extractItemFields(TmfEvent event) { | |
221 | String[] fields = new String[0]; | |
222 | if (event != null) { | |
223 | fields = new String[] { | |
224 | new Long(event.getTimestamp().getValue()).toString(), | |
225 | event.getSource().getSourceId().toString(), | |
226 | event.getType().getTypeId().toString(), | |
28b94d61 FC |
227 | event.getReference().getReference().toString(), |
228 | event.getContent().toString() | |
b0d3496e ASL |
229 | }; |
230 | } | |
231 | return fields; | |
232 | } | |
233 | ||
234 | /* (non-Javadoc) | |
235 | * @see org.eclipse.ui.part.WorkbenchPart#setFocus() | |
236 | */ | |
237 | @Override | |
238 | public void setFocus() { | |
239 | } | |
240 | ||
8d2e2848 FC |
241 | /* (non-Javadoc) |
242 | * @see java.lang.Object#toString() | |
243 | */ | |
244 | @Override | |
245 | public String toString() { | |
246 | return "[TmfEventsView]"; | |
247 | } | |
248 | ||
e31e01e8 | 249 | // ------------------------------------------------------------------------ |
b0d3496e | 250 | // Signal handlers |
e31e01e8 | 251 | // ------------------------------------------------------------------------ |
b0d3496e | 252 | |
e31e01e8 | 253 | @SuppressWarnings("unchecked") |
b0d3496e | 254 | @TmfSignalHandler |
951d134a | 255 | public void experimentSelected(TmfExperimentSelectedSignal<TmfEvent> signal) { |
b0d3496e | 256 | // Update the trace reference |
e31e01e8 | 257 | fExperiment = (TmfExperiment<TmfEvent>) signal.getExperiment(); |
9f584e4c | 258 | setPartName(fTitlePrefix + " - " + fExperiment.getName()); |
b0d3496e ASL |
259 | |
260 | // Perform the updates on the UI thread | |
261 | fTable.getDisplay().asyncExec(new Runnable() { | |
262 | public void run() { | |
85fb0e54 | 263 | fTable.setSelection(0); |
550d787e | 264 | fTable.removeAll(); |
cd63d14b | 265 | cacheStartIndex = cacheEndIndex = 0; // Clear the cache |
b0d3496e ASL |
266 | } |
267 | }); | |
268 | } | |
269 | ||
270 | @TmfSignalHandler | |
4e3aa37d | 271 | public void experimentUpdated(TmfExperimentUpdatedSignal signal) { |
b0d3496e ASL |
272 | // Perform the refresh on the UI thread |
273 | fTable.getDisplay().asyncExec(new Runnable() { | |
274 | public void run() { | |
4e3aa37d | 275 | if (!fTable.isDisposed() && fExperiment != null) { |
550d787e FC |
276 | int nbEvents = (int) fExperiment.getNbEvents(); |
277 | fTable.setItemCount((nbEvents > 100) ? nbEvents : 100); | |
b0d3496e ASL |
278 | } |
279 | } | |
280 | }); | |
281 | } | |
282 | ||
550d787e FC |
283 | private boolean fRefreshPending = false; |
284 | @TmfSignalHandler | |
285 | public synchronized void rangeSynched(TmfRangeSynchSignal signal) { | |
286 | if (!fRefreshPending) { | |
287 | // Perform the refresh on the UI thread | |
288 | fRefreshPending = true; | |
289 | fTable.getDisplay().asyncExec(new Runnable() { | |
290 | public void run() { | |
291 | fRefreshPending = false; | |
292 | if (!fTable.isDisposed() && fExperiment != null) { | |
293 | fTable.setItemCount((int) fExperiment.getNbEvents()); | |
294 | // if (Tracer.INTERNALS) Tracer.trace("TmfEventsView: itemCount=" + fTable.getItemCount()); | |
295 | } | |
296 | } | |
297 | }); | |
298 | } | |
299 | } | |
300 | ||
7f407ead FC |
301 | // @TmfSignalHandler |
302 | // public void currentTimeUpdated(TmfTimeSynchSignal signal) { | |
303 | // if (signal.getSource() != fTable && fExperiment != null) { | |
304 | // final int index = (int) fExperiment.getRank(signal.getCurrentTime()); | |
305 | // // Perform the updates on the UI thread | |
306 | // fTable.getDisplay().asyncExec(new Runnable() { | |
307 | // public void run() { | |
308 | // fTable.setSelection(index); | |
309 | // // The timestamp might not correspond to an actual event | |
310 | // // and the selection will point to the next experiment event. | |
311 | // // But we would like to display both the event before and | |
312 | // // after the selected timestamp. | |
313 | // // This works fine by default except when the selected event | |
314 | // // is the top displayed event. The following ensures that we | |
315 | // // always see both events. | |
316 | // if ((index > 0) && (index == fTable.getTopIndex())) { | |
317 | // fTable.setTopIndex(index - 1); | |
318 | // } | |
319 | // } | |
320 | // }); | |
321 | // } | |
322 | // } | |
9aae0442 | 323 | |
e31e01e8 | 324 | } |