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