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