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
.core
;
15 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.drawings
.IColor
;
16 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.drawings
.IGC
;
17 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.preferences
.ISDPreferences
;
18 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.preferences
.SDViewPref
;
21 * The base UML2 syncMessages implementation.<br>
22 * This abstract class only define one event occurrence to attach to the message.<br>
23 * Usually a message has two event occurrences attached, one for both ends. But some syncMessages(like synchronous
24 * syncMessages) only need one event occurrence to represent the time when they appear. Others kind of message
25 * representations (like asynchronous syncMessages) will be responsible to define the missing second eventOccurrence
29 * @see Lifeline Lifeline for more event occurence details
33 public abstract class BaseMessage
extends GraphNode
{
35 private static final int ARROW_LENGTH
= 7;
36 private static final double ARROW_ANGLE
= 0.75;
37 private static final Double ARROW_HEAD_Y
= Double
.valueOf(Math
.sin(ARROW_ANGLE
) * ARROW_LENGTH
);
38 private static final Double ARROW_HEAD_X
= Double
.valueOf(Math
.cos(ARROW_ANGLE
) * ARROW_LENGTH
);
39 // ------------------------------------------------------------------------
41 // ------------------------------------------------------------------------
43 * The lifeline which send the message
45 private Lifeline fStartLifeline
= null;
47 * The lifeline which receive the message
49 private Lifeline fEndLifeline
= null;
51 * The visiblitiy flag.
53 private boolean fVisible
= true;
55 // ------------------------------------------------------------------------
57 // ------------------------------------------------------------------------
61 // returns the exact x coordinate
68 * Note: lifeline.getY() return the y coordinate of the top left corner of the rectangle which contain the
69 * lifeline name getHeight return the height of this rectangle The message y coordinate is then relative to this
70 * position depending of its eventOccurrence Space between syncMessages is constant
72 if ((fStartLifeline
!= null) && (fEndLifeline
!= null)) {
74 * Regular message, both ends are attached to a lifeline
76 return fEndLifeline
.getY() + fEndLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * getEndOccurrence();
80 * UML2 lost message kind
82 if (fStartLifeline
!= null) {
83 return fStartLifeline
.getY() + fStartLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * getEndOccurrence();
87 * UML2 found message kind
89 if (fEndLifeline
!= null) {
90 return fEndLifeline
.getY() + fEndLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * getEndOccurrence();
92 // return 0 by default
97 public int getWidth() {
98 // Returns the exact width
99 return getWidth(false);
103 public int getHeight() {
108 * Returns the graph node x coordinate.<br>
109 * Depending on the quick parameter a approximative or exact value is return.<br>
110 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
112 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
113 * affect the message x coordinate and width.<br>
115 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
118 * @param quick true to get an approximative value<br>
119 * false to get the exact x value<br>
120 * @return the graph node x coordinate
122 protected int getX(boolean quick
) {
124 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
125 if ((fStartLifeline
!= null) && (fEndLifeline
!= null)) {
126 x
= fStartLifeline
.getX() + Metrics
.getLifelineWidth() / 2;
128 if (fStartLifeline
!= null) {
129 x
= fStartLifeline
.getX() + Metrics
.getLifelineWidth() / 2;
132 if (fEndLifeline
!= null) {
133 x
= fEndLifeline
.getX() - Metrics
.LIFELINE_SPACING
/ 2;
141 if ((fStartLifeline
!= null) && (fEndLifeline
!= null) && (fStartLifeline
.getX() > fEndLifeline
.getX())) {
142 activationWidth
= -activationWidth
;
145 if (isMessageStartInActivation(getEndOccurrence())) {
146 x
= x
+ activationWidth
;
153 * Returns the graph node width.<br>
154 * Depending on the quick parameter a approximative or exact value is returned.<br>
155 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
157 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
158 * affect the message x coordinate and width.<br>
160 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
163 * @param quick true to get an approximative value<br>
164 * false to get the exact x value
165 * @return the graph node width
167 protected int getWidth(boolean quick
) {
169 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
170 if ((fStartLifeline
!= null) && (fEndLifeline
!= null)) {
171 if (fStartLifeline
== fEndLifeline
) {
172 width
= Metrics
.INTERNAL_MESSAGE_WIDTH
+ Metrics
.EXECUTION_OCCURRENCE_WIDTH
;
174 width
= fEndLifeline
.getX() + Metrics
.getLifelineWidth() / 2 - getX(true);
177 if (fStartLifeline
!= null) {
178 width
= Metrics
.swimmingLaneWidth() / 2;
180 if (fEndLifeline
!= null) {
181 width
= Metrics
.swimmingLaneWidth() / 2;
189 if ((fStartLifeline
!= null) && (fEndLifeline
!= null) && (fStartLifeline
.getX() > fEndLifeline
.getX())) {
190 activationWidth
= -activationWidth
;
193 if (isMessageStartInActivation(getEndOccurrence())) {
194 width
= width
- activationWidth
;
197 if (isMessageEndInActivation(getEndOccurrence())) {
198 width
= width
- activationWidth
;
205 public boolean isVisible(int x
, int y
, int width
, int height
) {
206 // ***Common*** syncMessages visibility
207 // draw the message only if at least one end is visible
208 if (fEndLifeline
!= null && (fEndLifeline
.isVisible(x
, y
, width
, height
)) || (fStartLifeline
!= null && fStartLifeline
.isVisible(x
, y
, width
, height
))) {
211 // In this case it can be a message which cross the whole visible area
212 else if (fEndLifeline
!= null && (!fEndLifeline
.isVisible(x
, y
, width
, height
)) && (fStartLifeline
!= null && !fStartLifeline
.isVisible(x
, y
, width
, height
))) {
213 if (fEndLifeline
.getX() > x
+ width
&& fStartLifeline
.getX() < x
) {
215 } else if (fStartLifeline
.getX() > x
+ width
&& fEndLifeline
.getX() < x
) {
223 * Sets the visibility value.
225 * @param value The visibility to set.
227 public void setVisible(boolean value
) {
232 * @return the visibility value.
234 public boolean isVisible() {
239 * Set the lifeline from which this message has been sent.
241 * @param lifeline - the message sender
243 public void setStartLifeline(Lifeline lifeline
) {
244 fStartLifeline
= lifeline
;
248 * Returns the lifeline from which this message has been sent.
250 * @return the message sender
252 public Lifeline
getStartLifeline() {
253 return fStartLifeline
;
257 * Returns the lifeline which has received this message.
259 * @return the message receiver
261 public Lifeline
getEndLifeline() {
266 * Set the lifeline which has receive this message.
268 * @param lifeline the message receiver
270 public void setEndLifeline(Lifeline lifeline
) {
271 fEndLifeline
= lifeline
;
275 * Set the event occurrence when this message occurs.<br>
277 * @param occurrence the event occurrence to assign to this message.<br>
278 * @see Lifeline Lifeline for more event occurence details
280 protected void setEventOccurrence(int occurrence
) {
281 setEndOccurrence(occurrence
);
285 * Returns the event occurence when is message occurs.<br>
287 * @return the event occurrence assigned to this message.<br>
288 * @see Lifeline Lifeline for more event occurence details
290 public int getEventOccurrence() {
291 return getEndOccurrence();
295 * Determines if the given eventOccurence occurs on a executionOccurence owned by the sending lifeline.<br>
296 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
297 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
298 * coordinate and width.<br>
300 * @see BaseMessage#getX(boolean)
301 * @param event the event occurrence to test
302 * @return true if occurs on a execution occurrence owned by the sending lifeine, false otherwise
304 protected boolean isMessageStartInActivation(int event
) {
305 boolean inActivation
= false;
306 if ((fStartLifeline
!= null) && (fStartLifeline
.getExecutions() != null)) {
307 // int acIndex=startLifeline.getExecOccurrenceDrawIndex();
308 // acIndex = first visible execution occurrence
309 // for drawing speed reason with only search on the visivle subset
311 for (int i
= 0; i
< fStartLifeline
.getExecutions().size(); i
++) {
312 BasicExecutionOccurrence toDraw
= (BasicExecutionOccurrence
) fStartLifeline
.getExecutions().get(i
);
313 if ((event
>= toDraw
.getStartOccurrence()) && (event
<= toDraw
.getEndOccurrence())) {
316 // if we are outside the visible area we stop right now
317 // This works because execution occurrences are ordered along the Y axis
318 if (toDraw
.getY() > thisY
) {
327 * Determines if the given event occurrence occurs on a execution occurrence owned by the receiving lifeline.<br>
328 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
329 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
330 * coordinate and width.<br>
332 * @see BaseMessage#getX(boolean)
333 * @param event the event occurrence to test
334 * @return true if occurs on a execution occurrence owned by the receiving lifeline, false otherwise
336 protected boolean isMessageEndInActivation(int event
) {
337 boolean inActivation
= false;
338 if ((fEndLifeline
!= null) && (fEndLifeline
.getExecutions() != null)) {
339 // acIndex = first visible execution occurrence
340 // for drawing speed reason with only search on the visivle subset
341 for (int i
= 0; i
< fEndLifeline
.getExecutions().size(); i
++) {
342 BasicExecutionOccurrence toDraw
= (BasicExecutionOccurrence
) fEndLifeline
.getExecutions().get(i
);
343 if ((event
>= toDraw
.getStartOccurrence()) && (event
<= toDraw
.getEndOccurrence())) {
346 // if we are outside the visible area we stop right now
347 // This works because execution occurrences are ordered along the Y axis
348 if (toDraw
.getY() > getY()) {
357 public boolean contains(int xValue
, int yValue
) {
360 int width
= getWidth();
361 int height
= getHeight();
363 // Used to create a rectangle which contains the message label to allow selection when clicking the label
364 int tempHeight
= Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth();
366 // Is it a self message?
367 if (fStartLifeline
== fEndLifeline
) {
369 * Rectangle.contains(x,y, width, height) does not works with negative height or width We check here if the
370 * rectangle width is negative.
372 if (getName().length() * Metrics
.getAverageCharWidth() > Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2 + -Metrics
.INTERNAL_MESSAGE_WIDTH
) {
373 if (GraphNode
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ 10, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2 + -Metrics
.INTERNAL_MESSAGE_WIDTH
, Metrics
.getMessageFontHeigth(), xValue
, yValue
)) {
377 if (GraphNode
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ 10, y
, getName().length() * Metrics
.getAverageCharWidth(), Metrics
.getMessageFontHeigth(), xValue
, yValue
)) {
382 // Test if the point is in part 1 of the self message
383 // see: "private void drawMessage (NGC context)" method for self message drawing schema
384 if (GraphNode
.contains(x
, y
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2, Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, Metrics
.MESSAGE_SELECTION_TOLERANCE
, xValue
, yValue
)) {
388 // Test if the point is in part 3 of the self message
389 if (GraphNode
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2, y
, Metrics
.MESSAGE_SELECTION_TOLERANCE
, height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, xValue
, yValue
)) {
393 // Test if the point is in part 5 of the self message
394 if (GraphNode
.contains(x
, y
+ height
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2 + Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, Metrics
.MESSAGE_SELECTION_TOLERANCE
, xValue
, yValue
)) {
401 if (GraphNode
.contains(x
, y
- tempHeight
, width
, tempHeight
, xValue
, yValue
)) {
409 * Method to draw the message using the graphical context.
411 * @param context A graphical context to draw in.
413 protected void drawMessage(IGC context
) {
419 // temporary store the coordinates to avoid more methods calls
422 int width
= getWidth();
423 int height
= getHeight();
425 ISDPreferences pref
= SDViewPref
.getInstance();
427 // UML2 found message (always drawn from left to right)
428 // or UML2 lost message (always drawn from left to right)
429 if ((fStartLifeline
== null || fEndLifeline
== null) && fStartLifeline
!= fEndLifeline
) {
430 // Draw the message label above the message and centered
431 // The label is truncated if it cannot fit between the two message end
432 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
433 IColor temp
= context
.getForeground();
434 context
.setForeground(pref
.getFontColor(getColorPrefId()));
435 context
.drawTextTruncatedCentred(getName(), x
, y
- Metrics
.getMessageFontHeigth() - 2 * Metrics
.MESSAGES_NAME_SPACING
, width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth(), !isSelected());
436 context
.setForeground(temp
);
438 if (fEndLifeline
== null) {
439 margin
= Metrics
.MESSAGE_CIRCLE_RAY
;
442 // Draw the message main line
443 context
.drawLine(x
, y
, x
+ width
, y
+ height
);
444 // Draw the two little lines which make a arrow part of the message
445 Double xt
= ARROW_HEAD_X
;
446 Double yt
= ARROW_HEAD_Y
;
447 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
448 IColor backcolor
= context
.getBackground();
449 context
.setBackground(context
.getForeground());
450 int[] points
= { x
+ width
- margin
, y
+ height
, x
+ width
- xt
.intValue() - margin
, y
+ height
- yt
.intValue(), x
+ width
- xt
.intValue() - margin
, y
+ height
+ yt
.intValue(), x
+ width
- margin
, y
+ height
};
451 context
.fillPolygon(points
);
452 context
.drawPolygon(points
);
453 context
.setBackground(backcolor
);
455 int currentStyle
= context
.getLineStyle();
456 int currentWidth
= context
.getLineWidth();
457 context
.setLineWidth(currentWidth
+ 2);
458 context
.setLineStyle(context
.getLineSolidStyle());
459 context
.drawLine(x
+ width
- xt
.intValue() - margin
, y
+ height
- yt
.intValue(), x
+ width
- margin
, y
+ height
);
460 context
.drawLine(x
+ width
- xt
.intValue() - margin
, y
+ height
+ yt
.intValue(), x
+ width
- margin
, y
+ height
);
461 context
.setLineStyle(currentStyle
);
462 context
.setLineWidth(currentWidth
);
464 IColor storedColor
= context
.getBackground();
465 context
.setBackground(context
.getForeground());
467 // Draw a circle at the message end (endLifeline side)
468 int ray
= Metrics
.MESSAGE_CIRCLE_RAY
;
469 if (context
.getLineWidth() != Metrics
.NORMAL_LINE_WIDTH
) {
470 ray
= ray
+ Metrics
.SELECTION_LINE_WIDTH
- Metrics
.NORMAL_LINE_WIDTH
;
472 if (fStartLifeline
== null) {
473 context
.fillOval(x
- ray
, y
- ray
, ray
* 2, ray
* 2);
475 context
.fillOval(x
+ width
- ray
, y
+ height
- ray
, ray
* 2, ray
* 2);
477 context
.setBackground(storedColor
);
478 context
.setForeground(pref
.getFontColor(getColorPrefId()));
480 fY
= y
- yt
.intValue();
482 fH
= height
+ 2 * yt
.intValue();
484 // it is self message (always drawn at the left side of the owning lifeLifeline)
485 else if (fStartLifeline
!= null && fEndLifeline
!= null && fStartLifeline
== fEndLifeline
) {
487 * Self syncMessages are drawn in 5 parts 1 -----------+ + 2 + | | | 3 | + 5 + 4 -----------+
489 int tempy
= Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2;
490 if (Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
<= Metrics
.INTERNAL_MESSAGE_WIDTH
) {
491 tempy
= Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
/ 2;
495 context
.drawLine(x
, y
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
);
497 context
.drawLine(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ tempy
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- tempy
);
499 context
.drawLine(x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
501 Double xt
= ARROW_HEAD_X
;
502 Double yt
= ARROW_HEAD_Y
;
506 fW
= Metrics
.INTERNAL_MESSAGE_WIDTH
;
507 fH
= height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
;
509 // Draw the two little lines which make a arrow part of the message
510 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
511 IColor backcolor
= context
.getBackground();
512 context
.setBackground(context
.getForeground());
513 int[] points
= { x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ yt
.intValue(), x
+ xt
.intValue(),
514 y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
};
515 context
.fillPolygon(points
);
516 context
.drawPolygon(points
);
517 context
.setBackground(backcolor
);
519 int currentStyle
= context
.getLineStyle();
520 int currentWidth
= context
.getLineWidth();
521 context
.setLineWidth(currentWidth
+ 2);
522 context
.setLineStyle(context
.getLineSolidStyle());
523 context
.drawLine(x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
524 context
.drawLine(x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
525 context
.setLineStyle(currentStyle
);
526 context
.setLineWidth(currentWidth
);
530 context
.drawArc(x
, y
, Metrics
.INTERNAL_MESSAGE_WIDTH
, 2 * tempy
, 0, 90);
532 context
.drawArc(x
, y
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, Metrics
.INTERNAL_MESSAGE_WIDTH
, -2 * tempy
, 0, -90);
534 // Draw the message label above the message and centered
535 // The label is truncated if it cannot fit between the two message end
536 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
538 // the space available for the text is sorter if are drawing internal message on the last lifeline
539 context
.setForeground(pref
.getFontColor(getColorPrefId()));
540 if (fStartLifeline
.getIndex() == fStartLifeline
.getFrame().getHorizontalIndex()) {
541 context
.drawTextTruncated(getName(), x
+ width
+ Metrics
.INTERNAL_MESSAGE_V_MARGIN
/ 2, y
, Metrics
.swimmingLaneWidth() / 2 - Metrics
.EXECUTION_OCCURRENCE_WIDTH
+ -Metrics
.INTERNAL_MESSAGE_WIDTH
, +Metrics
.MESSAGES_NAME_SPACING
542 - Metrics
.getMessageFontHeigth(), !isSelected());
544 context
.drawTextTruncated(getName(), x
+ width
+ Metrics
.INTERNAL_MESSAGE_V_MARGIN
/ 2, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
+ -Metrics
.INTERNAL_MESSAGE_WIDTH
,
545 +Metrics
.MESSAGES_NAME_SPACING
- Metrics
.getMessageFontHeigth(), !isSelected());
548 // it is regular message
549 else if (fStartLifeline
!= null && fEndLifeline
!= null) {
550 // Draw the message main line
551 context
.drawLine(x
, y
, x
+ width
, y
+ height
);
553 int spaceBTWStartEnd
= fEndLifeline
.getX() - fStartLifeline
.getX();
557 double angle
= Math
.atan(a
/ b
);
558 // Compute the coordinates of the two little lines which make the arrow part of the message
560 if (spaceBTWStartEnd
< 0) {
563 Double x1
= Double
.valueOf(sign
* Math
.cos(angle
- ARROW_ANGLE
) * ARROW_LENGTH
);
564 Double y1
= Double
.valueOf(sign
* Math
.sin(angle
- ARROW_ANGLE
) * ARROW_LENGTH
);
565 Double x2
= Double
.valueOf(sign
* Math
.cos(angle
+ ARROW_ANGLE
) * ARROW_LENGTH
);
566 Double y2
= Double
.valueOf(sign
* Math
.sin(angle
+ ARROW_ANGLE
) * ARROW_LENGTH
);
569 fY
= y
+ height
- y2
.intValue();
571 fH
= y2
.intValue() - y1
.intValue() + 1;
582 // Draw the two little lines which make a arrow part of the message
583 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
584 IColor backcolor
= context
.getBackground();
585 context
.setBackground(context
.getForeground());
586 int[] points
= { x
+ width
- x1
.intValue(), y
+ height
- y1
.intValue(), x
+ width
, y
+ height
, x
+ width
- x2
.intValue(), y
+ height
- y2
.intValue(), x
+ width
- x1
.intValue(), y
+ height
- y1
.intValue() };
587 context
.fillPolygon(points
);
588 context
.drawPolygon(points
);
589 context
.setBackground(backcolor
);
591 int currentStyle
= context
.getLineStyle();
592 int currentWidth
= context
.getLineWidth();
593 context
.setLineWidth(currentWidth
+ 2);
594 context
.setLineStyle(context
.getLineSolidStyle());
595 context
.drawLine(x
+ width
- x1
.intValue(), y
+ height
- y1
.intValue(), x
+ width
, y
+ height
);
596 context
.drawLine(x
+ width
- x2
.intValue(), y
+ height
- y2
.intValue(), x
+ width
, y
+ height
);
597 context
.setLineStyle(currentStyle
);
598 context
.setLineWidth(currentWidth
);
601 // Draw the message label above the message and centered
602 // The label is truncated if it cannot fit between the two message end
603 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
604 context
.setForeground(pref
.getFontColor(getColorPrefId()));
605 if (spaceBTWStartEnd
> 0) {
606 context
.drawTextTruncatedCentred(getName(), x
, y
+ height
/ 2 - (2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()), width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth(), !isSelected());
608 context
.drawTextTruncatedCentred(getName(), x
+ width
, y
+ height
/ 2 - (2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()), -width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ +Metrics
.getMessageFontHeigth(), !isSelected());
614 public void draw(IGC context
) {
619 // Draw it selected?*/
621 ISDPreferences pref
= SDViewPref
.getInstance();
623 * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
624 * colors This create the highlight effect
626 context
.setForeground(pref
.getBackGroundColorSelection());
627 context
.setLineWidth(Metrics
.SELECTION_LINE_WIDTH
);
628 drawMessage(context
);
629 context
.setBackground(pref
.getBackGroundColorSelection());
630 context
.setForeground(pref
.getForeGroundColorSelection());
631 // Second drawing is done after
633 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
635 context
.setDrawTextWithFocusStyle(true);
637 drawMessage(context
);
638 int oldStyle
= context
.getLineStyle();
640 context
.setDrawTextWithFocusStyle(false);
643 // restore the context
644 context
.setLineStyle(oldStyle
);
648 * Determine if two messages are identical. This default implementation considers that overlapping messages with
649 * same coordinates are identical.
651 * @param message - the message to compare with
652 * @return true if identical false otherwise
654 * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode#isSameAs(org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode)
657 public boolean isSameAs(GraphNode message
) {
658 if (message
== null) {
661 if (!(message
instanceof BaseMessage
)) {
662 return super.isSameAs(message
);
664 return ((getX() == message
.getX()) && (getY() == message
.getY()) && (getWidth() == message
.getWidth()) && (getHeight() == message
.getHeight()));
670 * @param x A x coordinate
671 * @param y A y coordinate
674 * @param context A graphical context
676 public void drawRot(int x
, int y
, int w
, int h
, IGC context
) {
677 double angleA
= Math
.atan2(getHeight(), getWidth());
678 double cosA
= Math
.cos(angleA
);
679 double sinA
= Math
.sin(angleA
);
685 localHeight
= localHeight
/ 2;
687 double cw
= Math
.sqrt(w
* w
+ getHeight() * getHeight());
689 int x1
= Math
.round((float) ((x
- gx
) * cosA
- (y
- gy
) * sinA
));
690 int y1
= Math
.round((float) ((x
- gx
) * sinA
+ (y
- gy
) * cosA
));
692 int x2
= Math
.round((float) (cw
* cosA
- (y
- gy
) * sinA
));
693 int y2
= Math
.round((float) (cw
* sinA
+ (y
- gy
) * cosA
));
695 int x3
= Math
.round((float) (cw
* cosA
- (localHeight
) * sinA
));
696 int y3
= Math
.round((float) (cw
* sinA
+ (localHeight
) * cosA
));
698 int x4
= Math
.round((float) ((x
- gx
) * cosA
- (localHeight
) * sinA
));
699 int y4
= Math
.round((float) ((x
- gx
) * sinA
+ (localHeight
) * cosA
));
701 int[] points
= { x1
+ getX(), y1
+ getY(), x2
+ getX(), y2
+ getY(), x3
+ getX(), y3
+ getY(), x4
+ getX(), y4
+ getY() };
702 context
.drawPolygon(points
);
706 public void drawFocus(IGC context
) {
708 ISDPreferences pref
= SDViewPref
.getInstance();
710 if ((fStartLifeline
!= fEndLifeline
) && (getStartOccurrence() == getEndOccurrence())) {
711 context
.setLineStyle(context
.getLineDotStyle());
712 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
713 context
.setBackground(pref
.getBackGroundColorSelection());
714 context
.setForeground(pref
.getForeGroundColorSelection());
715 context
.drawFocus(getX(), getY() - 3, getWidth(), getHeight() + 6);
716 } else if ((fStartLifeline
== fEndLifeline
) && (getStartOccurrence() == getEndOccurrence())) {
717 context
.drawFocus(getX(), getY() - 3, getWidth(), Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ 6);
718 } else if ((fStartLifeline
!= fEndLifeline
) && (getStartOccurrence() != getEndOccurrence())) {
719 context
.setLineStyle(context
.getLineDotStyle());
720 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
721 context
.setBackground(pref
.getBackGroundColor(ISDPreferences
.PREF_LIFELINE_HEADER
));
722 context
.setForeground(pref
.getForeGroundColor(ISDPreferences
.PREF_LIFELINE_HEADER
));
723 drawRot(getX(), getY() - 5, getWidth(), 10, context
);
725 super.drawFocus(context
);