Fix for experiment context management
[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
e2561baf 13 * Patrick Tasse - Filter implementation (inspired by www.eclipse.org/mat)\r
abfad0aa
FC
14 *******************************************************************************/\r
15\r
16package org.eclipse.linuxtools.tmf.ui.viewers.events;\r
17\r
e2561baf
FC
18import java.util.ArrayList;\r
19import java.util.Arrays;\r
20import java.util.HashMap;\r
21import java.util.Map;\r
22import java.util.Map.Entry;\r
23import java.util.regex.Pattern;\r
24import java.util.regex.PatternSyntaxException;\r
25\r
26import org.eclipse.core.resources.IMarker;\r
27import org.eclipse.core.resources.IResource;\r
28import org.eclipse.core.runtime.CoreException;\r
bbb3457d
FC
29import org.eclipse.core.runtime.IProgressMonitor;\r
30import org.eclipse.core.runtime.IStatus;\r
31import org.eclipse.core.runtime.Status;\r
32import org.eclipse.core.runtime.jobs.Job;\r
e2561baf
FC
33import org.eclipse.jface.action.Action;\r
34import org.eclipse.jface.action.IAction;\r
35import org.eclipse.jface.action.IMenuListener;\r
36import org.eclipse.jface.action.IMenuManager;\r
37import org.eclipse.jface.action.MenuManager;\r
38import org.eclipse.jface.action.Separator;\r
39import org.eclipse.jface.dialogs.Dialog;\r
40import org.eclipse.jface.dialogs.InputDialog;\r
41import org.eclipse.jface.dialogs.MessageDialog;\r
42import org.eclipse.jface.resource.FontDescriptor;\r
43import org.eclipse.jface.resource.JFaceResources;\r
44import org.eclipse.jface.resource.LocalResourceManager;\r
abfad0aa
FC
45import org.eclipse.linuxtools.tmf.component.ITmfDataProvider;\r
46import org.eclipse.linuxtools.tmf.component.TmfComponent;\r
47import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
e2561baf 48import org.eclipse.linuxtools.tmf.event.TmfEventContent;\r
abfad0aa 49import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
e2561baf
FC
50import org.eclipse.linuxtools.tmf.filter.ITmfFilter;\r
51import org.eclipse.linuxtools.tmf.filter.model.ITmfFilterTreeNode;\r
52import org.eclipse.linuxtools.tmf.filter.model.TmfFilterAndNode;\r
53import org.eclipse.linuxtools.tmf.filter.model.TmfFilterMatchesNode;\r
54import org.eclipse.linuxtools.tmf.filter.model.TmfFilterNode;\r
c1c69938 55import org.eclipse.linuxtools.tmf.request.ITmfDataRequest.ExecutionType;\r
abfad0aa
FC
56import org.eclipse.linuxtools.tmf.request.TmfDataRequest;\r
57import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal;\r
58import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;\r
59import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;\r
60import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;\r
61import org.eclipse.linuxtools.tmf.signal.TmfTraceUpdatedSignal;\r
e2561baf 62import org.eclipse.linuxtools.tmf.trace.ITmfLocation;\r
abfad0aa 63import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
e2561baf 64import org.eclipse.linuxtools.tmf.trace.TmfContext;\r
bbb3457d 65import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
7995b722 66import org.eclipse.linuxtools.tmf.ui.internal.Messages;\r
e2561baf
FC
67import org.eclipse.linuxtools.tmf.ui.views.colors.ColorSetting;\r
68import org.eclipse.linuxtools.tmf.ui.views.colors.ColorSettingsManager;\r
69import org.eclipse.linuxtools.tmf.ui.views.colors.IColorSettingsListener;\r
70import org.eclipse.linuxtools.tmf.ui.views.filter.FilterManager;\r
9ccc6d01 71import org.eclipse.linuxtools.tmf.ui.widgets.ColumnData;\r
e2561baf 72import org.eclipse.linuxtools.tmf.ui.widgets.TmfRawEventViewer;\r
9ccc6d01 73import org.eclipse.linuxtools.tmf.ui.widgets.TmfVirtualTable;\r
abfad0aa 74import org.eclipse.swt.SWT;\r
e2561baf
FC
75import org.eclipse.swt.custom.SashForm;\r
76import org.eclipse.swt.custom.TableEditor;\r
77import org.eclipse.swt.events.FocusAdapter;\r
78import org.eclipse.swt.events.FocusEvent;\r
79import org.eclipse.swt.events.KeyAdapter;\r
80import org.eclipse.swt.events.KeyEvent;\r
81import org.eclipse.swt.events.MouseAdapter;\r
82import org.eclipse.swt.events.MouseEvent;\r
abfad0aa
FC
83import org.eclipse.swt.events.SelectionAdapter;\r
84import org.eclipse.swt.events.SelectionEvent;\r
e2561baf
FC
85import org.eclipse.swt.graphics.Color;\r
86import org.eclipse.swt.graphics.Font;\r
87import org.eclipse.swt.graphics.Image;\r
88import org.eclipse.swt.graphics.Point;\r
89import org.eclipse.swt.graphics.Rectangle;\r
abfad0aa 90import org.eclipse.swt.layout.GridData;\r
e2561baf 91import org.eclipse.swt.layout.GridLayout;\r
abfad0aa 92import org.eclipse.swt.widgets.Composite;\r
e2561baf 93import org.eclipse.swt.widgets.Display;\r
abfad0aa
FC
94import org.eclipse.swt.widgets.Event;\r
95import org.eclipse.swt.widgets.Listener;\r
e2561baf 96import org.eclipse.swt.widgets.Menu;\r
abfad0aa
FC
97import org.eclipse.swt.widgets.TableColumn;\r
98import org.eclipse.swt.widgets.TableItem;\r
e2561baf
FC
99import org.eclipse.swt.widgets.Text;\r
100import org.eclipse.ui.PlatformUI;\r
101import org.eclipse.ui.ide.IGotoMarker;\r
102import org.eclipse.ui.themes.ColorUtil;\r
abfad0aa
FC
103\r
104/**\r
105 * <b><u>TmfEventsTable</u></b>\r
106 */\r
e2561baf 107public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorSettingsListener, ITmfEventsFilterProvider {\r
abfad0aa 108\r
e2561baf
FC
109 private static final Image BOOKMARK_IMAGE = TmfUiPlugin.getDefault().getImageFromPath("icons/elcl16/bookmark_obj.gif"); //$NON-NLS-1$\r
110 private static final Image SEARCH_IMAGE = TmfUiPlugin.getDefault().getImageFromPath("icons/elcl16/search.gif"); //$NON-NLS-1$\r
111 private static final Image SEARCH_MATCH_IMAGE = TmfUiPlugin.getDefault().getImageFromPath("icons/elcl16/search_match.gif"); //$NON-NLS-1$\r
112 private static final Image SEARCH_MATCH_BOOKMARK_IMAGE = TmfUiPlugin.getDefault().getImageFromPath("icons/elcl16/search_match_bookmark.gif"); //$NON-NLS-1$\r
113 private static final Image FILTER_IMAGE = TmfUiPlugin.getDefault().getImageFromPath("icons/elcl16/filter_items.gif"); //$NON-NLS-1$\r
114 private static final Image STOP_IMAGE = TmfUiPlugin.getDefault().getImageFromPath("icons/elcl16/stop.gif"); //$NON-NLS-1$\r
115 private static final String SEARCH_HINT = Messages.TmfEventsTable_SearchHint;\r
116 private static final String FILTER_HINT = Messages.TmfEventsTable_FilterHint;\r
117 \r
118 public interface Key {\r
119 String SEARCH_TXT = "$srch_txt"; //$NON-NLS-1$\r
120 String SEARCH_OBJ = "$srch_obj"; //$NON-NLS-1$\r
121 String FILTER_TXT = "$fltr_txt"; //$NON-NLS-1$\r
122 String FILTER_OBJ = "$fltr_obj"; //$NON-NLS-1$\r
123 String TIMESTAMP = "$time"; //$NON-NLS-1$\r
124 String RANK = "$rank"; //$NON-NLS-1$\r
125 String FIELD_ID = "$field_id"; //$NON-NLS-1$\r
126 }\r
127 \r
128 public static enum HeaderState {\r
129 SEARCH,\r
130 FILTER\r
131 }\r
132 \r
133 interface Direction {\r
134 int FORWARD = +1;\r
135 int BACKWARD = -1;\r
136 }\r
137 \r
abfad0aa
FC
138 // ------------------------------------------------------------------------\r
139 // Table data\r
140 // ------------------------------------------------------------------------\r
141\r
e2561baf
FC
142 protected Composite fComposite;\r
143 protected SashForm fSashForm;\r
9ccc6d01 144 protected TmfVirtualTable fTable;\r
e2561baf 145 protected TmfRawEventViewer fRawViewer;\r
abfad0aa
FC
146 protected ITmfTrace fTrace;\r
147 protected boolean fPackDone = false;\r
e2561baf
FC
148 protected HeaderState fHeaderState = HeaderState.SEARCH;\r
149 protected long fSelectedRank = 0;\r
150 \r
151 // Filter data\r
152 protected ArrayList<FilteredEvent> fFilteredEventCache = new ArrayList<FilteredEvent>();\r
153 protected long fFilterMatchCount;\r
154 protected long fFilterCheckCount;\r
155 protected FilterThread fFilterThread;\r
156 protected final Object fFilterSyncObj = new Object();\r
157 protected SearchThread fSearchThread;\r
158 protected final Object fSearchSyncObj = new Object();\r
159 protected ArrayList<ITmfEventsFilterListener> fEventsFilterListeners = new ArrayList<ITmfEventsFilterListener>();\r
160 \r
161 // Bookmark map <Rank, MarkerId>\r
162 protected Map<Long, Long> fBookmarksMap = new HashMap<Long, Long>();\r
163 protected IResource fBookmarksResource;\r
164 protected long fPendingGotoRank = -1;\r
165 \r
166 // SWT resources\r
167 protected LocalResourceManager fResourceManager = new LocalResourceManager(JFaceResources.getResources());\r
168 protected Color fGrayColor;\r
169 protected Color fGreenColor;\r
170 protected Font fBoldFont;\r
abfad0aa
FC
171\r
172 // Table column names\r
529ee6a9 173 static private final String[] COLUMN_NAMES = new String[] {\r
b9763f53
FC
174 Messages.TmfEventsTable_TimestampColumnHeader,\r
175 Messages.TmfEventsTable_SourceColumnHeader,\r
176 Messages.TmfEventsTable_TypeColumnHeader,\r
177 Messages.TmfEventsTable_ReferenceColumnHeader,\r
178 Messages.TmfEventsTable_ContentColumnHeader\r
abfad0aa
FC
179 };\r
180\r
529ee6a9
FC
181 static private ColumnData[] COLUMN_DATA = new ColumnData[] {\r
182 new ColumnData(COLUMN_NAMES[0], 100, SWT.LEFT),\r
183 new ColumnData(COLUMN_NAMES[1], 100, SWT.LEFT),\r
184 new ColumnData(COLUMN_NAMES[2], 100, SWT.LEFT),\r
185 new ColumnData(COLUMN_NAMES[3], 100, SWT.LEFT),\r
186 new ColumnData(COLUMN_NAMES[4], 100, SWT.LEFT)\r
abfad0aa
FC
187 };\r
188\r
e2561baf
FC
189 private class FilteredEvent {\r
190 TmfEvent event;\r
191 long rank;\r
192\r
193 public FilteredEvent (TmfEvent event, long rank) {\r
194 this.event = event;\r
195 this.rank = rank;\r
196 }\r
197 }\r
198 \r
abfad0aa
FC
199 // ------------------------------------------------------------------------\r
200 // Event cache\r
201 // ------------------------------------------------------------------------\r
202\r
9ccc6d01
FC
203 private final int fCacheSize;\r
204 private TmfEvent[] fCache;\r
205 private int fCacheStartIndex = 0;\r
206 private int fCacheEndIndex = 0;\r
207\r
529ee6a9 208 private boolean fDisposeOnClose;\r
abfad0aa
FC
209\r
210 // ------------------------------------------------------------------------\r
211 // Constructor\r
212 // ------------------------------------------------------------------------\r
213\r
214 public TmfEventsTable(Composite parent, int cacheSize) {\r
9ccc6d01
FC
215 this(parent, cacheSize, COLUMN_DATA);\r
216 }\r
217\r
218 public TmfEventsTable(Composite parent, int cacheSize, ColumnData[] columnData) {\r
3b38ea61 219 super("TmfEventsTable"); //$NON-NLS-1$\r
abfad0aa 220 \r
e2561baf
FC
221 fComposite = new Composite(parent, SWT.NONE);\r
222 GridLayout gl = new GridLayout(1, false);\r
223 gl.marginHeight = 0;\r
224 gl.marginWidth = 0;\r
225 gl.verticalSpacing = 0;\r
226 fComposite.setLayout(gl);\r
227\r
228 fSashForm = new SashForm(fComposite, SWT.HORIZONTAL);\r
229 fSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
abfad0aa
FC
230 \r
231 // Create a virtual table\r
b21305c2 232 final int style = SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION;\r
e2561baf 233 fTable = new TmfVirtualTable(fSashForm, style);\r
abfad0aa
FC
234\r
235 // Set the table layout\r
236 GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);\r
237 fTable.setLayoutData(layoutData);\r
238\r
239 // Some cosmetic enhancements\r
240 fTable.setHeaderVisible(true);\r
241 fTable.setLinesVisible(true);\r
242\r
243 // Set the columns\r
9ccc6d01 244 setColumnHeaders(columnData);\r
e2561baf
FC
245 \r
246 // Set the default column field ids if this is not a subclass\r
247 if (Arrays.equals(columnData, COLUMN_DATA)) {\r
248 fTable.getColumns()[0].setData(Key.FIELD_ID, TmfEventContent.FIELD_ID_TIMESTAMP);\r
249 fTable.getColumns()[1].setData(Key.FIELD_ID, TmfEventContent.FIELD_ID_SOURCE);\r
250 fTable.getColumns()[2].setData(Key.FIELD_ID, TmfEventContent.FIELD_ID_TYPE);\r
251 fTable.getColumns()[3].setData(Key.FIELD_ID, TmfEventContent.FIELD_ID_REFERENCE);\r
252 fTable.getColumns()[4].setData(Key.FIELD_ID, TmfEventContent.FIELD_ID_CONTENT);\r
253 }\r
abfad0aa 254\r
e2561baf
FC
255 // Set the frozen row for header row\r
256 fTable.setFrozenRowCount(1);\r
257\r
258 // Create the header row cell editor\r
259 createHeaderEditor();\r
260 \r
261 // Handle the table item selection\r
abfad0aa 262 fTable.addSelectionListener(new SelectionAdapter() {\r
abfad0aa
FC
263 @Override\r
264 public void widgetSelected(SelectionEvent e) {\r
e2561baf
FC
265 TableItem[] selection = fTable.getSelection();\r
266 if (selection.length > 0) {\r
267 TableItem selectedTableItem = selection[0];\r
268 if (selectedTableItem != null) {\r
269 if (selectedTableItem.getData(Key.RANK) instanceof Long) {\r
270 fSelectedRank = (Long) selectedTableItem.getData(Key.RANK);\r
271 fRawViewer.selectAndReveal((Long) selectedTableItem.getData(Key.RANK));\r
272 }\r
273 if (selectedTableItem.getData(Key.TIMESTAMP) instanceof TmfTimestamp) {\r
274 TmfTimestamp ts = (TmfTimestamp) selectedTableItem.getData(Key.TIMESTAMP);\r
275 broadcast(new TmfTimeSynchSignal(fTable, ts));\r
276 }\r
277 }\r
278 }\r
abfad0aa
FC
279 }\r
280 });\r
281\r
e2561baf
FC
282 fCacheSize = Math.max(cacheSize, Display.getDefault().getBounds().height / fTable.getItemHeight());\r
283 fCache = new TmfEvent[fCacheSize];\r
284\r
abfad0aa
FC
285 // Handle the table item requests \r
286 fTable.addListener(SWT.SetData, new Listener() {\r
287\r
d4011df2 288 @Override\r
abfad0aa
FC
289 public void handleEvent(Event event) {\r
290\r
291 final TableItem item = (TableItem) event.item;\r
e2561baf
FC
292 final int index = event.index - 1; // -1 for the header row\r
293\r
294 if (index == -1) {\r
295 String txtKey = null;\r
296 if (fHeaderState == HeaderState.SEARCH) {\r
297 item.setImage(SEARCH_IMAGE);\r
298 txtKey = Key.SEARCH_TXT;\r
299 } else if (fHeaderState == HeaderState.FILTER) {\r
300 item.setImage(FILTER_IMAGE);\r
301 txtKey = Key.FILTER_TXT;\r
302 }\r
303 item.setForeground(fGrayColor);\r
304 for (int i = 0; i < fTable.getColumns().length; i++) {\r
305 TableColumn column = fTable.getColumns()[i];\r
306 String filter = (String) column.getData(txtKey);\r
307 if (filter == null) {\r
308 if (fHeaderState == HeaderState.SEARCH) {\r
309 item.setText(i, SEARCH_HINT);\r
310 } else if (fHeaderState == HeaderState.FILTER) {\r
311 item.setText(i, FILTER_HINT);\r
312 }\r
313 item.setForeground(i, fGrayColor);\r
314 item.setFont(i, fTable.getFont());\r
315 } else {\r
316 item.setText(i, filter);\r
317 item.setForeground(i, fGreenColor);\r
318 item.setFont(i, fBoldFont);\r
319 }\r
320 }\r
321 return;\r
322 }\r
abfad0aa 323\r
bbb3457d 324 // If available, return the cached data \r
9ccc6d01
FC
325 if ((index >= fCacheStartIndex) && (index < fCacheEndIndex)) {\r
326 int i = index - fCacheStartIndex;\r
e2561baf 327 setItemData(item, fCache[i], index);\r
abfad0aa
FC
328 return;\r
329 }\r
330\r
e2561baf
FC
331 // If filter is applied, use the filtered event cache\r
332 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
333 setFilteredItemData(item, index);\r
334 return;\r
335 }\r
336\r
bbb3457d
FC
337 // Else, fill the cache asynchronously (and off the UI thread)\r
338 populateCache(index);\r
e2561baf 339 event.doit = false;\r
abfad0aa
FC
340 }\r
341 });\r
342\r
e2561baf
FC
343 fTable.addMouseListener(new MouseAdapter() {\r
344 @Override\r
345 public void mouseDoubleClick(MouseEvent event) {\r
346 if (event.button != 1) {\r
347 return;\r
348 }\r
349 // Identify the selected row\r
350 Point point = new Point(event.x, event.y);\r
351 TableItem item = fTable.getItem(point);\r
352 if (item != null) {\r
353 Rectangle imageBounds = item.getImageBounds(0);\r
354 imageBounds.width = BOOKMARK_IMAGE.getBounds().width;\r
355 if (imageBounds.contains(point)) {\r
356 Long rank = (Long) item.getData(Key.RANK);\r
357 if (rank != null) {\r
358 toggleBookmark(rank);\r
359 }\r
360 }\r
361 }\r
362 }\r
363 });\r
364 \r
365 // Create resources\r
366 createResources();\r
367\r
368 ColorSettingsManager.addColorSettingsListener(this);\r
369 \r
370 fTable.setItemCount(+1); // +1 for header row\r
371 \r
372 fRawViewer = new TmfRawEventViewer(fSashForm, SWT.H_SCROLL | SWT.V_SCROLL);\r
373 \r
374 fRawViewer.addSelectionListener(new SelectionAdapter() {\r
375 @Override\r
376 public void widgetSelected(SelectionEvent e) {\r
377 if (e.data instanceof Long) {\r
378 long rank = (Long) e.data;\r
379 int index = (int) rank;\r
380 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
381 index = getFilteredEventIndex(rank) + 1; // +1 for top filter status row\r
382 }\r
383 fTable.setSelection(index + 1); // +1 for header row\r
384 fSelectedRank = rank;\r
385 } else if (e.data instanceof ITmfLocation<?>) {\r
386 // DOES NOT WORK: rank undefined in context from seekLocation()\r
387// ITmfLocation<?> location = (ITmfLocation<?>) e.data;\r
388// TmfContext context = fTrace.seekLocation(location);\r
389// fTable.setSelection((int) context.getRank());\r
390 return;\r
391 } else {\r
392 return;\r
393 }\r
394 TableItem[] selection = fTable.getSelection();\r
395 if (selection != null && selection.length > 0) {\r
396 TmfTimestamp ts = (TmfTimestamp) fTable.getSelection()[0].getData(Key.TIMESTAMP);\r
397 if (ts != null) {\r
398 broadcast(new TmfTimeSynchSignal(fTable, ts));\r
399 }\r
400 }\r
401 }\r
402 });\r
403\r
404 fSashForm.setWeights(new int[] {1, 1});\r
405 fRawViewer.setVisible(false);\r
406\r
407 createPopupMenu();\r
abfad0aa
FC
408 }\r
409\r
e2561baf
FC
410 protected void createPopupMenu() {\r
411 final IAction showTableAction = new Action(Messages.TmfEventsTable_ShowTableActionText) {\r
412 @Override\r
413 public void run() {\r
414 fTable.setVisible(true);\r
415 fSashForm.layout();\r
416 }\r
417 };\r
418 \r
419 final IAction hideTableAction = new Action(Messages.TmfEventsTable_HideTableActionText) {\r
420 @Override\r
421 public void run() {\r
422 fTable.setVisible(false);\r
423 fSashForm.layout();\r
424 }\r
425 };\r
426 \r
427 final IAction showRawAction = new Action(Messages.TmfEventsTable_ShowRawActionText) {\r
428 @Override\r
429 public void run() {\r
430 fRawViewer.setVisible(true);\r
431 fSashForm.layout();\r
432 int index = fTable.getSelectionIndex();\r
433 if (index >= +1) { // +1 for header row\r
434 fRawViewer.selectAndReveal(index - 1);\r
435 }\r
436 }\r
437 };\r
438 \r
439 final IAction hideRawAction = new Action(Messages.TmfEventsTable_HideRawActionText) {\r
440 @Override\r
441 public void run() {\r
442 fRawViewer.setVisible(false);\r
443 fSashForm.layout();\r
444 }\r
445 };\r
446\r
447 final IAction showSearchBarAction = new Action(Messages.TmfEventsTable_ShowSearchBarActionText) {\r
448 @Override\r
449 public void run() {\r
450 fHeaderState = HeaderState.SEARCH;\r
451 fTable.refresh();\r
452 }\r
453 };\r
454\r
455 final IAction showFilterBarAction = new Action(Messages.TmfEventsTable_ShowFilterBarActionText) {\r
456 @Override\r
457 public void run() {\r
458 fHeaderState = HeaderState.FILTER;\r
459 fTable.refresh();\r
460 }\r
461 };\r
462\r
463 final IAction clearFiltersAction = new Action(Messages.TmfEventsTable_ClearFiltersActionText) {\r
464 @Override\r
465 public void run() {\r
466 stopFilterThread();\r
467 stopSearchThread();\r
468 clearFilters();\r
469 }\r
470 };\r
471\r
472 class ToggleBookmarkAction extends Action {\r
473 long fRank;\r
474 public ToggleBookmarkAction(String text, long rank) {\r
475 super(text);\r
476 fRank = rank;\r
477 }\r
478 \r
479 @Override\r
480 public void run() {\r
481 toggleBookmark(fRank);\r
482 }\r
483 }\r
484\r
485 final MenuManager tablePopupMenu = new MenuManager();\r
486 tablePopupMenu.setRemoveAllWhenShown(true);\r
487 tablePopupMenu.addMenuListener(new IMenuListener() {\r
488 @Override\r
489 public void menuAboutToShow(IMenuManager manager) {\r
490 if (fTable.getSelectionIndex() == 0) {\r
491 // Right-click on header row\r
492 if (fHeaderState == HeaderState.FILTER) {\r
493 tablePopupMenu.add(showSearchBarAction);\r
494 } else {\r
495 tablePopupMenu.add(showFilterBarAction);\r
496 }\r
497 return;\r
498 }\r
499 Point point = fTable.toControl(Display.getDefault().getCursorLocation());\r
500 TableItem item = fTable.getItem(point);\r
501 if (item != null) {\r
502 Rectangle imageBounds = item.getImageBounds(0);\r
503 imageBounds.width = BOOKMARK_IMAGE.getBounds().width;\r
504 if (imageBounds.contains(point)) {\r
505 // Right-click on left margin \r
506 Long rank = (Long) item.getData(Key.RANK);\r
507 if (rank != null) {\r
508 if (fBookmarksMap.containsKey(rank)) {\r
509 tablePopupMenu.add(new ToggleBookmarkAction(Messages.TmfEventsTable_RemoveBookmarkActionText, rank));\r
510 } else {\r
511 tablePopupMenu.add(new ToggleBookmarkAction(Messages.TmfEventsTable_AddBookmarkActionText, rank));\r
512 }\r
513 }\r
514 return;\r
515 }\r
516 }\r
517 // Right-click on table\r
518 if (fTable.isVisible() && fRawViewer.isVisible()) {\r
519 tablePopupMenu.add(hideTableAction);\r
520 tablePopupMenu.add(hideRawAction);\r
521 } else if (!fTable.isVisible()) {\r
522 tablePopupMenu.add(showTableAction);\r
523 } else if (!fRawViewer.isVisible()) {\r
524 tablePopupMenu.add(showRawAction);\r
525 }\r
526 tablePopupMenu.add(new Separator());\r
527 tablePopupMenu.add(clearFiltersAction);\r
528 ITmfFilterTreeNode[] savedFilters = FilterManager.getSavedFilters();\r
529 if (savedFilters.length > 0) {\r
530 MenuManager subMenu = new MenuManager(Messages.TmfEventsTable_ApplyPresetFilterMenuName);\r
531 for (ITmfFilterTreeNode node : savedFilters) {\r
532 if (node instanceof TmfFilterNode) {\r
533 final TmfFilterNode filter = (TmfFilterNode) node;\r
534 subMenu.add(new Action(filter.getFilterName()) {\r
535 @Override\r
536 public void run() {\r
537 synchronized (fFilteredEventCache) {\r
538 fFilteredEventCache.clear();\r
539 fFilterMatchCount = 0;\r
540 fFilterCheckCount = 0;\r
541 }\r
542 fCacheStartIndex = 0;\r
543 fCacheEndIndex = 0;\r
544 fTable.clearAll();\r
545 fTable.setData(Key.FILTER_OBJ, filter);\r
546 fTable.setItemCount(3); // +1 for header row, +2 for top and bottom filter status rows\r
547 startFilterThread();\r
548 fireFilterApplied(filter);\r
549 }});\r
550 }\r
551 }\r
552 tablePopupMenu.add(subMenu);\r
553 }\r
554 appendToTablePopupMenu(tablePopupMenu, item);\r
555 }\r
556 });\r
557 \r
558 final MenuManager rawViewerPopupMenu = new MenuManager();\r
559 rawViewerPopupMenu.setRemoveAllWhenShown(true);\r
560 rawViewerPopupMenu.addMenuListener(new IMenuListener() {\r
561 @Override\r
562 public void menuAboutToShow(IMenuManager manager) {\r
563 if (fTable.isVisible() && fRawViewer.isVisible()) {\r
564 rawViewerPopupMenu.add(hideTableAction);\r
565 rawViewerPopupMenu.add(hideRawAction);\r
566 } else if (!fTable.isVisible()) {\r
567 rawViewerPopupMenu.add(showTableAction);\r
568 } else if (!fRawViewer.isVisible()) {\r
569 rawViewerPopupMenu.add(showRawAction);\r
570 }\r
571 appendToRawPopupMenu(tablePopupMenu);\r
572 }\r
573 });\r
574 \r
575 Menu menu = tablePopupMenu.createContextMenu(fTable);\r
576 fTable.setMenu(menu);\r
577 \r
578 menu = rawViewerPopupMenu.createContextMenu(fRawViewer);\r
579 fRawViewer.setMenu(menu);\r
580 }\r
581\r
582 protected void appendToTablePopupMenu(MenuManager tablePopupMenu, TableItem selectedItem) {\r
583 // override to append more actions\r
584 }\r
585 \r
586 protected void appendToRawPopupMenu(MenuManager rawViewerPopupMenu) {\r
587 // override to append more actions\r
588 }\r
589 \r
9ccc6d01
FC
590 @Override\r
591 public void dispose() {\r
e2561baf
FC
592 stopSearchThread();\r
593 stopFilterThread();\r
594 ColorSettingsManager.removeColorSettingsListener(this);\r
595 fComposite.dispose();\r
529ee6a9 596 if (fTrace != null && fDisposeOnClose) {\r
abfad0aa
FC
597 fTrace.dispose();\r
598 }\r
e2561baf 599 fResourceManager.dispose();\r
abfad0aa
FC
600 super.dispose();\r
601 }\r
602\r
e2561baf
FC
603 public void setLayoutData(Object layoutData) {\r
604 fComposite.setLayoutData(layoutData);\r
605 }\r
606 \r
9ccc6d01 607 public TmfVirtualTable getTable() {\r
abfad0aa
FC
608 return fTable;\r
609 }\r
610 \r
611 /**\r
612 * @param table\r
613 * \r
614 * FIXME: Add support for column selection\r
615 */\r
9ccc6d01
FC
616 protected void setColumnHeaders(ColumnData[] columnData) {\r
617 fTable.setColumnHeaders(columnData);\r
abfad0aa
FC
618 }\r
619\r
e2561baf
FC
620 protected void setItemData(TableItem item, TmfEvent event, long rank) {\r
621 item.setText(extractItemFields(event));\r
622 item.setData(Key.TIMESTAMP, new TmfTimestamp(event.getTimestamp()));\r
623 item.setData(Key.RANK, rank);\r
624 \r
625 boolean bookmark = false;\r
626 if (fBookmarksMap.containsKey(rank)) {\r
627 bookmark = true;\r
628 }\r
629 \r
630 boolean searchMatch = false;\r
631 boolean searchNoMatch = false;\r
632 ITmfFilter searchFilter = (ITmfFilter) fTable.getData(Key.SEARCH_OBJ);\r
633 if (searchFilter != null) {\r
634 if (searchFilter.matches(event)) {\r
635 searchMatch = true;\r
636 } else {\r
637 searchNoMatch = true;\r
638 }\r
639 }\r
640 \r
641 ColorSetting colorSetting = ColorSettingsManager.getColorSetting(event);\r
642 if (searchNoMatch) {\r
643 item.setForeground(colorSetting.getDimmedForegroundColor());\r
644 item.setBackground(colorSetting.getDimmedBackgroundColor());\r
645 } else {\r
646 item.setForeground(colorSetting.getForegroundColor());\r
647 item.setBackground(colorSetting.getBackgroundColor());\r
648 }\r
649 \r
650 if (searchMatch) {\r
651 if (bookmark) {\r
652 item.setImage(SEARCH_MATCH_BOOKMARK_IMAGE);\r
653 } else {\r
654 item.setImage(SEARCH_MATCH_IMAGE);\r
655 }\r
656 } else if (bookmark) {\r
657 item.setImage(BOOKMARK_IMAGE);\r
658 } else {\r
659 item.setImage((Image) null);\r
660 }\r
661 }\r
662 \r
663 protected void setFilteredItemData(final TableItem item, int index) {\r
664 synchronized (fFilteredEventCache) {\r
665 if (index > 0 && --index < fFilteredEventCache.size()) { // top and bottom rows are filter status rows\r
666 FilteredEvent filteredEvent = fFilteredEventCache.get(index);\r
667 setItemData(item, filteredEvent.event, filteredEvent.rank);\r
668 return;\r
669 }\r
670 for (int i = 0; i < fTable.getColumns().length; i++) {\r
671 if (i == 0) {\r
672 if (fFilterCheckCount == fTrace.getNbEvents()) {\r
673 item.setImage(FILTER_IMAGE);\r
674 } else {\r
675 item.setImage(STOP_IMAGE);\r
676 }\r
677 item.setText(0, fFilterMatchCount + "/" + fFilterCheckCount); //$NON-NLS-1$\r
678 } else {\r
679 item.setText(i, ""); //$NON-NLS-1$\r
680 }\r
681 }\r
682 }\r
683 item.setData(Key.TIMESTAMP, null);\r
684 item.setData(Key.RANK, null);\r
685 item.setForeground(null);\r
686 item.setBackground(null);\r
687 }\r
688 \r
689 protected int getFilteredEventIndex(long rank) {\r
690 synchronized (fFilteredEventCache) {\r
691 for (int i = 0; i < fFilteredEventCache.size(); i++) {\r
692 FilteredEvent filteredEvent = fFilteredEventCache.get(i);\r
693 if (filteredEvent.rank >= rank) {\r
694 return i;\r
695 }\r
696 }\r
697 }\r
698 return fFilteredEventCache.size();\r
699 }\r
700 \r
701 protected void createHeaderEditor() {\r
702 final TableEditor tableEditor = fTable.createTableEditor();\r
703 tableEditor.horizontalAlignment = SWT.LEFT;\r
704 tableEditor.verticalAlignment = SWT.CENTER;\r
705 tableEditor.grabHorizontal = true;\r
706 tableEditor.minimumWidth = 50;\r
707\r
708 // Handle the header row selection\r
709 fTable.addMouseListener(new MouseAdapter() {\r
710 int columnIndex;\r
711 TableColumn column;\r
712 TableItem item;\r
713 \r
714 @Override\r
715 public void mouseDown(MouseEvent event) {\r
716 if (event.button != 1) {\r
717 return;\r
718 }\r
719 // Identify the selected row\r
720 Point point = new Point(event.x, event.y);\r
721 item = fTable.getItem(point);\r
722 \r
723 // Header row selected\r
724 if (item != null && fTable.indexOf(item) == 0) {\r
725\r
726 // Icon selected\r
727 if (item.getImageBounds(0).contains(point)) {\r
728 if (fHeaderState == HeaderState.SEARCH) {\r
729 fHeaderState = HeaderState.FILTER;\r
730 } else if (fHeaderState == HeaderState.FILTER) {\r
731 fHeaderState = HeaderState.SEARCH;\r
732 }\r
733 fTable.refresh();\r
734 return;\r
735 }\r
736 \r
737 // Identify the selected column\r
738 columnIndex = -1;\r
739 for (int i = 0; i < fTable.getColumns().length; i++) {\r
740 Rectangle rect = item.getBounds(i);\r
741 if (rect.contains(point)) {\r
742 columnIndex = i;\r
743 break;\r
744 }\r
745 }\r
746 \r
747 if (columnIndex == -1) {\r
748 return;\r
749 }\r
750 \r
751 column = fTable.getColumns()[columnIndex];\r
752 \r
753 String txtKey = null;\r
754 if (fHeaderState == HeaderState.SEARCH) {\r
755 txtKey = Key.SEARCH_TXT;\r
756 } else if (fHeaderState == HeaderState.FILTER) {\r
757 txtKey = Key.FILTER_TXT;\r
758 }\r
759 \r
760 // The control that will be the editor must be a child of the Table\r
761 final Text newEditor = (Text) fTable.createTableEditorControl(Text.class);\r
762 String headerString = (String) column.getData(txtKey);\r
763 if (headerString != null) {\r
764 newEditor.setText(headerString);\r
765 }\r
766 newEditor.addFocusListener(new FocusAdapter() {\r
767 @Override\r
768 public void focusLost(FocusEvent e) {\r
769 boolean changed = updateHeader(newEditor.getText());\r
770 if (changed) {\r
771 applyHeader();\r
772 }\r
773 }\r
774 });\r
775 newEditor.addKeyListener(new KeyAdapter() {\r
776 @Override\r
777 public void keyPressed(KeyEvent e) {\r
778 if (e.character == SWT.CR) {\r
779 updateHeader(newEditor.getText());\r
780 applyHeader();\r
781 } else if (e.character == SWT.ESC) {\r
782 tableEditor.getEditor().dispose();\r
783 }\r
784 }\r
785 });\r
786 newEditor.selectAll();\r
787 newEditor.setFocus();\r
788 tableEditor.setEditor(newEditor, item, columnIndex);\r
789 }\r
790 }\r
791 \r
792 /*\r
793 * returns true is value was changed\r
794 */\r
795 private boolean updateHeader(String text) {\r
796 String objKey = null;\r
797 String txtKey = null;\r
798 if (fHeaderState == HeaderState.SEARCH) {\r
799 objKey = Key.SEARCH_OBJ;\r
800 txtKey = Key.SEARCH_TXT;\r
801 } else if (fHeaderState == HeaderState.FILTER) {\r
802 objKey = Key.FILTER_OBJ;\r
803 txtKey = Key.FILTER_TXT;\r
804 }\r
805 if (text.trim().length() > 0) {\r
806 try {\r
807 String regex = TmfFilterMatchesNode.regexFix(text);\r
808 Pattern.compile(regex);\r
809 if (regex.equals(column.getData(txtKey))) {\r
810 tableEditor.getEditor().dispose();\r
811 return false;\r
812 }\r
813 TmfFilterMatchesNode filter = new TmfFilterMatchesNode(null);\r
814 String fieldId = (String) column.getData(Key.FIELD_ID);\r
815 if (fieldId == null) {\r
816 fieldId = column.getText();\r
817 }\r
818 filter.setField(fieldId);\r
819 filter.setRegex(regex);\r
820 column.setData(objKey, filter);\r
821 column.setData(txtKey, regex);\r
822 } catch (PatternSyntaxException ex) {\r
823 tableEditor.getEditor().dispose();\r
824 MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), ex.getDescription(), ex.getMessage());\r
825 return false;\r
826 }\r
827 } else {\r
828 if (column.getData(txtKey) == null) {\r
829 tableEditor.getEditor().dispose();\r
830 return false;\r
831 }\r
832 column.setData(objKey, null);\r
833 column.setData(txtKey, null);\r
834 }\r
835 return true;\r
836 }\r
837 \r
838 private void applyHeader() {\r
839 stopSearchThread();\r
840 if (fHeaderState == HeaderState.SEARCH) {\r
841 final TmfFilterAndNode filter = new TmfFilterAndNode(null);\r
842 for (TableColumn column : fTable.getColumns()) {\r
843 Object filterObj = column.getData(Key.SEARCH_OBJ);\r
844 if (filterObj instanceof ITmfFilterTreeNode) {\r
845 filter.addChild((ITmfFilterTreeNode) filterObj);\r
846 }\r
847 }\r
848 if (filter.getChildrenCount() > 0) {\r
849 fTable.setData(Key.SEARCH_OBJ, filter);\r
850 fTable.refresh();\r
851 searchNext();\r
852 fireSearchApplied(filter);\r
853 } else {\r
854 fTable.setData(Key.SEARCH_OBJ, null);\r
855 fTable.refresh();\r
856 fireSearchApplied(null);\r
857 }\r
858 } else if (fHeaderState == HeaderState.FILTER) {\r
859 synchronized (fFilteredEventCache) {\r
860 fFilteredEventCache.clear();\r
861 fFilterMatchCount = 0;\r
862 fFilterCheckCount = 0;\r
863 }\r
864 fCacheStartIndex = 0;\r
865 fCacheEndIndex = 0;\r
866 TmfFilterAndNode filter = new TmfFilterAndNode(null);\r
867 for (TableColumn column : fTable.getColumns()) {\r
868 Object filterObj = column.getData(Key.FILTER_OBJ);\r
869 if (filterObj instanceof ITmfFilterTreeNode) {\r
870 filter.addChild((ITmfFilterTreeNode) filterObj);\r
871 }\r
872 }\r
873 if (filter.getChildrenCount() > 0) {\r
874 fTable.clearAll();\r
875 fTable.setData(Key.FILTER_OBJ, filter);\r
876 fTable.setItemCount(3); // +1 for header row, +2 for top and bottom filter status rows\r
877 startFilterThread();\r
878 fireFilterApplied(filter);\r
879 } else {\r
880 stopFilterThread();\r
881 fTable.clearAll();\r
882 fTable.setData(Key.FILTER_OBJ, null);\r
883 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
884 fireFilterApplied(null);\r
885 }\r
886 }\r
887 \r
888 tableEditor.getEditor().dispose();\r
889 }\r
890 });\r
891 \r
892 fTable.addKeyListener(new KeyAdapter() {\r
893 @Override\r
894 public void keyPressed(KeyEvent e) {\r
895 e.doit = false;\r
896 if (e.character == SWT.ESC) {\r
897 stopFilterThread();\r
898 stopSearchThread();\r
899 fTable.refresh();\r
900 } else if (e.character == SWT.DEL) {\r
901 stopFilterThread();\r
902 stopSearchThread();\r
903 if (fHeaderState == HeaderState.SEARCH) {\r
904 for (TableColumn column : fTable.getColumns()) {\r
905 column.setData(Key.SEARCH_OBJ, null);\r
906 column.setData(Key.SEARCH_TXT, null);\r
907 }\r
908 fTable.setData(Key.SEARCH_OBJ, null);\r
909 fTable.refresh();\r
910 fireSearchApplied(null);\r
911 } else if (fHeaderState == HeaderState.FILTER) {\r
912 clearFilters();\r
913 }\r
914 } else if (e.character == SWT.CR) {\r
915 if ((e.stateMask & SWT.SHIFT) == 0) {\r
916 searchNext();\r
917 } else {\r
918 searchPrevious();\r
919 }\r
920 }\r
921 }\r
922 });\r
923 }\r
924\r
925 protected void fireFilterApplied(ITmfFilter filter) {\r
926 for (ITmfEventsFilterListener listener : fEventsFilterListeners) {\r
927 listener.filterApplied(filter, fTrace);\r
928 }\r
929 }\r
930 \r
931 protected void fireSearchApplied(ITmfFilter filter) {\r
932 for (ITmfEventsFilterListener listener : fEventsFilterListeners) {\r
933 listener.searchApplied(filter, fTrace);\r
934 }\r
935 }\r
936 \r
937 protected void startFilterThread() {\r
938 synchronized (fFilterSyncObj) {\r
939 if (fFilterThread != null) {\r
940 fFilterThread.cancel();\r
941 }\r
942 final ITmfFilterTreeNode filter = (ITmfFilterTreeNode) fTable.getData(Key.FILTER_OBJ);\r
943 fFilterThread = new FilterThread(filter);\r
944 fFilterThread.start();\r
945 }\r
946 }\r
947\r
948 protected void stopFilterThread() {\r
949 synchronized (fFilterSyncObj) {\r
950 if (fFilterThread != null) {\r
951 fFilterThread.cancel();\r
952 }\r
953 }\r
954 }\r
955\r
956 protected void clearFilters() {\r
957 if (fTable.getData(Key.FILTER_OBJ) == null) {\r
958 return;\r
959 }\r
960 long selectedRank = -1;\r
961 synchronized (fFilteredEventCache) {\r
962 int selectedIndex = fTable.getSelectionIndex() - 2; // -1 for header row, -1 for top filter status row\r
963 if (selectedIndex >= 0 && selectedIndex < fFilteredEventCache.size()) {\r
964 selectedRank = fFilteredEventCache.get(selectedIndex).rank;\r
965 }\r
966 }\r
967 fTable.clearAll();\r
968 for (TableColumn column : fTable.getColumns()) {\r
969 column.setData(Key.FILTER_OBJ, null);\r
970 column.setData(Key.FILTER_TXT, null);\r
971 }\r
972 fTable.setData(Key.FILTER_OBJ, null);\r
973 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
974 synchronized (fFilteredEventCache) {\r
975 fFilteredEventCache.clear();\r
976 fFilterMatchCount = 0;\r
977 fFilterCheckCount = 0;\r
978 }\r
979 if (selectedRank >= 0) {\r
980 fTable.setSelection((int) selectedRank + 1); // +1 for header row\r
981 } else {\r
982 fTable.setSelection(0);\r
983 }\r
984 fireFilterApplied(null);\r
985 }\r
986 \r
987 protected class FilterThread extends Thread {\r
988 private volatile boolean interrupted = false;\r
989 private final ITmfFilterTreeNode filter;\r
990\r
991 public FilterThread(ITmfFilterTreeNode filter) {\r
992 super("Filter Thread"); //$NON-NLS-1$\r
993 this.filter = filter;\r
994 }\r
995 \r
996 @Override\r
997 public void run() {\r
998 final Display display = Display.getDefault();\r
999 long lastRefreshTime = System.currentTimeMillis();\r
1000 TmfContext context = fTrace.seekLocation(null);\r
1001 context.setRank(0);\r
1002 long rank = 0;\r
1003 /*\r
1004 TmfContext context;\r
1005 long rank;\r
1006 synchronized (fFilteredEventCache) {\r
1007 if (fFilterCheckCount == 0) {\r
1008 rank = 0;\r
1009 context = fTrace.seekLocation(null);\r
1010 context.setRank(0);\r
1011 } else {\r
1012 // Get the event following the last checked event\r
1013 rank = fFilterCheckCount;\r
1014 context = fTrace.seekEvent(rank);\r
1015 }\r
1016 }\r
1017 */\r
1018 \r
1019 TmfEvent event = fTrace.getNextEvent(context);\r
1020 while (!interrupted && event != null) {\r
1021 fFilterCheckCount++;\r
1022 if (filter.matches(event)) {\r
1023 synchronized (fFilteredEventCache) {\r
1024 fFilteredEventCache.add(new FilteredEvent(event, rank));\r
1025 fFilterMatchCount++;\r
1026 }\r
1027 display.asyncExec(new Runnable() {\r
1028 @Override\r
1029 public void run() {\r
1030 if (interrupted) return;\r
1031 if (fTable.isDisposed()) return;\r
1032 fTable.setItemCount(fFilteredEventCache.size() + 3); // +1 for header row, +2 for top and bottom filter status rows\r
1033 }\r
1034 });\r
1035 }\r
1036 if (fFilterCheckCount % 100 == 0) {\r
1037 long currentTime = System.currentTimeMillis();\r
1038 if (currentTime - lastRefreshTime > 1000) {\r
1039 lastRefreshTime = currentTime;\r
1040 display.asyncExec(new Runnable() {\r
1041 @Override\r
1042 public void run() {\r
1043 if (interrupted) return;\r
1044 if (fTable.isDisposed()) return;\r
1045 fTable.refresh();\r
1046 }\r
1047 });\r
1048 }\r
1049 }\r
1050 rank = context.getRank();\r
1051 event = fTrace.getNextEvent(context);\r
1052 }\r
1053 display.asyncExec(new Runnable() {\r
1054 @Override\r
1055 public void run() {\r
1056 if (fTable.isDisposed()) return;\r
1057 fTable.refresh();\r
1058 }\r
1059 });\r
1060 }\r
1061 \r
1062 public void cancel() {\r
1063 interrupted = true;\r
1064 }\r
1065 }\r
1066 \r
1067 protected void searchNext() {\r
1068 synchronized (fSearchSyncObj) {\r
1069 if (fSearchThread != null) {\r
1070 return;\r
1071 }\r
1072 final ITmfFilterTreeNode filter = (ITmfFilterTreeNode) fTable.getData(Key.SEARCH_OBJ);\r
1073 if (filter == null) {\r
1074 return;\r
1075 }\r
1076 int selectionIndex = fTable.getSelectionIndex();\r
1077 int startIndex;\r
1078 if (selectionIndex > 0) {\r
1079 startIndex = selectionIndex; // -1 for header row, +1 for next event\r
1080 } else {\r
1081 // header row is selected, start at top event\r
1082 startIndex = Math.max(0, fTable.getTopIndex() - 1); // -1 for header row\r
1083 }\r
1084 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
1085 fSearchThread = new SearchFilteredThread(filter, Math.max(0, startIndex - 1), Direction.FORWARD); // -1 for top filter status row\r
1086 } else {\r
1087 fSearchThread = new SearchThread(filter, startIndex, Direction.FORWARD);\r
1088 }\r
1089 fSearchThread.schedule();\r
1090 }\r
1091 }\r
1092 \r
1093 protected void searchPrevious() {\r
1094 synchronized (fSearchSyncObj) {\r
1095 if (fSearchThread != null) {\r
1096 return;\r
1097 }\r
1098 final ITmfFilterTreeNode filter = (ITmfFilterTreeNode) fTable.getData(Key.SEARCH_OBJ);\r
1099 if (filter == null) {\r
1100 return;\r
1101 }\r
1102 int selectionIndex = fTable.getSelectionIndex();\r
1103 int startIndex;\r
1104 if (selectionIndex > 0) {\r
1105 startIndex = selectionIndex - 2; // -1 for header row, -1 for previous event\r
1106 } else {\r
1107 // header row is selected, start at precedent of top event\r
1108 startIndex = fTable.getTopIndex() - 2; // -1 for header row, -1 for previous event\r
1109 }\r
1110 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
1111 fSearchThread = new SearchFilteredThread(filter, startIndex - 1, Direction.BACKWARD); // -1 for top filter status row\r
1112 } else {\r
1113 fSearchThread = new SearchThread(filter, startIndex, Direction.BACKWARD);\r
1114 }\r
1115 fSearchThread.schedule();\r
1116 }\r
1117 }\r
1118 \r
1119 protected void stopSearchThread() {\r
1120 fPendingGotoRank = -1;\r
1121 synchronized (fSearchSyncObj) {\r
1122 if (fSearchThread != null) {\r
1123 fSearchThread.cancel();\r
1124 fSearchThread = null;\r
1125 }\r
1126 }\r
1127 }\r
1128 \r
1129 protected class SearchThread extends Job {\r
1130 protected ITmfFilterTreeNode filter;\r
1131 protected long startRank;\r
1132 protected int direction;\r
1133\r
1134 public SearchThread(ITmfFilterTreeNode filter, int startIndex, int direction) {\r
1135 super(Messages.TmfEventsTable_SearchingJobName);\r
1136 this.filter = filter;\r
1137 this.startRank = startIndex;\r
1138 this.direction = direction;\r
1139 }\r
1140 \r
1141 @Override\r
1142 protected IStatus run(final IProgressMonitor monitor) {\r
1143 final Display display = Display.getDefault();\r
1144 if (startRank < 0) {\r
1145 startRank = fTrace.getNbEvents() - 1;\r
1146 } else if (startRank > fTrace.getNbEvents() - 1) {\r
1147 startRank = 0;\r
1148 }\r
1149 TmfContext context = fTrace.seekEvent(startRank);\r
1150 long rank = context.getRank();\r
1151 TmfEvent event = fTrace.getNextEvent(context);\r
1152 while (!monitor.isCanceled() && event != null) {\r
1153 if (filter.matches(event)) {\r
1154 break;\r
1155 }\r
1156 if (direction == Direction.FORWARD) {\r
1157 rank = context.getRank();\r
1158 if (rank == startRank) {\r
1159 return Status.OK_STATUS;\r
1160 }\r
1161 event = fTrace.getNextEvent(context);\r
1162 if (event == null) {\r
1163 if (startRank == 0) {\r
1164 return Status.OK_STATUS;\r
1165 }\r
1166 context = fTrace.seekLocation(null);\r
1167 context.setRank(0);\r
1168 rank = 0;\r
1169 event = fTrace.getNextEvent(context);\r
1170 }\r
1171 } else {\r
1172 rank--;\r
1173 if (rank < 0) rank = fTrace.getNbEvents() - 1;\r
1174 context = fTrace.seekEvent(rank);\r
1175 event = fTrace.getNextEvent(context);\r
1176 }\r
1177 }\r
1178 final int selection = (int) rank + 1; // +1 for header row\r
1179 \r
1180 display.asyncExec(new Runnable() {\r
1181 @Override\r
1182 public void run() {\r
1183 if (monitor.isCanceled()) return;\r
1184 if (fTable.isDisposed()) return;\r
1185 fTable.setSelection(selection);\r
1186 synchronized (fSearchSyncObj) {\r
1187 fSearchThread = null;\r
1188 }\r
1189 }\r
1190 });\r
1191 return Status.OK_STATUS;\r
1192 }\r
1193 }\r
1194 \r
1195 protected class SearchFilteredThread extends SearchThread {\r
1196\r
1197 public SearchFilteredThread(ITmfFilterTreeNode filter, int startIndex, int direction) {\r
1198 super(filter, startIndex, direction);\r
1199 }\r
1200 \r
1201 @Override\r
1202 protected IStatus run(final IProgressMonitor monitor) {\r
1203 final Display display = Display.getDefault();\r
1204 if (fFilteredEventCache.size() == 0) {\r
1205 return Status.OK_STATUS;\r
1206 }\r
1207 if (startRank < 0) {\r
1208 startRank = fFilteredEventCache.size() - 1;\r
1209 }\r
1210 int index = (int) startRank;\r
1211 if (direction == Direction.FORWARD) {\r
1212 if (index >= fFilteredEventCache.size()) {\r
1213 index = 0;\r
1214 }\r
1215 } else {\r
1216 if (index < 0) {\r
1217 index = fFilteredEventCache.size() - 1;\r
1218 }\r
1219 }\r
1220 TmfEvent event = null;\r
1221 while (!monitor.isCanceled()) {\r
1222 event = fFilteredEventCache.get(index).event;\r
1223 if (filter.matches(event)) {\r
1224 break;\r
1225 }\r
1226 if (direction == Direction.FORWARD) {\r
1227 index++;\r
1228 if (index == startRank) {\r
1229 return Status.OK_STATUS;\r
1230 }\r
1231 if (index >= fFilteredEventCache.size()) {\r
1232 index = 0;\r
1233 }\r
1234 } else {\r
1235 index--;\r
1236 if (index == startRank) {\r
1237 return Status.OK_STATUS;\r
1238 }\r
1239 if (index < 0) {\r
1240 index = fFilteredEventCache.size() - 1;\r
1241 }\r
1242 }\r
1243 }\r
1244 final int selection = (int) index + 2; // +1 for header row, +1 for top filter status row\r
1245 \r
1246 display.asyncExec(new Runnable() {\r
1247 @Override\r
1248 public void run() {\r
1249 if (monitor.isCanceled()) return;\r
1250 if (fTable.isDisposed()) return;\r
1251 fTable.setSelection(selection);\r
1252 synchronized (fSearchSyncObj) {\r
1253 fSearchThread = null;\r
1254 }\r
1255 }\r
1256 });\r
1257 return Status.OK_STATUS;\r
1258 }\r
1259 }\r
1260 \r
1261 protected void createResources() {\r
1262 fGrayColor = fResourceManager.createColor(ColorUtil.blend(fTable.getBackground().getRGB(), fTable.getForeground().getRGB()));\r
1263 fGreenColor = fTable.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN);\r
1264 fBoldFont = fResourceManager.createFont(FontDescriptor.createFrom(fTable.getFont()).setStyle(SWT.BOLD));\r
1265 }\r
1266 \r
9ccc6d01 1267 protected void packColumns() {\r
abfad0aa
FC
1268 if (fPackDone) return;\r
1269 for (TableColumn column : fTable.getColumns()) {\r
1270 int headerWidth = column.getWidth();\r
1271 column.pack();\r
1272 if (column.getWidth() < headerWidth) {\r
1273 column.setWidth(headerWidth);\r
1274 }\r
1275 }\r
1276 fPackDone = true;\r
1277 }\r
1278 \r
1279 /**\r
1280 * @param event\r
1281 * @return\r
1282 * \r
1283 * FIXME: Add support for column selection\r
1284 */\r
78c0de16 1285 protected String[] extractItemFields(TmfEvent event) {\r
abfad0aa
FC
1286 String[] fields = new String[0];\r
1287 if (event != null) {\r
1288 fields = new String[] {\r
1289 new Long(event.getTimestamp().getValue()).toString(), \r
1290 event.getSource().getSourceId().toString(),\r
1291 event.getType().getTypeId().toString(),\r
1292 event.getReference().getReference().toString(),\r
1293 event.getContent().toString()\r
1294 };\r
1295 }\r
1296 return fields;\r
1297 }\r
1298\r
1299 public void setFocus() {\r
1300 fTable.setFocus();\r
1301 }\r
1302\r
529ee6a9
FC
1303 /**\r
1304 * @param trace\r
1305 * @param disposeOnClose true if the trace should be disposed when the table is disposed\r
1306 */\r
1307 public void setTrace(ITmfTrace trace, boolean disposeOnClose) {\r
1308 if (fTrace != null && fDisposeOnClose) {\r
1309 fTrace.dispose();\r
1310 }\r
abfad0aa 1311 fTrace = trace;\r
e2561baf
FC
1312 fPackDone = false;\r
1313 fHeaderState = HeaderState.SEARCH;\r
1314 fSelectedRank = 0;\r
529ee6a9 1315 fDisposeOnClose = disposeOnClose;\r
abfad0aa
FC
1316 \r
1317 // Perform the updates on the UI thread\r
1318 fTable.getDisplay().syncExec(new Runnable() {\r
d4011df2
FC
1319 @Override\r
1320 public void run() {\r
abfad0aa 1321 fTable.removeAll();\r
e2561baf
FC
1322 fTable.setData(Key.FILTER_OBJ, null);\r
1323 fTable.setData(Key.FILTER_TXT, null);\r
1324 fTable.setData(Key.SEARCH_OBJ, null);\r
1325 fTable.setData(Key.SEARCH_TXT, null);\r
9ccc6d01 1326 fCacheStartIndex = fCacheEndIndex = 0; // Clear the cache\r
e2561baf
FC
1327 if (fTrace != null) {\r
1328 if (!fTable.isDisposed() && fTrace != null) {\r
1329 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1330 }\r
1331 fRawViewer.setTrace(fTrace);\r
abfad0aa
FC
1332 }\r
1333 }\r
1334 });\r
abfad0aa
FC
1335 }\r
1336\r
e2561baf
FC
1337 // ------------------------------------------------------------------------\r
1338 // Event cache population\r
1339 // ------------------------------------------------------------------------\r
1340 \r
1341 // The event fetching job\r
1342 private Job job;\r
1343 private synchronized void populateCache(final int index) {\r
1344\r
1345 /* Check if the current job will fetch the requested event:\r
1346 * 1. The job must exist\r
1347 * 2. It must be running (i.e. not completed)\r
1348 * 3. The requested index must be within the cache range\r
1349 * \r
1350 * If the job meets these conditions, we simply exit.\r
1351 * Otherwise, we create a new job but we might have to cancel\r
1352 * an existing job for an obsolete range.\r
1353 */\r
1354 if (job != null) {\r
1355 if (job.getState() != Job.NONE) {\r
1356 if (index >= fCacheStartIndex && index < (fCacheStartIndex + fCacheSize)) {\r
1357 return;\r
1358 }\r
1359 // The new index is out of the requested range\r
1360 // Kill the job and start a new one\r
1361 job.cancel();\r
1362 }\r
1363 }\r
1364 \r
1365 fCacheStartIndex = index;\r
1366 fCacheEndIndex = index;\r
1367\r
1368 job = new Job("Fetching Events") { //$NON-NLS-1$\r
1369 @Override\r
1370 @SuppressWarnings("unchecked")\r
1371 protected IStatus run(final IProgressMonitor monitor) {\r
1372\r
1373 TmfDataRequest<TmfEvent> request = new TmfDataRequest<TmfEvent>(TmfEvent.class, index, fCacheSize) {\r
1374 private int count = 0;\r
1375 @Override\r
1376 public void handleData(TmfEvent event) {\r
1377 // If the job is canceled, cancel the request so waitForCompletion() will unlock\r
1378 if (monitor.isCanceled()) {\r
1379 cancel();\r
1380 return;\r
1381 }\r
1382 super.handleData(event);\r
1383 if (event != null) {\r
1384 fCache[count++] = event.clone();\r
1385 fCacheEndIndex++; // TODO: Need to protect this??\r
1386 }\r
1387 }\r
1388 };\r
1389\r
1390 ((ITmfDataProvider<TmfEvent>) fTrace).sendRequest(request);\r
1391 try {\r
1392 request.waitForCompletion();\r
1393 } catch (InterruptedException e) {\r
1394 e.printStackTrace();\r
1395 }\r
1396\r
1397 // Event cache is now updated. Perform update on the UI thread\r
1398 if (!fTable.isDisposed() && !monitor.isCanceled()) {\r
1399 fTable.getDisplay().asyncExec(new Runnable() {\r
1400 @Override\r
1401 public void run() {\r
1402 if (!fTable.isDisposed()) {\r
1403 fTable.refresh();\r
1404 packColumns();\r
1405 }\r
1406 fTrace.seekEvent(fSelectedRank);\r
1407 }\r
1408 });\r
1409 }\r
1410 \r
1411 // Flag the UI thread that the cache is ready\r
1412 if (monitor.isCanceled()) {\r
1413 return Status.CANCEL_STATUS;\r
1414 } else {\r
1415 return Status.OK_STATUS;\r
1416 }\r
1417 }\r
1418 };\r
1419 //job.setSystem(true);\r
1420 job.setPriority(Job.SHORT);\r
1421 job.schedule();\r
1422 }\r
1423 \r
1424 // ------------------------------------------------------------------------\r
1425 // Bookmark handling\r
1426 // ------------------------------------------------------------------------\r
1427 \r
1428 public void addBookmark(IResource resource) {\r
1429 fBookmarksResource = resource;\r
1430 TableItem[] selection = fTable.getSelection();\r
1431 if (selection.length > 0) {\r
1432 TableItem tableItem = selection[0];\r
1433 if (tableItem.getData(Key.RANK) != null) {\r
1434 StringBuffer defaultMessage = new StringBuffer();\r
1435 for (int i = 0; i < fTable.getColumns().length; i++) {\r
1436 if (i > 0) {\r
1437 defaultMessage.append(", "); //$NON-NLS-1$\r
1438 }\r
1439 defaultMessage.append(tableItem.getText(i));\r
1440 }\r
1441 InputDialog dialog = new InputDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),\r
1442 Messages.TmfEventsTable_AddBookmarkDialogTitle, Messages.TmfEventsTable_AddBookmarkDialogText, defaultMessage.toString(), null);\r
1443 if (dialog.open() == Dialog.OK) {\r
1444 String message = dialog.getValue();\r
1445 try {\r
1446 IMarker bookmark = resource.createMarker(IMarker.BOOKMARK);\r
1447 if (bookmark.exists()) {\r
1448 bookmark.setAttribute(IMarker.MESSAGE, message.toString());\r
1449 long rank = (Long) tableItem.getData(Key.RANK);\r
1450 int location = (int) rank;\r
1451 bookmark.setAttribute(IMarker.LOCATION, (Integer) location);\r
1452 fBookmarksMap.put(rank, bookmark.getId());\r
1453 fTable.refresh();\r
1454 }\r
1455 } catch (CoreException e) {\r
1456 e.printStackTrace();\r
1457 }\r
1458 }\r
1459 }\r
1460 }\r
1461 \r
1462 }\r
1463\r
1464 public void removeBookmark(IMarker bookmark) {\r
1465 for (Entry<Long, Long> entry : fBookmarksMap.entrySet()) {\r
1466 if (entry.getValue().equals(bookmark.getId())) {\r
1467 fBookmarksMap.remove(entry.getKey());\r
1468 fTable.refresh();\r
1469 return;\r
1470 }\r
1471 }\r
1472 }\r
1473\r
1474 private void toggleBookmark(long rank) {\r
1475 if (fBookmarksResource == null) {\r
1476 return;\r
1477 }\r
1478 if (fBookmarksMap.containsKey(rank)) {\r
1479 Long markerId = fBookmarksMap.remove(rank);\r
1480 fTable.refresh();\r
1481 try {\r
1482 IMarker bookmark = fBookmarksResource.findMarker(markerId);\r
1483 if (bookmark != null) {\r
1484 bookmark.delete();\r
1485 }\r
1486 } catch (CoreException e) {\r
1487 e.printStackTrace();\r
1488 }\r
1489 } else {\r
1490 addBookmark(fBookmarksResource);\r
1491 }\r
1492 }\r
1493 \r
1494 public void refreshBookmarks(IResource resource) {\r
1495 fBookmarksResource = resource;\r
1496 try {\r
1497 fBookmarksMap.clear();\r
1498 for (IMarker bookmark : resource.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO)) {\r
1499 int location = bookmark.getAttribute(IMarker.LOCATION, -1);\r
1500 if (location != -1) {\r
1501 long rank = (long) location;\r
1502 fBookmarksMap.put(rank, bookmark.getId());\r
1503 }\r
1504 }\r
1505 fTable.refresh();\r
1506 } catch (CoreException e) {\r
1507 e.printStackTrace();\r
1508 }\r
1509 }\r
1510 \r
1511 @Override\r
1512 public void gotoMarker(IMarker marker) {\r
1513 int rank = marker.getAttribute(IMarker.LOCATION, -1);\r
1514 if (rank != -1) {\r
1515 int index = (int) rank;\r
1516 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
1517 index = getFilteredEventIndex(rank) + 1; //+1 for top filter status row\r
1518 } else if (rank >= fTable.getItemCount()) {\r
1519 fPendingGotoRank = rank;\r
1520 }\r
1521 fTable.setSelection(index + 1); // +1 for header row\r
1522 }\r
1523 }\r
1524 \r
1525 // ------------------------------------------------------------------------\r
1526 // Listeners\r
1527 // ------------------------------------------------------------------------\r
1528 \r
1529 /* (non-Javadoc)\r
1530 * @see org.eclipse.linuxtools.tmf.ui.views.colors.IColorSettingsListener#colorSettingsChanged(org.eclipse.linuxtools.tmf.ui.views.colors.ColorSetting[])\r
1531 */\r
1532 @Override\r
1533 public void colorSettingsChanged(ColorSetting[] colorSettings) {\r
1534 fTable.refresh();\r
1535 }\r
1536 \r
1537 @Override\r
1538 public void addEventsFilterListener(ITmfEventsFilterListener listener) {\r
1539 if (!fEventsFilterListeners.contains(listener)) {\r
1540 fEventsFilterListeners.add(listener);\r
1541 }\r
1542 }\r
1543\r
1544 @Override\r
1545 public void removeEventsFilterListener(ITmfEventsFilterListener listener) {\r
1546 fEventsFilterListeners.remove(listener);\r
1547 }\r
1548\r
abfad0aa
FC
1549 // ------------------------------------------------------------------------\r
1550 // Signal handlers\r
1551 // ------------------------------------------------------------------------\r
1552 \r
e2561baf 1553 @TmfSignalHandler\r
abfad0aa 1554 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {\r
db1ea19b 1555 if ((signal.getExperiment() != fTrace) || fTable.isDisposed()) return;\r
abfad0aa 1556 // Perform the refresh on the UI thread\r
e2561baf 1557 Display.getDefault().asyncExec(new Runnable() {\r
d4011df2
FC
1558 @Override\r
1559 public void run() {\r
abfad0aa 1560 if (!fTable.isDisposed() && fTrace != null) {\r
e2561baf
FC
1561// System.out.println("TmfEventsTable.experimentUpdated() - nbEvents = " + fTrace.getNbEvents());\r
1562 if (fTable.getData(Key.FILTER_OBJ) == null) {\r
1563 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1564 }\r
1565 if (fPendingGotoRank != -1 && fPendingGotoRank + 1 < fTable.getItemCount()) { // +1 for header row\r
1566 fTable.setSelection((int) fPendingGotoRank + 1); // +1 for header row\r
1567 fPendingGotoRank = -1;\r
1568 }\r
1569 }\r
1570 if (!fRawViewer.isDisposed() && fTrace != null) {\r
1571 fRawViewer.refreshEventCount();\r
abfad0aa
FC
1572 }\r
1573 }\r
1574 });\r
1575 }\r
1576 \r
1577 @TmfSignalHandler\r
1578 public void traceUpdated(TmfTraceUpdatedSignal signal) {\r
db1ea19b 1579 if ((signal.getTrace() != fTrace ) || fTable.isDisposed()) return;\r
abfad0aa 1580 // Perform the refresh on the UI thread\r
e2561baf 1581 Display.getDefault().asyncExec(new Runnable() {\r
d4011df2
FC
1582 @Override\r
1583 public void run() {\r
abfad0aa 1584 if (!fTable.isDisposed() && fTrace != null) {\r
e2561baf
FC
1585 if (fTable.getData(Key.FILTER_OBJ) == null) {\r
1586 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1587 if (fPendingGotoRank != -1 && fPendingGotoRank + 1 < fTable.getItemCount()) { // +1 for header row\r
1588 fTable.setSelection((int) fPendingGotoRank + 1); // +1 for header row\r
1589 fPendingGotoRank = -1;\r
1590 }\r
1591 }\r
1592 }\r
1593 if (!fRawViewer.isDisposed() && fTrace != null) {\r
1594 fRawViewer.refreshEventCount();\r
abfad0aa
FC
1595 }\r
1596 }\r
1597 });\r
1598 }\r
1599\r
1600 private boolean fRefreshPending = false;\r
1601 @TmfSignalHandler\r
1602 public synchronized void rangeSynched(TmfRangeSynchSignal signal) {\r
db1ea19b 1603 if (!fRefreshPending && !fTable.isDisposed()) {\r
abfad0aa
FC
1604 // Perform the refresh on the UI thread\r
1605 fRefreshPending = true;\r
e2561baf 1606 Display.getDefault().asyncExec(new Runnable() {\r
d4011df2
FC
1607 @Override\r
1608 public void run() {\r
abfad0aa
FC
1609 fRefreshPending = false;\r
1610 if (!fTable.isDisposed() && fTrace != null) {\r
e2561baf 1611 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
abfad0aa
FC
1612 }\r
1613 }\r
1614 });\r
1615 }\r
1616 }\r
1617 \r
e2561baf 1618 @SuppressWarnings("unchecked")\r
abfad0aa 1619 @TmfSignalHandler\r
529ee6a9 1620 public void currentTimeUpdated(final TmfTimeSynchSignal signal) {\r
c1c69938
FC
1621 if ((signal.getSource() != fTable) && (fTrace != null) && (!fTable.isDisposed())) {\r
1622\r
1623 // Create a request for one event that will be queued after other ongoing requests. When this request is completed \r
1624 // do the work to select the actual event with the timestamp specified in the signal. This procedure prevents \r
1625 // the method fTrace.getRank() from interfering and delaying ongoing requests.\r
1626 final TmfDataRequest<TmfEvent> subRequest = new TmfDataRequest<TmfEvent>(TmfEvent.class, 0, 1, ExecutionType.FOREGROUND) {\r
1627\r
1628 @Override\r
1629 public void handleData(TmfEvent event) {\r
1630 super.handleData(event);\r
1631 }\r
1632\r
1633 @Override\r
1634 public void handleCompleted() {\r
89dcf304
BH
1635\r
1636 // Verify if event is within the trace range\r
1637 final TmfTimestamp timestamp[] = new TmfTimestamp[1];\r
1638 timestamp[0] = signal.getCurrentTime();\r
1639 if (timestamp[0].compareTo(fTrace.getStartTime(), true) == -1) {\r
1640 timestamp[0] = fTrace.getStartTime();\r
1641 }\r
1642 if (timestamp[0].compareTo(fTrace.getEndTime(), true) == 1) {\r
1643 timestamp[0] = fTrace.getEndTime();\r
1644 }\r
1645\r
c1c69938 1646 // Get the rank for the event selection in the table\r
e2561baf
FC
1647 final long rank = fTrace.getRank(timestamp[0]);\r
1648 fSelectedRank = rank;\r
c1c69938
FC
1649\r
1650 fTable.getDisplay().asyncExec(new Runnable() {\r
1651 @Override\r
1652 public void run() {\r
1653 // Return if table is disposed\r
1654 if (fTable.isDisposed()) return;\r
1655\r
e2561baf
FC
1656 int index = (int) rank;\r
1657 if (fTable.isDisposed()) return;\r
1658 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
1659 index = getFilteredEventIndex(rank) + 1; //+1 for top filter status row\r
1660 }\r
1661 fTable.setSelection(index + 1); // +1 for header row\r
1662 fRawViewer.selectAndReveal(rank);\r
c1c69938
FC
1663 }\r
1664 });\r
1665 super.handleCompleted();\r
1666 }\r
1667 };\r
1668\r
e2561baf 1669 ((ITmfDataProvider<TmfEvent>) fTrace).sendRequest(subRequest);\r
c1c69938
FC
1670 }\r
1671 }\r
1672\r
e2561baf 1673}
This page took 0.111447 seconds and 5 git commands to generate.