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