ab36b912a82b4ad3a22824e0c5aeff1960f2e0c4
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / uml2sd / core / BaseMessage.java
1 /**********************************************************************
2 * Copyright (c) 2005, 2008 IBM Corporation and others.
3 * Copyright (c) 2011, 2012 Ericsson.
4 *
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
9 *
10 * Contributors:
11 * IBM - Initial API and implementation
12 * Bernd Hufmann - Updated for TMF
13 **********************************************************************/
14 package org.eclipse.linuxtools.tmf.ui.views.uml2sd.core;
15
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
20 /**
21 * The base UML2 syncMessages implementation.<br>
22 * This abstract class only define one event occurrence to attach to the message.<br>
23 * Usually a message has two event occurrences attached, one for both ends. But some syncMessages(like synchronous
24 * syncMessages) only need one event occurrence to represent the time when they appear. Others kind of message
25 * representations (like asynchronous syncMessages) will be responsible to define the missing second eventOccurrence
26 * property.<br>
27 * <br>
28 *
29 * @see Lifeline Lifeline for more event occurence details
30 * @version 1.0
31 * @author sveyrier
32 */
33 public abstract class BaseMessage extends GraphNode {
34
35 // ------------------------------------------------------------------------
36 // Attributes
37 // ------------------------------------------------------------------------
38 /**
39 * The lifeline which send the message
40 */
41 protected Lifeline fStartLifeline = null;
42 /**
43 * The lifeline which receive the message
44 */
45 protected Lifeline fEndLifeline = null;
46 /**
47 * The visiblitiy flag.
48 */
49 protected boolean fVisible = true;
50
51 // ------------------------------------------------------------------------
52 // Methods
53 // ------------------------------------------------------------------------
54 /*
55 * (non-Javadoc)
56 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getX()
57 */
58 @Override
59 public int getX() {
60 // returns the exact x coordinate
61 return getX(false);
62 }
63
64 /*
65 * (non-Javadoc)
66 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getY()
67 */
68 @Override
69 public int getY() {
70 /*
71 * Note: lifeline.getY() return the y coordinate of the top left corner of the rectangle which contain the
72 * lifeline name getHeight return the height of this rectangle The message y coordinate is then relative to this
73 * position depending of its eventOccurrence Space between syncMessages is constant
74 */
75 if ((fStartLifeline != null) && (fEndLifeline != null)) {
76 /*
77 * Regular message, both ends are attached to a lifeline
78 */
79 return fEndLifeline.getY() + fEndLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fEndEventOccurrence;
80
81 } else {
82 /*
83 * UML2 lost message kind
84 */
85 if (fStartLifeline != null) {
86 return fStartLifeline.getY() + fStartLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fEndEventOccurrence;
87 }
88
89 /*
90 * UML2 found message kind
91 */
92 if (fEndLifeline != null) {
93 return fEndLifeline.getY() + fEndLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fEndEventOccurrence;
94 }
95 }
96 // return 0 by default
97 return 0;
98 }
99
100 /*
101 * (non-Javadoc)
102 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getWidth()
103 */
104 @Override
105 public int getWidth() {
106 // Returns the exact width
107 return getWidth(false);
108 }
109
110 /*
111 * (non-Javadoc)
112 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getHeight()
113 */
114 @Override
115 public int getHeight() {
116 return 0;
117 }
118
119 /**
120 * Returns the graph node x coordinate.<br>
121 * Depending on the quick parameter a approximative or exact value is return.<br>
122 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
123 * Occurrence.<br>
124 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
125 * affect the message x coordinate and width.<br>
126 * <br>
127 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
128 * <br>
129 *
130 * @param quick true to get an approximative value<br>
131 * false to get the exact x value<br>
132 * @return the graph node x coordinate
133 */
134 protected int getX(boolean quick) {
135 int x = 0;
136 int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
137 if ((fStartLifeline != null) && (fEndLifeline != null)) {
138 x = fStartLifeline.getX() + Metrics.getLifelineWidth() / 2;
139 } else {
140 if (fStartLifeline != null) {
141 x = fStartLifeline.getX() + Metrics.getLifelineWidth() / 2;
142 }
143
144 if (fEndLifeline != null) {
145 x = fEndLifeline.getX() - Metrics.LIFELINE_SPACING / 2;
146 }
147 }
148
149 if (quick) {
150 return x;
151 }
152
153 if ((fStartLifeline != null) && (fEndLifeline != null) && (fStartLifeline.getX() > fEndLifeline.getX())) {
154 activationWidth = -activationWidth;
155 }
156
157 if (isMessageStartInActivation(fEndEventOccurrence)) {
158 x = x + activationWidth;
159 }
160
161 return x;
162 }
163
164 /**
165 * Returns the graph node width.<br>
166 * Depending on the quick parameter a approximative or exact value is returned.<br>
167 * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
168 * Occurrence.<br>
169 * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
170 * affect the message x coordinate and width.<br>
171 * <br>
172 * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
173 * <br>
174 *
175 * @param quick true to get an approximative value<br>
176 * false to get the exact x value
177 * @return the graph node width
178 */
179 protected int getWidth(boolean quick) {
180 int width = 0;
181 int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
182 if ((fStartLifeline != null) && (fEndLifeline != null)) {
183 if (fStartLifeline == fEndLifeline) {
184 width = Metrics.INTERNAL_MESSAGE_WIDTH + Metrics.EXECUTION_OCCURRENCE_WIDTH;
185 } else {
186 width = fEndLifeline.getX() + Metrics.getLifelineWidth() / 2 - getX(true);
187 }
188 } else {
189 if (fStartLifeline != null) {
190 width = Metrics.swimmingLaneWidth() / 2;
191 }
192 if (fEndLifeline != null) {
193 width = Metrics.swimmingLaneWidth() / 2;
194 }
195 }
196
197 if (quick) {
198 return width;
199 }
200
201 if ((fStartLifeline != null) && (fEndLifeline != null) && (fStartLifeline.getX() > fEndLifeline.getX())) {
202 activationWidth = -activationWidth;
203 }
204
205 if (isMessageStartInActivation(fEndEventOccurrence)) {
206 width = width - activationWidth;
207 }
208
209 if (isMessageEndInActivation(fEndEventOccurrence)) {
210 width = width - activationWidth;
211 }
212
213 return width;
214 }
215
216 /*
217 * (non-Javadoc)
218 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#isVisible(int, int, int, int)
219 */
220 @Override
221 public boolean isVisible(int x, int y, int width, int height) {
222 // ***Common*** syncMessages visibility
223 // draw the message only if at least one end is visible
224 if (fEndLifeline != null && (fEndLifeline.isVisible(x, y, width, height)) || (fStartLifeline != null && fStartLifeline.isVisible(x, y, width, height))) {
225 return true;
226 }
227 // In this case it can be a message which cross the whole visible area
228 else if (fEndLifeline != null && (!fEndLifeline.isVisible(x, y, width, height)) && (fStartLifeline != null && !fStartLifeline.isVisible(x, y, width, height))) {
229 if (fEndLifeline.getX() > x + width && fStartLifeline.getX() < x) {
230 return true;
231 } else if (fStartLifeline.getX() > x + width && fEndLifeline.getX() < x) {
232 return true;
233 }
234 }
235 return false;
236 }
237
238 /**
239 * Sets the visibility value.
240 *
241 * @param value The visibility to set.
242 */
243 public void setVisible(boolean value) {
244 fVisible = value;
245 }
246
247 /**
248 * @return the visibility value.
249 */
250 public boolean isVisible() {
251 return fVisible;
252 }
253
254 /**
255 * Set the lifeline from which this message has been sent.
256 *
257 * @param lifeline - the message sender
258 */
259 public void setStartLifeline(Lifeline lifeline) {
260 fStartLifeline = lifeline;
261 }
262
263 /**
264 * Returns the lifeline from which this message has been sent.
265 *
266 * @return the message sender
267 */
268 public Lifeline getStartLifeline() {
269 return fStartLifeline;
270 }
271
272 /**
273 * Returns the lifeline which has received this message.
274 *
275 * @return the message receiver
276 */
277 public Lifeline getEndLifeline() {
278 return fEndLifeline;
279 }
280
281 /**
282 * Set the lifeline which has receive this message.
283 *
284 * @param lifeline the message receiver
285 */
286 public void setEndLifeline(Lifeline lifeline) {
287 fEndLifeline = lifeline;
288 }
289
290 /**
291 * Set the event occurrence when this message occurs.<br>
292 *
293 * @param occurrence the event occurrence to assign to this message.<br>
294 * @see Lifeline Lifeline for more event occurence details
295 */
296 protected void setEventOccurrence(int occurrence) {
297 fEndEventOccurrence = occurrence;
298 }
299
300 /**
301 * Returns the event occurence when is message occurs.<br>
302 *
303 * @return the event occurrence assigned to this message.<br>
304 * @see Lifeline Lifeline for more event occurence details
305 */
306 public int getEventOccurrence() {
307 return fEndEventOccurrence;
308 }
309
310 /**
311 * Determines if the given eventOccurence occurs on a executionOccurence owned by the sending lifeline.<br>
312 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
313 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
314 * coordinate and width.<br>
315 *
316 * @see BaseMessage#getX(boolean)
317 * @param event the event occurrence to test
318 * @return true if occurs on a execution occurrence owned by the sending lifeine, false otherwise
319 */
320 protected boolean isMessageStartInActivation(int event) {
321 boolean inActivation = false;
322 if ((fStartLifeline != null) && (fStartLifeline.getExecutions() != null)) {
323 // int acIndex=startLifeline.getExecOccurrenceDrawIndex();
324 // acIndex = first visible execution occurrence
325 // for drawing speed reason with only search on the visivle subset
326 int thisY = getY();
327 for (int i = 0; i < fStartLifeline.getExecutions().size(); i++) {
328 BasicExecutionOccurrence toDraw = (BasicExecutionOccurrence) fStartLifeline.getExecutions().get(i);
329 if ((event >= toDraw.fStartEventOccurrence) && (event <= toDraw.fEndEventOccurrence)) {
330 inActivation = true;
331 }
332 // if we are outside the visible area we stop right now
333 // This works because execution occurrences are ordered along the Y axis
334 if (toDraw.getY() > thisY) {
335 break;
336 }
337 }
338 }
339 return inActivation;
340 }
341
342 /**
343 * Determines if the given event occurrence occurs on a execution occurrence owned by the receiving lifeline.<br>
344 * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
345 * As consequence this method is only used for drawing purpose, especially to determine the exact message x
346 * coordinate and width.<br>
347 *
348 * @see BaseMessage#getX(boolean)
349 * @param event the event occurrence to test
350 * @return true if occurs on a execution occurrence owned by the receiving lifeline, false otherwise
351 */
352 protected boolean isMessageEndInActivation(int event) {
353 boolean inActivation = false;
354 if ((fEndLifeline != null) && (fEndLifeline.getExecutions() != null)) {
355 // acIndex = first visible execution occurrence
356 // for drawing speed reason with only search on the visivle subset
357 for (int i = 0; i < fEndLifeline.getExecutions().size(); i++) {
358 BasicExecutionOccurrence toDraw = (BasicExecutionOccurrence) fEndLifeline.getExecutions().get(i);
359 if ((event >= toDraw.fStartEventOccurrence) && (event <= toDraw.fEndEventOccurrence)) {
360 inActivation = true;
361 }
362 // if we are outside the visible area we stop right now
363 // This works because execution occurrences are ordered along the Y axis
364 if (toDraw.getY() > getY()) {
365 break;
366 }
367 }
368 }
369 return inActivation;
370 }
371
372 /*
373 * (non-Javadoc)
374 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#contains(int, int)
375 */
376 @Override
377 public boolean contains(int xValue, int yValue) {
378 int x = getX();
379 int y = getY();
380 int width = getWidth();
381 int height = getHeight();
382
383 // Used to create a rectangle which contains the message label to allow selection when clicking the label
384 int tempHeight = Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth();
385
386 // Is it a self message?
387 if (fStartLifeline == fEndLifeline) {
388 /*
389 * Rectangle.contains(x,y, width, height) does not works with negative height or width We check here if the
390 * rectangle width is negative.
391 */
392 if (getName().length() * Metrics.getAverageCharWidth() > Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH / 2 + -Metrics.INTERNAL_MESSAGE_WIDTH) {
393 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)) {
394 return true;
395 }
396 } else {
397 if (Frame.contains(x + Metrics.INTERNAL_MESSAGE_WIDTH + 10, y, getName().length() * Metrics.getAverageCharWidth(), Metrics.getMessageFontHeigth(), xValue, yValue)) {
398 return true;
399 }
400 }
401
402 // Test if the point is in part 1 of the self message
403 // see: "private void drawMessage (NGC context)" method for self message drawing schema
404 if (Frame.contains(x, y - Metrics.MESSAGE_SELECTION_TOLERANCE / 2, Metrics.INTERNAL_MESSAGE_WIDTH / 2, Metrics.MESSAGE_SELECTION_TOLERANCE, xValue, yValue)) {
405 return true;
406 }
407
408 // Test if the point is in part 3 of the self message
409 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)) {
410 return true;
411 }
412
413 // Test if the point is in part 5 of the self message
414 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)) {
415 return true;
416 }
417
418 // false otherwise
419 return false;
420 }
421 if (Frame.contains(x, y - tempHeight, width, tempHeight, xValue, yValue)) {
422 return true;
423 }
424 // false otherwise
425 return false;
426 }
427
428 /**
429 * Method to draw the message using the graphical context.
430 *
431 * @param context A graphical context to draw in.
432 */
433 protected void drawMessage(IGC context) {
434 int fX, fY, fW, fH;
435 fX = fY = fW = fH = 0;
436
437 // temporay store the coordinates to avoid more methods calls
438 int x = getX();
439 int y = getY();
440 int width = getWidth();
441 int height = getHeight();
442
443 // UML2 found message (always drawn from left to right)
444 // or UML2 lost message (always drawn from left to right)
445 if ((fStartLifeline == null || fEndLifeline == null) && fStartLifeline != fEndLifeline) {
446 // Draw the message label above the message and centered
447 // The label is truncated if it cannot fit between the two message end
448 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
449 IColor temp = context.getForeground();
450 context.setForeground(Frame.getUserPref().getFontColor(fPrefId));
451 context.drawTextTruncatedCentred(getName(), x, y - Metrics.getMessageFontHeigth() - 2 * Metrics.MESSAGES_NAME_SPACING, width, 2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth(), !isSelected());
452 context.setForeground(temp);
453 int margin = 0;
454 if (fEndLifeline == null) {
455 margin = Metrics.MESSAGE_CIRCLE_RAY;
456 }
457
458 // Draw the message main line
459 context.drawLine(x, y, x + width, y + height);
460 // Draw the two little lines which make a arrow part of the message
461 Double xt = Double.valueOf(Math.cos(0.75) * 7);
462 Double yt = Double.valueOf(Math.sin(0.75) * 7);
463 if (context.getLineStyle() == context.getLineSolidStyle()) {
464 IColor backcolor = context.getBackground();
465 context.setBackground(context.getForeground());
466 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 };
467 context.fillPolygon(points);
468 context.drawPolygon(points);
469 context.setBackground(backcolor);
470 } else {
471 int currentStyle = context.getLineStyle();
472 int currentWidth = context.getLineWidth();
473 context.setLineWidth(currentWidth + 2);
474 context.setLineStyle(context.getLineSolidStyle());
475 context.drawLine(x + width - xt.intValue() - margin, y + height - yt.intValue(), x + width - margin, y + height);
476 context.drawLine(x + width - xt.intValue() - margin, y + height + yt.intValue(), x + width - margin, y + height);
477 context.setLineStyle(currentStyle);
478 context.setLineWidth(currentWidth);
479 }
480 IColor storedColor = context.getBackground();
481 context.setBackground(context.getForeground());
482
483 // Draw a circle at the message end (endLifeline side)
484 int ray = Metrics.MESSAGE_CIRCLE_RAY;
485 if (context.getLineWidth() != Metrics.NORMAL_LINE_WIDTH) {
486 ray = ray + Metrics.SELECTION_LINE_WIDTH - Metrics.NORMAL_LINE_WIDTH;
487 }
488 if (fStartLifeline == null) {
489 context.fillOval(x - ray, y - ray, ray * 2, ray * 2);
490 } else {
491 context.fillOval(x + width - ray, y + height - ray, ray * 2, ray * 2);
492 }
493 context.setBackground(storedColor);
494 context.setForeground(Frame.getUserPref().getFontColor(fPrefId));
495 fX = x;
496 fY = y - yt.intValue();
497 fW = width;
498 fH = height + 2 * yt.intValue();
499 }
500 // it is self message (always drawn at the left side of the owning lifeLifeline)
501 else if (fStartLifeline != null && fEndLifeline != null && fStartLifeline == fEndLifeline) {
502 /*
503 * Self syncMessages are drawn in 5 parts 1 -----------+ + 2 + | | | 3 | + 5 + 4 -----------+
504 */
505 int tempy = Metrics.INTERNAL_MESSAGE_WIDTH / 2;
506 if (Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT <= Metrics.INTERNAL_MESSAGE_WIDTH) {
507 tempy = Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT / 2;
508 }
509
510 // Part 1
511 context.drawLine(x, y, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y);
512 // Part 3
513 context.drawLine(x + Metrics.INTERNAL_MESSAGE_WIDTH, y + tempy, x + Metrics.INTERNAL_MESSAGE_WIDTH, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT - tempy);
514 // Part 5
515 context.drawLine(x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT);
516
517 Double xt = Double.valueOf(Math.cos(0.75) * 7);
518 Double yt = Double.valueOf(Math.sin(0.75) * 7);
519
520 fX = x;
521 fY = y;
522 fW = Metrics.INTERNAL_MESSAGE_WIDTH;
523 fH = height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT;
524
525 // Draw the two little lines which make a arrow part of the message
526 if (context.getLineStyle() == context.getLineSolidStyle()) {
527 IColor backcolor = context.getBackground();
528 context.setBackground(context.getForeground());
529 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(),
530 y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT - yt.intValue(), x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT };
531 context.fillPolygon(points);
532 context.drawPolygon(points);
533 context.setBackground(backcolor);
534 } else {
535 int currentStyle = context.getLineStyle();
536 int currentWidth = context.getLineWidth();
537 context.setLineWidth(currentWidth + 2);
538 context.setLineStyle(context.getLineSolidStyle());
539 context.drawLine(x + xt.intValue(), y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT + yt.intValue(), x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT);
540 context.drawLine(x + xt.intValue(), y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT - yt.intValue(), x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT);
541 context.setLineStyle(currentStyle);
542 context.setLineWidth(currentWidth);
543 }
544
545 // Part 2
546 context.drawArc(x, y, Metrics.INTERNAL_MESSAGE_WIDTH, 2 * tempy, 0, 90);
547 // Part 4
548 context.drawArc(x, y + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, Metrics.INTERNAL_MESSAGE_WIDTH, -2 * tempy, 0, -90);
549
550 // Draw the message label above the message and centered
551 // The label is truncated if it cannot fit between the two message end
552 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
553
554 // the space available for the text is sorter if are drawing internal message on the last lifeline
555 context.setForeground(Frame.getUserPref().getFontColor(fPrefId));
556 if (fStartLifeline.getIndex() == fStartLifeline.getFrame().getHorizontalIndex()) {
557 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
558 - Metrics.getMessageFontHeigth(), !isSelected());
559 } else {
560 context.drawTextTruncated(getName(), x + width + Metrics.INTERNAL_MESSAGE_V_MARGIN / 2, y, Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH + -Metrics.INTERNAL_MESSAGE_WIDTH,
561 +Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), !isSelected());
562 }
563 }
564 // it is regular message
565 else if (fStartLifeline != null && fEndLifeline != null) {
566 // Draw the message main line
567 context.drawLine(x, y, x + width, y + height);
568
569 int spaceBTWStartEnd = fEndLifeline.getX() - fStartLifeline.getX();
570
571 double a = height;
572 double b = width;
573 double angle = Math.atan(a / b);
574 // Compute the coordinates of the two little lines which make the arrow part of the message
575 int sign = 1;
576 if (spaceBTWStartEnd < 0) {
577 sign = -1;
578 }
579 Double x1 = Double.valueOf(sign * Math.cos(angle - 0.75) * 7);
580 Double y1 = Double.valueOf(sign * Math.sin(angle - 0.75) * 7);
581 Double x2 = Double.valueOf(sign * Math.cos(angle + 0.75) * 7);
582 Double y2 = Double.valueOf(sign * Math.sin(angle + 0.75) * 7);
583
584 fX = getX();
585 fY = y + height - y2.intValue();
586 fW = getWidth();
587 fH = y2.intValue() - y1.intValue() + 1;
588 if (fW < 0) {
589 fW = -fW;
590 fX = fX - fW;
591 }
592
593 if (fH < 0) {
594 fH = -fH;
595 fY = fY - fH;
596 }
597
598 // Draw the two little lines which make a arrow part of the message
599 if (context.getLineStyle() == context.getLineSolidStyle()) {
600 IColor backcolor = context.getBackground();
601 context.setBackground(context.getForeground());
602 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() };
603 context.fillPolygon(points);
604 context.drawPolygon(points);
605 context.setBackground(backcolor);
606 } else {
607 int currentStyle = context.getLineStyle();
608 int currentWidth = context.getLineWidth();
609 context.setLineWidth(currentWidth + 2);
610 context.setLineStyle(context.getLineSolidStyle());
611 context.drawLine(x + width - x1.intValue(), y + height - y1.intValue(), x + width, y + height);
612 context.drawLine(x + width - x2.intValue(), y + height - y2.intValue(), x + width, y + height);
613 context.setLineStyle(currentStyle);
614 context.setLineWidth(currentWidth);
615 }
616
617 // Draw the message label above the message and centered
618 // The label is truncated if it cannot fit between the two message end
619 // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
620 context.setForeground(Frame.getUserPref().getFontColor(fPrefId));
621 if (spaceBTWStartEnd > 0) {
622 context.drawTextTruncatedCentred(getName(), x, y + height / 2 - (2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth()), width, 2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth(), !isSelected());
623 } else {
624 context.drawTextTruncatedCentred(getName(), x + width, y + height / 2 - (2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth()), -width, 2 * Metrics.MESSAGES_NAME_SPACING + +Metrics.getMessageFontHeigth(), !isSelected());
625 }
626 }
627 }
628
629 /*
630 * (non-Javadoc)
631 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNodee#draw(org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC)
632 */
633 @Override
634 public void draw(IGC context) {
635 if (!isVisible()) {
636 return;
637 }
638 // Draw it selected?*/
639 if (isSelected()) {
640
641 /*
642 * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
643 * colors This create the highlight effect
644 */
645 context.setForeground(Frame.getUserPref().getBackGroundColorSelection());
646 context.setLineWidth(Metrics.SELECTION_LINE_WIDTH);
647 drawMessage(context);
648 context.setBackground(Frame.getUserPref().getBackGroundColorSelection());
649 context.setForeground(Frame.getUserPref().getForeGroundColorSelection());
650 // Second drawing is done after
651 }
652 context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
653 if (hasFocus()) {
654 context.setDrawTextWithFocusStyle(true);
655 }
656 drawMessage(context);
657 int oldStyle = context.getLineStyle();
658 if (hasFocus()) {
659 context.setDrawTextWithFocusStyle(false);
660 drawFocus(context);
661 }
662 // restore the context
663 context.setLineStyle(oldStyle);
664 }
665
666 /**
667 * Determine if two messages are identical. This default implementation considers that overlapping messages with
668 * same coordinates are identical.
669 *
670 * @param message - the message to compare with
671 * @return true if identical false otherwise
672 *
673 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#isSameAs(org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode)
674 */
675 @Override
676 public boolean isSameAs(GraphNode message) {
677 if (message == null) {
678 return false;
679 }
680 if (!(message instanceof BaseMessage)) {
681 return super.isSameAs(message);
682 }
683 return ((getX() == message.getX()) && (getY() == message.getY()) && (getWidth() == message.getWidth()) && (getHeight() == message.getHeight()));
684 }
685
686 /**
687 * Method drawRot.
688 *
689 * @param x A x coordinate
690 * @param y A y coordinate
691 * @param w A width
692 * @param h A height
693 * @param context A graphical context
694 */
695 public void drawRot(int x, int y, int w, int h, IGC context) {
696 double angleA = Math.atan2(getHeight(), getWidth());
697 double cosA = Math.cos(angleA);
698 double sinA = Math.sin(angleA);
699
700 int gx = getX();
701 int gy = getY();
702
703 int localHeight = h;
704 localHeight = localHeight / 2;
705
706 double cw = Math.sqrt(w * w + getHeight() * getHeight());
707
708 int x1 = Math.round((float) ((x - gx) * cosA - (y - gy) * sinA));
709 int y1 = Math.round((float) ((x - gx) * sinA + (y - gy) * cosA));
710
711 int x2 = Math.round((float) (cw * cosA - (y - gy) * sinA));
712 int y2 = Math.round((float) (cw * sinA + (y - gy) * cosA));
713
714 int x3 = Math.round((float) (cw * cosA - (localHeight) * sinA));
715 int y3 = Math.round((float) (cw * sinA + (localHeight) * cosA));
716
717 int x4 = Math.round((float) ((x - gx) * cosA - (localHeight) * sinA));
718 int y4 = Math.round((float) ((x - gx) * sinA + (localHeight) * cosA));
719
720 int[] points = { x1 + getX(), y1 + getY(), x2 + getX(), y2 + getY(), x3 + getX(), y3 + getY(), x4 + getX(), y4 + getY() };
721 context.drawPolygon(points);
722 }
723
724 /*
725 * (non-Javadoc)
726 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#drawFocus(org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC)
727 */
728 @Override
729 public void drawFocus(IGC context) {
730 if ((fStartLifeline != fEndLifeline) && (fStartEventOccurrence == fEndEventOccurrence)) {
731 context.setLineStyle(context.getLineDotStyle());
732 context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
733 context.setBackground(Frame.getUserPref().getBackGroundColorSelection());
734 context.setForeground(Frame.getUserPref().getForeGroundColorSelection());
735 context.drawFocus(getX(), getY() - 3, getWidth(), getHeight() + 6);
736 } else if ((fStartLifeline == fEndLifeline) && (fStartEventOccurrence == fEndEventOccurrence)) {
737 context.drawFocus(getX(), getY() - 3, getWidth(), Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT + 6);
738 } else if ((fStartLifeline != fEndLifeline) && (fStartEventOccurrence != fEndEventOccurrence)) {
739 context.setLineStyle(context.getLineDotStyle());
740 context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
741 context.setBackground(Frame.getUserPref().getBackGroundColor(ISDPreferences.PREF_LIFELINE_HEADER));
742 context.setForeground(Frame.getUserPref().getForeGroundColor(ISDPreferences.PREF_LIFELINE_HEADER));
743 drawRot(getX(), getY() - 5, getWidth(), 10, context);
744 } else {
745 super.drawFocus(context);
746 }
747 }
748 }
This page took 0.048558 seconds and 5 git commands to generate.