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; | |
b0d3496e ASL |
21 | import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; |
22 | import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; | |
23 | import org.eclipse.swt.SWT; | |
e31e01e8 | 24 | import org.eclipse.swt.events.SelectionAdapter; |
b0d3496e ASL |
25 | import org.eclipse.swt.events.SelectionEvent; |
26 | import org.eclipse.swt.layout.GridData; | |
27 | import org.eclipse.swt.widgets.Composite; | |
28 | import org.eclipse.swt.widgets.Event; | |
29 | import org.eclipse.swt.widgets.Listener; | |
30 | import org.eclipse.swt.widgets.Table; | |
31 | import org.eclipse.swt.widgets.TableColumn; | |
32 | import org.eclipse.swt.widgets.TableItem; | |
33 | ||
34 | /** | |
35 | * <b><u>TmfEventsView</u></b> | |
36 | * <p> | |
37 | * | |
38 | * TODO: Implement me. Please. | |
39 | * TODO: Handle column selection, sort, ... generically (nothing less...) | |
40 | * TODO: Implement hide/display columns | |
41 | */ | |
79a3a76e | 42 | public class TmfEventsView extends TmfView { |
b0d3496e | 43 | |
e31e01e8 | 44 | public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.events"; |
b0d3496e | 45 | |
e31e01e8 | 46 | private TmfExperiment<TmfEvent> fExperiment; |
62d1696a | 47 | private String fTitlePrefix; |
b0d3496e | 48 | |
e31e01e8 | 49 | // ------------------------------------------------------------------------ |
b0d3496e | 50 | // Table data |
e31e01e8 | 51 | // ------------------------------------------------------------------------ |
b0d3496e ASL |
52 | |
53 | private Table fTable; | |
54 | ||
55 | // Table column names | |
56 | private final String TIMESTAMP_COLUMN = "Timestamp"; | |
57 | private final String SOURCE_COLUMN = "Source"; | |
58 | private final String TYPE_COLUMN = "Type"; | |
59 | private final String REFERENCE_COLUMN = "File"; | |
60 | private final String CONTENT_COLUMN = "Content"; | |
61 | private final String[] columnProperties = new String[] { | |
e31e01e8 | 62 | TIMESTAMP_COLUMN, |
b0d3496e ASL |
63 | SOURCE_COLUMN, |
64 | TYPE_COLUMN, | |
65 | REFERENCE_COLUMN, | |
66 | CONTENT_COLUMN | |
67 | }; | |
68 | ||
69 | // Column data | |
70 | private class ColumnData { | |
71 | public final String header; | |
72 | public final int width; | |
73 | public final int alignment; | |
74 | ||
75 | public ColumnData(String h, int w, int a) { | |
76 | header = h; | |
77 | width = w; | |
78 | alignment = a; | |
79 | } | |
80 | }; | |
81 | ||
82 | private ColumnData[] columnData = new ColumnData[] { | |
83 | new ColumnData(columnProperties[0], 100, SWT.LEFT), | |
84 | new ColumnData(columnProperties[1], 100, SWT.LEFT), | |
85 | new ColumnData(columnProperties[2], 100, SWT.LEFT), | |
86 | new ColumnData(columnProperties[3], 100, SWT.LEFT), | |
87 | new ColumnData(columnProperties[4], 100, SWT.LEFT) | |
88 | }; | |
89 | ||
e31e01e8 FC |
90 | // ------------------------------------------------------------------------ |
91 | // Event cache | |
92 | // ------------------------------------------------------------------------ | |
93 | ||
94 | private static final int DEFAULT_CACHE_SIZE = 1000; | |
95 | private final int fCacheSize; | |
96 | private TmfEvent[] cache = new TmfEvent[1]; | |
97 | private int cacheStartIndex = 0; | |
98 | private int cacheEndIndex = 0; | |
99 | ||
100 | // ------------------------------------------------------------------------ | |
b0d3496e | 101 | // Constructor |
e31e01e8 | 102 | // ------------------------------------------------------------------------ |
b0d3496e | 103 | |
e31e01e8 | 104 | public TmfEventsView(int cacheSize) { |
fc6ccf6f | 105 | super("TmfEventsView"); |
e31e01e8 | 106 | fCacheSize = cacheSize; |
b0d3496e ASL |
107 | } |
108 | ||
e31e01e8 FC |
109 | public TmfEventsView() { |
110 | this(DEFAULT_CACHE_SIZE); | |
111 | } | |
112 | ||
113 | // ------------------------------------------------------------------------ | |
114 | // ViewPart | |
115 | // ------------------------------------------------------------------------ | |
116 | ||
117 | @SuppressWarnings("unchecked") | |
118 | @Override | |
b0d3496e ASL |
119 | public void createPartControl(Composite parent) { |
120 | ||
121 | // Create a virtual table | |
122 | // TODO: change SINGLE to MULTI line selection and adjust the selection listener | |
123 | final int style = SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.VIRTUAL; | |
124 | fTable = new Table(parent, style); | |
125 | ||
126 | // Set the table layout | |
127 | GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); | |
128 | fTable.setLayoutData(layoutData); | |
129 | ||
130 | // Some cosmetic enhancements | |
131 | fTable.setHeaderVisible(true); | |
132 | fTable.setLinesVisible(true); | |
133 | ||
134 | // Set the columns | |
e31e01e8 | 135 | createColumnHeaders(fTable); |
b0d3496e ASL |
136 | |
137 | // Handle the table item requests | |
e31e01e8 | 138 | fTable.addSelectionListener(new SelectionAdapter() { |
3231fbd9 | 139 | |
b9fb2d51 FC |
140 | @Override |
141 | public void widgetSelected(SelectionEvent e) { | |
e31e01e8 FC |
142 | TmfTimestamp ts = (TmfTimestamp) fTable.getSelection()[0].getData(); |
143 | broadcast(new TmfTimeSynchSignal(fTable, ts)); | |
b0d3496e ASL |
144 | } |
145 | }); | |
146 | ||
147 | // Handle the table item requests | |
148 | fTable.addListener(SWT.SetData, new Listener() { | |
e31e01e8 | 149 | |
b0d3496e | 150 | public void handleEvent(Event event) { |
e31e01e8 FC |
151 | |
152 | TableItem item = (TableItem) event.item; | |
98029bc9 | 153 | final int index = fTable.indexOf(item); |
e31e01e8 | 154 | |
98029bc9 FC |
155 | // Note: this works because handleEvent() is called once for each row, in sequence |
156 | if ((index >= cacheStartIndex ) && (index < cacheEndIndex)) { | |
e31e01e8 FC |
157 | int i = index - cacheStartIndex; |
158 | item.setText(extractItemFields(cache[i])); | |
159 | item.setData(new TmfTimestamp(cache[i].getTimestamp())); | |
98029bc9 FC |
160 | return; |
161 | } | |
e31e01e8 FC |
162 | |
163 | TmfDataRequest<TmfEvent> request = new TmfDataRequest<TmfEvent>(TmfEvent.class, index, fCacheSize) { | |
b0d3496e ASL |
164 | @Override |
165 | public void handleData() { | |
28b94d61 | 166 | TmfEvent[] tmpEvent = getData(); |
54d55ced | 167 | if ((tmpEvent != null) && (tmpEvent.length > 0)) { |
28b94d61 | 168 | cache = tmpEvent; |
e31e01e8 | 169 | cacheStartIndex = index; |
85fb0e54 | 170 | cacheEndIndex = index + tmpEvent.length; |
28b94d61 | 171 | } |
b0d3496e ASL |
172 | } |
173 | }; | |
951d134a | 174 | fExperiment.sendRequest(request); |
2fb2eb37 FC |
175 | try { |
176 | request.waitForCompletion(); | |
177 | } catch (InterruptedException e) { | |
178 | e.printStackTrace(); | |
179 | } | |
28b94d61 | 180 | |
e31e01e8 | 181 | if (cache[0] != null && cacheStartIndex == index) { |
28b94d61 | 182 | item.setText(extractItemFields(cache[0])); |
e31e01e8 | 183 | item.setData(new TmfTimestamp(cache[0].getTimestamp())); |
28b94d61 FC |
184 | } |
185 | ||
b0d3496e ASL |
186 | } |
187 | }); | |
188 | ||
189 | fTable.setItemCount(0); | |
62d1696a | 190 | fTitlePrefix = getTitle(); |
8d2e2848 FC |
191 | |
192 | // If an experiment is already selected, update the table | |
e31e01e8 | 193 | fExperiment = (TmfExperiment<TmfEvent>) TmfExperiment.getCurrentExperiment(); |
8d2e2848 | 194 | if (fExperiment != null) { |
951d134a | 195 | experimentSelected(new TmfExperimentSelectedSignal<TmfEvent>(fTable, fExperiment)); |
8d2e2848 FC |
196 | } |
197 | } | |
198 | ||
b0d3496e ASL |
199 | /** |
200 | * @param table | |
201 | * | |
202 | * FIXME: Add support for column selection | |
203 | */ | |
e31e01e8 | 204 | protected void createColumnHeaders(Table table) { |
b0d3496e ASL |
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); | |
209 | } | |
210 | } | |
211 | ||
212 | /** | |
213 | * @param event | |
214 | * @return | |
215 | * | |
216 | * FIXME: Add support for column selection | |
217 | */ | |
218 | protected String[] extractItemFields(TmfEvent event) { | |
219 | String[] fields = new String[0]; | |
220 | if (event != null) { | |
221 | fields = new String[] { | |
222 | new Long(event.getTimestamp().getValue()).toString(), | |
223 | event.getSource().getSourceId().toString(), | |
224 | event.getType().getTypeId().toString(), | |
28b94d61 FC |
225 | event.getReference().getReference().toString(), |
226 | event.getContent().toString() | |
b0d3496e ASL |
227 | }; |
228 | } | |
229 | return fields; | |
230 | } | |
231 | ||
232 | /* (non-Javadoc) | |
233 | * @see org.eclipse.ui.part.WorkbenchPart#setFocus() | |
234 | */ | |
235 | @Override | |
236 | public void setFocus() { | |
237 | } | |
238 | ||
8d2e2848 FC |
239 | /* (non-Javadoc) |
240 | * @see java.lang.Object#toString() | |
241 | */ | |
242 | @Override | |
243 | public String toString() { | |
244 | return "[TmfEventsView]"; | |
245 | } | |
246 | ||
e31e01e8 | 247 | // ------------------------------------------------------------------------ |
b0d3496e | 248 | // Signal handlers |
e31e01e8 | 249 | // ------------------------------------------------------------------------ |
b0d3496e | 250 | |
e31e01e8 | 251 | @SuppressWarnings("unchecked") |
b0d3496e | 252 | @TmfSignalHandler |
951d134a | 253 | public void experimentSelected(TmfExperimentSelectedSignal<TmfEvent> signal) { |
b0d3496e | 254 | // Update the trace reference |
e31e01e8 | 255 | fExperiment = (TmfExperiment<TmfEvent>) signal.getExperiment(); |
9f584e4c | 256 | setPartName(fTitlePrefix + " - " + fExperiment.getName()); |
b0d3496e ASL |
257 | |
258 | // Perform the updates on the UI thread | |
259 | fTable.getDisplay().asyncExec(new Runnable() { | |
260 | public void run() { | |
fc6ccf6f | 261 | // TODO: Potentially long operation. Add some feedback for the user |
85fb0e54 | 262 | fTable.setSelection(0); |
b0d3496e | 263 | fTable.clearAll(); |
cd63d14b | 264 | cacheStartIndex = cacheEndIndex = 0; // Clear the cache |
9f584e4c | 265 | fTable.setItemCount((int) fExperiment.getNbEvents()); |
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) { |
9f584e4c | 276 | fTable.setItemCount((int) fExperiment.getNbEvents()); |
b0d3496e ASL |
277 | } |
278 | } | |
279 | }); | |
280 | } | |
281 | ||
7f407ead FC |
282 | // @TmfSignalHandler |
283 | // public void currentTimeUpdated(TmfTimeSynchSignal signal) { | |
284 | // if (signal.getSource() != fTable && fExperiment != null) { | |
285 | // final int index = (int) fExperiment.getRank(signal.getCurrentTime()); | |
286 | // // Perform the updates on the UI thread | |
287 | // fTable.getDisplay().asyncExec(new Runnable() { | |
288 | // public void run() { | |
289 | // fTable.setSelection(index); | |
290 | // // The timestamp might not correspond to an actual event | |
291 | // // and the selection will point to the next experiment event. | |
292 | // // But we would like to display both the event before and | |
293 | // // after the selected timestamp. | |
294 | // // This works fine by default except when the selected event | |
295 | // // is the top displayed event. The following ensures that we | |
296 | // // always see both events. | |
297 | // if ((index > 0) && (index == fTable.getTopIndex())) { | |
298 | // fTable.setTopIndex(index - 1); | |
299 | // } | |
300 | // } | |
301 | // }); | |
302 | // } | |
303 | // } | |
9aae0442 | 304 | |
e31e01e8 | 305 | } |