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: AsyncMessage.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 java
.util
.Comparator
;
17 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
18 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
19 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.IGC
;
20 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.ISDPreferences
;
21 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.util
.SortAsyncForBackward
;
22 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.util
.SortAsyncMessageComparator
;
25 * A AsyncMessage is a asynchronous message which appear at two different event occurrences on each lifeline ends (sender
36 * AsyncMessage message = new AsyncMessage();
37 * // Create a new event occurrence on each lifeline
38 * lifeline1.getNewOccurrenceIndex();
39 * lifeline2.getNewOccurrenceIndex();
40 * // Set the message sender and receiver
41 * message.setStartLifeline(lifeLine1);
42 * message.setEndLifline(lifeline2);
43 * message.setName("Message label");
44 * // add the message to the frame
45 * frame.addMessage(message);
48 * @see Lifeline Lifeline for more event occurence details
52 public class AsyncMessage
extends BaseMessage
implements ITimeRange
{
54 protected boolean hasTime
= false;
56 * The time when the message begin
58 protected ITmfTimestamp endTime
= new TmfTimestamp();
61 * The time when the message end
63 protected ITmfTimestamp startTime
= new TmfTimestamp();
66 * The associated message.
68 protected AsyncMessageReturn messageReturn
= null;
70 public static final String ASYNC_MESS_TAG
= "AsyncMessage"; //$NON-NLS-1$
72 public AsyncMessage() {
73 prefId
= ISDPreferences
.PREF_ASYNC_MESS
;
78 int x
= super.getX(true);
79 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
80 if ((startLifeline
!= null) && (endLifeline
!= null) && (startLifeline
.getX() > endLifeline
.getX())) {
81 activationWidth
= -activationWidth
;
84 if (isMessageStartInActivation(startEventOccurrence
)) {
85 x
= x
+ activationWidth
;
92 if ((startLifeline
!= null) && (endLifeline
!= null)) {
93 return endLifeline
.getY() + endLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * startEventOccurrence
;
99 public int getWidth() {
100 int width
= super.getWidth(true);
101 int activationWidth
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
102 if ((startLifeline
!= null) && (endLifeline
!= null) && (startLifeline
.getX() > endLifeline
.getX())) {
103 activationWidth
= -activationWidth
;
106 if (isMessageStartInActivation(startEventOccurrence
))
107 width
= width
- activationWidth
;
109 if (isMessageEndInActivation(endEventOccurrence
))
110 width
= width
- activationWidth
;
116 public int getHeight() {
117 if ((startLifeline
!= null) && (endLifeline
!= null)) {
118 return (endLifeline
.getY() + endLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * endEventOccurrence
) - getY();
120 return super.getHeight();
124 * Set the message return associated with this message.
126 * @param message the message return to associate
128 protected void setMessageReturn(AsyncMessageReturn message
) {
129 messageReturn
= message
;
133 * Set the event occurrence attached to this message for its end lifeline
135 * @param occurrence the event occurrence to set
137 public void setEndOccurrence(int occurrence
) {
138 endEventOccurrence
= occurrence
;
139 if (getStartLifeline() == null)
140 startEventOccurrence
= occurrence
;
141 informFrame(getEndLifeline(), occurrence
);
144 protected void informFrame(Lifeline lifeLine
, int occurrence
) {
145 if ((lifeLine
!= null) && (lifeLine
.getFrame() != null))
146 if (lifeLine
.getFrame().getMaxEventOccurrence() < occurrence
)
147 lifeLine
.getFrame().setMaxEventOccurrence(occurrence
);
151 * Set the event occurrence attached to this message for its start lifeline
153 * @param occurrence the event occurrence to set
155 public void setStartOccurrence(int occurrence
) {
156 startEventOccurrence
= occurrence
;
157 if (getEndLifeline() == null)
158 endEventOccurrence
= startEventOccurrence
;
159 informFrame(getStartLifeline(), occurrence
);
163 * Set the lifeLine which has sent the message.<br>
164 * A new EventOccurence will be create on this lifeLine.<br>
166 * @param lifeline the message sender
167 * @param autoCreateEvent if true, create an eventOccurence lifeline given in parameter
169 public void autoSetStartLifeline(Lifeline lifeline
) {
170 lifeline
.getNewEventOccurrence();
171 setStartLifeline(lifeline
);
175 * Set the lifeLine which has received the message.<br>
176 * A new EventOccurence will be create on this lifeLine.<br>
178 * @param lifeline the message receiver
179 * @param autoCreateEvent if true, create an eventOccurence lifeline given in parameter
181 public void autoSetEndLifeline(Lifeline lifeline
) {
182 lifeline
.getNewEventOccurrence();
183 setEndLifeline(lifeline
);
187 * Set the lifeLine which has sent the message.<br>
189 * @param lifeline the message sender
192 public void setStartLifeline(Lifeline lifeline
) {
193 super.setStartLifeline(lifeline
);
194 setStartOccurrence(getStartLifeline().getEventOccurrence());
195 if (getEndLifeline() == null)
196 endEventOccurrence
= startEventOccurrence
;
200 * Set the lifeLine which has received the message.<br>
202 * @param lifeline the message receiver
205 public void setEndLifeline(Lifeline lifeline
) {
206 super.setEndLifeline(lifeline
);
207 setEventOccurrence(getEndLifeline().getEventOccurrence());
211 * Returns true if the point C is on the segment defined with the point A and B
213 * @param xA point A x coordinate
214 * @param yA point A y coordinate
215 * @param xB point B x coordinate
216 * @param yB point B y coordinate
217 * @param xC point C x coordinate
218 * @param yC point C y coordinate
219 * @return Return true if the point C is on the segment defined with the point A and B, else otherwise
221 protected boolean isNearSegment(int xA
, int yA
, int xB
, int yB
, int xC
, int yC
) {
222 if ((xA
> xB
) && (xC
> xA
))
224 if ((xA
< xB
) && (xC
> xB
))
226 if ((xA
< xB
) && (xC
< xA
))
228 if ((xA
> xB
) && (xC
< xB
))
230 double distAB
= Math
.sqrt((xB
- xA
) * (xB
- xA
) + (yB
- yA
) * (yB
- yA
));
231 double scalar
= ((xB
- xA
) * (xC
- xA
) + (yB
- yA
) * (yC
- yA
)) / distAB
;
232 double distAC
= Math
.sqrt((xC
- xA
) * (xC
- xA
) + (yC
- yA
) * (yC
- yA
));
233 double distToSegment
= Math
.sqrt(Math
.abs(distAC
* distAC
- scalar
* scalar
));
234 if (distToSegment
<= Metrics
.MESSAGE_SELECTION_TOLERANCE
)
240 public boolean contains(int x
, int y
) {
241 // Is it a self message?
242 if (startLifeline
== endLifeline
) {
243 return super.contains(x
, y
);
245 if (isNearSegment(getX(), getY(), getX() + getWidth(), getY() + getHeight(), x
, y
))
247 int messageMaxWidth
= Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
;
248 int nameWidth
= getName().length() * Metrics
.getAverageCharWidth();
249 if (getName().length() * Metrics
.getAverageCharWidth() > messageMaxWidth
) {
250 if (Frame
.contains(getX(), getY() - Metrics
.MESSAGES_NAME_SPACING
- Metrics
.getMessageFontHeigth(), messageMaxWidth
, Metrics
.getMessageFontHeigth(), x
, y
))
253 if (Frame
.contains(getX() + (messageMaxWidth
- nameWidth
) / 2, getY() + getHeight() / 2 - Metrics
.MESSAGES_NAME_SPACING
- Metrics
.getMessageFontHeigth(), nameWidth
, Metrics
.getMessageFontHeigth(), x
, y
))
259 protected void drawAsyncMessage(IGC context
) {
260 if (startLifeline
!= null && endLifeline
!= null && startLifeline
== endLifeline
&& (startEventOccurrence
!= endEventOccurrence
)) {
263 int height
= getHeight();
265 boolean startInActivation
= isMessageStartInActivation(startEventOccurrence
);
266 boolean endInActivation
= isMessageEndInActivation(endEventOccurrence
);
268 if (endInActivation
&& !startInActivation
)
269 tempx
= Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
270 if (startInActivation
&& !endInActivation
)
271 tempx
= -Metrics
.EXECUTION_OCCURRENCE_WIDTH
/ 2;
273 int tempy
= Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2;
274 if (getHeight() <= Metrics
.INTERNAL_MESSAGE_WIDTH
)
275 tempy
= getHeight() / 2;
277 context
.drawLine(x
, y
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
);
278 context
.drawLine(x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ tempy
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
, y
+ height
- tempy
);
279 context
.drawLine(x
+ tempx
, y
+ height
, x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
/ 2, y
+ height
);
281 Double xt
= new Double(Math
.cos(0.75) * 7);
282 Double yt
= new Double(Math
.sin(0.75) * 7);
284 context
.drawLine(x
+ xt
.intValue() + tempx
, y
+ height
+ yt
.intValue(), x
+ tempx
, y
+ height
);
285 context
.drawArc(x
, y
, Metrics
.INTERNAL_MESSAGE_WIDTH
, 2 * tempy
, 0, 90);
286 context
.drawArc(x
, y
+ height
, Metrics
.INTERNAL_MESSAGE_WIDTH
, -2 * tempy
, 0, -90);
287 context
.drawLine(x
+ xt
.intValue() + tempx
, y
+ height
- yt
.intValue(), x
+ tempx
, y
+ height
);
289 context
.drawTextTruncated(getName(), x
+ Metrics
.INTERNAL_MESSAGE_WIDTH
+ Metrics
.INTERNAL_MESSAGE_V_MARGIN
, y
, Metrics
.swimmingLaneWidth() - Metrics
.EXECUTION_OCCURRENCE_WIDTH
+ -Metrics
.INTERNAL_MESSAGE_WIDTH
,
290 +Metrics
.MESSAGES_NAME_SPACING
- Metrics
.getMessageFontHeigth(), !isSelected());
296 * Draws the asynchronous message in the given GC
299 public void draw(IGC context
) {
303 if (isSelected() && (startLifeline
!= null && endLifeline
!= null && startLifeline
== endLifeline
&& (startEventOccurrence
!= endEventOccurrence
))) {
305 * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
306 * colors This create the highlight effect
308 context
.setForeground(Frame
.getUserPref().getBackGroundColorSelection());
309 context
.setLineWidth(Metrics
.SELECTION_LINE_WIDTH
);
310 drawAsyncMessage(context
);
311 context
.setBackground(Frame
.getUserPref().getBackGroundColorSelection());
312 context
.setForeground(Frame
.getUserPref().getForeGroundColorSelection());
313 // Second drawing is done after the else
315 context
.setBackground(Frame
.getUserPref().getBackGroundColor(prefId
));
316 context
.setForeground(Frame
.getUserPref().getForeGroundColor(prefId
));
319 context
.setDrawTextWithFocusStyle(true);
321 context
.setLineWidth(Metrics
.NORMAL_LINE_WIDTH
);
322 drawAsyncMessage(context
);
324 context
.setDrawTextWithFocusStyle(false);
329 * Set the time when the message end
331 * @param time the time when the message end
333 public void setEndTime(ITmfTimestamp time
) {
334 endTime
= time
.clone();
336 if (getStartLifeline() != null && getStartLifeline().getFrame() != null)
337 getStartLifeline().getFrame().setHasTimeInfo(true);
338 else if (getEndLifeline() != null && getEndLifeline().getFrame() != null)
339 getEndLifeline().getFrame().setHasTimeInfo(true);
343 * Set the time when the message start
345 * @param time the time when the message start
347 public void setStartTime(ITmfTimestamp time
) {
348 startTime
= time
.clone();
350 if (getStartLifeline() != null && getStartLifeline().getFrame() != null)
351 getStartLifeline().getFrame().setHasTimeInfo(true);
352 else if (getEndLifeline() != null && getEndLifeline().getFrame() != null)
353 getEndLifeline().getFrame().setHasTimeInfo(true);
357 * Returns the time when the message begin
362 public ITmfTimestamp
getEndTime() {
367 * Returns the time when the message end
372 public ITmfTimestamp
getStartTime() {
377 public boolean hasTimeInfo() {
382 public boolean isVisible(int x
, int y
, int width
, int height
) {
383 int toDrawY
= getY();
384 int toDrawHeight
= getHeight();
385 if ((toDrawY
> y
+ height
+ Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()) && (toDrawY
+ toDrawHeight
> y
+ height
+ Metrics
.MESSAGES_NAME_SPACING
+ Metrics
.getMessageFontHeigth()))
387 if (toDrawY
< y
&& (toDrawY
+ toDrawHeight
< y
))
389 return super.isVisible(x
, y
, width
, height
);
393 public Comparator
<GraphNode
> getComparator() {
394 return new SortAsyncMessageComparator();
398 public String
getArrayId() {
399 return ASYNC_MESS_TAG
;
403 public Comparator
<GraphNode
> getBackComparator() {
404 return new SortAsyncForBackward();
408 public boolean positiveDistanceToPoint(int x
, int y
) {
410 int mH
= getHeight();
411 if ((mY
> y
) || (mY
+ mH
> y
))