1 /**********************************************************************
2 * Copyright (c) 2005, 2014 IBM Corporation, Ericsson
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
9 * IBM - Initial API and implementation
10 * Bernd Hufmann - Updated for TMF
11 **********************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.List
;
19 import org
.eclipse
.swt
.SWT
;
20 import org
.eclipse
.swt
.accessibility
.ACC
;
21 import org
.eclipse
.swt
.accessibility
.Accessible
;
22 import org
.eclipse
.swt
.accessibility
.AccessibleAdapter
;
23 import org
.eclipse
.swt
.accessibility
.AccessibleControlAdapter
;
24 import org
.eclipse
.swt
.accessibility
.AccessibleControlEvent
;
25 import org
.eclipse
.swt
.accessibility
.AccessibleEvent
;
26 import org
.eclipse
.swt
.events
.DisposeEvent
;
27 import org
.eclipse
.swt
.events
.DisposeListener
;
28 import org
.eclipse
.swt
.events
.FocusEvent
;
29 import org
.eclipse
.swt
.events
.FocusListener
;
30 import org
.eclipse
.swt
.events
.KeyEvent
;
31 import org
.eclipse
.swt
.events
.MouseEvent
;
32 import org
.eclipse
.swt
.events
.TraverseEvent
;
33 import org
.eclipse
.swt
.events
.TraverseListener
;
34 import org
.eclipse
.swt
.graphics
.Color
;
35 import org
.eclipse
.swt
.graphics
.GC
;
36 import org
.eclipse
.swt
.graphics
.Image
;
37 import org
.eclipse
.swt
.widgets
.Composite
;
38 import org
.eclipse
.swt
.widgets
.Control
;
39 import org
.eclipse
.swt
.widgets
.Display
;
40 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
43 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.AsyncMessage
;
44 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.AsyncMessageReturn
;
45 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.BaseMessage
;
46 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.ExecutionOccurrence
;
47 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.Frame
;
48 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.GraphNode
;
49 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.ITimeRange
;
50 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.Lifeline
;
51 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.Metrics
;
52 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.SDTimeEvent
;
53 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.SyncMessage
;
54 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.drawings
.IColor
;
55 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.drawings
.impl
.ColorImpl
;
56 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.preferences
.SDViewPref
;
57 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.util
.TimeEventComparator
;
61 * The time compression bar implementation.
67 public class TimeCompressionBar
extends ScrollView
implements DisposeListener
{
69 // ------------------------------------------------------------------------
71 // ------------------------------------------------------------------------
72 private static final int BASE_RED_VALUE
= 255;
73 private static final int BASE_GREEN_BLUE_VALUE
= 225;
74 private static final int COLOR_STEP
= 25;
75 private static final int NUMBER_STEPS
= 10;
77 // ------------------------------------------------------------------------
79 // ------------------------------------------------------------------------
84 private List
<ITimeCompressionListener
> fListenerList
= null;
86 * The current frame displayed.
88 private Frame fFrame
= null;
90 * List of time events.
92 private List
<SDTimeEvent
> fNodeList
= null;
94 * The minimum time delta.
96 private ITmfTimestamp fMinTime
= TmfTimestamp
.fromSeconds(0);
98 * The maximum time delta.
100 private ITmfTimestamp fMaxTime
= TmfTimestamp
.fromSeconds(0);
102 * The current zoom value.
104 private float fZoomValue
= 1;
106 * The tooltip to display.
108 private DrawableToolTip fTooltip
= null;
110 * Array of colors for displaying wight of time deltas.
112 private ColorImpl
[] fColors
;
114 * The accessible object reference.
116 private Accessible fAccessible
= null;
118 * The focused widget reference.
120 private int fFocusedWidget
= -1;
122 * The current lifeline.
124 private Lifeline fLifeline
= null;
126 * The current start event value.
128 private int fLifelineStart
= 0;
130 * The current number of events.
132 private int fLifelineNumEvents
= 0;
134 * The Current color of range to display.
136 private IColor fLifelineColor
= null;
138 * The next graph node y coordinate.
140 private int fNextNodeY
= 0;
142 * The previous graph node y coordinate.
144 private int fPrevNodeY
= 0;
146 // ------------------------------------------------------------------------
148 // ------------------------------------------------------------------------
150 * Standard constructor
153 * The parent composite
157 public TimeCompressionBar(Composite parent
, int s
) {
158 super(parent
, s
| SWT
.NO_BACKGROUND
, false);
159 setVScrollBarMode(ScrollView
.ALWAYS_OFF
);
160 setHScrollBarMode(ScrollView
.ALWAYS_OFF
);
161 fListenerList
= new ArrayList
<>();
162 fColors
= new ColorImpl
[NUMBER_STEPS
];
163 int greenBlue
= BASE_GREEN_BLUE_VALUE
;
164 final int step
= COLOR_STEP
;
165 for (int i
= 0; i
< fColors
.length
; i
++) {
166 fColors
[i
] = new ColorImpl(Display
.getDefault(), BASE_RED_VALUE
, greenBlue
, greenBlue
);
169 super.addDisposeListener(this);
171 fAccessible
= getViewControl().getAccessible();
173 fAccessible
.addAccessibleListener(new AccessibleAdapter() {
175 public void getName(AccessibleEvent e
) {
177 if (e
.childID
== 0) {
178 if (fTooltip
!= null) {
179 e
.result
= fTooltip
.getAccessibleText();
181 } else if (e
.childID
== 1) {
183 e
.result
= fTooltip
.getAccessibleText();
188 fAccessible
.addAccessibleControlListener(new AccessibleControlAdapter() {
190 public void getFocus(AccessibleControlEvent e
) {
191 if (fFocusedWidget
== -1) {
192 e
.childID
= ACC
.CHILDID_SELF
;
195 e
.childID
= fFocusedWidget
;
200 public void getRole(AccessibleControlEvent e
) {
202 case ACC
.CHILDID_SELF
:
203 e
.detail
= ACC
.ROLE_CLIENT_AREA
;
206 e
.detail
= ACC
.ROLE_TOOLTIP
;
209 e
.detail
= ACC
.ROLE_LABEL
;
217 public void getState(AccessibleControlEvent e
) {
218 e
.detail
= ACC
.STATE_FOCUSABLE
;
219 if (e
.childID
== ACC
.CHILDID_SELF
) {
220 e
.detail
|= ACC
.STATE_FOCUSED
;
222 e
.detail
|= ACC
.STATE_SELECTABLE
;
223 if (e
.childID
== fFocusedWidget
) {
224 e
.detail
|= ACC
.STATE_FOCUSED
| ACC
.STATE_SELECTED
| ACC
.STATE_CHECKED
;
230 getViewControl().addTraverseListener(new LocalTraverseListener());
232 addTraverseListener(new LocalTraverseListener());
234 getViewControl().addFocusListener(new FocusListener() {
236 public void focusGained(FocusEvent e
) {
241 public void focusLost(FocusEvent e
) {
247 // ------------------------------------------------------------------------
249 // ------------------------------------------------------------------------
252 * Sets the focus widget
254 * @param newFocusShape
255 * widget reference to set
257 void setFocus(int newFocusShape
) {
258 fFocusedWidget
= newFocusShape
;
259 if (fFocusedWidget
== -1) {
260 getViewControl().getAccessible().setFocus(ACC
.CHILDID_SELF
);
262 getViewControl().getAccessible().setFocus(fFocusedWidget
);
267 * Sets the current frame.
272 public void setFrame(Frame theFrame
) {
274 fMinTime
= fFrame
.getMinTime();
275 fMaxTime
= fFrame
.getMaxTime();
279 protected void drawContents(GC gc
, int clipx
, int clipy
, int clipw
, int cliph
) {
280 if (fFrame
== null) {
283 fNodeList
= new ArrayList
<>();
284 int messageArraysStep
= 1;
286 if ((Metrics
.getMessageFontHeigth() + Metrics
.MESSAGES_NAME_SPACING
* 2) * fZoomValue
< Metrics
.MESSAGE_SIGNIFICANT_VSPACING
+ 1) {
287 messageArraysStep
= Math
.round(Metrics
.MESSAGE_SIGNIFICANT_VSPACING
+ 1 / ((Metrics
.getMessageFontHeigth() + Metrics
.MESSAGES_NAME_SPACING
* 2) * fZoomValue
));
290 int firstVisible
= fFrame
.getFirstVisibleSyncMessage();
291 if (firstVisible
> 0) {
292 firstVisible
= firstVisible
- 1;
294 for (int i
= firstVisible
; i
< fFrame
.syncMessageCount(); i
= i
+ messageArraysStep
) {
295 SyncMessage m
= fFrame
.getSyncMessage(i
);
296 if (addMessageIfVisible(m
)) {
301 firstVisible
= fFrame
.getFirstVisibleSyncMessageReturn();
302 if (firstVisible
> 0) {
303 firstVisible
= firstVisible
- 1;
305 for (int i
= firstVisible
; i
< fFrame
.syncMessageReturnCount(); i
= i
+ messageArraysStep
) {
306 SyncMessage m
= fFrame
.getSyncMessageReturn(i
);
307 if (addMessageIfVisible(m
)) {
312 firstVisible
= fFrame
.getFirstVisibleAsyncMessage();
313 if (firstVisible
> 0) {
314 firstVisible
= firstVisible
- 1;
316 for (int i
= firstVisible
; i
< fFrame
.asyncMessageCount(); i
= i
+ messageArraysStep
) {
317 BaseMessage m
= fFrame
.getAsyncMessage(i
);
318 if (addMessageIfVisible(m
)) {
323 firstVisible
= fFrame
.getFirstVisibleAsyncMessageReturn();
324 if (firstVisible
> 0) {
325 firstVisible
= firstVisible
- 1;
327 for (int i
= firstVisible
; i
< fFrame
.asyncMessageReturnCount(); i
= i
+ messageArraysStep
) {
328 AsyncMessageReturn m
= fFrame
.getAsyncMessageReturn(i
);
329 if (addMessageIfVisible(m
)) {
334 List
<SDTimeEvent
> executionOccurrencesWithTime
= fFrame
.getExecutionOccurrencesWithTime();
335 if (executionOccurrencesWithTime
!= null) {
336 fNodeList
.addAll(executionOccurrencesWithTime
);
339 SDTimeEvent
[] temp
= fNodeList
.toArray(new SDTimeEvent
[fNodeList
.size()]);
340 Arrays
.sort(temp
, new TimeEventComparator());
341 fNodeList
= Arrays
.asList(temp
);
343 Image dbuffer
= new Image(getDisplay(), getClientArea().width
, getClientArea().height
);
344 GC gcim
= new GC(dbuffer
);
346 for (int i
= 0; i
< fNodeList
.size() - 1; i
++) {
347 SDTimeEvent m1
= fNodeList
.get(i
);
348 SDTimeEvent m2
= fNodeList
.get(i
+ 1);
350 if ((SDViewPref
.getInstance().excludeExternalTime()) && ((m1
.getGraphNode() instanceof BaseMessage
) && (m2
.getGraphNode() instanceof BaseMessage
))) {
351 BaseMessage mes1
= (BaseMessage
) m1
.getGraphNode();
352 BaseMessage mes2
= (BaseMessage
) m2
.getGraphNode();
353 if ((mes2
.getStartLifeline() == null) || (mes1
.getEndLifeline() == null)) {
358 fMinTime
= fFrame
.getMinTime();
359 fMaxTime
= fFrame
.getMaxTime();
360 ITmfTimestamp minMaxdelta
= fMaxTime
.getDelta(fMinTime
);
361 double gr
= (minMaxdelta
.getValue()) / (double) NUMBER_STEPS
;
363 ITmfTimestamp delta
= m2
.getTime().getDelta(m1
.getTime()).getDelta(fMinTime
);
364 long absDelta
= Math
.abs(delta
.getValue());
368 int colIndex
= Math
.round((float) (absDelta
/ gr
));
369 if (colIndex
< fColors
.length
&& colIndex
> 0) {
370 color
= fColors
[colIndex
- 1];
371 } else if (colIndex
<= 0) {
374 color
= fColors
[fColors
.length
- 1];
380 if (color
.getColor() instanceof Color
) {
381 gcim
.setBackground((Color
) color
.getColor());
383 PairOfYs poy
= adjustHeights(m1
, m2
);
384 int y1
= poy
.getY1();
385 int y2
= poy
.getY2();
386 gcim
.fillRectangle(contentsToViewX(0), contentsToViewY(Math
.round(y1
* fZoomValue
)), 10, Math
.round((y2
- y1
) * fZoomValue
) + 1);
387 if (messageArraysStep
== 1) {
388 Color backupColor
= gcim
.getForeground();
389 gcim
.setForeground(Display
.getDefault().getSystemColor(SWT
.COLOR_WHITE
));
390 gcim
.drawRectangle(contentsToViewX(0), contentsToViewY(Math
.round(y1
* fZoomValue
)), 9, Math
.round((y2
- y1
) * fZoomValue
));
391 gcim
.setForeground(backupColor
);
394 if (getViewControl().isFocusControl() || isFocusControl()) {
395 gcim
.drawFocus(contentsToViewX(0), contentsToViewY(Math
.round(fPrevNodeY
* fZoomValue
)), contentsToViewX(10), Math
.round((fNextNodeY
- fPrevNodeY
) * fZoomValue
));
398 gc
.drawImage(dbuffer
, 0, 0, getClientArea().width
, getClientArea().height
, 0, 0, getClientArea().width
, getClientArea().height
);
399 } catch (Exception e
) {
400 Activator
.getDefault().logError("Error drawing image", e
); //$NON-NLS-1$
407 private boolean addMessageIfVisible(BaseMessage m
) {
408 if (m
instanceof ITimeRange
) {
409 ITimeRange timeRange
= (ITimeRange
) m
;
410 if (timeRange
.hasTimeInfo()) {
411 SDTimeEvent t
= new SDTimeEvent(timeRange
.getStartTime(), m
.getStartOccurrence(), timeRange
);
413 if (m
instanceof AsyncMessage
) {
414 t
= new SDTimeEvent(timeRange
.getEndTime(), m
.getEndOccurrence(), timeRange
);
417 return isNotVisible(m
);
423 private boolean isNotVisible(BaseMessage m
) {
424 return m
.getY() * fZoomValue
> getContentsY() + getVisibleHeight();
427 private static int addHeightIfAsynchronousMessage(SDTimeEvent timeEvent
, int yPos
) {
428 if (timeEvent
.getGraphNode() instanceof AsyncMessage
) {
429 AsyncMessage as
= (AsyncMessage
) timeEvent
.getGraphNode();
430 if (as
.getEndTime() == timeEvent
.getTime()) {
431 return yPos
+ as
.getHeight();
437 private static int addHeight(SDTimeEvent timeEvent
, int yPos
) {
438 ExecutionOccurrence eo
= (ExecutionOccurrence
) timeEvent
.getGraphNode();
439 if (timeEvent
.getEvent() == eo
.getEndOccurrence()) {
440 return yPos
+ eo
.getHeight();
445 private static int addHeightIfExecutionOccurence(SDTimeEvent timeWidget
, int yPos
) {
446 if (timeWidget
.getGraphNode() instanceof ExecutionOccurrence
) {
447 ExecutionOccurrence eo2
= (ExecutionOccurrence
) timeWidget
.getGraphNode();
448 if (timeWidget
.getEvent() == eo2
.getEndOccurrence()) {
449 return yPos
+ eo2
.getHeight();
456 * Checks for focus of children.
460 * @return true if child is on focus else false
462 protected boolean checkFocusOnChilds(Control children
) {
463 if (children
instanceof Composite
) {
464 Control
[] child
= ((Composite
) children
).getChildren();
465 for (int i
= 0; i
< child
.length
; i
++) {
466 if (child
[i
].isFocusControl()) {
469 checkFocusOnChilds(child
[i
]);
476 public boolean isFocusControl() {
477 Control
[] child
= getChildren();
478 for (int i
= 0; i
< child
.length
; i
++) {
479 if (child
[i
].isFocusControl()) {
482 checkFocusOnChilds(child
[i
]);
488 protected void contentsMouseMoveEvent(MouseEvent event
) {
489 if (fTooltip
!= null) {
490 fTooltip
.hideToolTip();
492 super.contentsMouseMoveEvent(event
);
493 if (!isFocusControl() || getViewControl().isFocusControl()) {
494 Control
[] child
= getParent().getChildren();
495 for (int i
= 0; i
< child
.length
; i
++) {
496 if (child
[i
].isFocusControl()) {
505 protected void contentsMouseHover(MouseEvent e
) {
506 if (fTooltip
== null) {
507 fTooltip
= new DrawableToolTip(this);
509 if (fFrame
!= null) {
511 for (int i
= 0; i
< fNodeList
.size() - 1; i
++) {
512 SDTimeEvent m1
= fNodeList
.get(i
);
513 SDTimeEvent m2
= fNodeList
.get(i
+ 1);
515 if (skipIfLifelineIsNull(m1
, m2
)) {
518 PairOfYs poy
= adjustHeights(m1
, m2
);
520 int m1Y
= Math
.round(poy
.getY1() * fZoomValue
);
521 int m2Y
= Math
.round(poy
.getY2() * fZoomValue
);
522 if ((m1Y
< e
.y
) && (m2Y
>= e
.y
)) {
523 ITmfTimestamp delta
= m2
.getTime().getDelta(m1
.getTime());
524 fTooltip
.showToolTip(delta
, fMinTime
, fMaxTime
);
532 protected void contentsMouseExit(MouseEvent e
) {
533 if (fTooltip
!= null) {
534 fTooltip
.hideToolTip();
539 protected void contentsMouseUpEvent(MouseEvent event
) {
540 selectTimeDelta(event
.y
, 0);
542 super.contentsMouseUpEvent(event
);
546 * Force the time compression bar to highlight the event occurrences between
547 * the two given messages. The event occurrences are highlighted on the
548 * first message's end lifeline
555 public void highlightRegion(BaseMessage mes1
, BaseMessage mes2
) {
556 BaseMessage localMes1
= mes1
;
557 BaseMessage localMes2
= mes2
;
559 if (fFrame
== null) {
562 if (!(localMes1
instanceof ITimeRange
)) {
565 if (!(localMes2
instanceof ITimeRange
)) {
568 ITimeRange t1
= (ITimeRange
) localMes1
;
569 ITimeRange t2
= (ITimeRange
) localMes2
;
571 ITmfTimestamp time1
= t1
.getStartTime();
572 ITmfTimestamp time2
= t2
.getStartTime();
573 int event1
= localMes1
.getEventOccurrence();
574 int event2
= localMes2
.getEventOccurrence();
576 if (localMes1
instanceof AsyncMessage
) {
577 AsyncMessage as
= (AsyncMessage
) localMes1
;
578 time1
= as
.getEndTime();
579 event1
= as
.getEndOccurrence();
581 if (localMes2
instanceof AsyncMessage
) {
582 AsyncMessage as
= (AsyncMessage
) localMes2
;
583 if (as
.getEndOccurrence() > as
.getStartOccurrence()) {
584 time1
= as
.getEndTime();
585 event1
= as
.getEndOccurrence();
587 time1
= as
.getStartTime();
588 event1
= as
.getStartOccurrence();
592 if (event1
> event2
) {
593 BaseMessage tempMes
= localMes2
;
594 localMes2
= localMes1
;
597 t1
= (ITimeRange
) localMes1
;
598 t2
= (ITimeRange
) localMes2
;
600 time1
= t1
.getStartTime();
601 time2
= t2
.getStartTime();
602 event1
= localMes1
.getEventOccurrence();
603 event2
= localMes2
.getEventOccurrence();
605 if (localMes1
instanceof AsyncMessage
) {
606 AsyncMessage as
= (AsyncMessage
) localMes1
;
607 time1
= as
.getEndTime();
608 event1
= as
.getEndOccurrence();
610 if (localMes2
instanceof AsyncMessage
) {
611 AsyncMessage as
= (AsyncMessage
) localMes2
;
612 if (as
.getEndOccurrence() > as
.getStartOccurrence()) {
613 time1
= as
.getEndTime();
614 event1
= as
.getEndOccurrence();
616 time1
= as
.getStartTime();
617 event1
= as
.getStartOccurrence();
622 ITmfTimestamp minMaxdelta
= fMaxTime
.getDelta(fMinTime
);
623 double gr
= (minMaxdelta
.getValue()) / (double) NUMBER_STEPS
;
625 ITmfTimestamp delta
= time2
.getDelta(time1
).getDelta(fMinTime
);
626 long absDelta
= Math
.abs(delta
.getValue());
630 colIndex
= Math
.round((float) (absDelta
/ gr
));
631 if (colIndex
>= fColors
.length
) {
632 colIndex
= fColors
.length
- 1;
633 } else if (colIndex
< 0) {
639 for (int j
= 0; j
< fListenerList
.size(); j
++) {
640 ITimeCompressionListener list
= fListenerList
.get(j
);
641 if (localMes1
.getEndLifeline() != null) {
642 list
.deltaSelected(localMes1
.getEndLifeline(), event1
, event2
- event1
, fColors
[colIndex
]);
643 } else if (localMes2
.getStartLifeline() != null) {
644 list
.deltaSelected(localMes2
.getStartLifeline(), event1
, event2
- event1
, fColors
[colIndex
]);
646 list
.deltaSelected(localMes1
.getStartLifeline(), event1
, event2
- event1
, fColors
[colIndex
]);
652 * Force the time compression bar to highlight the event occurrences between
653 * the two given messages. The event occurrences are highlighted on the
654 * first message's end lifeline
661 public void highlightRegionSync(final BaseMessage mes1
, final BaseMessage mes2
) {
662 getDisplay().syncExec(new Runnable() {
665 highlightRegion(mes1
, mes2
);
671 public void scrollBy(int x
, int y
) {
675 * Sets the zoom value.
678 * The zoom value to set.
680 public void setZoom(float value
) {
686 * Adds a listener to the time compression listener list to be notified
687 * about selected deltas.
690 * The listener to add
692 public void addTimeCompressionListener(ITimeCompressionListener listener
) {
693 if (!fListenerList
.contains(listener
)) {
694 fListenerList
.add(listener
);
699 * Removes a time compression listener.
702 * The listener to remove.
704 public void removeSelectionChangedListener(ITimeCompressionListener listener
) {
705 fListenerList
.remove(listener
);
709 public void widgetDisposed(DisposeEvent e
) {
710 if (fTooltip
!= null) {
713 super.removeDisposeListener(this);
714 for (int i
= 0; i
< fColors
.length
; i
++) {
715 fColors
[i
].dispose();
720 protected void keyPressedEvent(KeyEvent event
) {
721 if (fTooltip
!= null) {
722 fTooltip
.hideToolTip();
724 if (!isFocusControl() || getViewControl().isFocusControl()) {
725 Control
[] child
= getParent().getChildren();
726 for (int i
= 0; i
< child
.length
; i
++) {
727 if (child
[i
].isFocusControl()) {
735 if (fNextNodeY
== 0) {
738 if ((fFrame
!= null) && (fNextNodeY
== 0)) {
739 for (int i
= 0; i
< fNodeList
.size() - 1 && i
< 1; i
++) {
740 SDTimeEvent m1
= fNodeList
.get(i
);
741 SDTimeEvent m2
= fNodeList
.get(i
+ 1);
742 if (skipIfLifelineIsNull(m1
, m2
)) {
746 PairOfYs poy
= adjustHeights(m1
, m2
);
748 fPrevNodeY
= Math
.round(poy
.getY1() * fZoomValue
);
749 fNextNodeY
= Math
.round(poy
.getY2() * fZoomValue
);
753 if (fLifeline
!= null) {
754 for (int j
= 0; j
< fListenerList
.size(); j
++) {
755 ITimeCompressionListener list
= fListenerList
.get(j
);
756 list
.deltaSelected(fLifeline
, fLifelineStart
, fLifelineNumEvents
, fLifelineColor
);
760 if (event
.keyCode
== SWT
.ARROW_DOWN
) {
762 selectTimeDelta(fNextNodeY
+ 1, 1);
764 selectTimeDelta(fPrevNodeY
+ 1, 1);
767 } else if (event
.keyCode
== SWT
.ARROW_UP
) {
768 selectTimeDelta(fPrevNodeY
- 1, 2);
770 } else if (event
.keyCode
== SWT
.ARROW_RIGHT
) {
771 selectTimeDelta(fPrevNodeY
, 1);
774 super.keyPressedEvent(event
);
778 * Selects the time delta for given delta y coordinate and direction.
781 * The delta in y coordinate.
783 * 0 no direction, 1 = down, 2 = up
785 protected void selectTimeDelta(int dy
, int direction
) {
786 SDTimeEvent lastM1
= null;
787 SDTimeEvent lastM2
= null;
790 boolean done
= false;
791 if (fFrame
!= null) {
792 for (int i
= 0; i
< fNodeList
.size() - 1; i
++) {
793 SDTimeEvent m1
= fNodeList
.get(i
);
794 SDTimeEvent m2
= fNodeList
.get(i
+ 1);
795 if (skipIfLifelineIsNull(m1
, m2
)) {
799 PairOfYs poy
= adjustHeights(m1
, m2
);
801 int m1Y
= Math
.round(poy
.getY1() * fZoomValue
);
802 int m2Y
= Math
.round(poy
.getY2() * fZoomValue
);
804 if ((m1Y
< dy
) && (m2Y
> dy
) || (!done
&& m2Y
> dy
&& direction
== 1 && lastM1
!= null) || (!done
&& m1Y
> dy
&& direction
== 2 && lastM1
!= null)) {
805 if (m1Y
> dy
&& direction
== 2) {
814 ITmfTimestamp minMaxdelta
= fMaxTime
.getDelta(fMinTime
);
815 double gr
= (minMaxdelta
.getValue()) / (double) NUMBER_STEPS
;
817 ITmfTimestamp delta
= m2
.getTime().getDelta(m1
.getTime()).getDelta(fMinTime
);
818 long absDelta
= Math
.abs(delta
.getValue());
822 colIndex
= Math
.round((float) (absDelta
/ gr
));
823 if (colIndex
>= fColors
.length
) {
824 colIndex
= fColors
.length
- 1;
825 } else if (colIndex
< 0) {
831 if (m1
.getGraphNode() instanceof BaseMessage
) {
832 BaseMessage mes1
= (BaseMessage
) m1
.getGraphNode();
833 if (mes1
.getEndLifeline() != null) {
834 fLifeline
= mes1
.getEndLifeline();
835 fLifelineStart
= m1
.getEvent();
836 fLifelineNumEvents
= m2
.getEvent() - m1
.getEvent();
837 fLifelineColor
= fColors
[colIndex
];
838 } else if (m2
.getGraphNode() instanceof BaseMessage
&& ((BaseMessage
) m2
.getGraphNode()).getStartLifeline() != null) {
839 fLifeline
= ((BaseMessage
) m2
.getGraphNode()).getStartLifeline();
840 fLifelineStart
= m1
.getEvent();
841 fLifelineNumEvents
= m2
.getEvent() - m1
.getEvent();
842 fLifelineColor
= fColors
[colIndex
];
844 fLifeline
= mes1
.getStartLifeline();
845 fLifelineStart
= m1
.getEvent();
846 fLifelineNumEvents
= m2
.getEvent() - m1
.getEvent();
847 fLifelineColor
= fColors
[colIndex
];
849 } else if (m1
.getGraphNode() instanceof ExecutionOccurrence
) {
850 if (m2
.getGraphNode() instanceof ExecutionOccurrence
) {
851 ExecutionOccurrence eo
= (ExecutionOccurrence
) m2
.getGraphNode();
852 fLifeline
= eo
.getLifeline();
853 fLifelineStart
= m1
.getEvent();
854 fLifelineNumEvents
= m2
.getEvent() - m1
.getEvent();
855 fLifelineColor
= fColors
[colIndex
];
857 ExecutionOccurrence eo
= (ExecutionOccurrence
) m1
.getGraphNode();
858 fLifeline
= eo
.getLifeline();
859 fLifelineStart
= m1
.getEvent();
860 fLifelineNumEvents
= m2
.getEvent() - m1
.getEvent();
861 fLifelineColor
= fColors
[colIndex
];
864 for (int j
= 0; j
< fListenerList
.size(); j
++) {
865 ITimeCompressionListener list
= fListenerList
.get(j
);
866 list
.deltaSelected(fLifeline
, fLifelineStart
, fLifelineNumEvents
, fLifelineColor
);
879 * Creates a fake tool tip.
881 protected void createFakeTooltip() {
882 if (fTooltip
== null) {
883 fTooltip
= new DrawableToolTip(this);
886 if (fFrame
!= null) {
888 for (int i
= 0; i
< fNodeList
.size() - 1; i
++) {
889 SDTimeEvent m1
= fNodeList
.get(i
);
890 SDTimeEvent m2
= fNodeList
.get(i
+ 1);
891 if (skipIfLifelineIsNull(m1
, m2
)) {
894 PairOfYs poy
= adjustHeights(m1
, m2
);
895 int m1Y
= Math
.round(poy
.getY1() * fZoomValue
);
896 int m2Y
= Math
.round(poy
.getY2() * fZoomValue
);
897 if ((m1Y
< fPrevNodeY
+ 1) && (m2Y
>= fPrevNodeY
+ 1)) {
898 ITmfTimestamp delta
= m2
.getTime().getDelta(m1
.getTime());
899 fTooltip
.showToolTip(delta
, fMinTime
, fMaxTime
);
900 fTooltip
.hideToolTip();
906 private static PairOfYs
adjustHeights(SDTimeEvent m1
, SDTimeEvent m2
) {
907 int y1
= ((GraphNode
) m1
.getGraphNode()).getY();
908 int y2
= ((GraphNode
) m2
.getGraphNode()).getY();
910 y1
= addHeightIfAsynchronousMessage(m1
, y1
);
911 y2
= addHeightIfAsynchronousMessage(m2
, y2
);
912 if (m1
.getGraphNode() instanceof ExecutionOccurrence
) {
913 y1
= addHeight(m1
, y1
);
914 y2
= addHeightIfExecutionOccurence(m2
, y2
);
916 return new PairOfYs(y1
, y2
);
919 private static class PairOfYs
{
920 private final int fY1
, fY2
;
922 public PairOfYs(int y1
, int y2
) {
937 private static boolean skipIfLifelineIsNull(SDTimeEvent m1
, SDTimeEvent m2
) {
938 if ((SDViewPref
.getInstance().excludeExternalTime()) && ((m1
.getGraphNode() instanceof BaseMessage
) && (m2
.getGraphNode() instanceof BaseMessage
))) {
939 BaseMessage mes1
= (BaseMessage
) m1
.getGraphNode();
940 BaseMessage mes2
= (BaseMessage
) m2
.getGraphNode();
941 if ((mes2
.getStartLifeline() == null) || (mes1
.getEndLifeline() == null)) {
949 * Traverse Listener implementation.
951 protected static class LocalTraverseListener
implements TraverseListener
{
953 public void keyTraversed(TraverseEvent e
) {
954 if ((e
.detail
== SWT
.TRAVERSE_TAB_NEXT
) || (e
.detail
== SWT
.TRAVERSE_TAB_PREVIOUS
)) {