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