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