4e8dc37d34cc3a718d4bdc8006b00294b5dc60c3
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / uml2sd / core / AsyncMessage.java
1 /**********************************************************************
2 * Copyright (c) 2005, 2008 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 *
8 * Contributors:
9 * IBM - Initial API and implementation
10 * Bernd Hufmann - Updated for TMF
11 **********************************************************************/
12 package org.eclipse.linuxtools.tmf.ui.views.uml2sd.core;
13
14 import java.util.Comparator;
15
16 import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
17 import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
18 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC;
19 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences.ISDPreferences;
20 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.util.SortAsyncForBackward;
21 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.util.SortAsyncMessageComparator;
22
23 /**
24 * A AsyncMessage is a asynchronous message which appear at two different event occurrences on each lifeline ends (sender
25 * and receiver).<br>
26 * <br>
27 * <br>
28 * Usage example:
29 *
30 * <pre>
31 * Frame frame;
32 * Lifeline lifeLine1;
33 * Lifeline lifeLine2;
34 *
35 * AsyncMessage message = new AsyncMessage();
36 * // Create a new event occurrence on each lifeline
37 * lifeline1.getNewOccurrenceIndex();
38 * lifeline2.getNewOccurrenceIndex();
39 * // Set the message sender and receiver
40 * message.setStartLifeline(lifeLine1);
41 * message.setEndLifline(lifeline2);
42 * message.setName(&quot;Message label&quot;);
43 * // add the message to the frame
44 * frame.addMessage(message);
45 * </pre>
46 *
47 * @see Lifeline Lifeline for more event occurence details
48 * @version 1.0
49 * @author sveyrier
50 *
51 */
52 public class AsyncMessage extends BaseMessage implements ITimeRange {
53
54 // ------------------------------------------------------------------------
55 // Constants
56 // ------------------------------------------------------------------------
57 /**
58 * The grahNode ID constant
59 */
60 public static final String ASYNC_MESS_TAG = "AsyncMessage"; //$NON-NLS-1$
61
62 // ------------------------------------------------------------------------
63 // Attributes
64 // ------------------------------------------------------------------------
65 /**
66 * Flag whether message has time information or not.
67 */
68 protected boolean hasTime = false;
69 /**
70 * The time when the message begin
71 */
72 protected ITmfTimestamp endTime = new TmfTimestamp();
73 /**
74 * The time when the message end
75 */
76 protected ITmfTimestamp startTime = new TmfTimestamp();
77 /**
78 * The associated message.
79 */
80 protected AsyncMessageReturn messageReturn = null;
81
82 // ------------------------------------------------------------------------
83 // Constructors
84 // ------------------------------------------------------------------------
85 /**
86 * Default constructor
87 */
88 public AsyncMessage() {
89 prefId = ISDPreferences.PREF_ASYNC_MESS;
90 }
91
92 // ------------------------------------------------------------------------
93 // Methods
94 // ------------------------------------------------------------------------
95 /*
96 * (non-Javadoc)
97 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#getX()
98 */
99 @Override
100 public int getX() {
101 int x = super.getX(true);
102 int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
103 if ((startLifeline != null) && (endLifeline != null) && (startLifeline.getX() > endLifeline.getX())) {
104 activationWidth = -activationWidth;
105 }
106
107 if (isMessageStartInActivation(startEventOccurrence)) {
108 x = x + activationWidth;
109 }
110 return x;
111 }
112
113 /*
114 * (non-Javadoc)
115 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#getY()
116 */
117 @Override
118 public int getY() {
119 if ((startLifeline != null) && (endLifeline != null)) {
120 return endLifeline.getY() + endLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * startEventOccurrence;
121 }
122 return super.getY();
123 }
124
125 /*
126 * (non-Javadoc)
127 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#getWidth()
128 */
129 @Override
130 public int getWidth() {
131 int width = super.getWidth(true);
132 int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
133 if ((startLifeline != null) && (endLifeline != null) && (startLifeline.getX() > endLifeline.getX())) {
134 activationWidth = -activationWidth;
135 }
136
137 if (isMessageStartInActivation(startEventOccurrence)) {
138 width = width - activationWidth;
139 }
140
141 if (isMessageEndInActivation(endEventOccurrence)) {
142 width = width - activationWidth;
143 }
144
145 return width;
146 }
147
148 /*
149 * (non-Javadoc)
150 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#getHeight()
151 */
152 @Override
153 public int getHeight() {
154 if ((startLifeline != null) && (endLifeline != null)) {
155 return (endLifeline.getY() + endLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * endEventOccurrence) - getY();
156 }
157 return super.getHeight();
158 }
159
160 /**
161 * Set the message return associated with this message.
162 *
163 * @param message the message return to associate
164 */
165 protected void setMessageReturn(AsyncMessageReturn message) {
166 messageReturn = message;
167 }
168
169 /**
170 * Set the event occurrence attached to this message for its end lifeline
171 *
172 * @param occurrence the event occurrence to set
173 */
174 public void setEndOccurrence(int occurrence) {
175 endEventOccurrence = occurrence;
176 if (getStartLifeline() == null) {
177 startEventOccurrence = occurrence;
178 }
179 informFrame(getEndLifeline(), occurrence);
180 }
181
182 /**
183 * Informs the given lifeline about the maximum occurrence if applicable.
184 *
185 * @param lifeLine
186 * @param occurrence
187 */
188 protected void informFrame(Lifeline lifeLine, int occurrence) {
189 if ((lifeLine != null) && (lifeLine.getFrame() != null) && (lifeLine.getFrame().getMaxEventOccurrence() < occurrence)) {
190 lifeLine.getFrame().setMaxEventOccurrence(occurrence);
191 }
192 }
193
194 /**
195 * Set the event occurrence attached to this message for its start lifeline
196 *
197 * @param occurrence the event occurrence to set
198 */
199 public void setStartOccurrence(int occurrence) {
200 startEventOccurrence = occurrence;
201 if (getEndLifeline() == null) {
202 endEventOccurrence = startEventOccurrence;
203 }
204 informFrame(getStartLifeline(), occurrence);
205 }
206
207 /**
208 * Set the lifeLine which has sent the message.<br>
209 * A new EventOccurence will be create on this lifeLine.<br>
210 *
211 * @param lifeline the message sender
212 */
213 public void autoSetStartLifeline(Lifeline lifeline) {
214 lifeline.getNewEventOccurrence();
215 setStartLifeline(lifeline);
216 }
217
218 /**
219 * Set the lifeLine which has received the message.<br>
220 * A new EventOccurence will be create on this lifeLine.<br>
221 *
222 * @param lifeline the message receiver
223 */
224 public void autoSetEndLifeline(Lifeline lifeline) {
225 lifeline.getNewEventOccurrence();
226 setEndLifeline(lifeline);
227 }
228
229 /*
230 * (non-Javadoc)
231 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#setStartLifeline(org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline)
232 */
233 @Override
234 public void setStartLifeline(Lifeline lifeline) {
235 super.setStartLifeline(lifeline);
236 setStartOccurrence(getStartLifeline().getEventOccurrence());
237 if (getEndLifeline() == null) {
238 endEventOccurrence = startEventOccurrence;
239 }
240 }
241
242 /*
243 * (non-Javadoc)
244 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#setEndLifeline(org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline)
245 */
246 @Override
247 public void setEndLifeline(Lifeline lifeline) {
248 super.setEndLifeline(lifeline);
249 setEventOccurrence(getEndLifeline().getEventOccurrence());
250 }
251
252 /**
253 * Returns true if the point C is on the segment defined with the point A and B
254 *
255 * @param xA point A x coordinate
256 * @param yA point A y coordinate
257 * @param xB point B x coordinate
258 * @param yB point B y coordinate
259 * @param xC point C x coordinate
260 * @param yC point C y coordinate
261 * @return Return true if the point C is on the segment defined with the point A and B, else otherwise
262 */
263 protected boolean isNearSegment(int xA, int yA, int xB, int yB, int xC, int yC) {
264 if ((xA > xB) && (xC > xA)) {
265 return false;
266 }
267 if ((xA < xB) && (xC > xB)) {
268 return false;
269 }
270 if ((xA < xB) && (xC < xA)) {
271 return false;
272 }
273 if ((xA > xB) && (xC < xB)) {
274 return false;
275 }
276 double distAB = Math.sqrt((xB - xA) * (xB - xA) + (yB - yA) * (yB - yA));
277 double scalar = ((xB - xA) * (xC - xA) + (yB - yA) * (yC - yA)) / distAB;
278 double distAC = Math.sqrt((xC - xA) * (xC - xA) + (yC - yA) * (yC - yA));
279 double distToSegment = Math.sqrt(Math.abs(distAC * distAC - scalar * scalar));
280 if (distToSegment <= Metrics.MESSAGE_SELECTION_TOLERANCE) {
281 return true;
282 }
283 return false;
284 }
285
286 /*
287 * (non-Javadoc)
288 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#contains(int, int)
289 */
290 @Override
291 public boolean contains(int x, int y) {
292 // Is it a self message?
293 if (startLifeline == endLifeline) {
294 return super.contains(x, y);
295 }
296 if (isNearSegment(getX(), getY(), getX() + getWidth(), getY() + getHeight(), x, y))
297 return true;
298 int messageMaxWidth = Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH;
299 int nameWidth = getName().length() * Metrics.getAverageCharWidth();
300 if (getName().length() * Metrics.getAverageCharWidth() > messageMaxWidth) {
301 if (Frame.contains(getX(), getY() - Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), messageMaxWidth, Metrics.getMessageFontHeigth(), x, y)) {
302 return true;
303 }
304 } else {
305 if (Frame.contains(getX() + (messageMaxWidth - nameWidth) / 2, getY() + getHeight() / 2 - Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), nameWidth, Metrics.getMessageFontHeigth(), x, y)) {
306 return true;
307 }
308 }
309 return false;
310 }
311
312 /**
313 * Draws the asynchronous message using giving graphical context.
314 *
315 * @param context A graphical context to draw in.
316 */
317 protected void drawAsyncMessage(IGC context) {
318 if (startLifeline != null && endLifeline != null && startLifeline == endLifeline && (startEventOccurrence != endEventOccurrence)) {
319 int x = getX();
320 int y = getY();
321 int height = getHeight();
322 int tempx = 0;
323 boolean startInActivation = isMessageStartInActivation(startEventOccurrence);
324 boolean endInActivation = isMessageEndInActivation(endEventOccurrence);
325
326 if (endInActivation && !startInActivation) {
327 tempx = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
328 }
329 if (startInActivation && !endInActivation) {
330 tempx = -Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
331 }
332
333 int tempy = Metrics.INTERNAL_MESSAGE_WIDTH / 2;
334 if (getHeight() <= Metrics.INTERNAL_MESSAGE_WIDTH) {
335 tempy = getHeight() / 2;
336 }
337
338 context.drawLine(x, y, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y);
339 context.drawLine(x + Metrics.INTERNAL_MESSAGE_WIDTH, y + tempy, x + Metrics.INTERNAL_MESSAGE_WIDTH, y + height - tempy);
340 context.drawLine(x + tempx, y + height, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y + height);
341
342 Double xt = new Double(Math.cos(0.75) * 7);
343 Double yt = new Double(Math.sin(0.75) * 7);
344
345 context.drawLine(x + xt.intValue() + tempx, y + height + yt.intValue(), x + tempx, y + height);
346 context.drawArc(x, y, Metrics.INTERNAL_MESSAGE_WIDTH, 2 * tempy, 0, 90);
347 context.drawArc(x, y + height, Metrics.INTERNAL_MESSAGE_WIDTH, -2 * tempy, 0, -90);
348 context.drawLine(x + xt.intValue() + tempx, y + height - yt.intValue(), x + tempx, y + height);
349
350 context.drawTextTruncated(getName(), x + Metrics.INTERNAL_MESSAGE_WIDTH + Metrics.INTERNAL_MESSAGE_V_MARGIN, y, Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH + -Metrics.INTERNAL_MESSAGE_WIDTH,
351 +Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), !isSelected());
352 } else {
353 super.draw(context);
354 }
355 }
356
357 /*
358 * (non-Javadoc)
359 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#draw(org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC)
360 */
361 @Override
362 public void draw(IGC context) {
363 if (!isVisible()) {
364 return;
365 }
366 // Draw it selected?
367 if (isSelected() && (startLifeline != null && endLifeline != null && startLifeline == endLifeline && (startEventOccurrence != endEventOccurrence))) {
368 /*
369 * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
370 * colors This create the highlight effect
371 */
372 context.setForeground(Frame.getUserPref().getBackGroundColorSelection());
373 context.setLineWidth(Metrics.SELECTION_LINE_WIDTH);
374 drawAsyncMessage(context);
375 context.setBackground(Frame.getUserPref().getBackGroundColorSelection());
376 context.setForeground(Frame.getUserPref().getForeGroundColorSelection());
377 // Second drawing is done after the else
378 } else {
379 context.setBackground(Frame.getUserPref().getBackGroundColor(prefId));
380 context.setForeground(Frame.getUserPref().getForeGroundColor(prefId));
381 }
382 if (hasFocus()) {
383 context.setDrawTextWithFocusStyle(true);
384 }
385 context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
386 drawAsyncMessage(context);
387 if (hasFocus()) {
388 context.setDrawTextWithFocusStyle(false);
389 }
390 }
391
392 /**
393 * Set the time when the message end
394 *
395 * @param time the time when the message end
396 */
397 public void setEndTime(ITmfTimestamp time) {
398 endTime = time.clone();
399 hasTime = true;
400 if (getStartLifeline() != null && getStartLifeline().getFrame() != null) {
401 getStartLifeline().getFrame().setHasTimeInfo(true);
402 } else if (getEndLifeline() != null && getEndLifeline().getFrame() != null) {
403 getEndLifeline().getFrame().setHasTimeInfo(true);
404 }
405 }
406
407 /**
408 * Set the time when the message start
409 *
410 * @param time the time when the message start
411 */
412 public void setStartTime(ITmfTimestamp time) {
413 startTime = time.clone();
414 hasTime = true;
415 if (getStartLifeline() != null && getStartLifeline().getFrame() != null) {
416 getStartLifeline().getFrame().setHasTimeInfo(true);
417 } else if (getEndLifeline() != null && getEndLifeline().getFrame() != null) {
418 getEndLifeline().getFrame().setHasTimeInfo(true);
419 }
420 }
421
422 /*
423 * (non-Javadoc)
424 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.ITimeRange#getEndTime()
425 */
426 @Override
427 public ITmfTimestamp getEndTime() {
428 return endTime;
429 }
430
431 /*
432 * (non-Javadoc)
433 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.ITimeRange#getStartTime()
434 */
435 @Override
436 public ITmfTimestamp getStartTime() {
437 return startTime;
438 }
439
440 /*
441 * (non-Javadoc)
442 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.ITimeRange#hasTimeInfo()
443 */
444 @Override
445 public boolean hasTimeInfo() {
446 return hasTime;
447 }
448
449 /*
450 * (non-Javadoc)
451 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.BaseMessage#isVisible(int, int, int, int)
452 */
453 @Override
454 public boolean isVisible(int x, int y, int width, int height) {
455 int toDrawY = getY();
456 int toDrawHeight = getHeight();
457 if ((toDrawY > y + height + Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth()) && (toDrawY + toDrawHeight > y + height + Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth())) {
458 return false;
459 }
460 if (toDrawY < y && (toDrawY + toDrawHeight < y)) {
461 return false;
462 }
463 return super.isVisible(x, y, width, height);
464 }
465
466 /*
467 * (non-Javadoc)
468 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getComparator()
469 */
470 @Override
471 public Comparator<GraphNode> getComparator() {
472 return new SortAsyncMessageComparator();
473 }
474
475 /*
476 * (non-Javadoc)
477 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getArrayId()
478 */
479 @Override
480 public String getArrayId() {
481 return ASYNC_MESS_TAG;
482 }
483
484 /*
485 * (non-Javadoc)
486 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getBackComparator()
487 */
488 @Override
489 public Comparator<GraphNode> getBackComparator() {
490 return new SortAsyncForBackward();
491 }
492
493 /*
494 * (non-Javadoc)
495 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#positiveDistanceToPoint(int, int)
496 */
497 @Override
498 public boolean positiveDistanceToPoint(int x, int y) {
499 int mY = getY();
500 int mH = getHeight();
501 if ((mY > y) || (mY + mH > y)) {
502 return true;
503 }
504 return false;
505 }
506 }
This page took 0.041658 seconds and 5 git commands to generate.