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