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