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