Contribute native CTF Parser (bug370499)
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / timeAnalysis / widgets / TmfTimeStatesCtrl.java
1 /*****************************************************************************
2 * Copyright (c) 2007, 2008 Intel Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel Corporation - Initial API and implementation
10 * Ruslan A. Scherbakov, Intel - Initial API and implementation
11 * Alvaro Sanchex-Leon - Udpated for TMF
12 *
13 * $Id: ThreadStatesCtrl.java,v 1.15 2008/07/11 13:49:01 aalexeev Exp $
14 *****************************************************************************/
15
16 package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Vector;
24
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.ISelectionChangedListener;
27 import org.eclipse.jface.viewers.ISelectionProvider;
28 import org.eclipse.linuxtools.tmf.ui.internal.Messages;
29 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider;
30 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent;
31 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
32 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent;
33 import org.eclipse.osgi.util.NLS;
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.events.ControlEvent;
36 import org.eclipse.swt.events.ControlListener;
37 import org.eclipse.swt.events.FocusEvent;
38 import org.eclipse.swt.events.FocusListener;
39 import org.eclipse.swt.events.KeyEvent;
40 import org.eclipse.swt.events.KeyListener;
41 import org.eclipse.swt.events.MouseEvent;
42 import org.eclipse.swt.events.MouseListener;
43 import org.eclipse.swt.events.MouseMoveListener;
44 import org.eclipse.swt.events.MouseTrackListener;
45 import org.eclipse.swt.events.MouseWheelListener;
46 import org.eclipse.swt.events.PaintEvent;
47 import org.eclipse.swt.events.SelectionEvent;
48 import org.eclipse.swt.events.SelectionListener;
49 import org.eclipse.swt.events.TraverseEvent;
50 import org.eclipse.swt.events.TraverseListener;
51 import org.eclipse.swt.graphics.Cursor;
52 import org.eclipse.swt.graphics.GC;
53 import org.eclipse.swt.graphics.Image;
54 import org.eclipse.swt.graphics.Point;
55 import org.eclipse.swt.graphics.Rectangle;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Event;
58 import org.eclipse.swt.widgets.Listener;
59 import org.eclipse.swt.widgets.ScrollBar;
60
61 /**
62 * @author alvaro
63 *
64 */
65 public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, KeyListener, MouseMoveListener, MouseListener, MouseWheelListener, ControlListener, SelectionListener, MouseTrackListener, TraverseListener, ISelectionProvider {
66
67 private static final int DRAG_NONE = 0;
68 private static final int DRAG_TRACE_ITEM = 1;
69 private static final int DRAG_GROUP_ITEM = 2;
70 private static final int DRAG_SPLIT_LINE = 3;
71 public static final boolean DEFAULT_DRAW_THREAD_JOIN = true;
72 public static final boolean DEFAULT_DRAW_THREAD_WAIT = true;
73 public static final boolean DEFAULT_DRAW_THREAD_RELEASE = true;
74 public static final int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1;
75
76 private static final double zoomCoeff = 1.5;
77
78 private ITimeDataProvider _timeProvider;
79 private boolean _isInFocus = false;
80 private boolean _isDragCursor3 = false;
81 private boolean _isWaitCursor = true;
82 private boolean _mouseHover = false;
83 private int _itemHeightDefault = 19;
84 private int _itemHeight = _itemHeightDefault;
85 private int _minimumItemWidth = 0;
86 private int _topItem = 0;
87 private int _dragState = DRAG_NONE;
88 private int _hitIdx = 0;
89 private int _dragX0 = 0;
90 private int _dragX = 0;
91 private int _idealNameWidth = 0;
92 // private double _timeStep = 10000000;
93 private long _time0bak;
94 private long _time1bak;
95 private TmfTimeAnalysisProvider utilImpl = null;
96 private ItemData _data = null;
97 private List<SelectionListener> _selectionListeners;
98 private List<ISelectionChangedListener> _selectionChangedListeners = new ArrayList<ISelectionChangedListener>();
99 private Rectangle _rect0 = new Rectangle(0, 0, 0, 0);
100 private Rectangle _rect1 = new Rectangle(0, 0, 0, 0);
101 private Cursor _dragCursor3;
102 private Cursor _WaitCursor;
103 private boolean drawTracesInteraction = false;
104 private boolean drawTraceJoins = DEFAULT_DRAW_THREAD_JOIN;
105 private boolean drawTraceWaits = DEFAULT_DRAW_THREAD_WAIT;
106 private boolean drawTraceReleases = DEFAULT_DRAW_THREAD_RELEASE;
107
108 // Vertical formatting formatting for the state control view
109 private boolean _visibleVerticalScroll = true;
110 private int _borderWidth = 0;
111 private int _headerHeight = 0;
112
113 private Listener mouseScrollFilterListener;
114
115 public TmfTimeStatesCtrl(Composite parent, TraceColorScheme colors, TmfTimeAnalysisProvider rutilImp) {
116
117 super(parent, colors, SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL | SWT.DOUBLE_BUFFERED);
118
119 this.utilImpl = rutilImp;
120 _data = new ItemData(utilImpl);
121
122 addFocusListener(this);
123 addMouseListener(this);
124 addMouseMoveListener(this);
125 addMouseTrackListener(this);
126 addMouseWheelListener(this);
127 addTraverseListener(this);
128 addKeyListener(this);
129 addControlListener(this);
130 ScrollBar scrollVer = getVerticalBar();
131 ScrollBar scrollHor = getHorizontalBar();
132 if (scrollVer != null) {
133 scrollVer.addSelectionListener(this);
134 scrollVer.setVisible(_visibleVerticalScroll);
135 }
136
137 if (scrollHor != null) {
138 scrollHor.addSelectionListener(this);
139 }
140
141 _dragCursor3 = new Cursor(super.getDisplay(), SWT.CURSOR_SIZEWE);
142 _WaitCursor = new Cursor(super.getDisplay(), SWT.CURSOR_WAIT);
143 }
144
145 @Override
146 public void dispose() {
147 super.dispose();
148 _dragCursor3.dispose();
149 _WaitCursor.dispose();
150 }
151
152 public void setTimeProvider(ITimeDataProvider timeProvider) {
153 _timeProvider = timeProvider;
154 adjustScrolls();
155 redraw();
156 }
157
158 public void addSelectionListener(SelectionListener listener) {
159 if (listener == null)
160 SWT.error(SWT.ERROR_NULL_ARGUMENT);
161 if (null == _selectionListeners)
162 _selectionListeners = new ArrayList<SelectionListener>();
163 _selectionListeners.add(listener);
164 }
165
166 public void removeSelectionListener(SelectionListener listener) {
167 if (null != _selectionListeners)
168 _selectionListeners.remove(listener);
169 }
170
171 public void fireSelectionChanged() {
172 if (null != _selectionListeners) {
173 Iterator<SelectionListener> it = _selectionListeners.iterator();
174 while (it.hasNext()) {
175 SelectionListener listener = it.next();
176 listener.widgetSelected(null);
177 }
178 }
179 }
180
181 public void fireDefaultSelection() {
182 if (null != _selectionListeners) {
183 Iterator<SelectionListener> it = _selectionListeners.iterator();
184 while (it.hasNext()) {
185 SelectionListener listener = it.next();
186 listener.widgetDefaultSelected(null);
187 }
188 }
189 }
190
191 public Object[] getTraces() {
192 return _data.getTraces();
193 }
194
195 public boolean[] getTraceFilter() {
196 return _data.getTraceFilter();
197 }
198
199 public void refreshData() {
200 _data.refreshData();
201 adjustScrolls();
202 redraw();
203 }
204
205 public void refreshData(Object traces[]) {
206 _data.refreshData(traces);
207 adjustScrolls();
208 redraw();
209 }
210
211 public void refreshPartial(ITmfTimeAnalysisEntry parent, TimeEvent item) {
212 _data.refreshPartial(parent, item);
213 adjustScrolls();
214 redraw();
215 }
216
217 public void adjustScrolls() {
218 if (null == _timeProvider) {
219 getVerticalBar().setValues(0, 1, 1, 1, 1, 1);
220 getHorizontalBar().setValues(0, 1, 1, 1, 1, 1);
221 return;
222 }
223
224 // Vertical scroll bar
225 int page = countPerPage();
226 if (_topItem + page > _data._items.length)
227 _topItem = _data._items.length - page;
228 if (_topItem < 0)
229 _topItem = 0;
230 getVerticalBar().setValues(_topItem, 0, _data._items.length, page, 1, page);
231
232 // HORIZONTAL BAR
233 // Visible window
234 long time0 = _timeProvider.getTime0();
235 long time1 = _timeProvider.getTime1();
236 // Time boundaries
237 long timeMin = _timeProvider.getMinTime();
238 long timeMax = _timeProvider.getMaxTime();
239
240 long delta = timeMax - timeMin;
241
242 int timePos = 0;
243 int thumb = H_SCROLLBAR_MAX;
244
245 if (delta != 0) {
246 // Thumb size (page size)
247 thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta)));
248 // At the beginning of visible window
249 timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta));
250 }
251
252 // position, minimum, maximum, thumb size, increment (half page)t, page
253 // increment size (full page)
254 getHorizontalBar().setValues(timePos, 0, H_SCROLLBAR_MAX, thumb, Math.max(1, thumb / 2), Math.max(2, thumb));
255 }
256
257 boolean ensureVisibleItem(int idx, boolean redraw) {
258 boolean changed = false;
259 if (idx < 0) {
260 for (idx = 0; idx < _data._items.length; idx++) {
261 if (((Item) _data._items[idx])._selected)
262 break;
263 }
264 }
265 if (idx >= _data._items.length)
266 return changed;
267 if (idx < _topItem) {
268 _topItem = idx;
269 getVerticalBar().setSelection(_topItem);
270 if (redraw)
271 redraw();
272 changed = true;
273 } else {
274 int page = countPerPage();
275 if (idx >= _topItem + page) {
276 _topItem = idx - page + 1;
277 getVerticalBar().setSelection(_topItem);
278 if (redraw)
279 redraw();
280 changed = true;
281 }
282 }
283 return changed;
284 }
285
286 @Override
287 public ISelection getSelection() {
288 PlainSelection sel = new PlainSelection();
289 ITmfTimeAnalysisEntry trace = getSelectedTrace();
290 if (null != trace && null != _timeProvider) {
291 long selectedTime = _timeProvider.getSelectedTime();
292 ITimeEvent event = Utils.findEvent(trace, selectedTime, 0);
293 if (event != null)
294 sel.add(event);
295 else
296 sel.add(trace);
297 }
298 return sel;
299 }
300
301 public ISelection getSelectionTrace() {
302 PlainSelection sel = new PlainSelection();
303 ITmfTimeAnalysisEntry trace = getSelectedTrace();
304 if (null != trace) {
305 sel.add(trace);
306 }
307 return sel;
308 }
309
310 public void selectTrace(int n) {
311 if (n != 1 && n != -1)
312 return;
313 boolean changed = false;
314 int lastSelection = -1;
315 for (int i = 0; i < _data._items.length; i++) {
316 Item item = (Item) _data._items[i];
317 if (item._selected) {
318 lastSelection = i;
319 if (1 == n && i < _data._items.length - 1) {
320 item._selected = false;
321 if (item._hasChildren)
322 _data.expandItem(i, true);
323 item = (Item) _data._items[i + 1];
324 if (item._hasChildren) {
325 _data.expandItem(i + 1, true);
326 item = (Item) _data._items[i + 2];
327 }
328 item._selected = true;
329 changed = true;
330 } else if (-1 == n && i > 0) {
331 i--;
332 Item prevItem = (Item) _data._items[i];
333 if (prevItem._hasChildren) {
334 if (prevItem._expanded) {
335 if (i > 0) {
336 i--;
337 prevItem = (Item) _data._items[i];
338 }
339 }
340 if (!prevItem._expanded) {
341 int added = _data.expandItem(i, true);
342 prevItem = (Item) _data._items[i + added];
343 item._selected = false;
344 prevItem._selected = true;
345 changed = true;
346 }
347 } else {
348 item._selected = false;
349 prevItem._selected = true;
350 changed = true;
351 }
352 }
353 break;
354 }
355 }
356 if (lastSelection < 0 && _data._items.length > 0) {
357 Item item = (Item) _data._items[0];
358 if (item._hasChildren) {
359 _data.expandItem(0, true);
360 item = (Item) _data._items[1];
361 item._selected = true;
362 changed = true;
363 } else {
364 item._selected = true;
365 changed = true;
366 }
367 }
368 if (changed) {
369 ensureVisibleItem(-1, false);
370 redraw();
371 fireSelectionChanged();
372 }
373 }
374
375 public void selectEvent(int n) {
376 if (null == _timeProvider)
377 return;
378 ITmfTimeAnalysisEntry trace = getSelectedTrace();
379 if (trace == null)
380 return;
381 long selectedTime = _timeProvider.getSelectedTime();
382 long endTime = _timeProvider.getEndTime();
383 ITimeEvent nextEvent;
384 if (-1 == n && selectedTime > endTime)
385 nextEvent = Utils.findEvent(trace, selectedTime, 0);
386 else
387 nextEvent = Utils.findEvent(trace, selectedTime, n);
388 if (null == nextEvent && -1 == n)
389 nextEvent = Utils.getFirstEvent(trace);
390 if (null != nextEvent) {
391 long nextTime = nextEvent.getTime();
392 // If last event detected e.g. going back or not moving to a next
393 // event
394 if (nextTime <= selectedTime && n == 1) {
395 // Select to the end of this last event
396 nextTime = nextEvent.getTime() + nextEvent.getDuration();
397 // but not beyond the end of the trace
398 if (nextTime > endTime) {
399 nextTime = endTime;
400 }
401 }
402 _timeProvider.setSelectedTimeInt(nextTime, true);
403 fireSelectionChanged();
404 } else if (1 == n) {
405 _timeProvider.setSelectedTimeInt(endTime, true);
406 fireSelectionChanged();
407 }
408 }
409
410 public void selectNextEvent() {
411 selectEvent(1);
412 // Notify if visible time window has been adjusted
413 _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1());
414 }
415
416 public void selectPrevEvent() {
417 selectEvent(-1);
418 // Notify if visible time window has been adjusted
419 _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1());
420 }
421
422 public void selectNextTrace() {
423 selectTrace(1);
424 }
425
426 public void selectPrevTrace() {
427 selectTrace(-1);
428 }
429
430 /**
431 * Zooming based on mouse cursor location with mouse scrolling
432 *
433 * @param zoomIn
434 */
435 public void zoom(boolean zoomIn) {
436 int globalX = getDisplay().getCursorLocation().x;
437 Point p = toControl(globalX, 0);
438 int nameSpace = _timeProvider.getNameSpace();
439 int timeSpace = _timeProvider.getTimeSpace();
440 int xPos = Math.max(nameSpace, Math.min(nameSpace + timeSpace, p.x));
441 long time0 = _timeProvider.getTime0();
442 long time1 = _timeProvider.getTime1();
443 long interval = time1 - time0;
444 if (interval == 0) {
445 interval = 1;
446 } // to allow getting out of single point interval
447 long newInterval;
448 if (zoomIn) {
449 newInterval = Math.max(Math.round((double) interval * 0.8), _timeProvider.getMinTimeInterval());
450 } else {
451 newInterval = (long) Math.ceil((double) interval * 1.25);
452 }
453 long center = time0 + Math.round(((double) (xPos - nameSpace) / timeSpace * interval));
454 long newTime0 = center - Math.round((double) newInterval * (center - time0) / interval);
455 long newTime1 = newTime0 + newInterval;
456 _timeProvider.setStartFinishTime(newTime0, newTime1);
457 }
458
459 /**
460 * zoom in using single click
461 */
462 public void zoomIn() {
463 long _time0 = _timeProvider.getTime0();
464 long _time1 = _timeProvider.getTime1();
465 long _range = _time1 - _time0;
466 long selTime = _timeProvider.getSelectedTime();
467 if (selTime <= _time0 || selTime >= _time1) {
468 selTime = (_time0 + _time1) / 2;
469 }
470 long time0 = selTime - (long) ((selTime - _time0) / zoomCoeff);
471 long time1 = selTime + (long) ((_time1 - selTime) / zoomCoeff);
472
473 long inaccuracy = (_timeProvider.getMaxTime() - _timeProvider.getMinTime()) - (time1 - time0);
474
475 // Trace.debug("selTime:" + selTime + " time0:" + time0 + " time1:"
476 // + time1 + " inaccuracy:" + inaccuracy);
477
478 if (inaccuracy > 0 && inaccuracy < 100) {
479 _timeProvider.setStartFinishTimeNotify(_timeProvider.getMinTime(), _timeProvider.getMaxTime());
480 return;
481 }
482
483 long m = _timeProvider.getMinTimeInterval();
484 if ((time1 - time0) < m) {
485 time0 = selTime - (long) ((selTime - _time0) * m / _range);
486 time1 = time0 + m;
487 }
488
489 _timeProvider.setStartFinishTimeNotify(time0, time1);
490 }
491
492 /**
493 * zoom out using single click
494 */
495 public void zoomOut() {
496 long _time0 = _timeProvider.getTime0();
497 long _time1 = _timeProvider.getTime1();
498 long selTime = _timeProvider.getSelectedTime();
499 if (selTime <= _time0 || selTime >= _time1) {
500 selTime = (_time0 + _time1) / 2;
501 }
502 long time0 = (long) (selTime - (selTime - _time0) * zoomCoeff);
503 long time1 = (long) (selTime + (_time1 - selTime) * zoomCoeff);
504
505 long inaccuracy = (_timeProvider.getMaxTime() - _timeProvider.getMinTime()) - (time1 - time0);
506 if (inaccuracy > 0 && inaccuracy < 100) {
507 _timeProvider.setStartFinishTimeNotify(_timeProvider.getMinTime(), _timeProvider.getMaxTime());
508 return;
509 }
510
511 _timeProvider.setStartFinishTimeNotify(time0, time1);
512 }
513
514 public void groupTraces(boolean on) {
515 _data.groupTraces(on);
516 adjustScrolls();
517 redraw();
518 }
519
520 public void toggleTraceInteractionDrawing() {
521 drawTracesInteraction = !drawTracesInteraction;
522 redraw();
523 }
524
525 public void setTraceJoinDrawing(boolean on) {
526 drawTraceJoins = on;
527 drawTracesInteraction = true;
528 redraw();
529 }
530
531 public void setTraceWaitDrawing(boolean on) {
532 drawTraceWaits = on;
533 drawTracesInteraction = true;
534 redraw();
535 }
536
537 public void setTraceReleaseDrawing(boolean on) {
538 drawTraceReleases = on;
539 drawTracesInteraction = true;
540 redraw();
541 }
542
543 public boolean getTracesInteractionDrawing() {
544 return drawTracesInteraction;
545 }
546
547 public boolean getTraceJoinDrawing() {
548 return drawTraceJoins;
549 }
550
551 public boolean getTraceWaitDrawing() {
552 return drawTraceWaits;
553 }
554
555 public boolean getTraceReleaseDrawing() {
556 return drawTraceReleases;
557 }
558
559 public ITmfTimeAnalysisEntry getSelectedTrace() {
560 ITmfTimeAnalysisEntry trace = null;
561 int idx = getSelectedIndex();
562 if (idx >= 0 && _data._items[idx] instanceof TraceItem)
563 trace = ((TraceItem) _data._items[idx])._trace;
564 return trace;
565 }
566
567 public int getSelectedIndex() {
568 int idx = -1;
569 for (int i = 0; i < _data._items.length; i++) {
570 Item item = (Item) _data._items[i];
571 if (item._selected) {
572 idx = i;
573 break;
574 }
575 }
576 return idx;
577 }
578
579 boolean toggle(int idx) {
580 boolean toggled = false;
581 if (idx >= 0 && idx < _data._items.length) {
582 Item item = (Item) _data._items[idx];
583 if (item._hasChildren) {
584 item._expanded = !item._expanded;
585 _data.updateItems();
586 adjustScrolls();
587 redraw();
588 toggled = true;
589 }
590 }
591 return toggled;
592 }
593
594 int hitTest(int x, int y) {
595 if (x < 0 || y < 0)
596 return -1;
597 int hit = -1;
598 int idx = y / _itemHeight;
599 idx += _topItem;
600 if (idx < _data._items.length)
601 hit = idx;
602 return hit;
603 }
604
605 int hitSplitTest(int x, int y) {
606 if (x < 0 || y < 0 || null == _timeProvider)
607 return -1;
608 int w = 4;
609 int hit = -1;
610 int nameWidth = _timeProvider.getNameSpace();
611 if (x > nameWidth - w && x < nameWidth + w)
612 hit = 1;
613 return hit;
614 }
615
616 Item getItem(Point pt) {
617 int idx = hitTest(pt.x, pt.y);
618 return idx >= 0 ? (Item) _data._items[idx] : null;
619 }
620
621 long hitTimeTest(int x) {
622 if (null == _timeProvider)
623 return -1;
624 long hitTime = -1;
625 Point size = getCtrlSize();
626 long time0 = _timeProvider.getTime0();
627 long time1 = _timeProvider.getTime1();
628 int nameWidth = _timeProvider.getNameSpace();
629 x -= nameWidth;
630 if (x >= 0 && size.x >= nameWidth) {
631 if (time1 - time0 > size.x - nameWidth - RIGHT_MARGIN) {
632 // get the last possible time represented by the pixel position
633 // by taking the time of the next pixel position minus 1
634 // nanosecond
635 hitTime = time0 + (long) ((time1 - time0) * ((double) (x + 1) / (size.x - nameWidth - RIGHT_MARGIN))) - 1;
636 } else {
637 hitTime = time0 + (long) ((time1 - time0) * ((double) (x) / (size.x - nameWidth - RIGHT_MARGIN)));
638 }
639 }
640 return hitTime;
641 }
642
643 void selectItem(int idx, boolean addSelection) {
644 boolean changed = false;
645 if (addSelection) {
646 if (idx >= 0 && idx < _data._items.length) {
647 Item item = (Item) _data._items[idx];
648 changed = (item._selected == false);
649 item._selected = true;
650 }
651 } else {
652 for (int i = 0; i < _data._items.length; i++) {
653 Item item = (Item) _data._items[i];
654 if (i == idx && item._selected == false) {
655 changed = true;
656 }
657 item._selected = i == idx;
658 }
659 }
660 changed |= ensureVisibleItem(idx, true);
661 if (changed)
662 redraw();
663 }
664
665 public void selectItem(ITmfTimeAnalysisEntry trace, boolean addSelection) {
666 Integer idx = _data.findTraceItemIndex(trace);
667 if (idx != null) {
668 selectItem(idx, addSelection);
669 }
670 }
671
672 public int countPerPage() {
673 int height = getCtrlSize().y;
674 int count = 0;
675 if (height > 0)
676 count = height / _itemHeight;
677 return count;
678 }
679
680 public int getTopIndex() {
681 int idx = -1;
682 if (_data._items.length > 0)
683 idx = 0;
684 return idx;
685 }
686
687 public int getBottomIndex() {
688 int idx = _data._items.length - 1;
689 return idx;
690 }
691
692 Point getCtrlSize() {
693 Point size = getSize();
694 if (getVerticalBar().isVisible()) {
695 size.x -= getVerticalBar().getSize().x;
696 }
697 if (getHorizontalBar().isVisible()) {
698 size.y -= getHorizontalBar().getSize().y;
699 }
700 return size;
701 }
702
703 void getNameRect(Rectangle rect, Rectangle bound, int idx, int nameWidth) {
704 idx -= _topItem;
705 rect.x = bound.x;
706 rect.y = bound.y + idx * _itemHeight;
707 rect.width = nameWidth;
708 rect.height = _itemHeight;
709 }
710
711 void getStatesRect(Rectangle rect, Rectangle bound, int idx, int nameWidth) {
712 idx -= _topItem;
713 rect.x = bound.x + nameWidth;
714 rect.y = bound.y + idx * _itemHeight;
715 rect.width = bound.width - rect.x;
716 rect.height = _itemHeight;
717 }
718
719 // private int getTraceNumber(int tid) {
720 // int num = -1;
721 //
722 // Object[] items = _data._items;
723 // for (int i = _topItem; i < items.length; i++) {
724 // Item item = (Item) items[i];
725 // if ((item instanceof TraceItem)) {
726 // TsfTmTrace trace = ((TraceItem) item)._trace;
727 // if (trace != null && trace.getId() == tid) {
728 // num = i;
729 // break;
730 // }
731 // }
732 // }
733 //
734 // return num;
735 // }
736
737 // private void drawArrow(GC gc, int x0, int y0, int x1, int y1, Color c) {
738 // gc.setForeground(c);
739 // gc.drawLine(x0, y0, x1, y1);
740 //
741 // if (y1 > y0) {
742 // gc.drawLine(x1 - 3, y1 - 3, x1, y1);
743 // gc.drawLine(x1 + 3, y1 - 3, x1, y1);
744 // } else {
745 // gc.drawLine(x1 - 3, y1 + 3, x1, y1);
746 // gc.drawLine(x1 + 3, y1 + 3, x1, y1);
747 // }
748 // }
749
750 // TODO: CC: used in the removed functionality to draw thread interactions.
751 // private void drawTraceThreadEvent(Rectangle bound, TsfTmEvent e,
752 // TsfTmTrace trace, int nItem, int color, GC gc) {
753 // if (trace == null)
754 // return;
755 //
756 // int tid = trace.getId();
757 // if (tid < 0 || getTraceNumber(tid) == -1)
758 // return;
759 //
760 // int nameWidth = _timeProvider.getNameSpace();
761 //
762 // double time0 = _timeProvider.getTime0();
763 // double time1 = _timeProvider.getTime1();
764 // if (time0 == time1)
765 // return;
766 //
767 // int xr = bound.x + nameWidth;
768 // double K = (double) (bound.width - xr) / (time1 - time0);
769 //
770 // int x0 = xr + (int) ((e.getTime() - time0) * K);
771 // if (x0 < xr)
772 // x0 = xr;
773 //
774 // int x1 = xr + (int) ((trace.getStartTime() - time0) * K);
775 // if (x1 < xr)
776 // return;
777 //
778 // int y0 = bound.y + (nItem - _topItem) * _itemHeight + 3
779 // + (_itemHeight - 6) / 2;
780 // int y1 = bound.y + (getTraceNumber(tid) - _topItem) * _itemHeight + 3
781 // + (_itemHeight - 6) / 2;
782 //
783 // drawArrow(gc, x0, y0, x1, y1, _colors.getColor(color));
784 // }
785
786 public void drawTraceEvent(Rectangle bound, ITimeEvent e, int nItem, int color, GC gc) {
787 int nameWidth = _timeProvider.getNameSpace();
788
789 long time0 = _timeProvider.getTime0();
790 long time1 = _timeProvider.getTime1();
791 if (time0 == time1)
792 return;
793
794 int xr = bound.x + nameWidth;
795 double pixelsPerNanoSec = (bound.width - xr <= RIGHT_MARGIN) ? 0 : (double) (bound.width - xr - RIGHT_MARGIN) / (time1 - time0);
796
797 int x0 = xr + (int) ((e.getTime() - time0) * pixelsPerNanoSec);
798 if (x0 < xr)
799 return;
800
801 int y0 = bound.y + (nItem - _topItem) * _itemHeight + 3;
802
803 gc.setBackground(_colors.getColor(color));
804 int c[] = { x0 - 3, y0 - 3, x0, y0, x0 + 3, y0 - 3 };
805 gc.fillPolygon(c);
806 }
807
808 // TODO: CC:
809 // private void drawExecEvent(Rectangle bound, TsfTmTraceExecEventImpl e,
810 // int nitem, int color, GC gc) {
811 // List runnings = e.getRunningEvents();
812 // if (runnings == null)
813 // return;
814 //
815 // int nameWidth = _timeProvider.getNameSpace();
816 //
817 // double time0 = _timeProvider.getTime0();
818 // double time1 = _timeProvider.getTime1();
819 // if (time0 == time1)
820 // return;
821 //
822 // int xr = bound.x + nameWidth;
823 // double K = (double) (bound.width - xr) / (time1 - time0);
824 //
825 // int x0 = xr + (int) ((e.getTime() - time0) * K);
826 // if (x0 < xr)
827 // x0 = xr;
828 //
829 // Iterator it = runnings.iterator();
830 // while (it.hasNext()) {
831 // TsfTmTraceRunningEventImpl re = (TsfTmTraceRunningEventImpl) it
832 // .next();
833 // int tid = re.getThread().getId();
834 // if (tid < 0 || getThreadNumber(tid) == -1)
835 // continue;
836 //
837 // int x1 = xr + (int) ((re.getTime() - time0) * K);
838 // if (x1 < xr)
839 // continue;
840 //
841 // int y0 = bound.y + (nitem - _topItem) * _itemHeight + 3
842 // + (_itemHeight - 6) / 2;
843 // int y1 = bound.y + (getThreadNumber(tid) - _topItem) * _itemHeight
844 // + 3 + (_itemHeight - 6) / 2;
845 //
846 // drawArrow(gc, x0, y0, x1, y1, _colors.getColor(color));
847 // }
848 // }
849
850 public void drawTraceInteractions(Rectangle bound, GC gc) {
851 // int nameWidth = _timeProvider.getNameSpace();
852 // Object[] items = _data._items;
853 //
854 // double time0 = _timeProvider.getTime0();
855 // double time1 = _timeProvider.getTime1();
856 //
857 // if (time0 == time1)
858 // return;
859 //
860 // int xr = bound.x + nameWidth;
861 // double K = (double) (bound.width - xr) / (time1 - time0);
862
863 // for (int i = 0; i < items.length; i++) {
864 // Item item = (Item) items[i];
865 // if (!(item instanceof TraceItem))
866 // continue;
867 //
868 // TsfTmTrace trace = ((TraceItem) item)._trace;
869 // if (trace == null)
870 // continue;
871 //
872 // List<TsfTmEvent> list = trace.getTraceEvents();
873 // Iterator<TsfTmEvent> it = list.iterator();
874 // while (it.hasNext()) {
875 // TsfTmEvent te = (TsfTmEvent) it.next();
876 // TODO: CC: Thread Interactions,
877 // This needs to be accessed externally via a specific
878 // implementation.
879 // if (te instanceof TsfTmTraceStartThreadEventImpl) {
880 // TsfTmTrace child = ((TsfTmTraceStartThreadEventImpl) te)
881 // .getStartedThread();
882 // drawThreadThreadEvent(bound, te, child, i,
883 // TraceColorScheme.TI_START_THREAD, gc);
884 // } else if (te instanceof TsfTmTraceHandoffLockEventImpl) {
885 // if (drawThreadReleases)
886 // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i,
887 // TraceColorScheme.TI_HANDOFF_LOCK, gc);
888 // } else if (te instanceof TsfTmTraceNotifyAllEventImpl) {
889 // if (drawThreadWaits)
890 // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i,
891 // TraceColorScheme.TI_NOTIFY_ALL, gc);
892 // } else if (te instanceof TsfTmTraceNotifyEventImpl) {
893 // if (drawThreadWaits)
894 // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i,
895 // TraceColorScheme.TI_NOTIFY, gc);
896 // } else if (te instanceof
897 // TsfTmTraceDeadAndNotifyJoinedEventImpl) {
898 // if (drawThreadJoins)
899 // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i,
900 // TraceColorScheme.TI_NOTIFY_JOINED, gc);
901 // } else if (te instanceof TsfTmTraceInterruptThreadEventImpl)
902 // {
903 // if (drawThreadWaits)
904 // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i,
905 // TraceColorScheme.TI_INTERRUPT, gc);
906 // } else if (te instanceof
907 // TsfTmTraceWaitTimeoutExceedEventImpl) {
908 // drawThreadEvent(bound, te, i,
909 // TraceColorScheme.TI_WAIT_EXCEEDED, gc);
910 // }
911 // }
912 // }
913 }
914
915 @Override
916 void paint(Rectangle bound, PaintEvent e) {
917 GC gc = e.gc;
918 gc.setBackground(_colors.getColor(TraceColorScheme.BACKGROUND));
919 drawBackground(gc, bound.x, bound.y, bound.width, bound.height);
920
921 if (bound.width < 2 || bound.height < 2 || null == _timeProvider)
922 return;
923
924 _idealNameWidth = 0;
925 int nameWidth = _timeProvider.getNameSpace();
926 long time0 = _timeProvider.getTime0();
927 long time1 = _timeProvider.getTime1();
928 long endTime = _timeProvider.getEndTime();
929 long selectedTime = _timeProvider.getSelectedTime();
930 // draw trace states
931 Object[] items = _data._items;
932 for (int i = _topItem; i < items.length; i++) {
933 Item item = (Item) items[i];
934
935 getNameRect(_rect0, bound, i, nameWidth);
936 if (_rect0.y >= bound.y + bound.height)
937 break;
938
939 if (item instanceof GroupItem) {
940 getStatesRect(_rect1, bound, i, nameWidth);
941 _rect0.width += _rect1.width;
942 drawName(item, _rect0, gc);
943 } else {
944 drawName(item, _rect0, gc);
945 }
946 getStatesRect(_rect0, bound, i, nameWidth);
947 drawItemDataDurations(item, _rect0, time0, time1, endTime, selectedTime, gc);
948 }
949
950 if (drawTracesInteraction)
951 drawTraceInteractions(bound, e.gc);
952
953 // draw empty name space background
954 if (_itemHeight * items.length < bound.height) {
955 gc.setBackground(_colors.getBkColor(false, false, true));
956 drawBackground(gc, bound.x, _itemHeight * items.length, nameWidth, bound.height - _itemHeight * items.length);
957 }
958
959 // draw drag line, no line if name space is 0.
960 if (DRAG_SPLIT_LINE == _dragState) {
961 gc.setForeground(_colors.getColor(TraceColorScheme.BLACK));
962 gc.drawLine(bound.x + nameWidth, bound.y, bound.x + nameWidth, bound.y + bound.height - 1);
963 } else if (DRAG_NONE == _dragState && _mouseHover && _timeProvider.getNameSpace() > 0) {
964 gc.setForeground(_colors.getColor(TraceColorScheme.RED));
965 gc.drawLine(bound.x + nameWidth, bound.y, bound.x + nameWidth, bound.y + bound.height - 1);
966 }
967 }
968
969 void drawName(Item item, Rectangle rect, GC gc) {
970 // No name to be drawn
971 if (_timeProvider.getNameSpace() == 0)
972 return;
973 boolean group = item instanceof GroupItem;
974
975 int elemHeight = rect.height / 2;
976 int elemWidth = elemHeight;
977 String name = item._name;
978 if (group) {
979 gc.setBackground(_colors.getBkColorGroup(item._selected, _isInFocus));
980 gc.fillRectangle(rect);
981 if (item._selected && _isInFocus) {
982 gc.setForeground(_colors.getBkColor(item._selected, _isInFocus, false));
983 gc.drawRectangle(rect.x, rect.y, rect.width - 2, rect.height - 2);
984 }
985 gc.setForeground(_colors.getBkColor(false, false, false));
986 gc.drawLine(rect.x, rect.y + rect.height - 1, rect.width - 1, rect.y + rect.height - 1);
987 gc.setForeground(_colors.getFgColorGroup(false, false));
988 gc.setBackground(_colors.getBkColor(false, false, false));
989 Utils.init(_rect1, rect);
990 _rect1.x += MARGIN;
991 _rect1.y += (rect.height - elemHeight) / 2;
992 _rect1.width = elemWidth;
993 _rect1.height = elemHeight;
994 // Get the icon rectangle in the group items
995 gc.fillRectangle(_rect1);
996 gc.drawRectangle(_rect1.x, _rect1.y, _rect1.width - 1, _rect1.height - 1);
997 int p = _rect1.y + _rect1.height / 2;
998 gc.drawLine(_rect1.x + 2, p, _rect1.x + _rect1.width - 3, p);
999 if (!item._expanded) {
1000 p = _rect1.x + _rect1.width / 2;
1001 gc.drawLine(p, _rect1.y + 2, p, _rect1.y + _rect1.height - 3);
1002 }
1003 gc.setForeground(_colors.getFgColorGroup(item._selected, _isInFocus));
1004 elemWidth += MARGIN;
1005 } else {
1006 gc.setBackground(_colors.getBkColor(item._selected, _isInFocus, true));
1007 gc.setForeground(_colors.getFgColor(item._selected, _isInFocus));
1008 gc.fillRectangle(rect);
1009 Utils.init(_rect1, rect);
1010 _rect1.x += MARGIN;
1011 // draw icon
1012 ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace;
1013 Image img = utilImpl.getItemImage(trace);
1014 if (null != img) {
1015 _rect1.y += (rect.height - img.getImageData().height) / 2;
1016 gc.drawImage(img, _rect1.x, _rect1.y);
1017 }
1018 elemWidth = SMALL_ICON_SIZE;
1019 // cut long string with "..."
1020 Point size = gc.stringExtent(name);
1021 if (_idealNameWidth < size.x)
1022 _idealNameWidth = size.x;
1023 int width = rect.width - MARGIN - MARGIN - elemWidth;
1024 int cuts = 0;
1025 while (size.x > width && name.length() > 1) {
1026 cuts++;
1027 name = name.substring(0, name.length() - 1);
1028 size = gc.stringExtent(name + "..."); //$NON-NLS-1$
1029 }
1030 if (cuts > 0)
1031 name += "..."; //$NON-NLS-1$
1032 elemWidth += MARGIN;
1033 }
1034 Utils.init(_rect1, rect);
1035 int leftMargin = MARGIN + elemWidth;
1036 _rect1.x += leftMargin;
1037 _rect1.width -= leftMargin;
1038 int textWidth = 0;
1039 // draw text
1040 if (_rect1.width > 0) {
1041 _rect1.y += 2;
1042 textWidth = Utils.drawText(gc, name, _rect1, true) + 8;
1043 _rect1.y -= 2;
1044 }
1045 // draw middle line
1046 if (_rect1.width > 0 && !group) {
1047 Utils.init(_rect1, rect);
1048 _rect1.x += leftMargin + textWidth;
1049 _rect1.width -= textWidth;
1050 gc.setForeground(_colors.getColor(TraceColorScheme.MID_LINE));
1051 int midy = _rect1.y + _rect1.height / 2;
1052 gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy);
1053 }
1054 // gc.drawLine(_rect1.x + _rect1.width - 1, _rect1.y, _rect1.x +
1055 // _rect1.width - 1, _rect1.y + _rect1.height);
1056 }
1057
1058 void drawItemData(Item item, Rectangle rect, long time0, long time1, long endTime, long selectedTime, GC gc) {
1059 if (rect.isEmpty())
1060 return;
1061 if (time1 <= time0) {
1062 gc.setBackground(_colors.getBkColor(false, false, false));
1063 gc.fillRectangle(rect);
1064 return;
1065 }
1066
1067 Utils.init(_rect1, rect);
1068 boolean selected = item._selected;
1069 double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0);
1070 boolean group = item instanceof GroupItem;
1071
1072 if (group) {
1073 // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus));
1074 // gc.fillRectangle(rect);
1075 } else if (item instanceof TraceItem) {
1076 ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace;
1077
1078 int x0 = rect.x;
1079 Iterator<ITimeEvent> iterator = trace.getTraceEventsIterator();
1080 ITimeEvent lastEvent = null;
1081 if (iterator.hasNext()) {
1082 ITimeEvent currEvent = iterator.next();
1083 ITimeEvent nextEvent = null;
1084 long currEventTime = currEvent.getTime();
1085 long nextEventTime = currEventTime;
1086 x0 = rect.x + (int) ((currEventTime - time0) * pixelsPerNanoSec);
1087 int xEnd = rect.x + (int) ((time1 - time0) * pixelsPerNanoSec);
1088 int x1 = -1;
1089
1090 // reduce rect
1091 _rect1.y += 3;
1092 _rect1.height -= 6;
1093 fillSpace(rect, gc, selected);
1094
1095 // draw event states
1096 while (x0 <= xEnd && null != currEvent) {
1097 boolean stopped = false;// currEvent instanceof
1098 // TsfTmTraceDeadEvent;
1099 if (iterator.hasNext()) {
1100 nextEvent = iterator.next();
1101 nextEventTime = nextEvent.getTime();
1102 } else if (stopped) {
1103 nextEvent = null;
1104 nextEventTime = time1;
1105 } else {
1106 nextEvent = null;
1107 nextEventTime = endTime;
1108 }
1109 x1 = rect.x + (int) ((nextEventTime - time0) * pixelsPerNanoSec);
1110 if (x1 >= rect.x) {
1111 _rect1.x = x0 >= rect.x ? x0 : rect.x;
1112 _rect1.width = (x1 <= xEnd ? x1 : xEnd) - _rect1.x;
1113 boolean timeSelected = currEventTime <= selectedTime && selectedTime < nextEventTime;
1114 // Trace.debug("Drawing rectangle: " + _rect1.x + ","
1115 // + _rect1.y + "," + _rect1.height + ", "
1116 // + _rect1.width + "-->"
1117 // + ((int) _rect1.x + (int) _rect1.width));
1118 utilImpl.drawState(_colors, currEvent, _rect1, gc, selected, false, timeSelected);
1119 }
1120 lastEvent = currEvent;
1121 currEvent = nextEvent;
1122 currEventTime = nextEventTime;
1123 x0 = x1;
1124 }
1125 }
1126
1127 // fill space after last event
1128 int xEnd = rect.x + rect.width;
1129 if (x0 < xEnd) {
1130 _rect1.x = x0 >= rect.x ? x0 : rect.x;
1131 _rect1.width = xEnd - _rect1.x;
1132 gc.setBackground(_colors.getBkColor(selected, _isInFocus, false));
1133 gc.fillRectangle(_rect1);
1134 // draw middle line
1135 gc.setForeground(_colors.getColor(utilImpl.getEventColorVal(lastEvent)));
1136 int midy = _rect1.y + _rect1.height / 2;
1137 int lw = gc.getLineWidth();
1138 gc.setLineWidth(2);
1139 gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy);
1140 gc.setLineWidth(lw);
1141 }
1142 }
1143
1144 // draw selected time
1145 int x = rect.x + (int) ((selectedTime - time0) * pixelsPerNanoSec);
1146 if (x >= rect.x && x < rect.x + rect.width) {
1147 gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME));
1148 if (group)
1149 gc.drawLine(x, rect.y + rect.height - 1, x, rect.y + rect.height);
1150 else
1151 gc.drawLine(x, rect.y, x, rect.y + rect.height);
1152 }
1153 }
1154
1155 /**
1156 * Represent the event in series of bursts rather than sequence of states
1157 *
1158 * @param item
1159 * @param rect
1160 * - The container rectangle to be colored to different states
1161 * @param time0
1162 * - Base time of all events
1163 * @param time1
1164 * - End time of all events
1165 * @param endTime
1166 * @param selectedTime
1167 * @param gc
1168 */
1169 void drawItemDataBurst(Item item, Rectangle rect, long time0, long time1, long endTime, long selectedTime, GC gc) {
1170 if (rect.isEmpty())
1171 return;
1172 if (time1 <= time0) {
1173 gc.setBackground(_colors.getBkColor(false, false, false));
1174 gc.fillRectangle(rect);
1175 return;
1176 }
1177
1178 // Initialize _rect1 to same values as enclosing rectangle rect
1179 Utils.init(_rect1, rect);
1180 boolean selected = item._selected;
1181 // K pixels per second
1182 double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0);
1183 // Trace.debug("Value of K: " + K + " width:" + rect.width + " time0: "
1184 // + time0 + " time1:" + time1 + " endTime: " + endTime);
1185
1186 boolean group = item instanceof GroupItem;
1187
1188 if (group) {
1189 // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus));
1190 // gc.fillRectangle(rect);
1191 // if (Trace.isDEBUG()) {
1192 // Trace.debug("Group");
1193 // }
1194 } else if (item instanceof TraceItem) {
1195 ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace;
1196
1197 double x0 = rect.x;
1198 Iterator<ITimeEvent> iterator = trace.getTraceEventsIterator();
1199 ITimeEvent lastEvent = null;
1200 // Trace.debug("count is: " + count);
1201 if (iterator.hasNext()) {
1202 ITimeEvent currEvent = iterator.next();
1203 ITimeEvent nextEvent = null;
1204 long currEventTime = currEvent.getTime();
1205 long nextEventTime = currEventTime;
1206 // x0 - Points to the beginning of the event being drawn
1207 double step = (double) ((currEventTime - time0) * pixelsPerNanoSec);
1208 x0 = rect.x + step;
1209 // xEnd - Points to the end of the events rectangle
1210 double xEnd = rect.x + (double) ((time1 - time0) * pixelsPerNanoSec);
1211 double x1 = -1;
1212 //double xNext = 0;
1213
1214 // Drawing rectangle is smaller than reserved space
1215 _rect1.y += 3;
1216 _rect1.height -= 6;
1217
1218 // Clean up to empty line to draw on top
1219 fillSpace(rect, gc, selected);
1220 // draw event states
1221 while (x0 <= xEnd && null != currEvent) {
1222 boolean stopped = false;// currEvent instanceof
1223 // TsfTmTraceDeadEvent;
1224 if (iterator.hasNext()) {
1225 nextEvent = iterator.next();
1226 nextEventTime = nextEvent.getTime();
1227 } else if (stopped) {
1228 nextEvent = null;
1229 nextEventTime = time1;
1230 } else {
1231 nextEvent = null;
1232 nextEventTime = endTime;
1233 // Trace
1234 // .debug("nexEventTime is endTime: "
1235 // + nextEventTime);
1236 }
1237
1238 // Draw it as a burst, one unit of width.
1239 x1 = x0 + (int) 2;
1240 if (x1 >= rect.x && x0 <= xEnd) {
1241 // Fill with space until x0
1242 _rect1.x = (int) (x0 >= rect.x ? x0 : rect.x);
1243 _rect1.width = (int) ((x1 <= xEnd ? x1 : xEnd) - _rect1.x);
1244 boolean timeSelected = currEventTime <= selectedTime && selectedTime < nextEventTime;
1245 utilImpl.drawState(_colors, currEvent, _rect1, gc, selected, false, timeSelected);
1246 // Trace.debug("Drawing rectangle: " + _rect1.x + ","
1247 // + _rect1.y + "," + _rect1.height + ", "
1248 // + _rect1.width + "-->"
1249 // + ((int) _rect1.x + (int) _rect1.width));
1250 // Advance rectangle to next start position and Fill
1251 // with space until next event
1252 _rect1.x += _rect1.width;
1253 x0 = x1;
1254 //xNext = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec);
1255 }
1256 // Fill space till next event
1257 fillSpace(rect, gc, selected);
1258
1259 lastEvent = currEvent;
1260 currEvent = nextEvent;
1261 currEventTime = nextEventTime;
1262 // Move x0 to the beginning of next event
1263 x0 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec);
1264 // Trace.debug("rect.x: " + rect.x + " + " +
1265 // "(nextEvenTime: "
1266 // + nextEventTime + "- time0: " + time0 + ") * K: "
1267 // + K + " = " + x0);
1268 }
1269 }
1270
1271 // fill space after last event
1272 int xEnd = rect.x + rect.width;
1273 if (x0 < xEnd) {
1274 // Trace.debug("Space after last event, x0: " + x0 + ", xEnd: "
1275 // + xEnd);
1276 _rect1.x = (int) (x0 >= rect.x ? x0 : rect.x);
1277 _rect1.width = xEnd - _rect1.x;
1278 gc.setBackground(_colors.getBkColor(selected, _isInFocus, false));
1279 gc.fillRectangle(_rect1);
1280 // draw middle line
1281 gc.setForeground(_colors.getColor(utilImpl.getEventColorVal(lastEvent)));
1282 int midy = _rect1.y + _rect1.height / 2;
1283 int lw = gc.getLineWidth();
1284 gc.setLineWidth(2);
1285 gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy);
1286 gc.setLineWidth(lw);
1287 }
1288 }
1289
1290 // draw selected time
1291 int x = rect.x + (int) ((selectedTime - time0) * pixelsPerNanoSec);
1292 if (x >= rect.x && x < rect.x + rect.width) {
1293 gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME));
1294 if (group)
1295 gc.drawLine(x, rect.y + rect.height - 1, x, rect.y + rect.height);
1296 else
1297 gc.drawLine(x, rect.y, x, rect.y + rect.height);
1298 }
1299 }
1300
1301 /**
1302 * Represent the series of events with specified durations
1303 *
1304 * @param item
1305 * @param rect
1306 * - The container rectangle to be colored to different states
1307 * @param time0
1308 * - Base time of all events - start of visible window
1309 * @param time1
1310 * - End time of visible events - end time of visible window
1311 * @param endTime
1312 * - End time of all events - may not be visible in selected
1313 * visible window
1314 * @param selectedTime
1315 * @param gc
1316 */
1317 void drawItemDataDurations(Item item, Rectangle rect, long time0, long time1, long endTime, long selectedTime, GC gc) {
1318 if (rect.isEmpty())
1319 return;
1320 if (time1 <= time0) {
1321 gc.setBackground(_colors.getBkColor(false, false, false));
1322 gc.fillRectangle(rect);
1323 return;
1324 }
1325
1326 // Initialize _rect1 to same values as enclosing rectangle rect
1327 Utils.init(_rect1, rect);
1328 boolean selected = item._selected;
1329 // K pixels per second
1330 double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0);
1331 // Trace.debug("Value of K: " + K + " width:" + rect.width + " time0: "
1332 // + time0 + " time1:" + time1 + " endTime: " + endTime);
1333
1334 boolean group = item instanceof GroupItem;
1335
1336 if (group) {
1337 // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus));
1338 // gc.fillRectangle(rect);
1339 } else if (item instanceof TraceItem) {
1340 ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace;
1341
1342 double x0 = rect.x;
1343 long maxDuration = (_timeProvider.getTimeSpace() == 0) ? Long.MAX_VALUE : 1 * (_timeProvider.getTime1() - _timeProvider.getTime0()) / _timeProvider.getTimeSpace();
1344 Iterator<ITimeEvent> iterator = trace.getTraceEventsIterator(_timeProvider.getTime0(), _timeProvider.getTime1(), maxDuration);
1345 // ITimeEvent lastEvent = null;
1346 // if (Trace.isDEBUG()) {
1347 // Trace.debug("\n\t\t\tTrace: " + trace.getName()
1348 // + utilImpl.getTraceClassName(trace));
1349 // }
1350 // Trace.debug("count is: " + count);
1351 // Drawing rectangle is smaller than reserved space
1352 _rect1.y += 3;
1353 _rect1.height -= 6;
1354
1355 // Clean up to empty line to draw on top
1356 int xEnd = rect.x + rect.width;
1357 fillSpace(rect, gc, selected);
1358 if (iterator.hasNext()) {
1359 ITimeEvent currEvent = iterator.next();
1360 ITimeEvent nextEvent = null;
1361 long currEventTime = currEvent.getTime();
1362 long currEventDuration = currEvent.getDuration();
1363 // initial value
1364 long nextEventTime = currEventTime;
1365 // x0 - Points to the beginning of the event being drawn
1366 double step = (double) ((currEventTime - time0) * pixelsPerNanoSec);
1367 x0 = rect.x + step;
1368 // xEnd - Points to the end of the events rectangle
1369 double x1 = -1;
1370 double xNext = 0;
1371
1372 // draw event states
1373 while (/* x0 <= xEnd && */null != currEvent) {
1374 boolean stopped = false;// currEvent instanceof
1375 // refresh current event duration as the loop moves
1376 currEventDuration = currEvent.getDuration();
1377 // TsfTmTraceDeadEvent;
1378 if (iterator.hasNext()) {
1379 nextEvent = iterator.next();
1380 nextEventTime = nextEvent.getTime();
1381 } else if (stopped) {
1382 nextEvent = null;
1383 nextEventTime = time1;
1384 } else {
1385 nextEvent = null;
1386 nextEventTime = endTime;
1387 // Trace
1388 // .debug("nexEventTime is endTime: "
1389 // + nextEventTime);
1390 }
1391
1392 // Calculate position to next event
1393 xNext = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec);
1394
1395 // Calculate end position of current event
1396 if (currEventDuration < 0) {
1397 x1 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec);
1398 } else if (currEventDuration == 0) {
1399 x1 = x0;
1400 } else {
1401 x1 = x0 + (double) ((currEventDuration) * pixelsPerNanoSec);
1402 }
1403
1404 // If event end position x1 further away than start position
1405 // of
1406 // next event, cut width till next event
1407 // Trace.debug("Next Event Pos: " + xNext
1408 // + " End Of Current at: " + x1 + " Event Duration: "
1409 // + currEventDuration);
1410 if (currEventDuration != 0) {
1411 x1 = x1 > xNext ? xNext : x1;
1412 }
1413 // if event end boundary is within time range
1414 if (x1 >= rect.x && x0 <= xEnd) {
1415 if (currEventDuration != 0) {
1416 x0 = (double) (x0 >= rect.x ? x0 : rect.x);
1417 _rect1.width = (int) ((x1 <= xEnd ? x1 : xEnd) - x0);
1418 } else {
1419 _rect1.width = 1;
1420 }
1421 _rect1.width = Math.max(_minimumItemWidth, _rect1.width);
1422 _rect1.x = (int) x0;
1423 boolean timeSelected = currEventTime <= selectedTime && selectedTime < nextEventTime;
1424 utilImpl.drawState(_colors, currEvent, _rect1, gc, selected, false, timeSelected);
1425 // Trace.debug("Drawing rectangle: " + _rect1.x + ","
1426 // + _rect1.y + "," + _rect1.height + ", "
1427 // + _rect1.width + "-->"
1428 // + ((int) _rect1.x + (int) _rect1.width));
1429 // Advance rectangle to next start position and Fill
1430 // with space until next event
1431 _rect1.x += _rect1.width;
1432 x0 = _rect1.x;
1433 }
1434
1435 // Fill space till next event
1436 // fillSpace(rect, gc, selected, x0, xNext, xEnd);
1437
1438 // lastEvent = currEvent;
1439 currEvent = nextEvent;
1440 currEventTime = nextEventTime;
1441 // Move x0 to the beginning of next event
1442 x0 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec);
1443 // Trace.debug("rect.x: " + rect.x + " + " +
1444 // "(nextEvenTime: "
1445 // + nextEventTime + "- time0: " + time0 + ") * K: "
1446 // + K + " = " + x0);
1447 }
1448 }
1449 }
1450
1451 // draw selected time
1452 int x = rect.x + (int) ((double) (selectedTime - time0) * pixelsPerNanoSec);
1453 if (x >= rect.x && x < rect.x + rect.width) {
1454 gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME));
1455 if (group)
1456 gc.drawLine(x, rect.y + rect.height - 1, x, rect.y + rect.height);
1457 else
1458 gc.drawLine(x, rect.y, x, rect.y + rect.height);
1459 }
1460 }
1461
1462 private void fillSpace(Rectangle rect, GC gc, boolean selected) {
1463 gc.setBackground(_colors.getBkColor(selected, _isInFocus, false));
1464 gc.fillRectangle(rect);
1465 // draw middle line
1466 gc.setForeground(_colors.getColor(TraceColorScheme.MID_LINE));
1467 int midy = rect.y + rect.height / 2;
1468 gc.drawLine(rect.x, midy, rect.x + rect.width, midy);
1469 }
1470
1471 @Override
1472 public void keyTraversed(TraverseEvent e) {
1473 if ((e.detail == SWT.TRAVERSE_TAB_NEXT) || (e.detail == SWT.TRAVERSE_TAB_PREVIOUS))
1474 e.doit = true;
1475 }
1476
1477 @Override
1478 public void keyPressed(KeyEvent e) {
1479 int idx = -1;
1480 if (SWT.HOME == e.keyCode) {
1481 idx = getTopIndex();
1482 } else if (SWT.END == e.keyCode) {
1483 idx = getBottomIndex();
1484 } else if (SWT.ARROW_DOWN == e.keyCode) {
1485 idx = getSelectedIndex();
1486 if (idx < 0)
1487 idx = 0;
1488 else if (idx < _data._items.length - 1)
1489 idx++;
1490 } else if (SWT.ARROW_UP == e.keyCode) {
1491 idx = getSelectedIndex();
1492 if (idx < 0)
1493 idx = 0;
1494 else if (idx > 0)
1495 idx--;
1496 } else if (SWT.ARROW_LEFT == e.keyCode) {
1497 selectPrevEvent();
1498 } else if (SWT.ARROW_RIGHT == e.keyCode) {
1499 selectNextEvent();
1500 } else if (SWT.PAGE_DOWN == e.keyCode) {
1501 int page = countPerPage();
1502 idx = getSelectedIndex();
1503 if (idx < 0)
1504 idx = 0;
1505 idx += page;
1506 if (idx >= _data._items.length)
1507 idx = _data._items.length - 1;
1508 } else if (SWT.PAGE_UP == e.keyCode) {
1509 int page = countPerPage();
1510 idx = getSelectedIndex();
1511 if (idx < 0)
1512 idx = 0;
1513 idx -= page;
1514 if (idx < 0)
1515 idx = 0;
1516 } else if (SWT.CR == e.keyCode) {
1517 idx = getSelectedIndex();
1518 if (idx >= 0) {
1519 if (_data._items[idx] instanceof TraceItem)
1520 fireDefaultSelection();
1521 else if (_data._items[idx] instanceof GroupItem)
1522 toggle(idx);
1523 }
1524 idx = -1;
1525 }
1526 if (idx >= 0) {
1527 selectItem(idx, false);
1528 fireSelectionChanged();
1529 }
1530 }
1531
1532 @Override
1533 public void keyReleased(KeyEvent e) {
1534 }
1535
1536 @Override
1537 public void focusGained(FocusEvent e) {
1538 _isInFocus = true;
1539 redraw();
1540 if (mouseScrollFilterListener == null) {
1541 mouseScrollFilterListener = new Listener() {
1542 // This filter is used to prevent scrolling of the view when the
1543 // mouse wheel is used to zoom
1544 @Override
1545 public void handleEvent(Event event) {
1546 event.doit = false;
1547 }
1548 };
1549 getDisplay().addFilter(SWT.MouseWheel, mouseScrollFilterListener);
1550 }
1551 }
1552
1553 @Override
1554 public void focusLost(FocusEvent e) {
1555 _isInFocus = false;
1556 if (DRAG_NONE != _dragState) {
1557 setCapture(false);
1558 _dragState = DRAG_NONE;
1559 }
1560 redraw();
1561 if (mouseScrollFilterListener != null) {
1562 getDisplay().removeFilter(SWT.MouseWheel, mouseScrollFilterListener);
1563 mouseScrollFilterListener = null;
1564 }
1565 }
1566
1567 public boolean isInFocus() {
1568 return _isInFocus;
1569 }
1570
1571 @Override
1572 public void mouseMove(MouseEvent e) {
1573 if (null == _timeProvider)
1574 return;
1575 Point size = getCtrlSize();
1576 if (DRAG_TRACE_ITEM == _dragState) {
1577 int nameWidth = _timeProvider.getNameSpace();
1578 int x = e.x - nameWidth;
1579 if (x > 0 && size.x > nameWidth && _dragX != x) {
1580 _dragX = x;
1581 double pixelsPerNanoSec = (size.x - nameWidth <= RIGHT_MARGIN) ? 0 : (double) (size.x - nameWidth - RIGHT_MARGIN) / (_time1bak - _time0bak);
1582 long timeDelta = (long) ((pixelsPerNanoSec == 0) ? 0 : ((_dragX - _dragX0) / pixelsPerNanoSec));
1583 long time1 = _time1bak - timeDelta;
1584 long maxTime = _timeProvider.getMaxTime();
1585 if (time1 > maxTime)
1586 time1 = maxTime;
1587 long time0 = time1 - (_time1bak - _time0bak);
1588 if (time0 < _timeProvider.getMinTime()) {
1589 time0 = _timeProvider.getMinTime();
1590 time1 = time0 + (_time1bak - _time0bak);
1591 }
1592 _timeProvider.setStartFinishTime(time0, time1);
1593 }
1594 } else if (DRAG_SPLIT_LINE == _dragState) {
1595 _dragX = e.x;
1596 _timeProvider.setNameSpace(_hitIdx + _dragX - _dragX0);
1597 } else if (DRAG_NONE == _dragState) {
1598 boolean mouseHover = hitSplitTest(e.x, e.y) > 0;
1599 if (_mouseHover != mouseHover)
1600 redraw();
1601 _mouseHover = mouseHover;
1602 // Make sure any time changes are notified to the application e.g.
1603 // getting back from the horizontal scroll bar or zoomed using the
1604 // mouse wheel
1605 _timeProvider.notifyStartFinishTime();
1606 }
1607 updateCursor(e.x, e.y);
1608 }
1609
1610 @Override
1611 public void mouseDoubleClick(MouseEvent e) {
1612 if (null == _timeProvider)
1613 return;
1614 if (1 == e.button) {
1615 int idx = hitSplitTest(e.x, e.y);
1616 if (idx >= 0) {
1617 _timeProvider.setNameSpace(_idealNameWidth + 3 * MARGIN + SMALL_ICON_SIZE);
1618 return;
1619 }
1620 idx = hitTest(e.x, e.y);
1621 if (idx >= 0) {
1622 selectItem(idx, false);
1623 if (_data._items[idx] instanceof TraceItem) {
1624 fireDefaultSelection();
1625 }
1626 }
1627 }
1628 }
1629
1630 /**
1631 * <p>
1632 * If the x, y position is over the vertical split line (name to time
1633 * ranges), then change the cursor to a drag cursor to indicate the user the
1634 * possibility of resizing
1635 * </p>
1636 *
1637 * @param x
1638 * @param y
1639 */
1640 void updateCursor(int x, int y) {
1641 // if Wait cursor not active, check for the need to change to a drag
1642 // cursor
1643 if (_isWaitCursor == false) {
1644 int idx = hitSplitTest(x, y);
1645 // No dragcursor is name space is fixed to zero
1646 if (idx > 0 && !_isDragCursor3 && _timeProvider.getNameSpace() > 0) {
1647 setCursor(_dragCursor3);
1648 _isDragCursor3 = true;
1649 } else if (idx <= 0 && _isDragCursor3) {
1650 setCursor(null);
1651 _isDragCursor3 = false;
1652 }
1653 }
1654 }
1655
1656 /**
1657 * Provide the possibilty to control the wait cursor externally e.g. data
1658 * requests in progress
1659 *
1660 * @param waitInd
1661 */
1662 public void waitCursor(boolean waitInd) {
1663 // Update cursor as indicated
1664 if (waitInd) {
1665 setCursor(_WaitCursor);
1666 _isWaitCursor = true;
1667 } else {
1668 setCursor(null);
1669 _isWaitCursor = false;
1670 }
1671
1672 // Get ready for next mouse move
1673 _isDragCursor3 = false;
1674 }
1675
1676 @Override
1677 public void mouseDown(MouseEvent e) {
1678 if (null == _timeProvider)
1679 return;
1680 int idx;
1681 if (1 == e.button) {
1682 int namewidth = _timeProvider.getNameSpace();
1683 if (namewidth != 0) {
1684 idx = hitSplitTest(e.x, e.y);
1685 if (idx > 0) {
1686 _dragState = DRAG_SPLIT_LINE;
1687 _dragX = _dragX0 = e.x;
1688 _hitIdx = _timeProvider.getNameSpace();
1689 ;
1690 _time0bak = _timeProvider.getTime0();
1691 _time1bak = _timeProvider.getTime1();
1692 redraw();
1693 return;
1694 }
1695 }
1696
1697 idx = hitTest(e.x, e.y);
1698 if (idx >= 0) {
1699 if (_data._items[idx] instanceof TraceItem) {
1700 long hitTime = hitTimeTest(e.x);
1701 if (hitTime >= 0) {
1702 // _timeProvider.setSelectedTimeInt(hitTime, false);
1703 setCapture(true);
1704 _dragState = DRAG_TRACE_ITEM;
1705 _dragX = _dragX0 = e.x - _timeProvider.getNameSpace();
1706 _hitIdx = idx;
1707 _time0bak = _timeProvider.getTime0();
1708 _time1bak = _timeProvider.getTime1();
1709 return;
1710 }
1711 } else if (_data._items[idx] instanceof GroupItem) {
1712 _dragX0 = e.x;
1713 _dragState = DRAG_GROUP_ITEM;
1714 }
1715 selectItem(idx, false);
1716 fireSelectionChanged();
1717 } else {
1718 selectItem(idx, false); // clear selection
1719 redraw();
1720 }
1721 }
1722 }
1723
1724 @Override
1725 public void mouseUp(MouseEvent e) {
1726 if (DRAG_NONE != _dragState) {
1727 setCapture(false);
1728 if (DRAG_TRACE_ITEM == _dragState) {
1729 // Notify time provider to check the need for listener
1730 // notification
1731 _timeProvider.notifyStartFinishTime();
1732 if (_dragX == _dragX0) { // click without drag
1733 long time = hitTimeTest(e.x);
1734 _timeProvider.setSelectedTimeInt(time, false);
1735 selectItem(_hitIdx, false);
1736 fireSelectionChanged();
1737 }
1738 } else if (DRAG_GROUP_ITEM == _dragState) {
1739 if (e.x == _dragX0) // click without drag
1740 toggle(_hitIdx);
1741 } else if (DRAG_SPLIT_LINE == _dragState) {
1742 redraw();
1743 }
1744 _dragState = DRAG_NONE;
1745 }
1746 }
1747
1748 @Override
1749 public void controlMoved(ControlEvent e) {
1750 }
1751
1752 @Override
1753 public void controlResized(ControlEvent e) {
1754 adjustScrolls();
1755 }
1756
1757 @Override
1758 public void widgetDefaultSelected(SelectionEvent e) {
1759 }
1760
1761 @Override
1762 public void widgetSelected(SelectionEvent e) {
1763 if (e.widget == getVerticalBar()) {
1764 _topItem = getVerticalBar().getSelection();
1765 if (_topItem < 0)
1766 _topItem = 0;
1767 redraw();
1768 } else if (e.widget == getHorizontalBar() && null != _timeProvider) {
1769 int start = getHorizontalBar().getSelection();
1770 long time0 = _timeProvider.getTime0();
1771 long time1 = _timeProvider.getTime1();
1772 long timeMin = _timeProvider.getMinTime();
1773 long timeMax = _timeProvider.getMaxTime();
1774 long delta = timeMax - timeMin;
1775
1776 long range = time1 - time0;
1777 // _timeRangeFixed = true;
1778 time0 = timeMin + (long) (delta * ((double) start / H_SCROLLBAR_MAX));
1779 time1 = time0 + range;
1780
1781 // TODO: Follow-up with Bug 310310
1782 // In Linux SWT.DRAG is the only value received
1783 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310310
1784 if (e.detail == SWT.DRAG) {
1785 _timeProvider.setStartFinishTime(time0, time1);
1786 } else {
1787 _timeProvider.setStartFinishTimeNotify(time0, time1);
1788 }
1789 }
1790 }
1791
1792 @Override
1793 public void mouseEnter(MouseEvent e) {
1794 }
1795
1796 @Override
1797 public void mouseExit(MouseEvent e) {
1798 if (_mouseHover) {
1799 _mouseHover = false;
1800 redraw();
1801 }
1802 }
1803
1804 @Override
1805 public void mouseHover(MouseEvent e) {
1806 }
1807
1808 @Override
1809 public void mouseScrolled(MouseEvent e) {
1810 if (!_isInFocus || _dragState != DRAG_NONE)
1811 return;
1812 if (e.count > 0) {
1813 zoom(true);
1814 } else if (e.count < 0) {
1815 zoom(false);
1816 }
1817 }
1818
1819 public boolean isVisibleVerticalScroll() {
1820 return _visibleVerticalScroll;
1821 }
1822
1823 public void setVisibleVerticalScroll(boolean visibleVerticalScroll) {
1824 ScrollBar scrollVer = getVerticalBar();
1825 if (scrollVer != null) {
1826 scrollVer.setVisible(visibleVerticalScroll);
1827 }
1828 this._visibleVerticalScroll = visibleVerticalScroll;
1829 }
1830
1831 @Override
1832 public int getBorderWidth() {
1833 return _borderWidth;
1834 }
1835
1836 public void setBorderWidth(int borderWidth) {
1837 this._borderWidth = borderWidth;
1838 }
1839
1840 public int getHeaderHeight() {
1841 return _headerHeight;
1842 }
1843
1844 public void setHeaderHeight(int headerHeight) {
1845 this._headerHeight = headerHeight;
1846 }
1847
1848 public int getItemHeight() {
1849 return _itemHeight;
1850 }
1851
1852 public void setItemHeight(int rowHeight) {
1853 this._itemHeight = rowHeight;
1854 }
1855
1856 public void setMinimumItemWidth(int width) {
1857 this._minimumItemWidth = width;
1858 }
1859
1860 public Vector<ITmfTimeAnalysisEntry> getFilteredOut() {
1861 return _data.getFilteredOut();
1862 }
1863
1864 // @Override
1865 @Override
1866 public void addSelectionChangedListener(ISelectionChangedListener listener) {
1867 if (listener != null) {
1868 if (!_selectionChangedListeners.contains(listener)) {
1869 _selectionChangedListeners.add(listener);
1870 }
1871 }
1872 }
1873
1874 // @Override
1875 @Override
1876 public void removeSelectionChangedListener(ISelectionChangedListener listener) {
1877 if (listener != null) {
1878 _selectionChangedListeners.remove(listener);
1879 }
1880 }
1881
1882 // @Override
1883 @Override
1884 public void setSelection(ISelection selection) {
1885 if (selection instanceof PlainSelection) {
1886 PlainSelection sel = (PlainSelection) selection;
1887 Object ob = sel.getFirstElement();
1888 if (ob instanceof ITmfTimeAnalysisEntry) {
1889 ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) ob;
1890 selectItem(trace, false);
1891 }
1892 }
1893
1894 }
1895 }
1896
1897 class Item {
1898 public boolean _expanded;
1899 public boolean _selected;
1900 public boolean _hasChildren;
1901 public String _name;
1902
1903 Item(String name) {
1904 _name = name;
1905 }
1906
1907 @Override
1908 public String toString() {
1909 return _name;
1910 }
1911 }
1912
1913 class TraceItem extends Item {
1914 public ITmfTimeAnalysisEntry _trace;
1915
1916 TraceItem(ITmfTimeAnalysisEntry trace, String name) {
1917 super(name);
1918 _trace = trace;
1919 }
1920 }
1921
1922 class GroupItem extends Item {
1923 public List<ITmfTimeAnalysisEntry> _traces;
1924
1925 GroupItem(String name) {
1926 super(name);
1927 _traces = new ArrayList<ITmfTimeAnalysisEntry>();
1928 _hasChildren = true;
1929 }
1930
1931 void add(ITmfTimeAnalysisEntry trace) {
1932 _traces.add(trace);
1933 }
1934 }
1935
1936 class ItemData {
1937 public Object[] _items = new Object[0];
1938 private Object _traces[] = new Object[0];
1939 private boolean traceFilter[] = new boolean[0];
1940 private Map<String, GroupItem> _groupTable = new HashMap<String, GroupItem>();
1941 private boolean _flatList = false;
1942 private TmfTimeAnalysisProvider utilsImp;
1943 private Vector<ITmfTimeAnalysisEntry> filteredOut = new Vector<ITmfTimeAnalysisEntry>();
1944
1945 public ItemData(TmfTimeAnalysisProvider utils) {
1946 this.utilsImp = utils;
1947 }
1948
1949 protected void groupTraces(boolean on) {
1950 if (_flatList == on) {
1951 _flatList = !on;
1952 updateItems();
1953 }
1954 }
1955
1956 void clearGroups() {
1957 Iterator<GroupItem> it = _groupTable.values().iterator();
1958 while (it.hasNext()) {
1959 GroupItem group = it.next();
1960 group._traces.clear();
1961 }
1962 }
1963
1964 void deleteEmptyGroups() {
1965 Iterator<GroupItem> it = _groupTable.values().iterator();
1966 while (it.hasNext()) {
1967 GroupItem group = it.next();
1968 if (group._traces.size() == 0)
1969 it.remove();
1970 }
1971 }
1972
1973 TraceItem findTraceItem(ITmfTimeAnalysisEntry trace) {
1974 if (trace == null)
1975 return null;
1976
1977 int traceId = trace.getId();
1978 TraceItem traceItem = null;
1979
1980 for (int i = 0; i < _items.length; i++) {
1981 Object item = _items[i];
1982 if (item instanceof TraceItem) {
1983 TraceItem ti = (TraceItem) item;
1984 if (ti._trace.getId() == traceId) {
1985 traceItem = ti;
1986 break;
1987 }
1988 }
1989 }
1990
1991 return traceItem;
1992 }
1993
1994 Integer findTraceItemIndex(ITmfTimeAnalysisEntry trace) {
1995 if (trace == null)
1996 return null;
1997
1998 for (int i = 0; i < _items.length; i++) {
1999 Object item = _items[i];
2000 if (item instanceof TraceItem) {
2001 TraceItem ti = (TraceItem) item;
2002 if (ti._trace == trace) {
2003 return i;
2004 }
2005 }
2006 }
2007
2008 return null;
2009 }
2010
2011 public void updateItems() {
2012 List<Item> itemList = new ArrayList<Item>();
2013 String name = ""; //$NON-NLS-1$
2014
2015 Iterator<GroupItem> it = _groupTable.values().iterator();
2016 while (it.hasNext()) {
2017 GroupItem group = it.next();
2018 if (!_flatList)
2019 itemList.add(group);
2020
2021 if (_flatList || group._expanded) {
2022 Iterator<ITmfTimeAnalysisEntry> it2 = group._traces.iterator();
2023 while (it2.hasNext()) {
2024 ITmfTimeAnalysisEntry trace = it2.next();
2025 TraceItem traceItem = findTraceItem(trace);
2026 name = utilsImp.composeTraceName(trace, false);
2027 traceItem = new TraceItem(trace, name);
2028 itemList.add(traceItem);
2029 }
2030 }
2031 }
2032 _items = itemList.toArray();
2033 }
2034
2035 public int expandItem(int idx, boolean expand) {
2036 if (idx < 0 || idx >= _items.length)
2037 return 0;
2038 int ret = 0;
2039 Item item = (Item) _items[idx];
2040 if (item._hasChildren && !item._expanded) {
2041 item._expanded = expand;
2042 ret = _items.length;
2043 updateItems();
2044 ret = _items.length - ret;
2045 }
2046 return ret;
2047 }
2048
2049 public void refreshData(Object traces[]) {
2050 if (traces == null || traces.length == 0) {
2051 traceFilter = null;
2052 } else if (traceFilter == null || traces.length != traceFilter.length) {
2053 traceFilter = new boolean[traces.length];
2054 java.util.Arrays.fill(traceFilter, true);
2055 }
2056
2057 _traces = traces;
2058 refreshData();
2059 }
2060
2061 /**
2062 * Allows to update the GUI from a stream of events handling addition one by
2063 * one over known TmfTaTrace parents.
2064 *
2065 * @param parent
2066 * @param childItem
2067 */
2068 public void refreshPartial(ITmfTimeAnalysisEntry parent, TimeEvent childItem) {
2069 // Find the Trace item within the current list
2070 // TraceItem item = findTraceItem(parent);
2071
2072 // This method is not used (yet) so this code can be commented out for
2073 // now
2074 // FIXME: Arrays.copyOf is a Java6 feature
2075 // if (item == null) {
2076 // // If the parent item is not found, make room for it in the current
2077 // // array
2078 // int length = 1;
2079 // Object[] traces;
2080 // if (_traces != null) {
2081 // length = _traces.length + 1;
2082 // traces = Arrays.copyOf(_traces, length);
2083 // } else {
2084 // traces = new Object[length];
2085 // }
2086 //
2087 // // Add the new parent element to the end of the array.
2088 // traces[length - 1] = parent;
2089 //
2090 // // update the filter array to accomodate a postion to the new
2091 // // element
2092 // traceFilter = new boolean[traces.length];
2093 // java.util.Arrays.fill(traceFilter, true);
2094 //
2095 // // rebuild internal data
2096 // _traces = traces;
2097 // refreshData();
2098 //
2099 // // item must be there
2100 // item = findTraceItem(parent);
2101 // }
2102
2103 /*
2104 * Check if this is still needed!
2105 ITmfTimeAnalysisEntry localTraceItem = item._trace;
2106 // Local trace found
2107 Vector<TimeEvent> children = localTraceItem.getTraceEvents();
2108 TimeEvent lastChildIn = children.lastElement();
2109 long lastChildSTime = lastChildIn.getTime();
2110 long newChildSTime = childItem.getTime();
2111 if (newChildSTime < lastChildSTime) {
2112 // The children are expected to arrive sorted by time
2113 // since the new time is earlier than the last child
2114 // The infomation is being refreshed from start, remove all
2115 // children and start over
2116 children.clear();
2117 }
2118 // Add the new item
2119 children.add(childItem);
2120 */
2121
2122 }
2123
2124 public void refreshData() {
2125 clearGroups();
2126 filteredOut.clear();
2127 String undef = Messages.TmfTimeStatesCtrl_UNDEFINED_GROUP;
2128 List<GroupItem> groupList = new ArrayList<GroupItem>();
2129 for (int i = 0; i < _traces.length; i++) {
2130 ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) _traces[i];
2131 if (!traceFilter[i]) {
2132 filteredOut.add(trace);
2133 continue;
2134 }
2135
2136 String groupName = trace.getGroupName();
2137 if (null == groupName)
2138 groupName = undef;
2139
2140 GroupItem group = _groupTable.get(groupName);
2141 if (null == group) {
2142 group = new GroupItem(NLS.bind(Messages.TmfTimeStatesCtrl_TRACE_GROUP_LABEL, groupName));
2143 group._expanded = !groupName.equalsIgnoreCase("system") && !groupName.equalsIgnoreCase(undef); //$NON-NLS-1$
2144 _groupTable.put(groupName, group);
2145 groupList.add(group);
2146 }
2147 group.add(trace);
2148 }
2149
2150 deleteEmptyGroups();
2151 updateItems();
2152 }
2153
2154 public Object[] getTraces() {
2155 return _traces;
2156 }
2157
2158 public boolean[] getTraceFilter() {
2159 return traceFilter;
2160 }
2161
2162 public Vector<ITmfTimeAnalysisEntry> getFilteredOut() {
2163 return filteredOut;
2164 }
2165 }
This page took 0.08719 seconds and 5 git commands to generate.