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