2940fe67bccff712c040f1f577fb3ed576a55d70
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / uml2sd / core / Lifeline.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 java.util.ArrayList;
17 import java.util.List;
18
19 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IColor;
20 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC;
21 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IImage;
22 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences.ISDPreferences;
23 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences.SDViewPref;
24
25 /**
26 * Lifeline is the UML2 lifeline graphical representation.<br>
27 * Each lifeline owns a set of event occurrences. An event occurrence is the base element in UML2 to set an event in a
28 * sequence diagram.<br>
29 * Event occurrence define the drawing order of graph node along a lifeline. In this lifeline implementation, event
30 * occurrences are just integer index. The event occurrences with the same value on different lifelines will correspond
31 * the same y coordinate value.
32 *
33 * @version 1.0
34 * @author sveyrier
35 *
36 */
37 public class Lifeline extends GraphNode {
38 // ------------------------------------------------------------------------
39 // Constants
40 // ------------------------------------------------------------------------
41 /**
42 * The life line tag.
43 */
44 public static final String LIFELINE_TAG = "Lifeline"; //$NON-NLS-1$
45
46 // ------------------------------------------------------------------------
47 // Attribute
48 // ------------------------------------------------------------------------
49 /**
50 * The lifeline position in the containing frame
51 */
52 protected int fIndexInFrame = 0;
53 /**
54 * The frame where the lifeline is drawn
55 */
56 protected Frame fFrame = null;
57 /**
58 * The current event occurrence created in the lifeline
59 */
60 protected int fEventOccurrence = 0;
61 /**
62 * The lifeline category.
63 */
64 protected int fCategory = -1;
65 /**
66 * Flag whether lifeline has time information available or not
67 */
68 protected boolean fHasTimeInfo = false;
69
70 // ------------------------------------------------------------------------
71 // Constructors
72 // ------------------------------------------------------------------------
73 /**
74 * Default constructor
75 */
76 public Lifeline() {
77 fPrefId = ISDPreferences.PREF_LIFELINE;
78 }
79
80 // ------------------------------------------------------------------------
81 // Methods
82 // ------------------------------------------------------------------------
83 /*
84 * (non-Javadoc)
85 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getX()
86 */
87 @Override
88 public int getX() {
89 return Metrics.FRAME_H_MARGIN + Metrics.LIFELINE_H_MAGIN + (fIndexInFrame - 1) * Metrics.swimmingLaneWidth();
90 }
91
92 /*
93 * (non-Javadoc)
94 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getY()
95 */
96 @Override
97 public int getY() {
98 return 2 * Metrics.FRAME_NAME_H_MARGIN + Metrics.LIFELINE_VT_MAGIN / 2 + Metrics.getFrameFontHeigth() + Metrics.getLifelineHeaderFontHeigth() + Metrics.FRAME_V_MARGIN + 2 * Metrics.LIFELINE_HEARDER_TEXT_V_MARGIN;
99 }
100
101 /*
102 * (non-Javadoc)
103 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getWidth()
104 */
105 @Override
106 public int getWidth() {
107 return Metrics.getLifelineWidth();
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 // Set room for two text lines
117 return Metrics.getLifelineFontHeigth()/** 2 */
118 + 2 * Metrics.LIFELINE_NAME_H_MARGIN;
119 }
120
121 /**
122 * Set the lifeline category for this lifeline.
123 *
124 * @param arrayIndex the index of the category to use
125 * @see Frame#setLifelineCategories(LifelineCategories[])
126 */
127 public void setCategory(int arrayIndex) {
128 fCategory = arrayIndex;
129 }
130
131 /**
132 * Returns the tooltip text for the lifeline. It is the combination between the category name(if any) and the
133 * lifeline name
134 *
135 * @return the tooltip text
136 */
137 public String getToolTipText() {
138 if (fCategory >= 0) {
139 LifelineCategories[] categories = fFrame.getLifelineCategories();
140 if (fCategory < categories.length) {
141 return categories[fCategory].getName() + " " + getName(); //$NON-NLS-1$
142 }
143 }
144 return ""; //$NON-NLS-1$
145 }
146
147 /**
148 * Returns the index of the first visible Execution Occurrence in the execution occurrence array.<br>
149 * Execution Occurrences are Y ordered in this array
150 *
151 * @return the first visible Execution Occurrence
152 */
153 public int getExecOccurrenceDrawIndex() {
154 if (!fHasChilden) {
155 return 0;
156 }
157 if (fIndexes.get(BasicExecutionOccurrence.EXEC_OCC_TAG) != null) {
158 return fIndexes.get(BasicExecutionOccurrence.EXEC_OCC_TAG).intValue();
159 }
160 return 0;
161 }
162
163 /**
164 * Set the frame on which this lifeline must be drawn
165 *
166 * @param parentFrame
167 * Parent frame
168 */
169 protected void setFrame(Frame parentFrame) {
170 fFrame = parentFrame;
171 if (fHasTimeInfo) {
172 fFrame.setHasTimeInfo(true);
173 }
174 if (fFrame.getMaxEventOccurrence() < getEventOccurrence() + 1) {
175 fFrame.setMaxEventOccurrence(getEventOccurrence() + 1);
176 }
177 }
178
179 /**
180 * Returns the frame which this lifeline is drawn
181 *
182 * @return the Frame
183 */
184 protected Frame getFrame() {
185 return fFrame;
186 }
187
188 /**
189 * Set the lifeline position index in the containing frame
190 *
191 * @param index the lifeline X position
192 */
193 protected void setIndex(int index) {
194 fIndexInFrame = index;
195 }
196
197 /**
198 * Returns the lifeline position in de the containing frame
199 *
200 * @return the X position
201 */
202 public int getIndex() {
203 return fIndexInFrame;
204 }
205
206 /**
207 * Set the lifeline event occurrence to the value given in parameter This only change the current event occurrence,
208 * greater event created on this lifeline are still valid and usable. This also need to inform the frame of the
209 * operation mostly to store in the frame the greater event found in the diagram (used to determine the frame
210 * height)
211 *
212 * @param eventOcc the new current event occurrence
213 */
214 public void setCurrentEventOccurrence(int eventOcc) {
215 if ((fFrame != null) && (fFrame.getMaxEventOccurrence() < eventOcc)) {
216 fFrame.setMaxEventOccurrence(eventOcc);
217 }
218 fEventOccurrence = eventOcc;
219 }
220
221 /**
222 * Returns the last created event occurrence along the lifeline.
223 *
224 * @return the current event occurrence
225 */
226 public int getEventOccurrence() {
227 return fEventOccurrence;
228 }
229
230 /**
231 * Creates a new event occurrence along the lifeline.
232 *
233 * @return the new created event occurrence
234 */
235 public int getNewEventOccurrence() {
236 setCurrentEventOccurrence(fEventOccurrence + 1);
237 return fEventOccurrence;
238 }
239
240 /**
241 * Adds the execution occurrence given in parameter to the lifeline.<br>
242 * A Execution occurrence is never drawn in the frame instead it is added to a lifeline
243 *
244 * @param exec the execution occurrence to add
245 */
246 public void addExecution(BasicExecutionOccurrence exec) {
247 exec.setLifeline(this);
248 addNode(exec);
249 if ((fFrame != null) && (fFrame.getMaxEventOccurrence() < exec.fEndEventOccurrence)) {
250 fFrame.setMaxEventOccurrence(exec.fEndEventOccurrence);
251 }
252 }
253
254 /**
255 * Set whether lifeline has time information available or not.
256 * @param value The value to set
257 */
258 protected void setTimeInfo(boolean value) {
259 fHasTimeInfo = value;
260 if ((fFrame != null) && value) {
261 fFrame.setHasTimeInfo(value);
262 }
263 }
264
265 /**
266 * Returns true if at least one execution occurrence has time info.
267 *
268 * @return true if at least one execution occurrence has time info
269 */
270 public boolean hasTimeInfo() {
271 return fHasTimeInfo;
272 }
273
274 /**
275 * Returns the list of execution occurrence on this lifeline.
276 *
277 * @return the execution occurrence list
278 */
279 public List<GraphNode> getExecutions() {
280 if (fHasChilden) {
281 return fNodes.get(BasicExecutionOccurrence.EXEC_OCC_TAG);
282 }
283 return new ArrayList<GraphNode>();
284 }
285
286 /*
287 * (non-Javadoc)
288 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#contains(int, int)
289 */
290 @Override
291 public boolean contains(int xValue, int yValue) {
292 int x = getX();
293 int y = getY();
294 int width = getWidth();
295 int height = getHeight();
296
297 if (fFrame == null) {
298 return false;
299 }
300 if (GraphNode.contains(x, y, width, height, xValue, yValue)) {
301 return true;
302 }
303 if (GraphNode.contains(x + Metrics.getLifelineWidth() / 2 - Metrics.EXECUTION_OCCURRENCE_WIDTH / 2, y + height, Metrics.EXECUTION_OCCURRENCE_WIDTH, (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fFrame.getMaxEventOccurrence()
304 + Metrics.LIFELINE_VB_MAGIN - 4, xValue, yValue)) {
305 return true;
306 }
307
308 height = Metrics.getLifelineFontHeigth() + 2 * Metrics.LIFELINE_HEARDER_TEXT_V_MARGIN;
309 int hMargin = (Metrics.LIFELINE_VT_MAGIN - height) / 2;
310
311 if (hMargin >= 2) {
312 if (fFrame.getVisibleAreaY() < y - height - hMargin) {
313 if (GraphNode.contains(x - Metrics.LIFELINE_SPACING / 2 + 1, y - height - hMargin, Metrics.swimmingLaneWidth() - 2, height + 1, xValue, yValue)) {
314 return true;
315 }
316 } else {
317 if (GraphNode.contains(x - Metrics.LIFELINE_SPACING / 2 + 1, fFrame.getVisibleAreaY(), Metrics.swimmingLaneWidth() - 2, height, xValue, yValue)) {
318 return true;
319 }
320 }
321 }
322 if (getNodeAt(xValue, yValue) != null) {
323 return true;
324 }
325 return false;
326 }
327
328 /**
329 * Returns the lifeline visibility for the given visible area
330 *
331 * @param vx The x coordinate of the visible area
332 * @param vy The y coordinate of the visible area
333 * @param vwidth The width of the visible area
334 * @param vheight The height of the visible area
335 * @return true if visible false otherwise
336 */
337 @Override
338 public boolean isVisible(int vx, int vy, int vwidth, int vheight) {
339 int x = getX();
340 int width = getWidth();
341 if (((x >= vx) && (x <= vx + vwidth)) || ((x + width >= vx) && (x <= vx))) {
342 return true;
343 }
344 return false;
345 }
346
347 /**
348 * Draws the name within the graphical context.
349 *
350 * @param context The graphical context.
351 */
352 protected void drawName(IGC context) {
353 ISDPreferences pref = SDViewPref.getInstance();
354
355 int x = getX();
356 int y = getY();
357 int height = Metrics.getLifelineHeaderFontHeigth() + 2 * Metrics.LIFELINE_HEARDER_TEXT_V_MARGIN;
358 int hMargin = Metrics.LIFELINE_VT_MAGIN / 4;// (Metrics.LIFELINE_NAME_H_MARGIN)/2;
359
360 context.setLineStyle(context.getLineSolidStyle());
361 context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_LIFELINE_HEADER));
362 context.setForeground(pref.getForeGroundColor(ISDPreferences.PREF_LIFELINE_HEADER));
363 context.setFont(pref.getFont(ISDPreferences.PREF_LIFELINE_HEADER));
364 if (hMargin >= 0) {
365 if (fFrame.getVisibleAreaY() < y - height - hMargin) {
366 context.fillRectangle(x - Metrics.LIFELINE_SPACING / 2 + 1, y - height - hMargin, Metrics.swimmingLaneWidth() - 2, height);
367 context.drawRectangle(x - Metrics.LIFELINE_SPACING / 2 + 1, y - height - hMargin, Metrics.swimmingLaneWidth() - 2, height);
368 context.setForeground(pref.getFontColor(ISDPreferences.PREF_LIFELINE_HEADER));
369 context.drawTextTruncatedCentred(getName(), x + Metrics.LIFELINE_NAME_V_MARGIN - Metrics.LIFELINE_SPACING / 2 + 1, y - height - hMargin, Metrics.swimmingLaneWidth() - 2 * Metrics.LIFELINE_NAME_V_MARGIN - 2, height, true);
370 } else {
371 context.fillRectangle(x - Metrics.LIFELINE_SPACING / 2 + 1, fFrame.getVisibleAreaY(), Metrics.swimmingLaneWidth() - 2, height);
372 context.drawRectangle(x - Metrics.LIFELINE_SPACING / 2 + 1, fFrame.getVisibleAreaY(), Metrics.swimmingLaneWidth() - 2, height);
373 context.setForeground(pref.getFontColor(ISDPreferences.PREF_LIFELINE_HEADER));
374 context.drawTextTruncatedCentred(getName(), x - Metrics.LIFELINE_SPACING / 2 + Metrics.LIFELINE_NAME_V_MARGIN + 1, fFrame.getVisibleAreaY(), Metrics.swimmingLaneWidth() - 2 * Metrics.LIFELINE_NAME_V_MARGIN - 2, height, true);
375 }
376 }
377 }
378
379 /**
380 * Force the lifeline to be drawn at the given coordinate
381 *
382 * @param context - the context to draw into
383 * @param x - the x coordinate
384 * @param y - the y coordinate
385 */
386 public void draw(IGC context, int x, int y) {
387
388 ISDPreferences pref = SDViewPref.getInstance();
389
390 // Set the draw color depending if the lifeline must be selected or not
391 context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
392 if (isSelected()) {
393 if (pref.useGradienColor()) {
394 context.setGradientColor(pref.getBackGroundColor(ISDPreferences.PREF_LIFELINE));
395 }
396 context.setBackground(pref.getBackGroundColorSelection());
397 context.setForeground(pref.getForeGroundColorSelection());
398 } else {
399 if (pref.useGradienColor()) {
400 context.setGradientColor(pref.getBackGroundColor(ISDPreferences.PREF_LIFELINE));
401 context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_FRAME));
402 } else {
403 context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_LIFELINE));
404 }
405 context.setForeground(pref.getForeGroundColor(ISDPreferences.PREF_LIFELINE));
406 }
407 // Store the lifeline coordinates to save some calls
408 int width = getWidth();
409 int height = getHeight();
410
411 // Draw the rectangle which contain the lifeline name
412 if (pref.useGradienColor()) {
413 context.fillGradientRectangle(x, y, width, height / 2 - 7, true);
414 context.fillRectangle(x, y + height / 2 - 8, width, +height / 2 - 5);
415 context.fillGradientRectangle(x, y + height, width, -height / 2 + 6, true);
416 } else {
417 context.fillRectangle(x, y, width, height);
418 }
419 context.drawRectangle(x, y, width, height);
420
421 if (fCategory >= 0) {
422 LifelineCategories[] categories = fFrame.getLifelineCategories();
423 if (fCategory < categories.length) {
424 IImage image = categories[fCategory].getImage();
425 if (image != null) {
426 context.drawImage(image, x, y, width, height);
427 }
428 }
429 }
430
431 // Draw the lifeline label into the rectangle
432 // The label is truncated if it cannot fit
433 IColor temp = context.getForeground();
434 context.setFont(pref.getFont(ISDPreferences.PREF_LIFELINE));
435 context.setForeground(pref.getFontColor(ISDPreferences.PREF_LIFELINE));
436 context.drawTextTruncatedCentred(getName(), x + Metrics.LIFELINE_NAME_V_MARGIN, y, Metrics.getLifelineWidth() - 2 * Metrics.LIFELINE_NAME_V_MARGIN, height, true);
437
438 context.setLineStyle(context.getLineDashStyle());
439 context.setForeground(temp);
440 int oldStyle = context.getLineStyle();
441
442 // Now draw the lifeline vertical line
443 // this line height depends on a stop assignment
444 // if there is no stop the line is drawn to the bottom of the frame
445
446 // by default set the height to reach the frame bottom
447 int dashedLineEnd = y + height + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fFrame.getMaxEventOccurrence() + Metrics.LIFELINE_VB_MAGIN;
448 /*
449 * if (stop != null) { dashedLineEnd = stop.getY(); }
450 */
451
452 if (isSelected()) {
453 context.setForeground(pref.getBackGroundColorSelection());
454 context.setLineWidth(5);
455 context.drawLine(x + Metrics.getLifelineWidth() / 2, y + height, x + Metrics.getLifelineWidth() / 2, dashedLineEnd - 4);
456 context.setForeground(pref.getForeGroundColorSelection());
457 }
458
459 context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
460 context.drawLine(x + Metrics.getLifelineWidth() / 2, y + height, x + Metrics.getLifelineWidth() / 2, dashedLineEnd - 4);
461 context.drawLine(x + Metrics.getLifelineWidth() / 2, y + height, x + Metrics.getLifelineWidth() / 2, dashedLineEnd - 4);
462 context.setLineStyle(oldStyle);
463
464 context.setLineStyle(context.getLineSolidStyle());
465
466 if (hasFocus()) {
467 drawFocus(context);
468 }
469
470 super.drawChildenNodes(context);
471 }
472
473 /**
474 * Draws the select execution occurrence region using the given color
475 *
476 * @param context the graphical context
477 * @param startEvent the region start
478 * @param nbEvent the region height
479 * @param color the color to use
480 */
481 public void highlightExecOccurrenceRegion(IGC context, int startEvent, int nbEvent, IColor color) {
482 IColor backupColor = context.getBackground();
483 context.setBackground(color);
484 int x = getX() + Metrics.getLifelineWidth() / 2 - Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
485 int y = getY() + getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * startEvent;
486 int width = Metrics.EXECUTION_OCCURRENCE_WIDTH;
487 int height = ((Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing())) * nbEvent;
488 context.fillRectangle(x, y, width, height);
489 context.setBackground(backupColor);
490 }
491
492 /*
493 * (non-Javadoc)
494 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#draw(org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC)
495 */
496 @Override
497 public void draw(IGC context) {
498 draw(context, getX(), getY());
499 }
500
501 /*
502 * (non-Javadoc)
503 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getArrayId()
504 */
505 @Override
506 public String getArrayId() {
507 return LIFELINE_TAG;
508 }
509
510 /*
511 * (non-Javadoc)
512 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#positiveDistanceToPoint(int, int)
513 */
514 @Override
515 public boolean positiveDistanceToPoint(int x, int y) {
516 if (getX() > x - Metrics.swimmingLaneWidth()) {
517 return true;
518 }
519 return false;
520 }
521
522 /*
523 * (non-Javadoc)
524 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#getNodeAt(int, int)
525 */
526 @Override
527 public GraphNode getNodeAt(int x, int y) {
528 int vy = 0;
529 int vh = 0;
530 if (getFrame() != null) {
531 vy = getFrame().getVisibleAreaY();
532 vh = getFrame().getVisibleAreaHeight();
533 } else {
534 return null;
535 }
536 if (getExecutions() == null) {
537 return null;
538 }
539 for (int i = getExecOccurrenceDrawIndex(); i < getExecutions().size(); i++) {
540 GraphNode node = getExecutions().get(i);
541 if (node.getHeight() < 0) {
542 if (node.getY() + node.getHeight() > vy + vh) {
543 break;
544 }
545 } else {
546 if (node.getY() > vy + vh) {
547 break;
548 }
549 }
550 if (node.contains(x, y)) {
551 GraphNode internal = node.getNodeAt(x, y);
552 if (internal != null) {
553 return internal;
554 }
555 return node;
556 }
557 }
558 return null;
559 }
560 }
This page took 0.043486 seconds and 5 git commands to generate.