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