Bug #348267 - Documentation navigation arrows missing
[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
334 fTable.setItemCount(+1); // +1 for header row\r
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
656 if (fFilterCheckCount == fTrace.getNbEvents()) {\r
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
852 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
853 fireFilterApplied(null);\r
854 }\r
855 }\r
856 \r
857 tableEditor.getEditor().dispose();\r
858 }\r
859 });\r
860 \r
861 fTable.addKeyListener(new KeyAdapter() {\r
862 @Override\r
863 public void keyPressed(KeyEvent e) {\r
864 e.doit = false;\r
865 if (e.character == SWT.ESC) {\r
866 stopFilterThread();\r
867 stopSearchThread();\r
868 fTable.refresh();\r
869 } else if (e.character == SWT.DEL) {\r
870 stopFilterThread();\r
871 stopSearchThread();\r
872 if (fHeaderState == HeaderState.SEARCH) {\r
873 for (TableColumn column : fTable.getColumns()) {\r
874 column.setData(Key.SEARCH_OBJ, null);\r
875 column.setData(Key.SEARCH_TXT, null);\r
876 }\r
877 fTable.setData(Key.SEARCH_OBJ, null);\r
878 fTable.refresh();\r
879 fireSearchApplied(null);\r
880 } else if (fHeaderState == HeaderState.FILTER) {\r
881 clearFilters();\r
882 }\r
883 } else if (e.character == SWT.CR) {\r
884 if ((e.stateMask & SWT.SHIFT) == 0) {\r
885 searchNext();\r
886 } else {\r
887 searchPrevious();\r
888 }\r
889 }\r
890 }\r
891 });\r
892 }\r
893\r
894 protected void fireFilterApplied(ITmfFilter filter) {\r
895 for (ITmfEventsFilterListener listener : fEventsFilterListeners) {\r
896 listener.filterApplied(filter, fTrace);\r
897 }\r
898 }\r
899 \r
900 protected void fireSearchApplied(ITmfFilter filter) {\r
901 for (ITmfEventsFilterListener listener : fEventsFilterListeners) {\r
902 listener.searchApplied(filter, fTrace);\r
903 }\r
904 }\r
905 \r
906 protected void startFilterThread() {\r
907 synchronized (fFilterSyncObj) {\r
908 if (fFilterThread != null) {\r
909 fFilterThread.cancel();\r
910 }\r
911 final ITmfFilterTreeNode filter = (ITmfFilterTreeNode) fTable.getData(Key.FILTER_OBJ);\r
912 fFilterThread = new FilterThread(filter);\r
913 fFilterThread.start();\r
914 }\r
915 }\r
916\r
917 protected void stopFilterThread() {\r
918 synchronized (fFilterSyncObj) {\r
919 if (fFilterThread != null) {\r
920 fFilterThread.cancel();\r
921 }\r
922 }\r
923 }\r
924\r
925 protected void clearFilters() {\r
926 if (fTable.getData(Key.FILTER_OBJ) == null) {\r
927 return;\r
928 }\r
2d55fd20 929 fCache.clearFilter();\r
e2561baf
FC
930 fTable.clearAll();\r
931 for (TableColumn column : fTable.getColumns()) {\r
932 column.setData(Key.FILTER_OBJ, null);\r
933 column.setData(Key.FILTER_TXT, null);\r
934 }\r
935 fTable.setData(Key.FILTER_OBJ, null);\r
936 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
2d55fd20
FC
937 fFilterMatchCount = 0;\r
938 fFilterCheckCount = 0;\r
939 if (fSelectedRank >= 0) {\r
940 fTable.setSelection((int) fSelectedRank + 1); // +1 for header row\r
e2561baf
FC
941 } else {\r
942 fTable.setSelection(0);\r
943 }\r
944 fireFilterApplied(null);\r
945 }\r
946 \r
947 protected class FilterThread extends Thread {\r
f4ed1093 948 private final ITmfFilterTreeNode filter;\r
2d55fd20
FC
949 private TmfEventRequest<TmfEvent> request;\r
950 private boolean refreshBusy = false;\r
951 private boolean refreshPending = false;\r
952 private Object syncObj = new Object();\r
e2561baf 953\r
f4ed1093
FC
954 public FilterThread(ITmfFilterTreeNode filter) {\r
955 super("Filter Thread"); //$NON-NLS-1$\r
956 this.filter = filter;\r
957 }\r
958\r
959 @SuppressWarnings("unchecked")\r
960 @Override\r
961 public void run() {\r
2d55fd20 962 request = new TmfEventRequest<TmfEvent>(TmfEvent.class, TmfTimeRange.Eternity, TmfDataRequest.ALL_DATA, fTrace.getCacheSize(), ExecutionType.BACKGROUND) {\r
f4ed1093
FC
963 @Override\r
964 public void handleData(TmfEvent event) {\r
965 super.handleData(event);\r
2d55fd20 966 if (request.isCancelled()) return;\r
f4ed1093 967 if (filter.matches(event)) {\r
2d55fd20
FC
968 long rank = fFilterCheckCount;\r
969 int index = (int) fFilterMatchCount;\r
970 fFilterMatchCount++;\r
971 fCache.storeEvent(event.clone(), rank, index);\r
972 refreshTable();\r
973 } else if (fFilterCheckCount % 100 == 0) {\r
974 refreshTable();\r
f4ed1093 975 }\r
2d55fd20 976 fFilterCheckCount++;\r
f4ed1093
FC
977 }\r
978 };\r
979 ((ITmfDataProvider<TmfEvent>) fTrace).sendRequest(request);\r
980 try {\r
981 request.waitForCompletion();\r
982 } catch (InterruptedException e) {\r
983 }\r
2d55fd20
FC
984 refreshTable();\r
985 }\r
986 \r
987 public void refreshTable() {\r
988 synchronized (syncObj) {\r
989 if (refreshBusy) {\r
990 refreshPending = true;\r
991 return;\r
992 } else {\r
993 refreshBusy = true;\r
994 }\r
995 }\r
996 Display.getDefault().asyncExec(new Runnable() {\r
997 @Override\r
998 public void run() {\r
999 if (request.isCancelled()) return;\r
1000 if (fTable.isDisposed()) return;\r
1001 fTable.setItemCount((int) fFilterMatchCount + 3); // +1 for header row, +2 for top and bottom filter status rows\r
1002 fTable.refresh();\r
1003 synchronized (syncObj) {\r
1004 refreshBusy = false;\r
1005 if (refreshPending) {\r
1006 refreshPending = false;\r
1007 refreshTable();\r
1008 }\r
1009 }\r
1010 }\r
1011 });\r
f4ed1093
FC
1012 }\r
1013\r
1014 public void cancel() {\r
1015 request.cancel();\r
1016 }\r
e2561baf 1017 }\r
f4ed1093 1018\r
e2561baf
FC
1019 protected void searchNext() {\r
1020 synchronized (fSearchSyncObj) {\r
1021 if (fSearchThread != null) {\r
1022 return;\r
1023 }\r
2d55fd20
FC
1024 final ITmfFilterTreeNode searchFilter = (ITmfFilterTreeNode) fTable.getData(Key.SEARCH_OBJ);\r
1025 if (searchFilter == null) {\r
e2561baf
FC
1026 return;\r
1027 }\r
1028 int selectionIndex = fTable.getSelectionIndex();\r
1029 int startIndex;\r
1030 if (selectionIndex > 0) {\r
1031 startIndex = selectionIndex; // -1 for header row, +1 for next event\r
1032 } else {\r
1033 // header row is selected, start at top event\r
1034 startIndex = Math.max(0, fTable.getTopIndex() - 1); // -1 for header row\r
1035 }\r
2d55fd20
FC
1036 final ITmfFilterTreeNode eventFilter = (ITmfFilterTreeNode) fTable.getData(Key.FILTER_OBJ);\r
1037 if (eventFilter != null) {\r
1038 startIndex = Math.max(0, startIndex - 1); // -1 for top filter status row\r
e2561baf 1039 }\r
2d55fd20 1040 fSearchThread = new SearchThread(searchFilter, eventFilter, startIndex, fSelectedRank, Direction.FORWARD);\r
e2561baf
FC
1041 fSearchThread.schedule();\r
1042 }\r
1043 }\r
1044 \r
1045 protected void searchPrevious() {\r
1046 synchronized (fSearchSyncObj) {\r
1047 if (fSearchThread != null) {\r
1048 return;\r
1049 }\r
2d55fd20
FC
1050 final ITmfFilterTreeNode searchFilter = (ITmfFilterTreeNode) fTable.getData(Key.SEARCH_OBJ);\r
1051 if (searchFilter == null) {\r
e2561baf
FC
1052 return;\r
1053 }\r
1054 int selectionIndex = fTable.getSelectionIndex();\r
1055 int startIndex;\r
1056 if (selectionIndex > 0) {\r
1057 startIndex = selectionIndex - 2; // -1 for header row, -1 for previous event\r
1058 } else {\r
1059 // header row is selected, start at precedent of top event\r
1060 startIndex = fTable.getTopIndex() - 2; // -1 for header row, -1 for previous event\r
1061 }\r
2d55fd20
FC
1062 final ITmfFilterTreeNode eventFilter = (ITmfFilterTreeNode) fTable.getData(Key.FILTER_OBJ);\r
1063 if (eventFilter != null) {\r
1064 startIndex = startIndex - 1; // -1 for top filter status row\r
e2561baf 1065 }\r
2d55fd20 1066 fSearchThread = new SearchThread(searchFilter, eventFilter, startIndex, fSelectedRank, Direction.BACKWARD);\r
e2561baf
FC
1067 fSearchThread.schedule();\r
1068 }\r
1069 }\r
1070 \r
1071 protected void stopSearchThread() {\r
1072 fPendingGotoRank = -1;\r
1073 synchronized (fSearchSyncObj) {\r
1074 if (fSearchThread != null) {\r
1075 fSearchThread.cancel();\r
1076 fSearchThread = null;\r
1077 }\r
1078 }\r
1079 }\r
1080 \r
1081 protected class SearchThread extends Job {\r
2d55fd20
FC
1082 protected ITmfFilterTreeNode searchFilter;\r
1083 protected ITmfFilterTreeNode eventFilter;\r
1084 protected int startIndex;\r
f4ed1093 1085 protected int direction;\r
2d55fd20
FC
1086 protected long rank;\r
1087 protected long foundRank = -1;\r
f4ed1093
FC
1088 protected TmfDataRequest<TmfEvent> request;\r
1089\r
2d55fd20 1090 public SearchThread(ITmfFilterTreeNode searchFilter, ITmfFilterTreeNode eventFilter, int startIndex, long currentRank, int direction) {\r
f4ed1093 1091 super(Messages.TmfEventsTable_SearchingJobName);\r
2d55fd20
FC
1092 this.searchFilter = searchFilter;\r
1093 this.eventFilter = eventFilter;\r
1094 this.startIndex = startIndex;\r
1095 this.rank = currentRank;\r
f4ed1093
FC
1096 this.direction = direction;\r
1097 }\r
1098\r
1099 @SuppressWarnings("unchecked")\r
1100 @Override\r
1101 protected IStatus run(final IProgressMonitor monitor) {\r
1102 final Display display = Display.getDefault();\r
2d55fd20
FC
1103 if (startIndex < 0) {\r
1104 rank = (int) fTrace.getNbEvents() - 1;\r
1105 } else if (startIndex >= fTable.getItemCount() - (eventFilter == null ? 1 : 3)) { // -1 for header row, -2 for top and bottom filter status rows\r
1106 rank = 0;\r
1107 } else {\r
1108 int idx = startIndex;\r
1109 while (foundRank == -1) {\r
1110 CachedEvent event = fCache.peekEvent(idx);\r
1111 if (event == null) {\r
1112 break;\r
1113 }\r
1114 rank = event.rank;\r
1115 if (searchFilter.matches(event.event) && (eventFilter == null || eventFilter.matches(event.event))) {\r
1116 foundRank = event.rank;\r
1117 break;\r
1118 }\r
1119 if (direction == Direction.FORWARD) {\r
1120 idx++;\r
1121 } else {\r
1122 idx--;\r
1123 }\r
1124 }\r
1125 if (foundRank == -1) {\r
1126 if (direction == Direction.FORWARD) {\r
1127 rank++;\r
1128 if (rank > fTrace.getNbEvents() - 1) {\r
1129 rank = 0;\r
1130 }\r
1131 } else {\r
1132 rank--;\r
1133 if (rank < 0) {\r
1134 rank = (int) fTrace.getNbEvents() - 1;\r
1135 }\r
1136 }\r
1137 }\r
f4ed1093 1138 }\r
2d55fd20
FC
1139 int startRank = (int) rank;\r
1140 boolean wrapped = false;\r
1141 while (!monitor.isCanceled() && foundRank == -1) {\r
1142 int nbRequested = (direction == Direction.FORWARD ? Integer.MAX_VALUE : Math.min((int) rank + 1, fTrace.getCacheSize()));\r
1143 if (direction == Direction.BACKWARD) {\r
1144 rank = Math.max(0, rank - fTrace.getCacheSize() + 1);\r
1145 }\r
1146 request = new TmfDataRequest<TmfEvent>(TmfEvent.class, (int) rank, nbRequested) {\r
1147 long currentRank = rank;\r
f4ed1093
FC
1148 @Override\r
1149 public void handleData(TmfEvent event) {\r
1150 super.handleData(event);\r
2d55fd20
FC
1151 if (searchFilter.matches(event) && (eventFilter == null || eventFilter.matches(event))) {\r
1152 foundRank = currentRank;\r
1153 if (direction == Direction.FORWARD) {\r
1154 done();\r
1155 return;\r
1156 }\r
f4ed1093 1157 }\r
2d55fd20 1158 currentRank++;\r
f4ed1093
FC
1159 }\r
1160 };\r
1161 ((ITmfDataProvider<TmfEvent>) fTrace).sendRequest(request);\r
1162 try {\r
1163 request.waitForCompletion();\r
1164 if (request.isCancelled()) {\r
1165 return Status.OK_STATUS;\r
1166 }\r
1167 } catch (InterruptedException e) {\r
2d55fd20
FC
1168 synchronized (fSearchSyncObj) {\r
1169 fSearchThread = null;\r
1170 }\r
f4ed1093
FC
1171 return Status.OK_STATUS;\r
1172 }\r
2d55fd20 1173 if (foundRank == -1) {\r
f4ed1093 1174 if (direction == Direction.FORWARD) {\r
2d55fd20
FC
1175 if (rank == 0) {\r
1176 synchronized (fSearchSyncObj) {\r
1177 fSearchThread = null;\r
1178 }\r
f4ed1093
FC
1179 return Status.OK_STATUS;\r
1180 } else {\r
2d55fd20
FC
1181 nbRequested = (int) rank;\r
1182 rank = 0;\r
1183 wrapped = true;\r
f4ed1093
FC
1184 }\r
1185 } else {\r
2d55fd20
FC
1186 rank--;\r
1187 if (rank < 0) {\r
1188 rank = (int) fTrace.getNbEvents() - 1;\r
1189 wrapped = true;\r
f4ed1093 1190 }\r
2d55fd20
FC
1191 if (rank <= startRank && wrapped) {\r
1192 synchronized (fSearchSyncObj) {\r
1193 fSearchThread = null;\r
1194 }\r
f4ed1093
FC
1195 return Status.OK_STATUS;\r
1196 }\r
1197 }\r
1198 }\r
1199 }\r
2d55fd20
FC
1200 int index = (int) foundRank;\r
1201 if (eventFilter != null) {\r
1202 index = fCache.getFilteredEventIndex(foundRank);\r
1203 }\r
1204 final int selection = (int) index + 1 + (eventFilter != null ? +1 : 0); // +1 for header row, +1 for top filter status row\r
f4ed1093
FC
1205\r
1206 display.asyncExec(new Runnable() {\r
1207 @Override\r
1208 public void run() {\r
1209 if (monitor.isCanceled()) return;\r
1210 if (fTable.isDisposed()) return;\r
1211 fTable.setSelection(selection);\r
2d55fd20 1212 fSelectedRank = foundRank;\r
f4ed1093
FC
1213 synchronized (fSearchSyncObj) {\r
1214 fSearchThread = null;\r
1215 }\r
1216 }\r
1217 });\r
1218 return Status.OK_STATUS;\r
1219 }\r
1220\r
1221 @Override\r
1222 protected void canceling() {\r
1223 request.cancel();\r
2d55fd20
FC
1224 synchronized (fSearchSyncObj) {\r
1225 fSearchThread = null;\r
1226 }\r
f4ed1093 1227 }\r
e2561baf 1228 }\r
f4ed1093 1229\r
e2561baf
FC
1230 protected void createResources() {\r
1231 fGrayColor = fResourceManager.createColor(ColorUtil.blend(fTable.getBackground().getRGB(), fTable.getForeground().getRGB()));\r
1232 fGreenColor = fTable.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN);\r
1233 fBoldFont = fResourceManager.createFont(FontDescriptor.createFrom(fTable.getFont()).setStyle(SWT.BOLD));\r
1234 }\r
1235 \r
9ccc6d01 1236 protected void packColumns() {\r
abfad0aa
FC
1237 if (fPackDone) return;\r
1238 for (TableColumn column : fTable.getColumns()) {\r
1239 int headerWidth = column.getWidth();\r
1240 column.pack();\r
1241 if (column.getWidth() < headerWidth) {\r
1242 column.setWidth(headerWidth);\r
1243 }\r
1244 }\r
1245 fPackDone = true;\r
1246 }\r
1247 \r
1248 /**\r
1249 * @param event\r
1250 * @return\r
1251 * \r
1252 * FIXME: Add support for column selection\r
1253 */\r
78c0de16 1254 protected String[] extractItemFields(TmfEvent event) {\r
abfad0aa
FC
1255 String[] fields = new String[0];\r
1256 if (event != null) {\r
1257 fields = new String[] {\r
1258 new Long(event.getTimestamp().getValue()).toString(), \r
1259 event.getSource().getSourceId().toString(),\r
1260 event.getType().getTypeId().toString(),\r
1261 event.getReference().getReference().toString(),\r
1262 event.getContent().toString()\r
1263 };\r
1264 }\r
1265 return fields;\r
1266 }\r
1267\r
1268 public void setFocus() {\r
1269 fTable.setFocus();\r
1270 }\r
1271\r
529ee6a9
FC
1272 /**\r
1273 * @param trace\r
1274 * @param disposeOnClose true if the trace should be disposed when the table is disposed\r
1275 */\r
1276 public void setTrace(ITmfTrace trace, boolean disposeOnClose) {\r
1277 if (fTrace != null && fDisposeOnClose) {\r
1278 fTrace.dispose();\r
1279 }\r
abfad0aa 1280 fTrace = trace;\r
e2561baf
FC
1281 fPackDone = false;\r
1282 fHeaderState = HeaderState.SEARCH;\r
1283 fSelectedRank = 0;\r
529ee6a9 1284 fDisposeOnClose = disposeOnClose;\r
abfad0aa
FC
1285 \r
1286 // Perform the updates on the UI thread\r
1287 fTable.getDisplay().syncExec(new Runnable() {\r
d4011df2
FC
1288 @Override\r
1289 public void run() {\r
abfad0aa 1290 fTable.removeAll();\r
0752514e 1291 // Clear filters if present\r
e2561baf
FC
1292 fTable.setData(Key.FILTER_OBJ, null);\r
1293 fTable.setData(Key.FILTER_TXT, null);\r
1294 fTable.setData(Key.SEARCH_OBJ, null);\r
1295 fTable.setData(Key.SEARCH_TXT, null);\r
0752514e
FC
1296 for (TableColumn column : fTable.getColumns()) {\r
1297 column.setData(Key.FILTER_OBJ, null);\r
1298 column.setData(Key.FILTER_TXT, null);\r
1299 column.setData(Key.SEARCH_OBJ, null);\r
1300 column.setData(Key.SEARCH_TXT, null);\r
1301 }\r
2d55fd20 1302 fCache.setTrace(fTrace); // Clear the cache\r
e2561baf
FC
1303 if (fTrace != null) {\r
1304 if (!fTable.isDisposed() && fTrace != null) {\r
1305 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1306 }\r
1307 fRawViewer.setTrace(fTrace);\r
abfad0aa
FC
1308 }\r
1309 }\r
1310 });\r
abfad0aa
FC
1311 }\r
1312\r
e2561baf 1313 // ------------------------------------------------------------------------\r
2d55fd20 1314 // Event cache\r
e2561baf 1315 // ------------------------------------------------------------------------\r
e2561baf 1316\r
2d55fd20
FC
1317 public void cacheUpdated(final boolean completed) {\r
1318 synchronized (fCacheUpdateSyncObj) {\r
1319 if (fCacheUpdateBusy) {\r
1320 fCacheUpdatePending = true;\r
1321 fCacheUpdateCompleted = completed;\r
1322 return;\r
1323 } else {\r
1324 fCacheUpdateBusy = true;\r
1325 }\r
1326 }\r
1327 // Event cache is now updated. Perform update on the UI thread\r
1328 if (!fTable.isDisposed()) {\r
1329 fTable.getDisplay().asyncExec(new Runnable() {\r
1330 @Override\r
1331 public void run() {\r
1332 if (!fTable.isDisposed()) {\r
1333 fTable.refresh();\r
1334 packColumns();\r
e2561baf 1335 }\r
2d55fd20
FC
1336 if (completed) {\r
1337 populateCompleted();\r
1338 }\r
1339 synchronized (fCacheUpdateSyncObj) {\r
1340 fCacheUpdateBusy = false;\r
1341 if (fCacheUpdatePending) {\r
1342 fCacheUpdatePending = false;\r
1343 cacheUpdated(fCacheUpdateCompleted);\r
1344 }\r
1345 }\r
e2561baf 1346 }\r
2d55fd20
FC
1347 });\r
1348 }\r
e2561baf 1349 }\r
2d55fd20 1350 \r
8e31f2d2
FC
1351 protected void populateCompleted() {\r
1352 // Nothing by default;\r
1353 }\r
1354\r
e2561baf
FC
1355 // ------------------------------------------------------------------------\r
1356 // Bookmark handling\r
1357 // ------------------------------------------------------------------------\r
1358 \r
1359 public void addBookmark(IResource resource) {\r
1360 fBookmarksResource = resource;\r
1361 TableItem[] selection = fTable.getSelection();\r
1362 if (selection.length > 0) {\r
1363 TableItem tableItem = selection[0];\r
1364 if (tableItem.getData(Key.RANK) != null) {\r
1365 StringBuffer defaultMessage = new StringBuffer();\r
1366 for (int i = 0; i < fTable.getColumns().length; i++) {\r
1367 if (i > 0) {\r
1368 defaultMessage.append(", "); //$NON-NLS-1$\r
1369 }\r
1370 defaultMessage.append(tableItem.getText(i));\r
1371 }\r
1372 InputDialog dialog = new InputDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),\r
1373 Messages.TmfEventsTable_AddBookmarkDialogTitle, Messages.TmfEventsTable_AddBookmarkDialogText, defaultMessage.toString(), null);\r
1374 if (dialog.open() == Dialog.OK) {\r
1375 String message = dialog.getValue();\r
1376 try {\r
1377 IMarker bookmark = resource.createMarker(IMarker.BOOKMARK);\r
1378 if (bookmark.exists()) {\r
1379 bookmark.setAttribute(IMarker.MESSAGE, message.toString());\r
1380 long rank = (Long) tableItem.getData(Key.RANK);\r
1381 int location = (int) rank;\r
1382 bookmark.setAttribute(IMarker.LOCATION, (Integer) location);\r
1383 fBookmarksMap.put(rank, bookmark.getId());\r
1384 fTable.refresh();\r
1385 }\r
1386 } catch (CoreException e) {\r
1387 e.printStackTrace();\r
1388 }\r
1389 }\r
1390 }\r
1391 }\r
1392 \r
1393 }\r
1394\r
1395 public void removeBookmark(IMarker bookmark) {\r
1396 for (Entry<Long, Long> entry : fBookmarksMap.entrySet()) {\r
1397 if (entry.getValue().equals(bookmark.getId())) {\r
1398 fBookmarksMap.remove(entry.getKey());\r
1399 fTable.refresh();\r
1400 return;\r
1401 }\r
1402 }\r
1403 }\r
1404\r
1405 private void toggleBookmark(long rank) {\r
1406 if (fBookmarksResource == null) {\r
1407 return;\r
1408 }\r
1409 if (fBookmarksMap.containsKey(rank)) {\r
1410 Long markerId = fBookmarksMap.remove(rank);\r
1411 fTable.refresh();\r
1412 try {\r
1413 IMarker bookmark = fBookmarksResource.findMarker(markerId);\r
1414 if (bookmark != null) {\r
1415 bookmark.delete();\r
1416 }\r
1417 } catch (CoreException e) {\r
1418 e.printStackTrace();\r
1419 }\r
1420 } else {\r
1421 addBookmark(fBookmarksResource);\r
1422 }\r
1423 }\r
1424 \r
1425 public void refreshBookmarks(IResource resource) {\r
1426 fBookmarksResource = resource;\r
1427 try {\r
1428 fBookmarksMap.clear();\r
1429 for (IMarker bookmark : resource.findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_ZERO)) {\r
1430 int location = bookmark.getAttribute(IMarker.LOCATION, -1);\r
1431 if (location != -1) {\r
1432 long rank = (long) location;\r
1433 fBookmarksMap.put(rank, bookmark.getId());\r
1434 }\r
1435 }\r
1436 fTable.refresh();\r
1437 } catch (CoreException e) {\r
1438 e.printStackTrace();\r
1439 }\r
1440 }\r
1441 \r
1442 @Override\r
1443 public void gotoMarker(IMarker marker) {\r
1444 int rank = marker.getAttribute(IMarker.LOCATION, -1);\r
1445 if (rank != -1) {\r
1446 int index = (int) rank;\r
1447 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
2d55fd20 1448 index = fCache.getFilteredEventIndex(rank) + 1; //+1 for top filter status row\r
e2561baf
FC
1449 } else if (rank >= fTable.getItemCount()) {\r
1450 fPendingGotoRank = rank;\r
1451 }\r
1452 fTable.setSelection(index + 1); // +1 for header row\r
1453 }\r
1454 }\r
1455 \r
1456 // ------------------------------------------------------------------------\r
1457 // Listeners\r
1458 // ------------------------------------------------------------------------\r
1459 \r
1460 /* (non-Javadoc)\r
1461 * @see org.eclipse.linuxtools.tmf.ui.views.colors.IColorSettingsListener#colorSettingsChanged(org.eclipse.linuxtools.tmf.ui.views.colors.ColorSetting[])\r
1462 */\r
1463 @Override\r
1464 public void colorSettingsChanged(ColorSetting[] colorSettings) {\r
1465 fTable.refresh();\r
1466 }\r
1467 \r
1468 @Override\r
1469 public void addEventsFilterListener(ITmfEventsFilterListener listener) {\r
1470 if (!fEventsFilterListeners.contains(listener)) {\r
1471 fEventsFilterListeners.add(listener);\r
1472 }\r
1473 }\r
1474\r
1475 @Override\r
1476 public void removeEventsFilterListener(ITmfEventsFilterListener listener) {\r
1477 fEventsFilterListeners.remove(listener);\r
1478 }\r
1479\r
abfad0aa
FC
1480 // ------------------------------------------------------------------------\r
1481 // Signal handlers\r
1482 // ------------------------------------------------------------------------\r
1483 \r
e2561baf 1484 @TmfSignalHandler\r
abfad0aa 1485 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {\r
db1ea19b 1486 if ((signal.getExperiment() != fTrace) || fTable.isDisposed()) return;\r
abfad0aa 1487 // Perform the refresh on the UI thread\r
e2561baf 1488 Display.getDefault().asyncExec(new Runnable() {\r
d4011df2
FC
1489 @Override\r
1490 public void run() {\r
abfad0aa 1491 if (!fTable.isDisposed() && fTrace != null) {\r
e2561baf
FC
1492 if (fTable.getData(Key.FILTER_OBJ) == null) {\r
1493 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1494 }\r
1495 if (fPendingGotoRank != -1 && fPendingGotoRank + 1 < fTable.getItemCount()) { // +1 for header row\r
1496 fTable.setSelection((int) fPendingGotoRank + 1); // +1 for header row\r
1497 fPendingGotoRank = -1;\r
1498 }\r
1499 }\r
1500 if (!fRawViewer.isDisposed() && fTrace != null) {\r
1501 fRawViewer.refreshEventCount();\r
abfad0aa
FC
1502 }\r
1503 }\r
1504 });\r
1505 }\r
1506 \r
1507 @TmfSignalHandler\r
1508 public void traceUpdated(TmfTraceUpdatedSignal signal) {\r
db1ea19b 1509 if ((signal.getTrace() != fTrace ) || fTable.isDisposed()) return;\r
abfad0aa 1510 // Perform the refresh on the UI thread\r
e2561baf 1511 Display.getDefault().asyncExec(new Runnable() {\r
d4011df2
FC
1512 @Override\r
1513 public void run() {\r
abfad0aa 1514 if (!fTable.isDisposed() && fTrace != null) {\r
e2561baf
FC
1515 if (fTable.getData(Key.FILTER_OBJ) == null) {\r
1516 fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1517 if (fPendingGotoRank != -1 && fPendingGotoRank + 1 < fTable.getItemCount()) { // +1 for header row\r
1518 fTable.setSelection((int) fPendingGotoRank + 1); // +1 for header row\r
1519 fPendingGotoRank = -1;\r
1520 }\r
1521 }\r
1522 }\r
1523 if (!fRawViewer.isDisposed() && fTrace != null) {\r
1524 fRawViewer.refreshEventCount();\r
abfad0aa
FC
1525 }\r
1526 }\r
1527 });\r
1528 }\r
1529\r
0752514e
FC
1530// private boolean fRefreshPending = false;\r
1531// @TmfSignalHandler\r
1532// public synchronized void rangeSynched(TmfRangeSynchSignal signal) {\r
1533// if (!fRefreshPending && !fTable.isDisposed()) {\r
1534// // Perform the refresh on the UI thread\r
1535// fRefreshPending = true;\r
1536// Display.getDefault().asyncExec(new Runnable() {\r
1537// @Override\r
1538// public void run() {\r
1539// fRefreshPending = false;\r
1540// if (!fTable.isDisposed() && fTrace != null) {\r
1541// fTable.setItemCount((int) fTrace.getNbEvents() + 1); // +1 for header row\r
1542// }\r
1543// }\r
1544// });\r
1545// }\r
1546// }\r
abfad0aa 1547 \r
e2561baf 1548 @SuppressWarnings("unchecked")\r
abfad0aa 1549 @TmfSignalHandler\r
529ee6a9 1550 public void currentTimeUpdated(final TmfTimeSynchSignal signal) {\r
c1c69938
FC
1551 if ((signal.getSource() != fTable) && (fTrace != null) && (!fTable.isDisposed())) {\r
1552\r
1553 // Create a request for one event that will be queued after other ongoing requests. When this request is completed \r
1554 // do the work to select the actual event with the timestamp specified in the signal. This procedure prevents \r
1555 // the method fTrace.getRank() from interfering and delaying ongoing requests.\r
1556 final TmfDataRequest<TmfEvent> subRequest = new TmfDataRequest<TmfEvent>(TmfEvent.class, 0, 1, ExecutionType.FOREGROUND) {\r
1557\r
1558 @Override\r
1559 public void handleData(TmfEvent event) {\r
1560 super.handleData(event);\r
1561 }\r
1562\r
1563 @Override\r
1564 public void handleCompleted() {\r
89dcf304
BH
1565\r
1566 // Verify if event is within the trace range\r
1567 final TmfTimestamp timestamp[] = new TmfTimestamp[1];\r
1568 timestamp[0] = signal.getCurrentTime();\r
1569 if (timestamp[0].compareTo(fTrace.getStartTime(), true) == -1) {\r
1570 timestamp[0] = fTrace.getStartTime();\r
1571 }\r
1572 if (timestamp[0].compareTo(fTrace.getEndTime(), true) == 1) {\r
1573 timestamp[0] = fTrace.getEndTime();\r
1574 }\r
1575\r
c1c69938 1576 // Get the rank for the event selection in the table\r
e2561baf
FC
1577 final long rank = fTrace.getRank(timestamp[0]);\r
1578 fSelectedRank = rank;\r
c1c69938
FC
1579\r
1580 fTable.getDisplay().asyncExec(new Runnable() {\r
1581 @Override\r
1582 public void run() {\r
1583 // Return if table is disposed\r
1584 if (fTable.isDisposed()) return;\r
1585\r
e2561baf
FC
1586 int index = (int) rank;\r
1587 if (fTable.isDisposed()) return;\r
1588 if (fTable.getData(Key.FILTER_OBJ) != null) {\r
2d55fd20 1589 index = fCache.getFilteredEventIndex(rank) + 1; //+1 for top filter status row\r
e2561baf
FC
1590 }\r
1591 fTable.setSelection(index + 1); // +1 for header row\r
1592 fRawViewer.selectAndReveal(rank);\r
c1c69938
FC
1593 }\r
1594 });\r
1595 super.handleCompleted();\r
1596 }\r
1597 };\r
1598\r
e2561baf 1599 ((ITmfDataProvider<TmfEvent>) fTrace).sendRequest(subRequest);\r
c1c69938
FC
1600 }\r
1601 }\r
1602\r
e2561baf 1603}
This page took 0.114895 seconds and 5 git commands to generate.