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