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