1 /**********************************************************************
2 * Copyright (c) 2005, 2008, 2011 IBM Corporation and others.
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 * $Id: BaseMessage.java,v 1.3 2008/01/24 02:28:49 apnan Exp $
10 * IBM - Initial API and implementation
11 * Bernd Hufmann - Updated for TMF
12 **********************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.core
;
15 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.IColor
;
16 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.IGC
;
17 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.ISDPreferences
;
20 * The base UML2 syncMessages implementation.<br>
21 * This abstract class only define one event occurrence to attach to the message.<br>
22 * Usually a message has two event occurrences attached, one for both ends. But some syncMessages(like synchronous
23 * syncMessages) only need one event occurrence to represent the time when they appear. Others kind of message
24 * representations (like asynchronous syncMessages) will be responsible to define the missing second eventOccurrence
28 * @see Lifeline Lifeline for more event occurence details
31 public abstract class BaseMessage
extends GraphNode
{
34 * The lifeline which send the message
36 protected Lifeline startLifeline
= null;
39 * The lifeline which receive the message
41 protected Lifeline endLifeline
= null;
43 protected boolean visible
= true;
47 // returns the exact x coordinate
54 * Note: lifeline.getY() return the y coordinate of the top left corner of the rectangle which contain the
55 * lifeline name getHeight return the height of this rectangle The message y coordinate is then relative to this
56 * position depending of its eventOccurrence Space between syncMessages is constant
58 if ((startLifeline
!= null) && (endLifeline
!= null)) {
60 * Regular message, both ends are attached to a lifeline
62 return endLifeline
.getY() + endLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * endEventOccurrence
;
66 * UML2 lost message kind
68 if (startLifeline
!= null) {
69 return startLifeline
.getY() + startLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * endEventOccurrence
;
73 * UML2 found message kind
75 if (endLifeline
!= null) {
76 return endLifeline
.getY() + endLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * endEventOccurrence
;
79 // return 0 by default
84 public int getWidth() {
85 // Returns the exact width
86 return getWidth(false);
90 public int getHeight() {
95 * Returns the graph node x coordinate.<br>
96 * Depending on the quick parameter a approximative or exact value is return.<br>
97 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
99 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
100 * affect the message x coordinate and width.<br>
102 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
105 * @param quick true to get an approximative value<br>
106 * false to get the exact x value<br>
107 * @return the graph node x coordinate
109 protected int getX(boolean quick
) {
111 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
112 if ((startLifeline
!= null) && (endLifeline
!= null)) {
113 x
= startLifeline
.getX() + Metrics
.getLifelineWidth() / 2;
115 if (startLifeline
!= null) {
116 x
= startLifeline
.getX() + Metrics
.getLifelineWidth() / 2;
119 if (endLifeline
!= null) {
120 x
= endLifeline
.getX() - Metrics
.LIFELINE_SPACING
/ 2;
127 if ((startLifeline
!= null) && (endLifeline
!= null) && (startLifeline
.getX() > endLifeline
.getX())) {
128 activationWidth
= -activationWidth
;
131 if (isMessageStartInActivation(endEventOccurrence
)) {
132 x
= x
+ activationWidth
;
139 * Returns the graph node width.<br>
140 * Depending on the quick parameter a approximative or exact value is returned.<br>
141 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
143 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
144 * affect the message x coordinate and width.<br>
146 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
149 * @param quick true to get an approximative value<br>
150 * false to get the exact x value
151 * @return the graph node width
153 protected int getWidth(boolean quick
) {
155 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
156 if ((startLifeline
!= null) && (endLifeline
!= null)) {
157 if (startLifeline
== endLifeline
)
158 width
= Metrics
.INTERNAL_MESSAGE_WIDTH
+ Metrics
.EXECUTION_OCCURRENCE_WIDTH
;
160 width
= endLifeline
.getX() + Metrics
.getLifelineWidth() / 2 - getX(true);
162 if (startLifeline
!= null) {
163 width
= Metrics
.swimmingLaneWidth() / 2;
165 if (endLifeline
!= null) {
166 width
= Metrics
.swimmingLaneWidth() / 2;
173 if ((startLifeline
!= null) && (endLifeline
!= null) && (startLifeline
.getX() > endLifeline
.getX())) {
174 activationWidth
= -activationWidth
;
177 if (isMessageStartInActivation(endEventOccurrence
))
178 width
= width
- activationWidth
;
180 if (isMessageEndInActivation(endEventOccurrence
))
181 width
= width
- activationWidth
;
187 public boolean isVisible(int x
, int y
, int width
, int height
) {
188 // ***Common*** syncMessages visibility
189 // draw the message only if at least one end is visible
190 if (endLifeline
!= null && (endLifeline
.isVisible(x
, y
, width
, height
)) || (startLifeline
!= null && startLifeline
.isVisible(x
, y
, width
, height
)))
192 // In this case it can be a message which cross the whole visible area
193 else if (endLifeline
!= null && (!endLifeline
.isVisible(x
, y
, width
, height
)) && (startLifeline
!= null && !startLifeline
.isVisible(x
, y
, width
, height
))) {
194 if (endLifeline
.getX() > x
+ width
&& startLifeline
.getX() < x
)
196 else if (startLifeline
.getX() > x
+ width
&& endLifeline
.getX() < x
)
202 public void setVisible(boolean value
) {
206 public boolean isVisible() {
211 * Set the lifeline from which this message has been sent.
213 * @param lifeline - the message sender
215 public void setStartLifeline(Lifeline lifeline
) {
216 startLifeline
= lifeline
;
220 * Returns the lifeline from which this message has been sent.
222 * @return the message sender
224 public Lifeline
getStartLifeline() {
225 return startLifeline
;
229 * Returns the lifeline which has received this message.
231 * @return the message receiver
233 public Lifeline
getEndLifeline() {
238 * Set the lifeline which has receive this message.
240 * @param lifeline the message receiver
242 public void setEndLifeline(Lifeline lifeline
) {
243 endLifeline
= lifeline
;
247 * Set the event occurrence when this message occurs.<br>
249 * @param occurrence the event occurrence to assign to this message.<br>
250 * @see Lifeline Lifeline for more event occurence details
252 protected void setEventOccurrence(int occurrence
) {
253 endEventOccurrence
= occurrence
;
257 * Returns the event occurence when is message occurs.<br>
259 * @return the event occurrence assigned to this message.<br>
260 * @see Lifeline Lifeline for more event occurence details
262 public int getEventOccurrence() {
263 return endEventOccurrence
;
267 * Determines if the given eventOccurence occurs on a executionOccurence owned by the sending lifeline.<br>
268 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
269 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
270 * coordinate and width.<br>
272 * @see BaseMessage#getX(boolean)
273 * @param event the event occurrence to test
274 * @return true if occurs on a execution occurrence owned by the sending lifeine, false otherwise
276 protected boolean isMessageStartInActivation(int event
) {
277 boolean inActivation
= false;
278 if ((startLifeline
!= null) && (startLifeline
.getExecutions() != null)) {
279 // int acIndex=startLifeline.getExecOccurrenceDrawIndex();
280 // acIndex = first visible execution occurrence
281 // for drawing speed reason with only search on the visivle subset
283 for (int i
= 0; i
< startLifeline
.getExecutions().size(); i
++) {
284 BasicExecutionOccurrence toDraw
= (BasicExecutionOccurrence
) startLifeline
.getExecutions().get(i
);
285 if ((event
>= toDraw
.startEventOccurrence
) && (event
<= toDraw
.endEventOccurrence
))
287 // if we are outside the visible area we stop right now
288 // This works because execution occurrences are ordered along the Y axis
289 if (toDraw
.getY() > thisY
)
297 * Determines if the given event occurrence occurs on a execution occurrence owned by the receiving lifeline.<br>
298 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
299 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
300 * coordinate and width.<br>
302 * @see BaseMessage#getX(boolean)
303 * @param event the event occurrence to test
304 * @return true if occurs on a execution occurrence owned by the receiving lifeline, false otherwise
306 protected boolean isMessageEndInActivation(int event
) {
307 boolean inActivation
= false;
308 if ((endLifeline
!= null) && (endLifeline
.getExecutions() != null)) {
309 // acIndex = first visible execution occurrence
310 // for drawing speed reason with only search on the visivle subset
311 for (int i
= 0; i
< endLifeline
.getExecutions().size(); i
++) {
312 BasicExecutionOccurrence toDraw
= (BasicExecutionOccurrence
) endLifeline
.getExecutions().get(i
);
313 if ((event
>= toDraw
.startEventOccurrence
) && (event
<= toDraw
.endEventOccurrence
))
315 // if we are outside the visible area we stop right now
316 // This works because execution occurrences are ordered along the Y axis
317 if (toDraw
.getY() > getY())
325 * Returns true if the message or the message label contains the point given in parameter
328 public boolean contains(int _x
, int _y
) {
331 int width
= getWidth();
332 int height
= getHeight();
334 // Used to create a rectangle which contains the message label to allow selection when clicking the label
335 int tempHeight
= Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth();
337 // Is it a self message?
338 if (startLifeline
== endLifeline
) {
340 * Rectangle.contains(x,y, width, height) does not works with negative height or width We check here if the
341 * rectangle width is negative.
343 if (getName().length() * Metrics
.getAverageCharWidth() > Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2 + -Metrics
.INTERNAL_MESSAGE_WIDTH
) {
344 if (Frame
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ 10, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2 + -Metrics
.INTERNAL_MESSAGE_WIDTH
, Metrics
.getMessageFontHeigth(), _x
, _y
))
347 if (Frame
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ 10, y
, getName().length() * Metrics
.getAverageCharWidth(), Metrics
.getMessageFontHeigth(), _x
, _y
))
351 // Test if the point is in part 1 of the self message
352 // see: "private void drawMessage (NGC context)" method for self message drawing schema
353 if (Frame
.contains(x
, y
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2, Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, Metrics
.MESSAGE_SELECTION_TOLERANCE
, _x
, _y
))
356 // Test if the point is in part 3 of the self message
357 if (Frame
.contains(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
- Metrics
.MESSAGE_SELECTION_TOLERANCE
/ 2, y
, Metrics
.MESSAGE_SELECTION_TOLERANCE
, height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, _x
, _y
))
360 // Test if the point is in part 5 of the self message
361 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
, _x
, _y
))
367 if (Frame
.contains(x
, y
- tempHeight
, width
, tempHeight
, _x
, _y
))
373 protected void drawMessage(IGC context
) {
375 fX
= fY
= fW
= fH
= 0;
377 // temporay store the coordinates to avoid more methods calls
380 int width
= getWidth();
381 int height
= getHeight();
383 // UML2 found message (always drawn from left to right)
384 // or UML2 lost message (always drawn from left to right)
385 if ((startLifeline
== null || endLifeline
== null) && startLifeline
!= endLifeline
) {
386 // Draw the message label above the message and centered
387 // The label is truncated if it cannot fit between the two message end
388 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
389 IColor temp
= context
.getForeground();
390 context
.setForeground(Frame
.getUserPref().getFontColor(prefId
));
391 context
.drawTextTruncatedCentred(getName(), x
, y
- Metrics
.getMessageFontHeigth() - 2 * Metrics
.MESSAGES_NAME_SPACING
, width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth(), !isSelected());
392 context
.setForeground(temp
);
394 if (endLifeline
== null)
395 margin
= Metrics
.MESSAGE_CIRCLE_RAY
;
397 // Draw the message main line
398 context
.drawLine(x
, y
, x
+ width
, y
+ height
);
399 // Draw the two little lines which make a arrow part of the message
400 Double xt
= new Double(Math
.cos(0.75) * 7);
401 Double yt
= new Double(Math
.sin(0.75) * 7);
402 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
403 IColor backcolor
= context
.getBackground();
404 context
.setBackground(context
.getForeground());
405 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
};
406 context
.fillPolygon(points
);
407 context
.drawPolygon(points
);
408 context
.setBackground(backcolor
);
410 int currentStyle
= context
.getLineStyle();
411 int currentWidth
= context
.getLineWidth();
412 context
.setLineWidth(currentWidth
+ 2);
413 context
.setLineStyle(context
.getLineSolidStyle());
414 context
.drawLine(x
+ width
- xt
.intValue() - margin
, y
+ height
- yt
.intValue(), x
+ width
- margin
, y
+ height
);
415 context
.drawLine(x
+ width
- xt
.intValue() - margin
, y
+ height
+ yt
.intValue(), x
+ width
- margin
, y
+ height
);
416 context
.setLineStyle(currentStyle
);
417 context
.setLineWidth(currentWidth
);
419 IColor storedColor
= context
.getBackground();
420 context
.setBackground(context
.getForeground());
422 // Draw a circle at the message end (endLifeline side)
423 int ray
= Metrics
.MESSAGE_CIRCLE_RAY
;
424 if (context
.getLineWidth() != Metrics
.NORMAL_LINE_WIDTH
)
425 ray
= ray
+ Metrics
.SELECTION_LINE_WIDTH
- Metrics
.NORMAL_LINE_WIDTH
;
426 if (startLifeline
== null)
427 context
.fillOval(x
- ray
, y
- ray
, ray
* 2, ray
* 2);
429 context
.fillOval(x
+ width
- ray
, y
+ height
- ray
, ray
* 2, ray
* 2);
430 context
.setBackground(storedColor
);
431 context
.setForeground(Frame
.getUserPref().getFontColor(prefId
));
433 fY
= y
- yt
.intValue();
435 fH
= height
+ 2 * yt
.intValue();
437 // it is self message (always drawn at the left side of the owning lifeLifeline)
438 else if (startLifeline
!= null && endLifeline
!= null && startLifeline
== endLifeline
) {
440 * Self syncMessages are drawn in 5 parts 1 -----------+ + 2 + | | | 3 | + 5 + 4 -----------+
442 int tempy
= Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2;
443 if (Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
<= Metrics
.INTERNAL_MESSAGE_WIDTH
)
444 tempy
= Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
/ 2;
447 context
.drawLine(x
, y
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
);
449 context
.drawLine(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ tempy
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- tempy
);
451 context
.drawLine(x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
453 Double xt
= new Double(Math
.cos(0.75) * 7);
454 Double yt
= new Double(Math
.sin(0.75) * 7);
458 fW
= Metrics
.INTERNAL_MESSAGE_WIDTH
;
459 fH
= height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
;
461 // Draw the two little lines which make a arrow part of the message
462 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
463 IColor backcolor
= context
.getBackground();
464 context
.setBackground(context
.getForeground());
465 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(),
466 y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
};
467 context
.fillPolygon(points
);
468 context
.drawPolygon(points
);
469 context
.setBackground(backcolor
);
471 int currentStyle
= context
.getLineStyle();
472 int currentWidth
= context
.getLineWidth();
473 context
.setLineWidth(currentWidth
+ 2);
474 context
.setLineStyle(context
.getLineSolidStyle());
475 context
.drawLine(x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
476 context
.drawLine(x
+ xt
.intValue(), y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
- yt
.intValue(), x
, y
+ height
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
);
477 context
.setLineStyle(currentStyle
);
478 context
.setLineWidth(currentWidth
);
482 context
.drawArc(x
, y
, Metrics
.INTERNAL_MESSAGE_WIDTH
, 2 * tempy
, 0, 90);
484 context
.drawArc(x
, y
+ Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
, Metrics
.INTERNAL_MESSAGE_WIDTH
, -2 * tempy
, 0, -90);
486 // Draw the message label above the message and centered
487 // The label is truncated if it cannot fit between the two message end
488 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
490 // the space available for the text is sorter if are drawing internal message on the last lifeline
491 context
.setForeground(Frame
.getUserPref().getFontColor(prefId
));
492 if (startLifeline
.getIndex() == startLifeline
.getFrame().getHorizontalIndex())
493 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
494 - Metrics
.getMessageFontHeigth(), !isSelected());
496 context
.drawTextTruncated(getName(), x
+ width
+ Metrics
.INTERNAL_MESSAGE_V_MARGIN
/ 2, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
+ -Metrics
.INTERNAL_MESSAGE_WIDTH
,
497 +Metrics
.MESSAGES_NAME_SPACING
- Metrics
.getMessageFontHeigth(), !isSelected());
499 // it is regular message
500 else if (startLifeline
!= null && endLifeline
!= null) {
501 // Draw the message main line
502 context
.drawLine(x
, y
, x
+ width
, y
+ height
);
504 int spaceBTWStartEnd
= endLifeline
.getX() - startLifeline
.getX();
508 double angle
= Math
.atan(a
/ b
);
509 // Compute the coordinates of the two little lines which make the arrow part of the message
511 if (spaceBTWStartEnd
< 0)
513 Double x1
= new Double(sign
* Math
.cos(angle
- 0.75) * 7);
514 Double y1
= new Double(sign
* Math
.sin(angle
- 0.75) * 7);
515 Double x2
= new Double(sign
* Math
.cos(angle
+ 0.75) * 7);
516 Double y2
= new Double(sign
* Math
.sin(angle
+ 0.75) * 7);
519 fY
= y
+ height
- y2
.intValue();
521 fH
= y2
.intValue() - y1
.intValue() + 1;
532 // Draw the two little lines which make a arrow part of the message
533 if (context
.getLineStyle() == context
.getLineSolidStyle()) {
534 IColor backcolor
= context
.getBackground();
535 context
.setBackground(context
.getForeground());
536 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() };
537 context
.fillPolygon(points
);
538 context
.drawPolygon(points
);
539 context
.setBackground(backcolor
);
541 int currentStyle
= context
.getLineStyle();
542 int currentWidth
= context
.getLineWidth();
543 context
.setLineWidth(currentWidth
+ 2);
544 context
.setLineStyle(context
.getLineSolidStyle());
545 context
.drawLine(x
+ width
- x1
.intValue(), y
+ height
- y1
.intValue(), x
+ width
, y
+ height
);
546 context
.drawLine(x
+ width
- x2
.intValue(), y
+ height
- y2
.intValue(), x
+ width
, y
+ height
);
547 context
.setLineStyle(currentStyle
);
548 context
.setLineWidth(currentWidth
);
551 // Draw the message label above the message and centered
552 // The label is truncated if it cannot fit between the two message end
553 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
554 context
.setForeground(Frame
.getUserPref().getFontColor(prefId
));
555 if (spaceBTWStartEnd
> 0)
556 context
.drawTextTruncatedCentred(getName(), x
, y
+ height
/ 2 - (2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()), width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth(), !isSelected());
558 context
.drawTextTruncatedCentred(getName(), x
+ width
, y
+ height
/ 2 - (2 * Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()), -width
, 2 * Metrics
.MESSAGES_NAME_SPACING
+ +Metrics
.getMessageFontHeigth(), !isSelected());
563 public void draw(IGC context
) {
566 // Draw it selected?*/
570 * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
571 * colors This create the highlight effect
573 context
.setForeground(Frame
.getUserPref().getBackGroundColorSelection());
574 context
.setLineWidth(Metrics
.SELECTION_LINE_WIDTH
);
575 drawMessage(context
);
576 context
.setBackground(Frame
.getUserPref().getBackGroundColorSelection());
577 context
.setForeground(Frame
.getUserPref().getForeGroundColorSelection());
578 // Second drawing is done after
580 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
582 context
.setDrawTextWithFocusStyle(true);
584 drawMessage(context
);
585 int oldStyle
= context
.getLineStyle();
587 context
.setDrawTextWithFocusStyle(false);
590 // restore the context
591 context
.setLineStyle(oldStyle
);
595 * Determine if two messages are identical. This default implementation considers that overlapping messages with
596 * same coordinates are identical.
598 * @param message - the message to compare with
599 * @return true if identical false otherwise
602 public boolean isSameAs(GraphNode message
) {
605 if (!(message
instanceof BaseMessage
))
606 return super.isSameAs(message
);
607 if (getX() == message
.getX() && getY() == message
.getY() && getWidth() == message
.getWidth() && getHeight() == message
.getHeight())
613 public void drawRot(int x
, int y
, int w
, int h
, IGC context
) {
614 double angleA
= Math
.atan2(getHeight(), getWidth());
615 double cosA
= Math
.cos(angleA
);
616 double sinA
= Math
.sin(angleA
);
623 double cw
= Math
.sqrt(w
* w
+ getHeight() * getHeight());
625 int x1
= Math
.round((float) ((x
- gx
) * cosA
- (y
- gy
) * sinA
));
626 int y1
= Math
.round((float) ((x
- gx
) * sinA
+ (y
- gy
) * cosA
));
628 int x2
= Math
.round((float) (cw
* cosA
- (y
- gy
) * sinA
));
629 int y2
= Math
.round((float) (cw
* sinA
+ (y
- gy
) * cosA
));
631 int x3
= Math
.round((float) (cw
* cosA
- (h
) * sinA
));
632 int y3
= Math
.round((float) (cw
* sinA
+ (h
) * cosA
));
634 int x4
= Math
.round((float) ((x
- gx
) * cosA
- (h
) * sinA
));
635 int y4
= Math
.round((float) ((x
- gx
) * sinA
+ (h
) * cosA
));
637 int[] points
= { x1
+ getX(), y1
+ getY(), x2
+ getX(), y2
+ getY(), x3
+ getX(), y3
+ getY(), x4
+ getX(), y4
+ getY() };
638 context
.drawPolygon(points
);
642 public void drawFocus(IGC context
) {
643 if ((startLifeline
!= endLifeline
) && (startEventOccurrence
== endEventOccurrence
)) {
644 context
.setLineStyle(context
.getLineDotStyle());
645 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
646 context
.setBackground(Frame
.getUserPref().getBackGroundColorSelection());
647 context
.setForeground(Frame
.getUserPref().getForeGroundColorSelection());
648 context
.drawFocus(getX(), getY() - 3, getWidth(), getHeight() + 6);
649 } else if ((startLifeline
== endLifeline
) && (startEventOccurrence
== endEventOccurrence
)) {
650 context
.drawFocus(getX(), getY() - 3, getWidth(), Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
+ 6);
651 } else if ((startLifeline
!= endLifeline
) && (startEventOccurrence
!= endEventOccurrence
)) {
652 context
.setLineStyle(context
.getLineDotStyle());
653 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
654 context
.setBackground(Frame
.getUserPref().getBackGroundColor(ISDPreferences
.PREF_LIFELINE_HEADER
));
655 context
.setForeground(Frame
.getUserPref().getForeGroundColor(ISDPreferences
.PREF_LIFELINE_HEADER
));
656 drawRot(getX(), getY() - 5, getWidth(), 10, context
);
658 super.drawFocus(context
);