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