Fix for bug 387934: Single event experiment not shown in events table.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / timegraph / widgets / TimeGraphControl.java
CommitLineData
fb5cad3d
PT
1/*****************************************************************************\r
2 * Copyright (c) 2007, 2008 Intel Corporation, 2009, 2010, 2011, 2012 Ericsson.\r
3 * All rights reserved. This program and the accompanying materials\r
4 * are made available under the terms of the Eclipse Public License v1.0\r
5 * which accompanies this distribution, and is available at\r
6 * http://www.eclipse.org/legal/epl-v10.html\r
7 *\r
8 * Contributors:\r
9 * Intel Corporation - Initial API and implementation\r
10 * Ruslan A. Scherbakov, Intel - Initial API and implementation\r
11 * Alvaro Sanchez-Leon - Updated for TMF\r
12 * Patrick Tasse - Refactoring\r
13 *\r
14 *****************************************************************************/\r
15\r
16package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets;\r
17\r
18import java.util.ArrayList;\r
19import java.util.Iterator;\r
20import java.util.List;\r
21import java.util.Vector;\r
22\r
b83af2c3
PT
23import org.eclipse.jface.resource.JFaceResources;\r
24import org.eclipse.jface.resource.LocalResourceManager;\r
fb5cad3d
PT
25import org.eclipse.jface.viewers.ISelection;\r
26import org.eclipse.jface.viewers.ISelectionChangedListener;\r
27import org.eclipse.jface.viewers.ISelectionProvider;\r
b83af2c3 28import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;\r
fb5cad3d 29import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTreeListener;\r
b83af2c3 30import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem;\r
fb5cad3d
PT
31import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTreeExpansionEvent;\r
32import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;\r
33import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;\r
34import org.eclipse.swt.SWT;\r
35import org.eclipse.swt.events.ControlEvent;\r
36import org.eclipse.swt.events.ControlListener;\r
37import org.eclipse.swt.events.FocusEvent;\r
38import org.eclipse.swt.events.FocusListener;\r
39import org.eclipse.swt.events.KeyEvent;\r
40import org.eclipse.swt.events.KeyListener;\r
41import org.eclipse.swt.events.MouseEvent;\r
42import org.eclipse.swt.events.MouseListener;\r
43import org.eclipse.swt.events.MouseMoveListener;\r
44import org.eclipse.swt.events.MouseTrackListener;\r
45import org.eclipse.swt.events.MouseWheelListener;\r
46import org.eclipse.swt.events.PaintEvent;\r
47import org.eclipse.swt.events.SelectionEvent;\r
48import org.eclipse.swt.events.SelectionListener;\r
49import org.eclipse.swt.events.TraverseEvent;\r
50import org.eclipse.swt.events.TraverseListener;\r
b83af2c3 51import org.eclipse.swt.graphics.Color;\r
fb5cad3d
PT
52import org.eclipse.swt.graphics.Cursor;\r
53import org.eclipse.swt.graphics.GC;\r
54import org.eclipse.swt.graphics.Image;\r
55import org.eclipse.swt.graphics.Point;\r
56import org.eclipse.swt.graphics.Rectangle;\r
57import org.eclipse.swt.widgets.Composite;\r
b83af2c3 58import org.eclipse.swt.widgets.Display;\r
fb5cad3d
PT
59import org.eclipse.swt.widgets.Event;\r
60import org.eclipse.swt.widgets.Listener;\r
61import org.eclipse.swt.widgets.ScrollBar;\r
62\r
013a5f1c
AM
63/**\r
64 * Time graph control implementation\r
65 *\r
66 * @version 1.0\r
67 * @author Alvaro Sanchez-Leon\r
68 * @author Patrick Tasse\r
69 */\r
610da665 70public class TimeGraphControl extends TimeGraphBaseControl implements FocusListener, KeyListener, MouseMoveListener, MouseListener, MouseWheelListener, ControlListener, SelectionListener, MouseTrackListener, TraverseListener, ISelectionProvider {\r
fb5cad3d
PT
71\r
72 private static final int DRAG_NONE = 0;\r
73 private static final int DRAG_TRACE_ITEM = 1;\r
74 private static final int DRAG_SPLIT_LINE = 2;\r
75 public static final boolean DEFAULT_DRAW_THREAD_JOIN = true;\r
76 public static final boolean DEFAULT_DRAW_THREAD_WAIT = true;\r
77 public static final boolean DEFAULT_DRAW_THREAD_RELEASE = true;\r
78 public static final int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1;\r
b83af2c3 79 private static final int CUSTOM_ITEM_HEIGHT = -1; // get item height from provider\r
fb5cad3d
PT
80\r
81 private static final double zoomCoeff = 1.5;\r
82\r
83 private ITimeDataProvider _timeProvider;\r
84 private boolean _isInFocus = false;\r
85 private boolean _isDragCursor3 = false;\r
86 private boolean _isWaitCursor = true;\r
87 private boolean _mouseOverSplitLine = false;\r
b83af2c3 88 private int _itemHeight = CUSTOM_ITEM_HEIGHT;\r
fb5cad3d
PT
89 private int _minimumItemWidth = 0;\r
90 private int _topIndex = 0;\r
91 private int _dragState = DRAG_NONE;\r
92 private int _dragX0 = 0;\r
93 private int _dragX = 0;\r
94 private int _idealNameSpace = 0;\r
95 // private double _timeStep = 10000000;\r
96 private long _time0bak;\r
97 private long _time1bak;\r
b83af2c3 98 private ITimeGraphPresentationProvider fTimeGraphProvider = null;\r
fb5cad3d
PT
99 private ItemData _data = null;\r
100 private List<SelectionListener> _selectionListeners;\r
013a5f1c
AM
101 private final List<ISelectionChangedListener> _selectionChangedListeners = new ArrayList<ISelectionChangedListener>();\r
102 private final List<ITimeGraphTreeListener> _treeListeners = new ArrayList<ITimeGraphTreeListener>();\r
103 private final Cursor _dragCursor3;\r
104 private final Cursor _WaitCursor;\r
fb5cad3d
PT
105\r
106 // Vertical formatting formatting for the state control view\r
013a5f1c 107 private final boolean _visibleVerticalScroll = true;\r
fb5cad3d
PT
108 private int _borderWidth = 0;\r
109 private int _headerHeight = 0;\r
110\r
111 private Listener mouseScrollFilterListener;\r
112\r
b83af2c3
PT
113 protected LocalResourceManager fResourceManager = new LocalResourceManager(JFaceResources.getResources());\r
114 protected Color[] fEventColorMap = null;\r
115\r
0c779b95 116 private MouseScrollNotifier fMouseScrollNotifier;\r
013a5f1c 117 private final Object fMouseScrollNotifierLock = new Object();\r
0c779b95
PT
118 private class MouseScrollNotifier extends Thread {\r
119 private final static long DELAY = 400L;\r
120 private final static long POLLING_INTERVAL = 10L;\r
121 private long fLastScrollTime = Long.MAX_VALUE;\r
122\r
123 @Override\r
124 public void run() {\r
125 while ((System.currentTimeMillis() - fLastScrollTime) < DELAY) {\r
126 try {\r
127 Thread.sleep(POLLING_INTERVAL);\r
128 } catch (Exception e) {\r
129 return;\r
130 }\r
131 }\r
132 if (!isInterrupted()) {\r
133 Display.getDefault().asyncExec(new Runnable() {\r
134 @Override\r
135 public void run() {\r
136 if (isDisposed()) {\r
137 return;\r
138 }\r
139 _timeProvider.notifyStartFinishTime();\r
140 }\r
141 });\r
142 }\r
143 synchronized (fMouseScrollNotifierLock) {\r
144 fMouseScrollNotifier = null;\r
145 }\r
146 }\r
147\r
148 public void mouseScrolled() {\r
149 fLastScrollTime = System.currentTimeMillis();\r
150 }\r
151 }\r
152\r
3934297e
AM
153 /**\r
154 * Standard constructor\r
155 *\r
156 * @param parent\r
157 * The parent composite object\r
158 * @param colors\r
159 * The color scheme to use\r
160 */\r
fb5cad3d
PT
161 public TimeGraphControl(Composite parent, TimeGraphColorScheme colors) {\r
162\r
163 super(parent, colors, SWT.NO_BACKGROUND | SWT.H_SCROLL | SWT.DOUBLE_BUFFERED);\r
164\r
165 _data = new ItemData();\r
166\r
167 addFocusListener(this);\r
168 addMouseListener(this);\r
169 addMouseMoveListener(this);\r
170 addMouseTrackListener(this);\r
171 addMouseWheelListener(this);\r
172 addTraverseListener(this);\r
173 addKeyListener(this);\r
174 addControlListener(this);\r
175 ScrollBar scrollHor = getHorizontalBar();\r
176\r
177 if (scrollHor != null) {\r
178 scrollHor.addSelectionListener(this);\r
179 }\r
180\r
181 _dragCursor3 = new Cursor(super.getDisplay(), SWT.CURSOR_SIZEWE);\r
182 _WaitCursor = new Cursor(super.getDisplay(), SWT.CURSOR_WAIT);\r
183 }\r
184\r
185 @Override\r
186 public void dispose() {\r
187 super.dispose();\r
188 _dragCursor3.dispose();\r
189 _WaitCursor.dispose();\r
b83af2c3 190 fResourceManager.dispose();\r
fb5cad3d
PT
191 }\r
192\r
193 /**\r
194 * Sets the timegraph provider used by this timegraph viewer.\r
013a5f1c 195 *\r
fb5cad3d
PT
196 * @param timeGraphProvider the timegraph provider\r
197 */\r
b83af2c3 198 public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider) {\r
fb5cad3d 199 fTimeGraphProvider = timeGraphProvider;\r
b83af2c3 200 _data.provider = timeGraphProvider;\r
b83af2c3 201\r
e9f70626
PT
202 if (fEventColorMap != null) {\r
203 for (Color color : fEventColorMap) {\r
204 fResourceManager.destroyColor(color.getRGB());\r
205 }\r
206 }\r
b83af2c3
PT
207 StateItem[] stateItems = fTimeGraphProvider.getStateTable();\r
208 if (stateItems != null) {\r
209 fEventColorMap = new Color[stateItems.length];\r
210 for (int i = 0; i < stateItems.length; i++) {\r
211 fEventColorMap[i] = fResourceManager.createColor(stateItems[i].getStateColor());\r
212 }\r
213 } else {\r
214 fEventColorMap = new Color[] { };\r
215 }\r
fb5cad3d
PT
216 }\r
217\r
3934297e
AM
218 /**\r
219 * Assign the given time provider\r
220 *\r
221 * @param timeProvider\r
222 * The time provider\r
223 */\r
fb5cad3d
PT
224 public void setTimeProvider(ITimeDataProvider timeProvider) {\r
225 _timeProvider = timeProvider;\r
226 adjustScrolls();\r
227 redraw();\r
228 }\r
229\r
3934297e
AM
230 /**\r
231 * Add a selection listener\r
232 *\r
233 * @param listener\r
234 * The listener to add\r
235 */\r
fb5cad3d 236 public void addSelectionListener(SelectionListener listener) {\r
013a5f1c 237 if (listener == null) {\r
fb5cad3d 238 SWT.error(SWT.ERROR_NULL_ARGUMENT);\r
013a5f1c
AM
239 }\r
240 if (null == _selectionListeners) {\r
fb5cad3d 241 _selectionListeners = new ArrayList<SelectionListener>();\r
013a5f1c 242 }\r
fb5cad3d
PT
243 _selectionListeners.add(listener);\r
244 }\r
245\r
3934297e
AM
246 /**\r
247 * Remove a selection listener\r
248 *\r
249 * @param listener\r
250 * The listener to remove\r
251 */\r
fb5cad3d 252 public void removeSelectionListener(SelectionListener listener) {\r
013a5f1c 253 if (null != _selectionListeners) {\r
fb5cad3d 254 _selectionListeners.remove(listener);\r
013a5f1c 255 }\r
fb5cad3d
PT
256 }\r
257\r
3934297e
AM
258 /**\r
259 * Selection changed callback\r
260 */\r
fb5cad3d
PT
261 public void fireSelectionChanged() {\r
262 if (null != _selectionListeners) {\r
263 Iterator<SelectionListener> it = _selectionListeners.iterator();\r
264 while (it.hasNext()) {\r
265 SelectionListener listener = it.next();\r
266 listener.widgetSelected(null);\r
267 }\r
268 }\r
269 }\r
270\r
3934297e
AM
271 /**\r
272 * Default selection callback\r
273 */\r
fb5cad3d
PT
274 public void fireDefaultSelection() {\r
275 if (null != _selectionListeners) {\r
276 Iterator<SelectionListener> it = _selectionListeners.iterator();\r
277 while (it.hasNext()) {\r
278 SelectionListener listener = it.next();\r
279 listener.widgetDefaultSelected(null);\r
280 }\r
281 }\r
282 }\r
283\r
3934297e
AM
284 /**\r
285 * Get the traces in the model\r
286 *\r
287 * @return The array of traces\r
288 */\r
b83af2c3 289 public ITimeGraphEntry[] getTraces() {\r
fb5cad3d
PT
290 return _data.getTraces();\r
291 }\r
292\r
3934297e
AM
293 /**\r
294 * Get the on/off trace filters\r
295 *\r
296 * @return The array of filters\r
297 */\r
fb5cad3d
PT
298 public boolean[] getTraceFilter() {\r
299 return _data.getTraceFilter();\r
300 }\r
301\r
3934297e
AM
302 /**\r
303 * Refresh the data for the thing\r
304 */\r
fb5cad3d
PT
305 public void refreshData() {\r
306 _data.refreshData();\r
307 adjustScrolls();\r
308 redraw();\r
309 }\r
310\r
3934297e
AM
311 /**\r
312 * Refresh data for the given traces\r
313 *\r
314 * @param traces\r
315 * The traces to refresh\r
316 */\r
f379b3eb 317 public void refreshData(ITimeGraphEntry[] traces) {\r
fb5cad3d
PT
318 _data.refreshData(traces);\r
319 adjustScrolls();\r
320 redraw();\r
321 }\r
322\r
3934297e
AM
323 /**\r
324 * Adjust the scoll bars\r
325 */\r
fb5cad3d
PT
326 public void adjustScrolls() {\r
327 if (null == _timeProvider) {\r
328 getHorizontalBar().setValues(0, 1, 1, 1, 1, 1);\r
329 return;\r
330 }\r
331\r
332 // HORIZONTAL BAR\r
333 // Visible window\r
334 long time0 = _timeProvider.getTime0();\r
335 long time1 = _timeProvider.getTime1();\r
336 // Time boundaries\r
337 long timeMin = _timeProvider.getMinTime();\r
338 long timeMax = _timeProvider.getMaxTime();\r
339\r
340 long delta = timeMax - timeMin;\r
341\r
342 int timePos = 0;\r
343 int thumb = H_SCROLLBAR_MAX;\r
344\r
345 if (delta != 0) {\r
346 // Thumb size (page size)\r
347 thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta)));\r
348 // At the beginning of visible window\r
349 timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta));\r
350 }\r
351\r
352 // position, minimum, maximum, thumb size, increment (half page)t, page\r
353 // increment size (full page)\r
354 getHorizontalBar().setValues(timePos, 0, H_SCROLLBAR_MAX, thumb, Math.max(1, thumb / 2), Math.max(2, thumb));\r
355 }\r
356\r
357 boolean ensureVisibleItem(int idx, boolean redraw) {\r
358 boolean changed = false;\r
359 if (idx < 0) {\r
360 for (idx = 0; idx < _data._expandedItems.length; idx++) {\r
abbdd66a 361 if (_data._expandedItems[idx]._selected) {\r
fb5cad3d 362 break;\r
013a5f1c 363 }\r
fb5cad3d
PT
364 }\r
365 }\r
013a5f1c 366 if (idx >= _data._expandedItems.length) {\r
fb5cad3d 367 return changed;\r
013a5f1c 368 }\r
fb5cad3d 369 if (idx < _topIndex) {\r
b83af2c3 370 setTopIndex(idx);\r
fb5cad3d 371 //FIXME:getVerticalBar().setSelection(_topItem);\r
013a5f1c 372 if (redraw) {\r
fb5cad3d 373 redraw();\r
013a5f1c 374 }\r
fb5cad3d
PT
375 changed = true;\r
376 } else {\r
377 int page = countPerPage();\r
378 if (idx >= _topIndex + page) {\r
b83af2c3 379 setTopIndex(idx - page + 1);\r
fb5cad3d 380 //FIXME:getVerticalBar().setSelection(_topItem);\r
013a5f1c 381 if (redraw) {\r
fb5cad3d 382 redraw();\r
013a5f1c 383 }\r
fb5cad3d
PT
384 changed = true;\r
385 }\r
386 }\r
387 return changed;\r
388 }\r
389\r
3934297e
AM
390 /**\r
391 * Assign the given index as the top one\r
392 *\r
393 * @param idx\r
394 * The index\r
395 */\r
fb5cad3d
PT
396 public void setTopIndex(int idx) {\r
397 idx = Math.min(idx, _data._expandedItems.length - countPerPage());\r
398 idx = Math.max(0, idx);\r
399 _topIndex = idx;\r
400 redraw();\r
401 }\r
402\r
3934297e
AM
403 /**\r
404 * Set the expanded state of a given entry\r
405 *\r
406 * @param entry\r
407 * The entry\r
408 * @param expanded\r
409 * True if expanded, false if collapsed\r
410 */\r
fb5cad3d 411 public void setExpandedState(ITimeGraphEntry entry, boolean expanded) {\r
f379b3eb 412 Item item = _data.findItem(entry);\r
fb5cad3d
PT
413 if (item != null && item._expanded != expanded) {\r
414 item._expanded = expanded;\r
415 _data.updateExpandedItems();\r
416 redraw();\r
417 }\r
418 }\r
419\r
3934297e
AM
420 /**\r
421 * Add a tree listener\r
422 *\r
423 * @param listener\r
424 * The listener to add\r
425 */\r
426 public void addTreeListener(ITimeGraphTreeListener listener) {\r
fb5cad3d
PT
427 if (!_treeListeners.contains(listener)) {\r
428 _treeListeners.add(listener);\r
429 }\r
430 }\r
431\r
3934297e
AM
432 /**\r
433 * Remove a tree listener\r
434 *\r
435 * @param listener\r
436 * The listener to remove\r
437 */\r
438 public void removeTreeListener(ITimeGraphTreeListener listener) {\r
fb5cad3d
PT
439 if (_treeListeners.contains(listener)) {\r
440 _treeListeners.remove(listener);\r
441 }\r
442 }\r
443\r
3934297e
AM
444 /**\r
445 * Tree event callback\r
446 *\r
447 * @param entry\r
448 * The affected entry\r
449 * @param expanded\r
450 * The expanded state (true for expanded, false for collapsed)\r
451 */\r
fb5cad3d
PT
452 public void fireTreeEvent(ITimeGraphEntry entry, boolean expanded) {\r
453 TimeGraphTreeExpansionEvent event = new TimeGraphTreeExpansionEvent(this, entry);\r
454 for (ITimeGraphTreeListener listener : _treeListeners) {\r
455 if (expanded) {\r
456 listener.treeExpanded(event);\r
457 } else {\r
458 listener.treeCollapsed(event);\r
459 }\r
460 }\r
461 }\r
462\r
463 @Override\r
464 public ISelection getSelection() {\r
465 TimeGraphSelection sel = new TimeGraphSelection();\r
466 ITimeGraphEntry trace = getSelectedTrace();\r
467 if (null != trace && null != _timeProvider) {\r
468 long selectedTime = _timeProvider.getSelectedTime();\r
469 ITimeEvent event = Utils.findEvent(trace, selectedTime, 0);\r
013a5f1c 470 if (event != null) {\r
fb5cad3d 471 sel.add(event);\r
013a5f1c 472 } else {\r
fb5cad3d 473 sel.add(trace);\r
013a5f1c 474 }\r
fb5cad3d
PT
475 }\r
476 return sel;\r
477 }\r
478\r
3934297e
AM
479 /**\r
480 * Get the selection object\r
481 *\r
482 * @return The selection\r
483 */\r
fb5cad3d
PT
484 public ISelection getSelectionTrace() {\r
485 TimeGraphSelection sel = new TimeGraphSelection();\r
486 ITimeGraphEntry trace = getSelectedTrace();\r
487 if (null != trace) {\r
488 sel.add(trace);\r
489 }\r
490 return sel;\r
491 }\r
492\r
3934297e
AM
493 /**\r
494 * Enable/disable one of the traces in the model\r
495 *\r
496 * @param n\r
497 * 1 to enable it, -1 to disable. The method returns immediately\r
498 * if another value is used.\r
499 */\r
fb5cad3d 500 public void selectTrace(int n) {\r
3ac6ad1a 501 if ((n != 1) && (n != -1)) {\r
fb5cad3d 502 return;\r
3ac6ad1a
BH
503 }\r
504\r
fb5cad3d
PT
505 boolean changed = false;\r
506 int lastSelection = -1;\r
507 for (int i = 0; i < _data._expandedItems.length; i++) {\r
abbdd66a 508 Item item = _data._expandedItems[i];\r
fb5cad3d
PT
509 if (item._selected) {\r
510 lastSelection = i;\r
3ac6ad1a 511 if ((1 == n) && (i < _data._expandedItems.length - 1)) {\r
fb5cad3d 512 item._selected = false;\r
abbdd66a 513 item = _data._expandedItems[i + 1];\r
fb5cad3d
PT
514 item._selected = true;\r
515 changed = true;\r
3ac6ad1a
BH
516 } else if ((-1 == n) && (i > 0)) {\r
517 item._selected = false;\r
abbdd66a 518 item = _data._expandedItems[i - 1];\r
3ac6ad1a
BH
519 item._selected = true;\r
520 changed = true;\r
fb5cad3d
PT
521 }\r
522 break;\r
523 }\r
524 }\r
3ac6ad1a 525\r
fb5cad3d 526 if (lastSelection < 0 && _data._expandedItems.length > 0) {\r
abbdd66a 527 Item item = _data._expandedItems[0];\r
3ac6ad1a
BH
528 item._selected = true;\r
529 changed = true;\r
fb5cad3d 530 }\r
3ac6ad1a 531\r
fb5cad3d
PT
532 if (changed) {\r
533 ensureVisibleItem(-1, false);\r
534 redraw();\r
535 fireSelectionChanged();\r
536 }\r
537 }\r
013a5f1c 538\r
3934297e
AM
539 /**\r
540 * Select an event\r
541 *\r
542 * @param n\r
a6b17f18 543 * 1 for next event, -1 for previous event\r
3934297e 544 */\r
fb5cad3d 545 public void selectEvent(int n) {\r
013a5f1c 546 if (null == _timeProvider) {\r
fb5cad3d 547 return;\r
013a5f1c 548 }\r
fb5cad3d 549 ITimeGraphEntry trace = getSelectedTrace();\r
013a5f1c 550 if (trace == null) {\r
fb5cad3d 551 return;\r
013a5f1c 552 }\r
fb5cad3d
PT
553 long selectedTime = _timeProvider.getSelectedTime();\r
554 long endTime = _timeProvider.getEndTime();\r
555 ITimeEvent nextEvent;\r
013a5f1c 556 if (-1 == n && selectedTime > endTime) {\r
fb5cad3d 557 nextEvent = Utils.findEvent(trace, selectedTime, 0);\r
013a5f1c 558 } else {\r
fb5cad3d 559 nextEvent = Utils.findEvent(trace, selectedTime, n);\r
013a5f1c
AM
560 }\r
561 if (null == nextEvent && -1 == n) {\r
fb5cad3d 562 nextEvent = Utils.getFirstEvent(trace);\r
013a5f1c 563 }\r
fb5cad3d
PT
564 if (null != nextEvent) {\r
565 long nextTime = nextEvent.getTime();\r
566 // If last event detected e.g. going back or not moving to a next\r
567 // event\r
568 if (nextTime <= selectedTime && n == 1) {\r
569 // Select to the end of this last event\r
570 nextTime = nextEvent.getTime() + nextEvent.getDuration();\r
571 // but not beyond the end of the trace\r
572 if (nextTime > endTime) {\r
573 nextTime = endTime;\r
574 }\r
a6b17f18
PT
575 } else if (n == -1) {\r
576 // for previous event go to its end time unless we were already there\r
577 if (nextEvent.getTime() + nextEvent.getDuration() < selectedTime) {\r
578 nextTime = nextEvent.getTime() + nextEvent.getDuration();\r
579 }\r
fb5cad3d 580 }\r
3ac6ad1a 581 _timeProvider.setSelectedTimeNotify(nextTime, true);\r
fb5cad3d
PT
582 fireSelectionChanged();\r
583 } else if (1 == n) {\r
3ac6ad1a 584 _timeProvider.setSelectedTimeNotify(endTime, true);\r
fb5cad3d
PT
585 fireSelectionChanged();\r
586 }\r
587 }\r
588\r
3934297e
AM
589 /**\r
590 * Select the next event\r
591 */\r
fb5cad3d
PT
592 public void selectNextEvent() {\r
593 selectEvent(1);\r
594 // Notify if visible time window has been adjusted\r
595 _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1());\r
596 }\r
597\r
3934297e
AM
598 /**\r
599 * Select the previous event\r
600 */\r
fb5cad3d
PT
601 public void selectPrevEvent() {\r
602 selectEvent(-1);\r
603 // Notify if visible time window has been adjusted\r
604 _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1());\r
605 }\r
606\r
3934297e
AM
607 /**\r
608 * Select the next trace\r
609 */\r
fb5cad3d
PT
610 public void selectNextTrace() {\r
611 selectTrace(1);\r
612 }\r
613\r
3934297e
AM
614 /**\r
615 * Select the previous trace\r
616 */\r
fb5cad3d
PT
617 public void selectPrevTrace() {\r
618 selectTrace(-1);\r
619 }\r
620\r
621 /**\r
e9f70626 622 * Zoom based on mouse cursor location with mouse scrolling\r
013a5f1c 623 *\r
e9f70626 624 * @param zoomIn true to zoom in, false to zoom out\r
fb5cad3d
PT
625 */\r
626 public void zoom(boolean zoomIn) {\r
627 int globalX = getDisplay().getCursorLocation().x;\r
628 Point p = toControl(globalX, 0);\r
629 int nameSpace = _timeProvider.getNameSpace();\r
630 int timeSpace = _timeProvider.getTimeSpace();\r
631 int xPos = Math.max(nameSpace, Math.min(nameSpace + timeSpace, p.x));\r
632 long time0 = _timeProvider.getTime0();\r
633 long time1 = _timeProvider.getTime1();\r
634 long interval = time1 - time0;\r
635 if (interval == 0) {\r
636 interval = 1;\r
637 } // to allow getting out of single point interval\r
638 long newInterval;\r
639 if (zoomIn) {\r
abbdd66a 640 newInterval = Math.max(Math.round(interval * 0.8), _timeProvider.getMinTimeInterval());\r
fb5cad3d 641 } else {\r
abbdd66a 642 newInterval = (long) Math.ceil(interval * 1.25);\r
fb5cad3d
PT
643 }\r
644 long center = time0 + Math.round(((double) (xPos - nameSpace) / timeSpace * interval));\r
645 long newTime0 = center - Math.round((double) newInterval * (center - time0) / interval);\r
646 long newTime1 = newTime0 + newInterval;\r
647 _timeProvider.setStartFinishTime(newTime0, newTime1);\r
0c779b95
PT
648 synchronized (fMouseScrollNotifierLock) {\r
649 if (fMouseScrollNotifier == null) {\r
650 fMouseScrollNotifier = new MouseScrollNotifier();\r
651 fMouseScrollNotifier.start();\r
652 }\r
653 fMouseScrollNotifier.mouseScrolled();\r
654 }\r
fb5cad3d
PT
655 }\r
656\r
657 /**\r
658 * zoom in using single click\r
659 */\r
660 public void zoomIn() {\r
661 long _time0 = _timeProvider.getTime0();\r
662 long _time1 = _timeProvider.getTime1();\r
663 long _range = _time1 - _time0;\r
664 long selTime = _timeProvider.getSelectedTime();\r
665 if (selTime <= _time0 || selTime >= _time1) {\r
666 selTime = (_time0 + _time1) / 2;\r
667 }\r
668 long time0 = selTime - (long) ((selTime - _time0) / zoomCoeff);\r
669 long time1 = selTime + (long) ((_time1 - selTime) / zoomCoeff);\r
670\r
671 long inaccuracy = (_timeProvider.getMaxTime() - _timeProvider.getMinTime()) - (time1 - time0);\r
672\r
673 // Trace.debug("selTime:" + selTime + " time0:" + time0 + " time1:"\r
674 // + time1 + " inaccuracy:" + inaccuracy);\r
675\r
676 if (inaccuracy > 0 && inaccuracy < 100) {\r
677 _timeProvider.setStartFinishTimeNotify(_timeProvider.getMinTime(), _timeProvider.getMaxTime());\r
678 return;\r
679 }\r
680\r
681 long m = _timeProvider.getMinTimeInterval();\r
682 if ((time1 - time0) < m) {\r
abbdd66a 683 time0 = selTime - (selTime - _time0) * m / _range;\r
fb5cad3d
PT
684 time1 = time0 + m;\r
685 }\r
686\r
687 _timeProvider.setStartFinishTimeNotify(time0, time1);\r
688 }\r
689\r
690 /**\r
691 * zoom out using single click\r
692 */\r
693 public void zoomOut() {\r
694 long _time0 = _timeProvider.getTime0();\r
695 long _time1 = _timeProvider.getTime1();\r
696 long selTime = _timeProvider.getSelectedTime();\r
697 if (selTime <= _time0 || selTime >= _time1) {\r
698 selTime = (_time0 + _time1) / 2;\r
699 }\r
700 long time0 = (long) (selTime - (selTime - _time0) * zoomCoeff);\r
701 long time1 = (long) (selTime + (_time1 - selTime) * zoomCoeff);\r
702\r
703 long inaccuracy = (_timeProvider.getMaxTime() - _timeProvider.getMinTime()) - (time1 - time0);\r
704 if (inaccuracy > 0 && inaccuracy < 100) {\r
705 _timeProvider.setStartFinishTimeNotify(_timeProvider.getMinTime(), _timeProvider.getMaxTime());\r
706 return;\r
707 }\r
708\r
709 _timeProvider.setStartFinishTimeNotify(time0, time1);\r
710 }\r
711\r
3934297e
AM
712 /**\r
713 * Return the currently selected trace\r
714 *\r
715 * @return The entry matching the trace\r
716 */\r
fb5cad3d
PT
717 public ITimeGraphEntry getSelectedTrace() {\r
718 ITimeGraphEntry trace = null;\r
719 int idx = getSelectedIndex();\r
013a5f1c 720 if (idx >= 0) {\r
fb5cad3d 721 trace = _data._expandedItems[idx]._trace;\r
013a5f1c 722 }\r
fb5cad3d
PT
723 return trace;\r
724 }\r
725\r
3934297e
AM
726 /**\r
727 * Retrieve the index of the currently selected item\r
728 *\r
729 * @return The index\r
730 */\r
fb5cad3d
PT
731 public int getSelectedIndex() {\r
732 int idx = -1;\r
733 for (int i = 0; i < _data._expandedItems.length; i++) {\r
abbdd66a 734 Item item = _data._expandedItems[i];\r
fb5cad3d
PT
735 if (item._selected) {\r
736 idx = i;\r
737 break;\r
738 }\r
739 }\r
740 return idx;\r
741 }\r
742\r
743 boolean toggle(int idx) {\r
744 boolean toggled = false;\r
745 if (idx >= 0 && idx < _data._expandedItems.length) {\r
abbdd66a 746 Item item = _data._expandedItems[idx];\r
fb5cad3d
PT
747 if (item._hasChildren) {\r
748 item._expanded = !item._expanded;\r
749 _data.updateExpandedItems();\r
750 adjustScrolls();\r
751 redraw();\r
752 toggled = true;\r
753 fireTreeEvent(item._trace, item._expanded);\r
754 }\r
755 }\r
756 return toggled;\r
757 }\r
758\r
759 int getItemIndexAtY(int y) {\r
760 if (y < 0) {\r
761 return -1;\r
762 }\r
b83af2c3
PT
763 if (_itemHeight == CUSTOM_ITEM_HEIGHT) {\r
764 int ySum = 0;\r
765 for (int idx = _topIndex; idx < _data._expandedItems.length; idx++) {\r
766 ySum += _data._expandedItems[idx].itemHeight;\r
767 if (y < ySum) {\r
768 return idx;\r
769 }\r
770 }\r
771 return -1;\r
772 }\r
fb5cad3d
PT
773 int idx = y / _itemHeight;\r
774 idx += _topIndex;\r
775 if (idx < _data._expandedItems.length) {\r
776 return idx;\r
777 }\r
778 return -1;\r
779 }\r
780\r
781 boolean isOverSplitLine(int x) {\r
013a5f1c 782 if (x < 0 || null == _timeProvider) {\r
fb5cad3d 783 return false;\r
013a5f1c 784 }\r
fb5cad3d
PT
785 int w = 4;\r
786 int nameWidth = _timeProvider.getNameSpace();\r
787 if (x > nameWidth - w && x < nameWidth + w) {\r
788 return true;\r
fb5cad3d 789 }\r
abbdd66a 790 return false;\r
fb5cad3d
PT
791 }\r
792\r
f379b3eb 793 ITimeGraphEntry getEntry(Point pt) {\r
fb5cad3d 794 int idx = getItemIndexAtY(pt.y);\r
f379b3eb 795 return idx >= 0 ? _data._expandedItems[idx]._trace : null;\r
fb5cad3d
PT
796 }\r
797\r
798 long getTimeAtX(int x) {\r
013a5f1c 799 if (null == _timeProvider) {\r
fb5cad3d 800 return -1;\r
013a5f1c 801 }\r
fb5cad3d
PT
802 long hitTime = -1;\r
803 Point size = getCtrlSize();\r
804 long time0 = _timeProvider.getTime0();\r
805 long time1 = _timeProvider.getTime1();\r
806 int nameWidth = _timeProvider.getNameSpace();\r
807 x -= nameWidth;\r
1571f4e4 808 int timeWidth = size.x - nameWidth - RIGHT_MARGIN;\r
fb5cad3d 809 if (x >= 0 && size.x >= nameWidth) {\r
da91648f
PT
810 if (time1 - time0 > timeWidth) {\r
811 // nanosecond smaller than one pixel: use the first integer nanosecond of this pixel's time range\r
812 hitTime = time0 + (long) Math.ceil((time1 - time0) * ((double) x / timeWidth));\r
813 } else {\r
814 // nanosecond greater than one pixel: use the nanosecond that covers this pixel start position\r
815 hitTime = time0 + (long) Math.floor((time1 - time0) * ((double) x / timeWidth));\r
816 }\r
fb5cad3d
PT
817 }\r
818 return hitTime;\r
819 }\r
820\r
821 void selectItem(int idx, boolean addSelection) {\r
822 boolean changed = false;\r
823 if (addSelection) {\r
824 if (idx >= 0 && idx < _data._expandedItems.length) {\r
abbdd66a 825 Item item = _data._expandedItems[idx];\r
fb5cad3d
PT
826 changed = (item._selected == false);\r
827 item._selected = true;\r
828 }\r
829 } else {\r
830 for (int i = 0; i < _data._expandedItems.length; i++) {\r
abbdd66a 831 Item item = _data._expandedItems[i];\r
fb5cad3d
PT
832 if ((i == idx && !item._selected) || (idx == -1 && item._selected)) {\r
833 changed = true;\r
834 }\r
835 item._selected = i == idx;\r
836 }\r
837 }\r
838 changed |= ensureVisibleItem(idx, true);\r
013a5f1c 839 if (changed) {\r
fb5cad3d 840 redraw();\r
013a5f1c 841 }\r
fb5cad3d
PT
842 }\r
843\r
3934297e
AM
844 /**\r
845 * Callback for item selection\r
846 *\r
847 * @param trace\r
848 * The entry matching the trace\r
849 * @param addSelection\r
850 * If the selection is added or removed\r
851 */\r
fb5cad3d
PT
852 public void selectItem(ITimeGraphEntry trace, boolean addSelection) {\r
853 int idx = _data.findItemIndex(trace);\r
854 selectItem(idx, addSelection);\r
855 }\r
856\r
3934297e
AM
857 /**\r
858 * Retrieve the number of entries shown per page.\r
859 *\r
860 * @return The count\r
861 */\r
fb5cad3d
PT
862 public int countPerPage() {\r
863 int height = getCtrlSize().y;\r
864 int count = 0;\r
b83af2c3
PT
865 if (_itemHeight == CUSTOM_ITEM_HEIGHT) {\r
866 int ySum = 0;\r
867 for (int idx = _topIndex; idx < _data._expandedItems.length; idx++) {\r
868 ySum += _data._expandedItems[idx].itemHeight;\r
869 if (ySum >= height) {\r
870 return count;\r
871 }\r
872 count++;\r
873 }\r
874 for (int idx = _topIndex - 1; idx >= 0; idx--) {\r
875 ySum += _data._expandedItems[idx].itemHeight;\r
876 if (ySum >= height) {\r
877 return count;\r
878 }\r
879 count++;\r
880 }\r
881 return count;\r
882 }\r
883 if (height > 0) {\r
fb5cad3d 884 count = height / _itemHeight;\r
b83af2c3 885 }\r
fb5cad3d
PT
886 return count;\r
887 }\r
888\r
3934297e
AM
889 /**\r
890 * Get the index of the top element\r
891 *\r
892 * @return The index\r
893 */\r
fb5cad3d
PT
894 public int getTopIndex() {\r
895 return _topIndex;\r
896 }\r
897\r
3934297e
AM
898 /**\r
899 * Get the number of expanded items\r
900 *\r
901 * @return The count of expanded items\r
902 */\r
fb5cad3d
PT
903 public int getExpandedElementCount() {\r
904 return _data._expandedItems.length;\r
905 }\r
906\r
3934297e
AM
907 /**\r
908 * Get an array of all expanded elements\r
909 *\r
910 * @return The expanded elements\r
911 */\r
549f3c43
PT
912 public ITimeGraphEntry[] getExpandedElements() {\r
913 ArrayList<ITimeGraphEntry> elements = new ArrayList<ITimeGraphEntry>();\r
f379b3eb 914 for (Item item : _data._expandedItems) {\r
549f3c43
PT
915 elements.add(item._trace);\r
916 }\r
917 return elements.toArray(new ITimeGraphEntry[0]);\r
918 }\r
919\r
fb5cad3d
PT
920 Point getCtrlSize() {\r
921 Point size = getSize();\r
922 if (getHorizontalBar().isVisible()) {\r
923 size.y -= getHorizontalBar().getSize().y;\r
924 }\r
925 return size;\r
926 }\r
927\r
928 Rectangle getNameRect(Rectangle bound, int idx, int nameWidth) {\r
fb5cad3d 929 int x = bound.x;\r
b83af2c3 930 int y = bound.y + (idx - _topIndex) * _itemHeight;\r
fb5cad3d
PT
931 int width = nameWidth;\r
932 int height = _itemHeight;\r
b83af2c3
PT
933 if (_itemHeight == CUSTOM_ITEM_HEIGHT) {\r
934 int ySum = 0;\r
935 for (int i = _topIndex; i < idx; i++) {\r
936 ySum += _data._expandedItems[i].itemHeight;\r
937 }\r
938 y = bound.y + ySum;\r
939 height = _data._expandedItems[idx].itemHeight;\r
940 }\r
fb5cad3d
PT
941 return new Rectangle(x, y, width, height);\r
942 }\r
943\r
944 Rectangle getStatesRect(Rectangle bound, int idx, int nameWidth) {\r
fb5cad3d 945 int x = bound.x + nameWidth;\r
b83af2c3 946 int y = bound.y + (idx - _topIndex) * _itemHeight;\r
fb5cad3d
PT
947 int width = bound.width - x;\r
948 int height = _itemHeight;\r
b83af2c3
PT
949 if (_itemHeight == CUSTOM_ITEM_HEIGHT) {\r
950 int ySum = 0;\r
951 for (int i = _topIndex; i < idx; i++) {\r
952 ySum += _data._expandedItems[i].itemHeight;\r
953 }\r
954 y = bound.y + ySum;\r
955 height = _data._expandedItems[idx].itemHeight;\r
956 }\r
fb5cad3d
PT
957 return new Rectangle(x, y, width, height);\r
958 }\r
959\r
fb5cad3d
PT
960 @Override\r
961 void paint(Rectangle bounds, PaintEvent e) {\r
962 GC gc = e.gc;\r
963 gc.setBackground(_colors.getColor(TimeGraphColorScheme.BACKGROUND));\r
964 drawBackground(gc, bounds.x, bounds.y, bounds.width, bounds.height);\r
965\r
013a5f1c 966 if (bounds.width < 2 || bounds.height < 2 || null == _timeProvider) {\r
fb5cad3d 967 return;\r
013a5f1c 968 }\r
fb5cad3d
PT
969\r
970 _idealNameSpace = 0;\r
971 int nameSpace = _timeProvider.getNameSpace();\r
972\r
973 // draw empty name space background\r
b83af2c3
PT
974 gc.setBackground(_colors.getBkColor(false, false, true));\r
975 drawBackground(gc, bounds.x, bounds.y, nameSpace, bounds.height);\r
fb5cad3d 976\r
b83af2c3 977 drawItems(bounds, _timeProvider, _data._expandedItems, _topIndex, nameSpace, gc);\r
fb5cad3d
PT
978\r
979 // draw selected time\r
980 long time0 = _timeProvider.getTime0();\r
981 long time1 = _timeProvider.getTime1();\r
982 long selectedTime = _timeProvider.getSelectedTime();\r
983 double pixelsPerNanoSec = (bounds.width - nameSpace <= RIGHT_MARGIN) ? 0 : (double) (bounds.width - nameSpace - RIGHT_MARGIN) / (time1 - time0);\r
da91648f 984 int x = bounds.x + nameSpace + (int) ((selectedTime - time0) * pixelsPerNanoSec);\r
fb5cad3d
PT
985 if (x >= nameSpace && x < bounds.x + bounds.width) {\r
986 gc.setForeground(_colors.getColor(TimeGraphColorScheme.SELECTED_TIME));\r
987 gc.drawLine(x, bounds.y, x, bounds.y + bounds.height);\r
988 }\r
989\r
990 // draw drag line, no line if name space is 0.\r
991 if (DRAG_SPLIT_LINE == _dragState) {\r
992 gc.setForeground(_colors.getColor(TimeGraphColorScheme.BLACK));\r
993 gc.drawLine(bounds.x + nameSpace, bounds.y, bounds.x + nameSpace, bounds.y + bounds.height - 1);\r
994 } else if (DRAG_NONE == _dragState && _mouseOverSplitLine && _timeProvider.getNameSpace() > 0) {\r
995 gc.setForeground(_colors.getColor(TimeGraphColorScheme.RED));\r
996 gc.drawLine(bounds.x + nameSpace, bounds.y, bounds.x + nameSpace, bounds.y + bounds.height - 1);\r
997 }\r
998 }\r
999\r
3934297e
AM
1000 /**\r
1001 * Draw many items at once\r
1002 *\r
1003 * @param bounds\r
1004 * The rectangle of the area\r
1005 * @param timeProvider\r
1006 * The time provider\r
1007 * @param items\r
1008 * The array items to draw\r
1009 * @param topIndex\r
1010 * The index of the first element to draw\r
1011 * @param nameSpace\r
1012 * The width reserved for the names\r
1013 * @param gc\r
1014 * Reference to the SWT GC object\r
1015 */\r
1016 public void drawItems(Rectangle bounds, ITimeDataProvider timeProvider,\r
1017 Item[] items, int topIndex, int nameSpace, GC gc) {\r
fb5cad3d 1018 for (int i = topIndex; i < items.length; i++) {\r
abbdd66a 1019 Item item = items[i];\r
b83af2c3 1020 drawItem(item, bounds, timeProvider, i, nameSpace, gc);\r
fb5cad3d 1021 }\r
b83af2c3 1022 fTimeGraphProvider.postDrawControl(bounds, gc);\r
fb5cad3d
PT
1023 }\r
1024\r
1025 /**\r
1026 * Draws the item\r
013a5f1c 1027 *\r
fb5cad3d
PT
1028 * @param item the item to draw\r
1029 * @param bounds the container rectangle\r
1030 * @param i the item index\r
1031 * @param nameSpace the name space\r
1032 * @param gc\r
1033 */\r
f379b3eb 1034 protected void drawItem(Item item, Rectangle bounds, ITimeDataProvider timeProvider, int i, int nameSpace, GC gc) {\r
b83af2c3 1035 ITimeGraphEntry entry = item._trace;\r
fb5cad3d
PT
1036 long time0 = timeProvider.getTime0();\r
1037 long time1 = timeProvider.getTime1();\r
fb5cad3d
PT
1038 long selectedTime = timeProvider.getSelectedTime();\r
1039\r
1040 Rectangle nameRect = getNameRect(bounds, i, nameSpace);\r
1041 if (nameRect.y >= bounds.y + bounds.height) {\r
1042 return;\r
1043 }\r
1044\r
bc51e30c 1045 if (! item._trace.hasTimeEvents()) {\r
fb5cad3d
PT
1046 Rectangle statesRect = getStatesRect(bounds, i, nameSpace);\r
1047 nameRect.width += statesRect.width;\r
1048 drawName(item, nameRect, gc);\r
1049 } else {\r
1050 drawName(item, nameRect, gc);\r
1051 }\r
1052 Rectangle rect = getStatesRect(bounds, i, nameSpace);\r
b83af2c3 1053 if (rect.isEmpty()) {\r
bc51e30c 1054 fTimeGraphProvider.postDrawEntry(entry, rect, gc);\r
fb5cad3d 1055 return;\r
b83af2c3 1056 }\r
fb5cad3d
PT
1057 if (time1 <= time0) {\r
1058 gc.setBackground(_colors.getBkColor(false, false, false));\r
1059 gc.fillRectangle(rect);\r
bc51e30c 1060 fTimeGraphProvider.postDrawEntry(entry, rect, gc);\r
fb5cad3d
PT
1061 return;\r
1062 }\r
1063\r
1064 // Initialize _rect1 to same values as enclosing rectangle rect\r
1065 Rectangle stateRect = Utils.clone(rect);\r
1066 boolean selected = item._selected;\r
1067 // K pixels per second\r
1068 double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0);\r
1069\r
bc51e30c 1070 if (item._trace.hasTimeEvents()) {\r
b83af2c3 1071 fillSpace(rect, gc, selected);\r
fb5cad3d
PT
1072 // Drawing rectangle is smaller than reserved space\r
1073 stateRect.y += 3;\r
1074 stateRect.height -= 6;\r
1075\r
b83af2c3
PT
1076 long maxDuration = (timeProvider.getTimeSpace() == 0) ? Long.MAX_VALUE : 1 * (time1 - time0) / timeProvider.getTimeSpace();\r
1077 Iterator<ITimeEvent> iterator = entry.getTimeEventsIterator(time0, time1, maxDuration);\r
1078\r
1079 int lastX = -1;\r
1080 while (iterator.hasNext()) {\r
1081 ITimeEvent event = iterator.next();\r
1082 int x = rect.x + (int) ((event.getTime() - time0) * pixelsPerNanoSec);\r
1083 int xEnd = rect.x + (int) ((event.getTime() + event.getDuration() - time0) * pixelsPerNanoSec);\r
1084 if (x >= rect.x + rect.width || xEnd < rect.x) {\r
1085 // event is out of bounds\r
1086 continue;\r
1087 }\r
1088 xEnd = Math.min(rect.x + rect.width, xEnd);\r
1089 stateRect.x = Math.max(rect.x, x);\r
1090 stateRect.width = Math.max(0, xEnd - stateRect.x + 1);\r
1091 if (stateRect.x == lastX) {\r
1092 stateRect.width -= 1;\r
1093 if (stateRect.width > 0) {\r
1094 gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));\r
1095 gc.drawPoint(stateRect.x, stateRect.y - 2);\r
1096 stateRect.x += 1;\r
f7e7159c 1097 }\r
b83af2c3
PT
1098 } else {\r
1099 lastX = x;\r
fb5cad3d 1100 }\r
b83af2c3
PT
1101 boolean timeSelected = selectedTime >= event.getTime() && selectedTime < event.getTime() + event.getDuration();\r
1102 drawState(_colors, event, stateRect, gc, selected, timeSelected);\r
fb5cad3d
PT
1103 }\r
1104 }\r
bc51e30c 1105 fTimeGraphProvider.postDrawEntry(entry, rect, gc);\r
fb5cad3d
PT
1106 }\r
1107\r
f379b3eb 1108 protected void drawName(Item item, Rectangle bounds, GC gc) {\r
bc51e30c
PT
1109 boolean hasTimeEvents = item._trace.hasTimeEvents();\r
1110 if (! hasTimeEvents) {\r
fb5cad3d
PT
1111 gc.setBackground(_colors.getBkColorGroup(item._selected, _isInFocus));\r
1112 gc.fillRectangle(bounds);\r
1113 if (item._selected && _isInFocus) {\r
1114 gc.setForeground(_colors.getBkColor(item._selected, _isInFocus, false));\r
1115 gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);\r
1116 }\r
1117 } else {\r
1118 gc.setBackground(_colors.getBkColor(item._selected, _isInFocus, true));\r
1119 gc.setForeground(_colors.getFgColor(item._selected, _isInFocus));\r
1120 gc.fillRectangle(bounds);\r
1121 }\r
1122\r
1123 // No name to be drawn\r
1124 if (_timeProvider.getNameSpace() == 0) {\r
1125 return;\r
1126 }\r
1127\r
1128 int leftMargin = MARGIN + item.level * EXPAND_SIZE;\r
1129 if (item._hasChildren) {\r
1130 gc.setForeground(_colors.getFgColorGroup(false, false));\r
1131 gc.setBackground(_colors.getBkColor(false, false, false));\r
1132 Rectangle rect = Utils.clone(bounds);\r
1133 rect.x += leftMargin;\r
1134 rect.y += (bounds.height - EXPAND_SIZE) / 2;\r
1135 rect.width = EXPAND_SIZE;\r
1136 rect.height = EXPAND_SIZE;\r
1137 gc.fillRectangle(rect);\r
1138 gc.drawRectangle(rect.x, rect.y, rect.width - 1, rect.height - 1);\r
1139 int midy = rect.y + rect.height / 2;\r
1140 gc.drawLine(rect.x + 2, midy, rect.x + rect.width - 3, midy);\r
1141 if (!item._expanded) {\r
1142 int midx = rect.x + rect.width / 2;\r
1143 gc.drawLine(midx, rect.y + 2, midx, rect.y + rect.height - 3);\r
1144 }\r
1145 }\r
1146 leftMargin += EXPAND_SIZE + MARGIN;\r
1147\r
1148 Image img = fTimeGraphProvider.getItemImage(item._trace);\r
1149 if (img != null) {\r
1150 // draw icon\r
1151 int imgHeight = img.getImageData().height;\r
1152 int imgWidth = img.getImageData().width;\r
1153 int x = leftMargin;\r
1154 int y = bounds.y + (bounds.height - imgHeight) / 2;\r
1155 gc.drawImage(img, x, y);\r
1156 leftMargin += imgWidth + MARGIN;\r
1157 }\r
1158 String name = item._name;\r
1159 Point size = gc.stringExtent(name);\r
1160 if (_idealNameSpace < leftMargin + size.x + MARGIN) {\r
1161 _idealNameSpace = leftMargin + size.x + MARGIN;\r
1162 }\r
bc51e30c 1163 if (hasTimeEvents) {\r
fb5cad3d
PT
1164 // cut long string with "..."\r
1165 int width = bounds.width - leftMargin;\r
1166 int cuts = 0;\r
1167 while (size.x > width && name.length() > 1) {\r
1168 cuts++;\r
1169 name = name.substring(0, name.length() - 1);\r
1170 size = gc.stringExtent(name + "..."); //$NON-NLS-1$\r
1171 }\r
1172 if (cuts > 0) {\r
1173 name += "..."; //$NON-NLS-1$\r
1174 }\r
1175 }\r
1176 Rectangle rect = Utils.clone(bounds);\r
1177 rect.x += leftMargin;\r
1178 rect.width -= leftMargin;\r
1179 // draw text\r
1180 if (rect.width > 0) {\r
b83af2c3
PT
1181 rect.y += (bounds.height - gc.stringExtent(name).y) / 2;\r
1182 gc.setForeground(_colors.getFgColor(item._selected, _isInFocus));\r
fb5cad3d
PT
1183 int textWidth = Utils.drawText(gc, name, rect, true);\r
1184 leftMargin += textWidth + MARGIN;\r
1185 rect.y -= 2;\r
1186\r
bc51e30c 1187 if (hasTimeEvents) {\r
fb5cad3d
PT
1188 // draw middle line\r
1189 int x = bounds.x + leftMargin;\r
1190 int width = bounds.width - x;\r
1191 int midy = bounds.y + bounds.height / 2;\r
1192 gc.setForeground(_colors.getColor(TimeGraphColorScheme.MID_LINE));\r
1193 gc.drawLine(x, midy, x + width, midy);\r
1194 }\r
1195 }\r
1196 }\r
1197\r
b83af2c3
PT
1198 protected void drawState(TimeGraphColorScheme colors, ITimeEvent event,\r
1199 Rectangle rect, GC gc, boolean selected, boolean timeSelected) {\r
fb5cad3d 1200\r
549f3c43 1201 int colorIdx = fTimeGraphProvider.getStateTableIndex(event);\r
b83af2c3
PT
1202 if (colorIdx < 0) {\r
1203 return;\r
f7e7159c 1204 }\r
b83af2c3 1205 boolean visible = rect.width == 0 ? false : true;\r
fb5cad3d
PT
1206\r
1207 if (visible) {\r
b83af2c3
PT
1208 Color stateColor = null;\r
1209 if (colorIdx < fEventColorMap.length) {\r
1210 stateColor = fEventColorMap[colorIdx];\r
1211 } else {\r
1212 stateColor = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);\r
1213 }\r
013a5f1c 1214\r
b83af2c3
PT
1215 timeSelected = timeSelected && selected;\r
1216 if (timeSelected) {\r
1217 // modify the color?\r
1218 }\r
fb5cad3d 1219 // fill all rect area\r
b83af2c3 1220 gc.setBackground(stateColor);\r
fb5cad3d 1221 gc.fillRectangle(rect);\r
b83af2c3
PT
1222 // get the border color?\r
1223 gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));\r
fb5cad3d
PT
1224\r
1225 // draw bounds\r
1226 if (!timeSelected) {\r
b83af2c3
PT
1227 // Draw the top and bottom borders i.e. no side borders\r
1228 // top\r
1229 gc.drawLine(rect.x, rect.y, rect.x + rect.width - 1, rect.y);\r
1230 // bottom\r
1231 gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width - 1, rect.y + rect.height - 1);\r
fb5cad3d
PT
1232 }\r
1233 } else {\r
b83af2c3
PT
1234 gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));\r
1235 gc.drawPoint(rect.x, rect.y - 2);\r
1236 /*\r
fb5cad3d
PT
1237 // selected rectangle area is not visible but can be represented\r
1238 // with a broken vertical line of specified width.\r
b83af2c3 1239 int width = 1;\r
fb5cad3d 1240 rect.width = width;\r
b83af2c3 1241 gc.setForeground(stateColor);\r
fb5cad3d
PT
1242 int s = gc.getLineStyle();\r
1243 int w = gc.getLineWidth();\r
1244 gc.setLineStyle(SWT.LINE_DOT);\r
1245 gc.setLineWidth(width);\r
b83af2c3 1246 // Trace.debug("Rectangle not visible, drawing vertical line with: "\r
fb5cad3d
PT
1247 // + rect.x + "," + rect.y + "," + rect.x + "," + rect.y\r
1248 // + rect.height);\r
b83af2c3 1249 gc.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height - 1);\r
fb5cad3d
PT
1250 gc.setLineStyle(s);\r
1251 gc.setLineWidth(w);\r
b83af2c3
PT
1252 if (!timeSelected) {\r
1253 gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));\r
1254 gc.drawPoint(rect.x, rect.y);\r
1255 gc.drawPoint(rect.x, rect.y + rect.height - 1);\r
1256 }\r
1257 */\r
fb5cad3d 1258 }\r
b83af2c3 1259 fTimeGraphProvider.postDrawEvent(event, rect, gc);\r
fb5cad3d
PT
1260 }\r
1261\r
b83af2c3 1262 protected void fillSpace(Rectangle rect, GC gc, boolean selected) {\r
fb5cad3d
PT
1263 gc.setBackground(_colors.getBkColor(selected, _isInFocus, false));\r
1264 gc.fillRectangle(rect);\r
1265 // draw middle line\r
1266 gc.setForeground(_colors.getColor(TimeGraphColorScheme.MID_LINE));\r
1267 int midy = rect.y + rect.height / 2;\r
1268 gc.drawLine(rect.x, midy, rect.x + rect.width, midy);\r
1269 }\r
1270\r
1271 @Override\r
1272 public void keyTraversed(TraverseEvent e) {\r
013a5f1c 1273 if ((e.detail == SWT.TRAVERSE_TAB_NEXT) || (e.detail == SWT.TRAVERSE_TAB_PREVIOUS)) {\r
fb5cad3d 1274 e.doit = true;\r
013a5f1c 1275 }\r
fb5cad3d
PT
1276 }\r
1277\r
1278 @Override\r
1279 public void keyPressed(KeyEvent e) {\r
1280 int idx = -1;\r
1281 if (_data._expandedItems.length == 0) {\r
1282 return;\r
1283 }\r
1284 if (SWT.HOME == e.keyCode) {\r
1285 idx = 0;\r
1286 } else if (SWT.END == e.keyCode) {\r
1287 idx = _data._expandedItems.length - 1;\r
1288 } else if (SWT.ARROW_DOWN == e.keyCode) {\r
1289 idx = getSelectedIndex();\r
013a5f1c 1290 if (idx < 0) {\r
fb5cad3d 1291 idx = 0;\r
013a5f1c 1292 } else if (idx < _data._expandedItems.length - 1) {\r
fb5cad3d 1293 idx++;\r
013a5f1c 1294 }\r
fb5cad3d
PT
1295 } else if (SWT.ARROW_UP == e.keyCode) {\r
1296 idx = getSelectedIndex();\r
013a5f1c 1297 if (idx < 0) {\r
fb5cad3d 1298 idx = 0;\r
013a5f1c 1299 } else if (idx > 0) {\r
fb5cad3d 1300 idx--;\r
013a5f1c 1301 }\r
fb5cad3d
PT
1302 } else if (SWT.ARROW_LEFT == e.keyCode) {\r
1303 selectPrevEvent();\r
1304 } else if (SWT.ARROW_RIGHT == e.keyCode) {\r
1305 selectNextEvent();\r
1306 } else if (SWT.PAGE_DOWN == e.keyCode) {\r
1307 int page = countPerPage();\r
1308 idx = getSelectedIndex();\r
013a5f1c 1309 if (idx < 0) {\r
fb5cad3d 1310 idx = 0;\r
013a5f1c 1311 }\r
fb5cad3d 1312 idx += page;\r
013a5f1c 1313 if (idx >= _data._expandedItems.length) {\r
fb5cad3d 1314 idx = _data._expandedItems.length - 1;\r
013a5f1c 1315 }\r
fb5cad3d
PT
1316 } else if (SWT.PAGE_UP == e.keyCode) {\r
1317 int page = countPerPage();\r
1318 idx = getSelectedIndex();\r
013a5f1c 1319 if (idx < 0) {\r
fb5cad3d 1320 idx = 0;\r
013a5f1c 1321 }\r
fb5cad3d 1322 idx -= page;\r
013a5f1c 1323 if (idx < 0) {\r
fb5cad3d 1324 idx = 0;\r
013a5f1c 1325 }\r
fb5cad3d
PT
1326 } else if (SWT.CR == e.keyCode) {\r
1327 idx = getSelectedIndex();\r
1328 if (idx >= 0) {\r
1329 if (_data._expandedItems[idx]._hasChildren) {\r
1330 toggle(idx);\r
1331 } else {\r
1332 fireDefaultSelection();\r
1333 }\r
1334 }\r
1335 idx = -1;\r
1336 }\r
1337 if (idx >= 0) {\r
1338 selectItem(idx, false);\r
1339 fireSelectionChanged();\r
1340 }\r
1341 }\r
1342\r
1343 @Override\r
1344 public void keyReleased(KeyEvent e) {\r
1345 }\r
1346\r
1347 @Override\r
1348 public void focusGained(FocusEvent e) {\r
1349 _isInFocus = true;\r
e9f70626
PT
1350 if (mouseScrollFilterListener == null) {\r
1351 mouseScrollFilterListener = new Listener() {\r
1352 // This filter is used to prevent horizontal scrolling of the view\r
1353 // when the mouse wheel is used to zoom\r
1354 @Override\r
1355 public void handleEvent(Event event) {\r
1356 event.doit = false;\r
1357 }\r
1358 };\r
1359 getDisplay().addFilter(SWT.MouseWheel, mouseScrollFilterListener);\r
1360 }\r
fb5cad3d
PT
1361 redraw();\r
1362 }\r
1363\r
1364 @Override\r
1365 public void focusLost(FocusEvent e) {\r
1366 _isInFocus = false;\r
e9f70626
PT
1367 if (mouseScrollFilterListener != null) {\r
1368 getDisplay().removeFilter(SWT.MouseWheel, mouseScrollFilterListener);\r
1369 mouseScrollFilterListener = null;\r
1370 }\r
fb5cad3d
PT
1371 if (DRAG_NONE != _dragState) {\r
1372 setCapture(false);\r
1373 _dragState = DRAG_NONE;\r
1374 }\r
1375 redraw();\r
1376 }\r
1377\r
3934297e
AM
1378 /**\r
1379 * @return If the current view is focused\r
1380 */\r
fb5cad3d
PT
1381 public boolean isInFocus() {\r
1382 return _isInFocus;\r
1383 }\r
1384\r
b83af2c3 1385 /**\r
3934297e 1386 * Provide the possibility to control the wait cursor externally e.g. data\r
b83af2c3 1387 * requests in progress\r
013a5f1c 1388 *\r
3934297e 1389 * @param waitInd Should we wait indefinitely?\r
b83af2c3
PT
1390 */\r
1391 public void waitCursor(boolean waitInd) {\r
1392 // Update cursor as indicated\r
1393 if (waitInd) {\r
1394 setCursor(_WaitCursor);\r
1395 _isWaitCursor = true;\r
1396 } else {\r
1397 setCursor(null);\r
1398 _isWaitCursor = false;\r
1399 }\r
1400\r
1401 // Get ready for next mouse move\r
1402 _isDragCursor3 = false;\r
1403 }\r
1404\r
1405 /**\r
1406 * <p>\r
1407 * If the x, y position is over the vertical split line (name to time\r
1408 * ranges), then change the cursor to a drag cursor to indicate the user the\r
1409 * possibility of resizing\r
1410 * </p>\r
013a5f1c 1411 *\r
b83af2c3
PT
1412 * @param x\r
1413 * @param y\r
1414 */\r
1415 void updateCursor(int x, int y) {\r
1416 // if Wait cursor not active, check for the need to change to a drag\r
1417 // cursor\r
1418 if (_isWaitCursor == false) {\r
1419 boolean isSplitLine = isOverSplitLine(x);\r
1420 // No dragcursor is name space is fixed to zero\r
1421 if (isSplitLine && !_isDragCursor3 && _timeProvider.getNameSpace() > 0) {\r
1422 setCursor(_dragCursor3);\r
1423 _isDragCursor3 = true;\r
1424 } else if (!isSplitLine && _isDragCursor3) {\r
1425 setCursor(null);\r
1426 _isDragCursor3 = false;\r
1427 }\r
1428 }\r
1429 }\r
1430\r
fb5cad3d
PT
1431 @Override\r
1432 public void mouseMove(MouseEvent e) {\r
013a5f1c 1433 if (null == _timeProvider) {\r
fb5cad3d 1434 return;\r
013a5f1c 1435 }\r
fb5cad3d
PT
1436 Point size = getCtrlSize();\r
1437 if (DRAG_TRACE_ITEM == _dragState) {\r
1438 int nameWidth = _timeProvider.getNameSpace();\r
1439 int x = e.x - nameWidth;\r
1440 if (x > 0 && size.x > nameWidth && _dragX != x) {\r
1441 _dragX = x;\r
1442 double pixelsPerNanoSec = (size.x - nameWidth <= RIGHT_MARGIN) ? 0 : (double) (size.x - nameWidth - RIGHT_MARGIN) / (_time1bak - _time0bak);\r
1443 long timeDelta = (long) ((pixelsPerNanoSec == 0) ? 0 : ((_dragX - _dragX0) / pixelsPerNanoSec));\r
1444 long time1 = _time1bak - timeDelta;\r
1445 long maxTime = _timeProvider.getMaxTime();\r
013a5f1c 1446 if (time1 > maxTime) {\r
fb5cad3d 1447 time1 = maxTime;\r
013a5f1c 1448 }\r
fb5cad3d
PT
1449 long time0 = time1 - (_time1bak - _time0bak);\r
1450 if (time0 < _timeProvider.getMinTime()) {\r
1451 time0 = _timeProvider.getMinTime();\r
1452 time1 = time0 + (_time1bak - _time0bak);\r
1453 }\r
1454 _timeProvider.setStartFinishTime(time0, time1);\r
1455 }\r
1456 } else if (DRAG_SPLIT_LINE == _dragState) {\r
1457 _dragX = e.x;\r
1458 _timeProvider.setNameSpace(e.x);\r
1459 } else if (DRAG_NONE == _dragState) {\r
1460 boolean mouseOverSplitLine = isOverSplitLine(e.x);\r
1461 if (_mouseOverSplitLine != mouseOverSplitLine) {\r
1462 redraw();\r
1463 }\r
1464 _mouseOverSplitLine = mouseOverSplitLine;\r
fb5cad3d
PT
1465 }\r
1466 updateCursor(e.x, e.y);\r
1467 }\r
1468\r
1469 @Override\r
1470 public void mouseDoubleClick(MouseEvent e) {\r
013a5f1c 1471 if (null == _timeProvider) {\r
fb5cad3d 1472 return;\r
013a5f1c 1473 }\r
fb5cad3d
PT
1474 if (1 == e.button) {\r
1475 if (isOverSplitLine(e.x) && _timeProvider.getNameSpace() != 0) {\r
1476 _timeProvider.setNameSpace(_idealNameSpace);\r
1477 boolean mouseOverSplitLine = isOverSplitLine(e.x);\r
1478 if (_mouseOverSplitLine != mouseOverSplitLine) {\r
1479 redraw();\r
1480 }\r
1481 _mouseOverSplitLine = mouseOverSplitLine;\r
1482 return;\r
1483 }\r
1484 int idx = getItemIndexAtY(e.y);\r
1485 if (idx >= 0) {\r
1486 selectItem(idx, false);\r
1487 fireDefaultSelection();\r
1488 }\r
1489 }\r
1490 }\r
1491\r
fb5cad3d
PT
1492 @Override\r
1493 public void mouseDown(MouseEvent e) {\r
013a5f1c 1494 if (null == _timeProvider) {\r
fb5cad3d 1495 return;\r
013a5f1c 1496 }\r
fb5cad3d
PT
1497 int idx;\r
1498 if (1 == e.button) {\r
1499 int nameSpace = _timeProvider.getNameSpace();\r
1500 if (nameSpace != 0) {\r
1501 if (isOverSplitLine(e.x)) {\r
1502 _dragState = DRAG_SPLIT_LINE;\r
1503 _dragX = _dragX0 = e.x;\r
1504 _time0bak = _timeProvider.getTime0();\r
1505 _time1bak = _timeProvider.getTime1();\r
1506 redraw();\r
1507 return;\r
1508 }\r
1509 }\r
1510\r
1511 idx = getItemIndexAtY(e.y);\r
1512 if (idx >= 0) {\r
f379b3eb 1513 Item item = _data._expandedItems[idx];\r
fb5cad3d
PT
1514 if (item._hasChildren && e.x < nameSpace && e.x < MARGIN + (item.level + 1) * EXPAND_SIZE) {\r
1515 toggle(idx);\r
1516 } else {\r
1517 long hitTime = getTimeAtX(e.x);\r
1518 if (hitTime >= 0) {\r
1519 // _timeProvider.setSelectedTimeInt(hitTime, false);\r
1520 setCapture(true);\r
1521 _dragState = DRAG_TRACE_ITEM;\r
1522 _dragX = _dragX0 = e.x - nameSpace;\r
1523 _time0bak = _timeProvider.getTime0();\r
1524 _time1bak = _timeProvider.getTime1();\r
1525 }\r
1526 }\r
1527 selectItem(idx, false);\r
1528 fireSelectionChanged();\r
1529 } else {\r
1530 selectItem(idx, false); // clear selection\r
1531 redraw();\r
1532 fireSelectionChanged();\r
1533 }\r
1534 }\r
1535 }\r
1536\r
1537 @Override\r
1538 public void mouseUp(MouseEvent e) {\r
1539 if (DRAG_NONE != _dragState) {\r
1540 setCapture(false);\r
1541 if (DRAG_TRACE_ITEM == _dragState) {\r
1542 // Notify time provider to check the need for listener\r
1543 // notification\r
1544 _timeProvider.notifyStartFinishTime();\r
1545 if (_dragX == _dragX0) { // click without drag\r
1546 long time = getTimeAtX(e.x);\r
3ac6ad1a 1547 _timeProvider.setSelectedTimeNotify(time, false);\r
fb5cad3d
PT
1548 }\r
1549 } else if (DRAG_SPLIT_LINE == _dragState) {\r
1550 redraw();\r
1551 }\r
1552 _dragState = DRAG_NONE;\r
1553 }\r
1554 }\r
1555\r
fb5cad3d
PT
1556 @Override\r
1557 public void mouseEnter(MouseEvent e) {\r
fb5cad3d
PT
1558 }\r
1559\r
1560 @Override\r
1561 public void mouseExit(MouseEvent e) {\r
fb5cad3d
PT
1562 if (_mouseOverSplitLine) {\r
1563 _mouseOverSplitLine = false;\r
1564 redraw();\r
1565 }\r
1566 }\r
1567\r
1568 @Override\r
1569 public void mouseHover(MouseEvent e) {\r
1570 }\r
1571\r
1572 @Override\r
1573 public void mouseScrolled(MouseEvent e) {\r
1574 if ((mouseScrollFilterListener == null) || _dragState != DRAG_NONE) {\r
1575 return;\r
1576 }\r
e9f70626
PT
1577 boolean zoomScroll = false;\r
1578 Point p = getParent().toControl(getDisplay().getCursorLocation());\r
1579 Point parentSize = getParent().getSize();\r
1580 if (p.x >= 0 && p.x < parentSize.x && p.y >= 0 && p.y < parentSize.y) {\r
1581 // over the parent control\r
1582 if (e.x > getCtrlSize().x) {\r
1583 // over the horizontal scroll bar\r
1584 zoomScroll = false;\r
1585 } else if (e.y >= 0 && e.y < getCtrlSize().y && e.x < _timeProvider.getNameSpace()) {\r
1586 // over the name space\r
1587 zoomScroll = false;\r
1588 } else {\r
1589 zoomScroll = true;\r
1590 }\r
1591 }\r
1592 if (zoomScroll && _timeProvider.getTime0() != _timeProvider.getTime1()) {\r
fb5cad3d
PT
1593 if (e.count > 0) {\r
1594 zoom(true);\r
1595 } else if (e.count < 0) {\r
1596 zoom(false);\r
1597 }\r
e9f70626
PT
1598 } else {\r
1599 setTopIndex(getTopIndex() - e.count);\r
fb5cad3d
PT
1600 }\r
1601 }\r
1602\r
b83af2c3
PT
1603 @Override\r
1604 public void controlMoved(ControlEvent e) {\r
1605 }\r
1606\r
1607 @Override\r
1608 public void controlResized(ControlEvent e) {\r
1609 adjustScrolls();\r
1610 }\r
1611\r
1612 @Override\r
1613 public void widgetDefaultSelected(SelectionEvent e) {\r
1614 }\r
1615\r
1616 @Override\r
1617 public void widgetSelected(SelectionEvent e) {\r
1618 if (e.widget == getVerticalBar()) {\r
1619 setTopIndex(getVerticalBar().getSelection());\r
1620 } else if (e.widget == getHorizontalBar() && null != _timeProvider) {\r
1621 int start = getHorizontalBar().getSelection();\r
1622 long time0 = _timeProvider.getTime0();\r
1623 long time1 = _timeProvider.getTime1();\r
1624 long timeMin = _timeProvider.getMinTime();\r
1625 long timeMax = _timeProvider.getMaxTime();\r
1626 long delta = timeMax - timeMin;\r
1627\r
1628 long range = time1 - time0;\r
1629 // _timeRangeFixed = true;\r
1630 time0 = timeMin + Math.round(delta * ((double) start / H_SCROLLBAR_MAX));\r
1631 time1 = time0 + range;\r
1632\r
1633 // TODO: Follow-up with Bug 310310\r
1634 // In Linux SWT.DRAG is the only value received\r
1635 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310310\r
1636 if (e.detail == SWT.DRAG) {\r
1637 _timeProvider.setStartFinishTime(time0, time1);\r
1638 } else {\r
1639 _timeProvider.setStartFinishTimeNotify(time0, time1);\r
1640 }\r
1641 }\r
1642 }\r
1643\r
3934297e
AM
1644 /**\r
1645 * @return The current visibility of the vertical scroll bar\r
1646 */\r
fb5cad3d
PT
1647 public boolean isVisibleVerticalScroll() {\r
1648 return _visibleVerticalScroll;\r
1649 }\r
1650\r
1651 @Override\r
1652 public int getBorderWidth() {\r
1653 return _borderWidth;\r
1654 }\r
1655\r
3934297e
AM
1656 /**\r
1657 * Set the border width\r
1658 *\r
1659 * @param borderWidth\r
1660 * The width\r
1661 */\r
fb5cad3d
PT
1662 public void setBorderWidth(int borderWidth) {\r
1663 this._borderWidth = borderWidth;\r
1664 }\r
1665\r
3934297e
AM
1666 /**\r
1667 * @return The current height of the header row\r
1668 */\r
fb5cad3d
PT
1669 public int getHeaderHeight() {\r
1670 return _headerHeight;\r
1671 }\r
1672\r
3934297e
AM
1673 /**\r
1674 * Set the height of the header row\r
1675 *\r
1676 * @param headerHeight\r
1677 * The height\r
1678 */\r
fb5cad3d
PT
1679 public void setHeaderHeight(int headerHeight) {\r
1680 this._headerHeight = headerHeight;\r
1681 }\r
1682\r
3934297e
AM
1683 /**\r
1684 * @return The height of regular item rows\r
1685 */\r
fb5cad3d
PT
1686 public int getItemHeight() {\r
1687 return _itemHeight;\r
1688 }\r
1689\r
3934297e
AM
1690 /**\r
1691 * Set the height of regular itew rows\r
1692 *\r
1693 * @param rowHeight\r
1694 * The height\r
1695 */\r
fb5cad3d
PT
1696 public void setItemHeight(int rowHeight) {\r
1697 this._itemHeight = rowHeight;\r
1698 }\r
1699\r
3934297e
AM
1700 /**\r
1701 * Set the minimum item width\r
1702 *\r
1703 * @param width The minimum width\r
1704 */\r
fb5cad3d
PT
1705 public void setMinimumItemWidth(int width) {\r
1706 this._minimumItemWidth = width;\r
1707 }\r
1708\r
3934297e
AM
1709 /**\r
1710 * @return The minimum item width\r
1711 */\r
fb5cad3d
PT
1712 public int getMinimumItemWidth() {\r
1713 return _minimumItemWidth;\r
1714 }\r
1715\r
3934297e
AM
1716 /**\r
1717 * @return The entries that are currently filtered out\r
1718 */\r
fb5cad3d
PT
1719 public Vector<ITimeGraphEntry> getFilteredOut() {\r
1720 return _data.getFilteredOut();\r
1721 }\r
1722\r
1723 // @Override\r
1724 @Override\r
1725 public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
1726 if (listener != null) {\r
1727 if (!_selectionChangedListeners.contains(listener)) {\r
1728 _selectionChangedListeners.add(listener);\r
1729 }\r
1730 }\r
1731 }\r
1732\r
1733 // @Override\r
1734 @Override\r
1735 public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
1736 if (listener != null) {\r
1737 _selectionChangedListeners.remove(listener);\r
1738 }\r
1739 }\r
1740\r
1741 // @Override\r
1742 @Override\r
1743 public void setSelection(ISelection selection) {\r
1744 if (selection instanceof TimeGraphSelection) {\r
1745 TimeGraphSelection sel = (TimeGraphSelection) selection;\r
1746 Object ob = sel.getFirstElement();\r
1747 if (ob instanceof ITimeGraphEntry) {\r
1748 ITimeGraphEntry trace = (ITimeGraphEntry) ob;\r
1749 selectItem(trace, false);\r
1750 }\r
1751 }\r
1752\r
1753 }\r
1754\r
f379b3eb
PT
1755 private class ItemData {\r
1756 public Item[] _expandedItems = new Item[0];\r
1757 public Item[] _items = new Item[0];\r
1758 private ITimeGraphEntry _traces[] = new ITimeGraphEntry[0];\r
1759 private boolean traceFilter[] = new boolean[0];\r
013a5f1c 1760 private final Vector<ITimeGraphEntry> filteredOut = new Vector<ITimeGraphEntry>();\r
f379b3eb 1761 public ITimeGraphPresentationProvider provider;\r
fb5cad3d 1762\r
f379b3eb
PT
1763 public ItemData() {\r
1764 }\r
fb5cad3d 1765\r
f379b3eb 1766 Item findItem(ITimeGraphEntry entry) {\r
013a5f1c 1767 if (entry == null) {\r
f379b3eb 1768 return null;\r
013a5f1c 1769 }\r
fb5cad3d 1770\r
f379b3eb
PT
1771 for (int i = 0; i < _items.length; i++) {\r
1772 Item item = _items[i];\r
1773 if (item._trace == entry) {\r
1774 return item;\r
1775 }\r
fb5cad3d 1776 }\r
f379b3eb
PT
1777\r
1778 return null;\r
fb5cad3d
PT
1779 }\r
1780\r
f379b3eb 1781 int findItemIndex(ITimeGraphEntry trace) {\r
013a5f1c 1782 if (trace == null) {\r
f379b3eb 1783 return -1;\r
013a5f1c 1784 }\r
f379b3eb
PT
1785\r
1786 for (int i = 0; i < _expandedItems.length; i++) {\r
1787 Item item = _expandedItems[i];\r
1788 if (item._trace == trace) {\r
1789 return i;\r
1790 }\r
1791 }\r
fb5cad3d 1792\r
fb5cad3d 1793 return -1;\r
f379b3eb 1794 }\r
fb5cad3d 1795\r
f379b3eb
PT
1796 public void refreshData() {\r
1797 List<Item> itemList = new ArrayList<Item>();\r
1798 filteredOut.clear();\r
1799 for (int i = 0; i < _traces.length; i++) {\r
1800 ITimeGraphEntry entry = _traces[i];\r
1801 refreshData(itemList, null, 0, entry);\r
fb5cad3d 1802 }\r
f379b3eb
PT
1803 _items = itemList.toArray(new Item[0]);\r
1804 updateExpandedItems();\r
fb5cad3d
PT
1805 }\r
1806\r
f379b3eb
PT
1807 private void refreshData(List<Item> itemList, Item parent, int level, ITimeGraphEntry entry) {\r
1808 Item item = new Item(entry, entry.getName(), level);\r
1809 if (parent != null) {\r
1810 parent.children.add(item);\r
1811 }\r
1812 item.itemHeight = provider.getItemHeight(entry);\r
1813 itemList.add(item);\r
1814 if (entry.hasChildren()) {\r
1815 item._expanded = true;\r
1816 item._hasChildren = true;\r
1817 for (ITimeGraphEntry child : entry.getChildren()) {\r
1818 refreshData(itemList, item, level + 1, child);\r
1819 }\r
1820 }\r
1821 }\r
fb5cad3d 1822\r
f379b3eb
PT
1823 public void updateExpandedItems() {\r
1824 List<Item> expandedItemList = new ArrayList<Item>();\r
1825 for (int i = 0; i < _traces.length; i++) {\r
1826 ITimeGraphEntry entry = _traces[i];\r
1827 Item item = findItem(entry);\r
1828 refreshExpanded(expandedItemList, item);\r
fb5cad3d 1829 }\r
f379b3eb 1830 _expandedItems = expandedItemList.toArray(new Item[0]);\r
fb5cad3d 1831 }\r
fb5cad3d 1832\r
f379b3eb
PT
1833 private void refreshExpanded(List<Item> expandedItemList, Item item) {\r
1834 expandedItemList.add(item);\r
1835 if (item._hasChildren && item._expanded) {\r
1836 for (Item child : item.children) {\r
1837 refreshExpanded(expandedItemList, child);\r
1838 }\r
1839 }\r
fb5cad3d 1840 }\r
fb5cad3d 1841\r
f379b3eb
PT
1842 public void refreshData(ITimeGraphEntry traces[]) {\r
1843 if (traces == null || traces.length == 0) {\r
1844 traceFilter = null;\r
1845 } else if (traceFilter == null || traces.length != traceFilter.length) {\r
1846 traceFilter = new boolean[traces.length];\r
1847 java.util.Arrays.fill(traceFilter, true);\r
1848 }\r
1849\r
1850 _traces = traces;\r
1851 refreshData();\r
fb5cad3d 1852 }\r
fb5cad3d 1853\r
f379b3eb
PT
1854 public ITimeGraphEntry[] getTraces() {\r
1855 return _traces;\r
fb5cad3d
PT
1856 }\r
1857\r
f379b3eb
PT
1858 public boolean[] getTraceFilter() {\r
1859 return traceFilter;\r
1860 }\r
fb5cad3d 1861\r
f379b3eb
PT
1862 public Vector<ITimeGraphEntry> getFilteredOut() {\r
1863 return filteredOut;\r
1864 }\r
fb5cad3d
PT
1865 }\r
1866\r
f379b3eb
PT
1867 private class Item {\r
1868 public boolean _expanded;\r
1869 public boolean _selected;\r
1870 public boolean _hasChildren;\r
1871 public int itemHeight;\r
1872 public int level;\r
1873 public List<Item> children;\r
1874 public String _name;\r
1875 public ITimeGraphEntry _trace;\r
fb5cad3d 1876\r
f379b3eb
PT
1877 public Item(ITimeGraphEntry trace, String name, int level) {\r
1878 this._trace = trace;\r
1879 this._name = name;\r
1880 this.level = level;\r
1881 this.children = new ArrayList<Item>();\r
1882 }\r
1883\r
1884 @Override\r
1885 public String toString() {\r
1886 return _name;\r
1887 }\r
fb5cad3d 1888 }\r
f379b3eb 1889\r
fb5cad3d 1890}\r
f379b3eb 1891\r
This page took 0.145677 seconds and 5 git commands to generate.