1 /**********************************************************************
2 * Copyright (c) 2005, 2008 IBM Corporation and others.
3 * Copyright (c) 2011, 2012 Ericsson.
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * which accompanies this distribution, and is available at
8 * http://www.eclipse.org/legal/epl-v10.html
11 * IBM - Initial API and implementation
12 * Bernd Hufmann - Updated for TMF
13 **********************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.core
;
16 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.IColor
;
17 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.IGC
;
18 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.preferences
.ISDPreferences
;
19 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.preferences
.SDViewPref
;
22 * The base UML2 syncMessages implementation.<br>
23 * This abstract class only define one event occurrence to attach to the message.<br>
24 * Usually a message has two event occurrences attached, one for both ends. But some syncMessages(like synchronous
25 * syncMessages) only need one event occurrence to represent the time when they appear. Others kind of message
26 * representations (like asynchronous syncMessages) will be responsible to define the missing second eventOccurrence
30 * @see Lifeline Lifeline for more event occurence details
34 public abstract class BaseMessage
extends GraphNode
{
36 // ------------------------------------------------------------------------
38 // ------------------------------------------------------------------------
40 * The lifeline which send the message
42 protected Lifeline fStartLifeline
= null;
44 * The lifeline which receive the message
46 protected Lifeline fEndLifeline
= null;
48 * The visiblitiy flag.
50 protected boolean fVisible
= true;
52 // ------------------------------------------------------------------------
54 // ------------------------------------------------------------------------
57 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getX()
61 // returns the exact x coordinate
67 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getY()
72 * Note: lifeline.getY() return the y coordinate of the top left corner of the rectangle which contain the
73 * lifeline name getHeight return the height of this rectangle The message y coordinate is then relative to this
74 * position depending of its eventOccurrence Space between syncMessages is constant
76 if ((fStartLifeline
!= null) && (fEndLifeline
!= null)) {
78 * Regular message, both ends are attached to a lifeline
80 return fEndLifeline
.getY() + fEndLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * fEndEventOccurrence
;
84 * UML2 lost message kind
86 if (fStartLifeline
!= null) {
87 return fStartLifeline
.getY() + fStartLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * fEndEventOccurrence
;
91 * UML2 found message kind
93 if (fEndLifeline
!= null) {
94 return fEndLifeline
.getY() + fEndLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * fEndEventOccurrence
;
97 // return 0 by default
103 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getWidth()
106 public int getWidth() {
107 // Returns the exact width
108 return getWidth(false);
113 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getHeight()
116 public int getHeight() {
121 * Returns the graph node x coordinate.<br>
122 * Depending on the quick parameter a approximative or exact value is return.<br>
123 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
125 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
126 * affect the message x coordinate and width.<br>
128 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
131 * @param quick true to get an approximative value<br>
132 * false to get the exact x value<br>
133 * @return the graph node x coordinate
135 protected int getX(boolean quick
) {
137 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
138 if ((fStartLifeline
!= null) && (fEndLifeline
!= null)) {
139 x
= fStartLifeline
.getX() + Metrics
.getLifelineWidth() / 2;
141 if (fStartLifeline
!= null) {
142 x
= fStartLifeline
.getX() + Metrics
.getLifelineWidth() / 2;
145 if (fEndLifeline
!= null) {
146 x
= fEndLifeline
.getX() - Metrics
.LIFELINE_SPACING
/ 2;
154 if ((fStartLifeline
!= null) && (fEndLifeline
!= null) && (fStartLifeline
.getX() > fEndLifeline
.getX())) {
155 activationWidth
= -activationWidth
;
158 if (isMessageStartInActivation(fEndEventOccurrence
)) {
159 x
= x
+ activationWidth
;
166 * Returns the graph node width.<br>
167 * Depending on the quick parameter a approximative or exact value is returned.<br>
168 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
170 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
171 * affect the message x coordinate and width.<br>
173 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
176 * @param quick true to get an approximative value<br>
177 * false to get the exact x value
178 * @return the graph node width
180 protected int getWidth(boolean quick
) {
182 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
183 if ((fStartLifeline
!= null) && (fEndLifeline
!= null)) {
184 if (fStartLifeline
== fEndLifeline
) {
185 width
= Metrics
.INTERNAL_MESSAGE_WIDTH
+ Metrics
.EXECUTION_OCCURRENCE_WIDTH
;
187 width
= fEndLifeline
.getX() + Metrics
.getLifelineWidth() / 2 - getX(true);
190 if (fStartLifeline
!= null) {
191 width
= Metrics
.swimmingLaneWidth() / 2;
193 if (fEndLifeline
!= null) {
194 width
= Metrics
.swimmingLaneWidth() / 2;
202 if ((fStartLifeline
!= null) && (fEndLifeline
!= null) && (fStartLifeline
.getX() > fEndLifeline
.getX())) {
203 activationWidth
= -activationWidth
;
206 if (isMessageStartInActivation(fEndEventOccurrence
)) {
207 width
= width
- activationWidth
;
210 if (isMessageEndInActivation(fEndEventOccurrence
)) {
211 width
= width
- activationWidth
;
219 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#isVisible(int, int, int, int)
222 public boolean isVisible(int x
, int y
, int width
, int height
) {
223 // ***Common*** syncMessages visibility
224 // draw the message only if at least one end is visible
225 if (fEndLifeline
!= null && (fEndLifeline
.isVisible(x
, y
, width
, height
)) || (fStartLifeline
!= null && fStartLifeline
.isVisible(x
, y
, width
, height
))) {
228 // In this case it can be a message which cross the whole visible area
229 else if (fEndLifeline
!= null && (!fEndLifeline
.isVisible(x
, y
, width
, height
)) && (fStartLifeline
!= null && !fStartLifeline
.isVisible(x
, y
, width
, height
))) {
230 if (fEndLifeline
.getX() > x
+ width
&& fStartLifeline
.getX() < x
) {
232 } else if (fStartLifeline
.getX() > x
+ width
&& fEndLifeline
.getX() < x
) {
240 * Sets the visibility value.
242 * @param value The visibility to set.
244 public void setVisible(boolean value
) {
249 * @return the visibility value.
251 public boolean isVisible() {
256 * Set the lifeline from which this message has been sent.
258 * @param lifeline - the message sender
260 public void setStartLifeline(Lifeline lifeline
) {
261 fStartLifeline
= lifeline
;
265 * Returns the lifeline from which this message has been sent.
267 * @return the message sender
269 public Lifeline
getStartLifeline() {
270 return fStartLifeline
;
274 * Returns the lifeline which has received this message.
276 * @return the message receiver
278 public Lifeline
getEndLifeline() {
283 * Set the lifeline which has receive this message.
285 * @param lifeline the message receiver
287 public void setEndLifeline(Lifeline lifeline
) {
288 fEndLifeline
= lifeline
;
292 * Set the event occurrence when this message occurs.<br>
294 * @param occurrence the event occurrence to assign to this message.<br>
295 * @see Lifeline Lifeline for more event occurence details
297 protected void setEventOccurrence(int occurrence
) {
298 fEndEventOccurrence
= occurrence
;
302 * Returns the event occurence when is message occurs.<br>
304 * @return the event occurrence assigned to this message.<br>
305 * @see Lifeline Lifeline for more event occurence details
307 public int getEventOccurrence() {
308 return fEndEventOccurrence
;
312 * Determines if the given eventOccurence occurs on a executionOccurence owned by the sending lifeline.<br>
313 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
314 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
315 * coordinate and width.<br>
317 * @see BaseMessage#getX(boolean)
318 * @param event the event occurrence to test
319 * @return true if occurs on a execution occurrence owned by the sending lifeine, false otherwise
321 protected boolean isMessageStartInActivation(int event
) {
322 boolean inActivation
= false;
323 if ((fStartLifeline
!= null) && (fStartLifeline
.getExecutions() != null)) {
324 // int acIndex=startLifeline.getExecOccurrenceDrawIndex();
325 // acIndex = first visible execution occurrence
326 // for drawing speed reason with only search on the visivle subset
328 for (int i
= 0; i
< fStartLifeline
.getExecutions().size(); i
++) {
329 BasicExecutionOccurrence toDraw
= (BasicExecutionOccurrence
) fStartLifeline
.getExecutions().get(i
);
330 if ((event
>= toDraw
.fStartEventOccurrence
) && (event
<= toDraw
.fEndEventOccurrence
)) {
333 // if we are outside the visible area we stop right now
334 // This works because execution occurrences are ordered along the Y axis
335 if (toDraw
.getY() > thisY
) {
344 * Determines if the given event occurrence occurs on a execution occurrence owned by the receiving lifeline.<br>
345 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
346 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
347 * coordinate and width.<br>
349 * @see BaseMessage#getX(boolean)
350 * @param event the event occurrence to test
351 * @return true if occurs on a execution occurrence owned by the receiving lifeline, false otherwise
353 protected boolean isMessageEndInActivation(int event
) {
354 boolean inActivation
= false;
355 if ((fEndLifeline
!= null) && (fEndLifeline
.getExecutions() != null)) {
356 // acIndex = first visible execution occurrence
357 // for drawing speed reason with only search on the visivle subset
358 for (int i
= 0; i
< fEndLifeline
.getExecutions().size(); i
++) {
359 BasicExecutionOccurrence toDraw
= (BasicExecutionOccurrence
) fEndLifeline
.getExecutions().get(i
);
360 if ((event
>= toDraw
.fStartEventOccurrence
) && (event
<= toDraw
.fEndEventOccurrence
)) {
363 // if we are outside the visible area we stop right now
364 // This works because execution occurrences are ordered along the Y axis
365 if (toDraw
.getY() > getY()) {
375 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#contains(int, int)
378 public boolean contains(int xValue
, int yValue
) {
381 int width
= getWidth();
382 int height
= getHeight();
384 // Used to create a rectangle which contains the message label to allow selection when clicking the label
385 int tempHeight
= Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth();
387 // Is it a self message?
388 if (fStartLifeline
== fEndLifeline
) {
390 * Rectangle.contains(x,y, width, height) does not works with negative height or width We check here if the
391 * rectangle width is negative.
393 if (getName().length() * Metrics
.getAverageCharWidth() > Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2 + -Metrics
.INTERNAL_MESSAGE_WIDTH
) {
394 if (Frame
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ 10, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2 + -Metrics
.INTERNAL_MESSAGE_WIDTH
, Metrics
.getMessageFontHeigth(), xValue
, yValue
)) {
398 if (Frame
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ 10, y
, getName().length() * Metrics
.getAverageCharWidth(), Metrics
.getMessageFontHeigth(), xValue
, yValue
)) {
403 // Test if the point is in part 1 of the self message
404 // see: "private void drawMessage (NGC context)" method for self message drawing schema
405 if (Frame
.contains(x
, y
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2, Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, Metrics
.MESSAGE_SELECTION_TOLERANCE
, xValue
, yValue
)) {
409 // Test if the point is in part 3 of the self message
410 if (Frame
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2, y
, Metrics
.MESSAGE_SELECTION_TOLERANCE
, height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, xValue
, yValue
)) {
414 // Test if the point is in part 5 of the self message
415 if (Frame
.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
)) {
422 if (Frame
.contains(x
, y
- tempHeight
, width
, tempHeight
, xValue
, yValue
)) {
430 * Method to draw the message using the graphical context.
432 * @param context A graphical context to draw in.
434 protected void drawMessage(IGC context
) {
436 fX
= fY
= fW
= fH
= 0;
438 // temporary store the coordinates to avoid more methods calls
441 int width
= getWidth();
442 int height
= getHeight();
444 ISDPreferences pref
= SDViewPref
.getInstance();
446 // UML2 found message (always drawn from left to right)
447 // or UML2 lost message (always drawn from left to right)
448 if ((fStartLifeline
== null || fEndLifeline
== null) && fStartLifeline
!= fEndLifeline
) {
449 // Draw the message label above the message and centered
450 // The label is truncated if it cannot fit between the two message end
451 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
452 IColor temp
= context
.getForeground();
453 context
.setForeground(pref
.getFontColor(fPrefId
));
454 context
.drawTextTruncatedCentred(getName(), x
, y
- Metrics
.getMessageFontHeigth() - 2 * Metrics
.MESSAGES_NAME_SPACING
, width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth(), !isSelected());
455 context
.setForeground(temp
);
457 if (fEndLifeline
== null) {
458 margin
= Metrics
.MESSAGE_CIRCLE_RAY
;
461 // Draw the message main line
462 context
.drawLine(x
, y
, x
+ width
, y
+ height
);
463 // Draw the two little lines which make a arrow part of the message
464 Double xt
= Double
.valueOf(Math
.cos(0.75) * 7);
465 Double yt
= Double
.valueOf(Math
.sin(0.75) * 7);
466 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
467 IColor backcolor
= context
.getBackground();
468 context
.setBackground(context
.getForeground());
469 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
};
470 context
.fillPolygon(points
);
471 context
.drawPolygon(points
);
472 context
.setBackground(backcolor
);
474 int currentStyle
= context
.getLineStyle();
475 int currentWidth
= context
.getLineWidth();
476 context
.setLineWidth(currentWidth
+ 2);
477 context
.setLineStyle(context
.getLineSolidStyle());
478 context
.drawLine(x
+ width
- xt
.intValue() - margin
, y
+ height
- yt
.intValue(), x
+ width
- margin
, y
+ height
);
479 context
.drawLine(x
+ width
- xt
.intValue() - margin
, y
+ height
+ yt
.intValue(), x
+ width
- margin
, y
+ height
);
480 context
.setLineStyle(currentStyle
);
481 context
.setLineWidth(currentWidth
);
483 IColor storedColor
= context
.getBackground();
484 context
.setBackground(context
.getForeground());
486 // Draw a circle at the message end (endLifeline side)
487 int ray
= Metrics
.MESSAGE_CIRCLE_RAY
;
488 if (context
.getLineWidth() != Metrics
.NORMAL_LINE_WIDTH
) {
489 ray
= ray
+ Metrics
.SELECTION_LINE_WIDTH
- Metrics
.NORMAL_LINE_WIDTH
;
491 if (fStartLifeline
== null) {
492 context
.fillOval(x
- ray
, y
- ray
, ray
* 2, ray
* 2);
494 context
.fillOval(x
+ width
- ray
, y
+ height
- ray
, ray
* 2, ray
* 2);
496 context
.setBackground(storedColor
);
497 context
.setForeground(pref
.getFontColor(fPrefId
));
499 fY
= y
- yt
.intValue();
501 fH
= height
+ 2 * yt
.intValue();
503 // it is self message (always drawn at the left side of the owning lifeLifeline)
504 else if (fStartLifeline
!= null && fEndLifeline
!= null && fStartLifeline
== fEndLifeline
) {
506 * Self syncMessages are drawn in 5 parts 1 -----------+ + 2 + | | | 3 | + 5 + 4 -----------+
508 int tempy
= Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2;
509 if (Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
<= Metrics
.INTERNAL_MESSAGE_WIDTH
) {
510 tempy
= Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
/ 2;
514 context
.drawLine(x
, y
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
);
516 context
.drawLine(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ tempy
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- tempy
);
518 context
.drawLine(x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
520 Double xt
= Double
.valueOf(Math
.cos(0.75) * 7);
521 Double yt
= Double
.valueOf(Math
.sin(0.75) * 7);
525 fW
= Metrics
.INTERNAL_MESSAGE_WIDTH
;
526 fH
= height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
;
528 // Draw the two little lines which make a arrow part of the message
529 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
530 IColor backcolor
= context
.getBackground();
531 context
.setBackground(context
.getForeground());
532 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(),
533 y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
};
534 context
.fillPolygon(points
);
535 context
.drawPolygon(points
);
536 context
.setBackground(backcolor
);
538 int currentStyle
= context
.getLineStyle();
539 int currentWidth
= context
.getLineWidth();
540 context
.setLineWidth(currentWidth
+ 2);
541 context
.setLineStyle(context
.getLineSolidStyle());
542 context
.drawLine(x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
543 context
.drawLine(x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
544 context
.setLineStyle(currentStyle
);
545 context
.setLineWidth(currentWidth
);
549 context
.drawArc(x
, y
, Metrics
.INTERNAL_MESSAGE_WIDTH
, 2 * tempy
, 0, 90);
551 context
.drawArc(x
, y
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, Metrics
.INTERNAL_MESSAGE_WIDTH
, -2 * tempy
, 0, -90);
553 // Draw the message label above the message and centered
554 // The label is truncated if it cannot fit between the two message end
555 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
557 // the space available for the text is sorter if are drawing internal message on the last lifeline
558 context
.setForeground(pref
.getFontColor(fPrefId
));
559 if (fStartLifeline
.getIndex() == fStartLifeline
.getFrame().getHorizontalIndex()) {
560 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
561 - Metrics
.getMessageFontHeigth(), !isSelected());
563 context
.drawTextTruncated(getName(), x
+ width
+ Metrics
.INTERNAL_MESSAGE_V_MARGIN
/ 2, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
+ -Metrics
.INTERNAL_MESSAGE_WIDTH
,
564 +Metrics
.MESSAGES_NAME_SPACING
- Metrics
.getMessageFontHeigth(), !isSelected());
567 // it is regular message
568 else if (fStartLifeline
!= null && fEndLifeline
!= null) {
569 // Draw the message main line
570 context
.drawLine(x
, y
, x
+ width
, y
+ height
);
572 int spaceBTWStartEnd
= fEndLifeline
.getX() - fStartLifeline
.getX();
576 double angle
= Math
.atan(a
/ b
);
577 // Compute the coordinates of the two little lines which make the arrow part of the message
579 if (spaceBTWStartEnd
< 0) {
582 Double x1
= Double
.valueOf(sign
* Math
.cos(angle
- 0.75) * 7);
583 Double y1
= Double
.valueOf(sign
* Math
.sin(angle
- 0.75) * 7);
584 Double x2
= Double
.valueOf(sign
* Math
.cos(angle
+ 0.75) * 7);
585 Double y2
= Double
.valueOf(sign
* Math
.sin(angle
+ 0.75) * 7);
588 fY
= y
+ height
- y2
.intValue();
590 fH
= y2
.intValue() - y1
.intValue() + 1;
601 // Draw the two little lines which make a arrow part of the message
602 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
603 IColor backcolor
= context
.getBackground();
604 context
.setBackground(context
.getForeground());
605 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() };
606 context
.fillPolygon(points
);
607 context
.drawPolygon(points
);
608 context
.setBackground(backcolor
);
610 int currentStyle
= context
.getLineStyle();
611 int currentWidth
= context
.getLineWidth();
612 context
.setLineWidth(currentWidth
+ 2);
613 context
.setLineStyle(context
.getLineSolidStyle());
614 context
.drawLine(x
+ width
- x1
.intValue(), y
+ height
- y1
.intValue(), x
+ width
, y
+ height
);
615 context
.drawLine(x
+ width
- x2
.intValue(), y
+ height
- y2
.intValue(), x
+ width
, y
+ height
);
616 context
.setLineStyle(currentStyle
);
617 context
.setLineWidth(currentWidth
);
620 // Draw the message label above the message and centered
621 // The label is truncated if it cannot fit between the two message end
622 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
623 context
.setForeground(pref
.getFontColor(fPrefId
));
624 if (spaceBTWStartEnd
> 0) {
625 context
.drawTextTruncatedCentred(getName(), x
, y
+ height
/ 2 - (2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()), width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth(), !isSelected());
627 context
.drawTextTruncatedCentred(getName(), x
+ width
, y
+ height
/ 2 - (2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()), -width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ +Metrics
.getMessageFontHeigth(), !isSelected());
634 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNodee#draw(org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC)
637 public void draw(IGC context
) {
642 // Draw it selected?*/
644 ISDPreferences pref
= SDViewPref
.getInstance();
646 * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
647 * colors This create the highlight effect
649 context
.setForeground(pref
.getBackGroundColorSelection());
650 context
.setLineWidth(Metrics
.SELECTION_LINE_WIDTH
);
651 drawMessage(context
);
652 context
.setBackground(pref
.getBackGroundColorSelection());
653 context
.setForeground(pref
.getForeGroundColorSelection());
654 // Second drawing is done after
656 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
658 context
.setDrawTextWithFocusStyle(true);
660 drawMessage(context
);
661 int oldStyle
= context
.getLineStyle();
663 context
.setDrawTextWithFocusStyle(false);
666 // restore the context
667 context
.setLineStyle(oldStyle
);
671 * Determine if two messages are identical. This default implementation considers that overlapping messages with
672 * same coordinates are identical.
674 * @param message - the message to compare with
675 * @return true if identical false otherwise
677 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#isSameAs(org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode)
680 public boolean isSameAs(GraphNode message
) {
681 if (message
== null) {
684 if (!(message
instanceof BaseMessage
)) {
685 return super.isSameAs(message
);
687 return ((getX() == message
.getX()) && (getY() == message
.getY()) && (getWidth() == message
.getWidth()) && (getHeight() == message
.getHeight()));
693 * @param x A x coordinate
694 * @param y A y coordinate
697 * @param context A graphical context
699 public void drawRot(int x
, int y
, int w
, int h
, IGC context
) {
700 double angleA
= Math
.atan2(getHeight(), getWidth());
701 double cosA
= Math
.cos(angleA
);
702 double sinA
= Math
.sin(angleA
);
708 localHeight
= localHeight
/ 2;
710 double cw
= Math
.sqrt(w
* w
+ getHeight() * getHeight());
712 int x1
= Math
.round((float) ((x
- gx
) * cosA
- (y
- gy
) * sinA
));
713 int y1
= Math
.round((float) ((x
- gx
) * sinA
+ (y
- gy
) * cosA
));
715 int x2
= Math
.round((float) (cw
* cosA
- (y
- gy
) * sinA
));
716 int y2
= Math
.round((float) (cw
* sinA
+ (y
- gy
) * cosA
));
718 int x3
= Math
.round((float) (cw
* cosA
- (localHeight
) * sinA
));
719 int y3
= Math
.round((float) (cw
* sinA
+ (localHeight
) * cosA
));
721 int x4
= Math
.round((float) ((x
- gx
) * cosA
- (localHeight
) * sinA
));
722 int y4
= Math
.round((float) ((x
- gx
) * sinA
+ (localHeight
) * cosA
));
724 int[] points
= { x1
+ getX(), y1
+ getY(), x2
+ getX(), y2
+ getY(), x3
+ getX(), y3
+ getY(), x4
+ getX(), y4
+ getY() };
725 context
.drawPolygon(points
);
730 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#drawFocus(org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC)
733 public void drawFocus(IGC context
) {
735 ISDPreferences pref
= SDViewPref
.getInstance();
737 if ((fStartLifeline
!= fEndLifeline
) && (fStartEventOccurrence
== fEndEventOccurrence
)) {
738 context
.setLineStyle(context
.getLineDotStyle());
739 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
740 context
.setBackground(pref
.getBackGroundColorSelection());
741 context
.setForeground(pref
.getForeGroundColorSelection());
742 context
.drawFocus(getX(), getY() - 3, getWidth(), getHeight() + 6);
743 } else if ((fStartLifeline
== fEndLifeline
) && (fStartEventOccurrence
== fEndEventOccurrence
)) {
744 context
.drawFocus(getX(), getY() - 3, getWidth(), Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ 6);
745 } else if ((fStartLifeline
!= fEndLifeline
) && (fStartEventOccurrence
!= fEndEventOccurrence
)) {
746 context
.setLineStyle(context
.getLineDotStyle());
747 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
748 context
.setBackground(pref
.getBackGroundColor(ISDPreferences
.PREF_LIFELINE_HEADER
));
749 context
.setForeground(pref
.getForeGroundColor(ISDPreferences
.PREF_LIFELINE_HEADER
));
750 drawRot(getX(), getY() - 5, getWidth(), 10, context
);
752 super.drawFocus(context
);