930a5f978477850596de86608ef9f5309600b697
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / uml2sd / core / BasicFrame.java
1 /**********************************************************************
2 * Copyright (c) 2005, 2014 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 static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import java.util.ArrayList;
18 import java.util.Iterator;
19 import java.util.List;
20
21 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
22 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
23 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IGC;
24 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.ISDPreferences;
25 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.SDViewPref;
26
27 /**
28 * The Frame class is the base sequence diagram graph nodes container.<br>
29 * For instance, only one frame can be drawn in the View.<br>
30 * Lifelines, Messages and Stop which are supposed to represent a Sequence diagram are drawn in a Frame.<br>
31 * Only the graph node added to their representing list will be drawn.
32 *
33 * The lifelines are appended along the X axsis when added in a frame.<br>
34 * The syncMessages are ordered along the Y axsis depending on the event occurrence they are attached to.<br>
35 *
36 * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.Lifeline Lifeline for more event occurence details
37 * @author sveyrier
38 * @version 1.0
39 */
40 public class BasicFrame extends GraphNode {
41
42 // ------------------------------------------------------------------------
43 // Attributes
44 // ------------------------------------------------------------------------
45
46 /**
47 * Contains the max elapsed time between two consecutive messages in the whole frame
48 */
49 private ITmfTimestamp fMaxTime = new TmfTimestamp(0);
50 /**
51 * Contains the min elapsed time between two consecutive messages in the whole frame
52 */
53 private ITmfTimestamp fMinTime = new TmfTimestamp(0);
54 /**
55 * Indicate if the min and max elapsed time between two consecutive messages in the whole frame need to be computed
56 */
57 private boolean fComputeMinMax = true;
58 /**
59 * Store the preference set by the user regarding the external time. This flag is used determine if the min and max
60 * need to be recomputed in case this preference is changed.
61 */
62 private boolean fLastExternalTimePref = SDViewPref.getInstance().excludeExternalTime();
63 /**
64 * The greater event occurrence created on graph nodes drawn in this Frame This directly impact the Frame height
65 */
66 private int fVerticalIndex = 0;
67 /**
68 * The index along the x axis where the next lifeline will is drawn This directly impact the Frame width
69 */
70 private int fHorizontalIndex = 0;
71 /**
72 * The time information flag.
73 */
74 private boolean fHasTimeInfo = false;
75 /**
76 * The current Frame visible area - x coordinates
77 */
78 private int fVisibleAreaX;
79 /**
80 * The current Frame visible area - y coordinates
81 */
82 private int fVisibleAreaY;
83 /**
84 * The current Frame visible area - width
85 */
86 private int fVisibleAreaWidth;
87 /**
88 * The current Frame visible area - height
89 */
90 private int fVisibleAreaHeight;
91 /**
92 * The event occurrence spacing (-1 for none)
93 */
94 private int fForceEventOccurrenceSpacing = -1;
95 /**
96 * Flag to indicate customized minumum and maximum.
97 */
98 private boolean fCustomMinMax = false;
99 /**
100 * The minimum time between messages of the sequence diagram frame.
101 */
102 private ITmfTimestamp fMinSDTime = new TmfTimestamp();
103 /**
104 * The maximum time between messages of the sequence diagram frame.
105 */
106 private ITmfTimestamp fMaxSDTime = new TmfTimestamp();
107 /**
108 * Flag to indicate that initial minimum has to be computed.
109 */
110 private boolean fInitSDMin = true;
111
112 // ------------------------------------------------------------------------
113 // Constructors
114 // ------------------------------------------------------------------------
115
116 /**
117 * Creates an empty frame.
118 */
119 public BasicFrame() {
120 Metrics.setForcedEventSpacing(fForceEventOccurrenceSpacing);
121 }
122
123 // ------------------------------------------------------------------------
124 // Methods
125 // ------------------------------------------------------------------------
126
127 /**
128 *
129 * Returns the greater event occurence known by the Frame
130 *
131 * @return the greater event occurrence
132 */
133 protected int getMaxEventOccurrence() {
134 return fVerticalIndex;
135 }
136
137 /**
138 * Set the greater event occurrence created in GraphNodes included in the frame
139 *
140 * @param eventOccurrence the new greater event occurrence
141 */
142 protected void setMaxEventOccurrence(int eventOccurrence) {
143 fVerticalIndex = eventOccurrence;
144 }
145
146 /**
147 * This method increase the lifeline place holder The return value is usually assign to a lifeline. This can be used
148 * to set the lifelines drawing order. Also, calling this method two times and assigning only the last given index
149 * to a lifeline will increase this lifeline draw spacing (2 times the default spacing) from the last added
150 * lifeline.
151 *
152 * @return a new lifeline index
153 */
154 protected int getNewHorizontalIndex() {
155 return ++fHorizontalIndex;
156 }
157
158 /**
159 * Returns the current horizontal index
160 *
161 * @return the current horizontal index
162 * @see Frame#getNewHorizontalIndex() for horizontal index description
163 */
164 protected int getHorizontalIndex() {
165 return fHorizontalIndex;
166 }
167
168 @Override
169 public void addNode(GraphNode nodeToAdd) {
170 setComputeMinMax(true);
171 super.addNode(nodeToAdd);
172 }
173
174 @Override
175 public int getX() {
176 return Metrics.FRAME_H_MARGIN;
177 }
178
179 @Override
180 public int getY() {
181 return Metrics.FRAME_V_MARGIN;
182 }
183
184 @Override
185 public int getWidth() {
186 if (fHorizontalIndex == 0) {
187 return 3 * Metrics.swimmingLaneWidth() + Metrics.LIFELINE_H_MAGIN * 2 - Metrics.FRAME_H_MARGIN - Metrics.LIFELINE_SPACING / 2;
188 }
189 return fHorizontalIndex * Metrics.swimmingLaneWidth() + Metrics.LIFELINE_H_MAGIN * 2 + 1 - Metrics.LIFELINE_SPACING;
190 }
191
192 @Override
193 public int getHeight() {
194 // The Frame height depends on the maximum number of messages added to a lifeline
195 if (fVerticalIndex == 0) {
196 return 5 * (Metrics.getMessagesSpacing() + Metrics.getMessageFontHeigth()) + Metrics.LIFELINE_NAME_H_MARGIN + Metrics.FRAME_NAME_H_MARGIN + Metrics.getFrameFontHeigth() + Metrics.LIFELINE_VT_MAGIN + Metrics.LIFELINE_VB_MAGIN
197 + Metrics.LIFELINE_NAME_H_MARGIN + Metrics.FRAME_NAME_H_MARGIN + Metrics.getLifelineFontHeigth() * 2;
198 }
199 if (fForceEventOccurrenceSpacing >= 0) {
200 Metrics.setForcedEventSpacing(fForceEventOccurrenceSpacing);
201 }
202 return fVerticalIndex * (Metrics.getMessagesSpacing() + Metrics.getMessageFontHeigth()) + Metrics.LIFELINE_NAME_H_MARGIN + Metrics.FRAME_NAME_H_MARGIN + Metrics.getFrameFontHeigth() + Metrics.LIFELINE_VT_MAGIN + Metrics.LIFELINE_VB_MAGIN
203 + Metrics.LIFELINE_NAME_H_MARGIN + Metrics.FRAME_NAME_H_MARGIN + Metrics.getLifelineFontHeigth() * 2;
204 }
205
206 /**
207 * @return true if mininum and maximum time needs to be calculated else false
208 */
209 protected boolean isComputeMinMax() {
210 return fComputeMinMax;
211 }
212
213 /**
214 * @return true if mininum and maximum time needs to be calculated else false
215 */
216 protected boolean isCustomMinMax() {
217 return fCustomMinMax;
218 }
219
220 /**
221 * gets the initialization flag for SD minimum.
222 *
223 * @return the initialization flag for SD minimum
224 */
225 protected boolean getInitSDMin() {
226 return fInitSDMin;
227 }
228
229 /**
230 * Returns the graph node which contains the point given in parameter for the given graph node list and starting the
231 * iteration at the given index<br>
232 * WARNING: Only graph nodes with smaller coordinates than the current visible area can be returned.<br>
233 *
234 * @param x the x coordinate of the point to test
235 * @param y the y coordinate of the point to test
236 * @param list the list to search in
237 * @param fromIndex list browsing starting point
238 * @return the graph node containing the point given in parameter, null otherwise
239 *
240 * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode#getNodeFromListAt(int, int, java.util.List, int)
241 */
242 @Override
243 protected GraphNode getNodeFromListAt(int x, int y, List<GraphNode> list, int fromIndex) {
244 if (list == null) {
245 return null;
246 }
247 for (int i = fromIndex; i < list.size(); i++) {
248 GraphNode node = list.get(i);
249 // only lifeline list is x ordered
250 // Stop browsing the list if the node is outside the visible area
251 // all others nodes will be not visible
252 if ((node instanceof Lifeline) && (node.getX() > fVisibleAreaX + fVisibleAreaWidth)) {
253 break;
254 }
255 if (node.getHeight() < 0) {
256 if (node.getY() + node.getHeight() > fVisibleAreaY + fVisibleAreaHeight) {
257 break;
258 }
259 } else {
260 if (node.getY() > fVisibleAreaY + fVisibleAreaHeight) {
261 break;
262 }
263 }
264 if (node.contains(x, y)) {
265 return node;
266 }
267 }
268 return null;
269 }
270
271 /**
272 * Draw the Frame rectangle
273 *
274 * @param context the context to draw to
275 */
276 protected void drawFrame(IGC context) {
277
278 ISDPreferences pref = SDViewPref.getInstance();
279
280 context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_FRAME));
281 context.setForeground(pref.getForeGroundColor(ISDPreferences.PREF_FRAME));
282
283 int x = getX();
284 int y = getY();
285 int w = getWidth();
286 int h = getHeight();
287
288 // Draw the frame main rectangle
289 context.fillRectangle(x, y, w, h);
290 context.drawRectangle(x, y, w, h);
291
292 context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_FRAME_NAME));
293 context.setForeground(pref.getForeGroundColor(ISDPreferences.PREF_FRAME_NAME));
294 context.setFont(pref.getFont(ISDPreferences.PREF_FRAME_NAME));
295
296 int nameWidth = context.textExtent(getName()) + 2 * Metrics.FRAME_NAME_V_MARGIN;
297 int nameHeight = Metrics.getFrameFontHeigth() + +Metrics.FRAME_NAME_H_MARGIN * 2;
298
299 // Draw the frame name area
300 if (nameWidth > w) {
301 nameWidth = w;
302 }
303
304 int[] points = { x, y, x + nameWidth, y, x + nameWidth, y - 11 + nameHeight, x - 11 + nameWidth, y + nameHeight, x, y + nameHeight, x, y + nameHeight };
305 context.fillPolygon(points);
306 context.drawPolygon(points);
307 context.drawLine(x, y, x, y + nameHeight);
308
309 context.setForeground(pref.getFontColor(ISDPreferences.PREF_FRAME_NAME));
310 context.drawTextTruncatedCentred(getName(), x, y, nameWidth - 11, nameHeight, false);
311
312 context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_FRAME));
313 context.setForeground(pref.getForeGroundColor(ISDPreferences.PREF_FRAME));
314 }
315
316 @Override
317 public void draw(IGC context) {
318 draw(context, true);
319 }
320
321 /**
322 * Draws the Frame on the given context.<br>
323 * This method start width GraphNodes ordering if needed.<br>
324 * After, depending on the visible area, only visible GraphNodes are drawn.<br>
325 *
326 * @param context the context to draw to
327 * @param drawFrame indicate if the frame rectangle need to be redrawn
328 * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode#draw(IGC)
329 */
330 protected void draw(IGC context, boolean drawFrame) {
331 fVisibleAreaHeight = context.getVisibleHeight();
332 fVisibleAreaWidth = context.getVisibleWidth();
333 fVisibleAreaX = context.getContentsX();
334 fVisibleAreaY = context.getContentsY();
335
336 if (fForceEventOccurrenceSpacing >= 0) {
337 Metrics.setForcedEventSpacing(fForceEventOccurrenceSpacing);
338 } else {
339 Metrics.setForcedEventSpacing(-1);
340 }
341
342 super.drawChildenNodes(context);
343 }
344
345 /**
346 * Sets the event occurrence spacing (-1 for none)
347 *
348 * @param space A spacing to set.
349 */
350 public void forceEventOccurrenceSpacing(int space) {
351 fForceEventOccurrenceSpacing = space;
352 }
353
354 /**
355 * Return the X coordinates of the frame visible area
356 *
357 * @return the X coordinates of the frame visible area
358 */
359 public int getVisibleAreaX() {
360 return fVisibleAreaX;
361 }
362
363 /**
364 * Return the frame visible area width
365 *
366 * @return the frame visible area width
367 */
368 public int getVisibleAreaWidth() {
369 return fVisibleAreaWidth;
370 }
371
372 /**
373 * Return the frame visible area height
374 *
375 * @return the frame visible area height
376 */
377 public int getVisibleAreaHeight() {
378 return fVisibleAreaHeight;
379 }
380
381 /**
382 * Return the X coordinates of the frame visible area
383 *
384 * @return the X coordinates of the frame visible area
385 */
386 public int getVisibleAreaY() {
387 return fVisibleAreaY;
388 }
389
390 /**
391 * Return the minimum time stored in the frame taking all GraphNodes into account
392 *
393 * @return the minimum GraphNode time
394 */
395 public ITmfTimestamp getMinTime() {
396 if (fLastExternalTimePref != SDViewPref.getInstance().excludeExternalTime()) {
397 fLastExternalTimePref = SDViewPref.getInstance().excludeExternalTime();
398 setComputeMinMax(true);
399 }
400 if ((fComputeMinMax) && (!fCustomMinMax)) {
401 computeMinMax();
402 setComputeMinMax(false);
403 }
404 return fMinTime;
405 }
406
407 /**
408 * Set the minimum timestamp of the frame.
409 *
410 * @param min
411 * The minimum timestamp
412 */
413 public void setMin(ITmfTimestamp min) {
414 fMinTime = min;
415 fCustomMinMax = true;
416 }
417
418 /**
419 * Set the maximum timestamp of the frame.
420 *
421 * @param max
422 * The maximum timestamp
423 */
424 public void setMax(ITmfTimestamp max) {
425 fMaxTime = max;
426 fCustomMinMax = true;
427 }
428
429 /**
430 * Reset min/max timestamp values to the default ones.
431 */
432 public void resetCustomMinMax() {
433 fCustomMinMax = false;
434 setComputeMinMax(true);
435 }
436
437 /**
438 * Return the maximum time stored in the frame taking all GraphNodes into account
439 *
440 * @return the maximum GraphNode time
441 */
442 public ITmfTimestamp getMaxTime() {
443 if (fLastExternalTimePref != SDViewPref.getInstance().excludeExternalTime()) {
444 fLastExternalTimePref = SDViewPref.getInstance().excludeExternalTime();
445 setComputeMinMax(true);
446 }
447 if (fComputeMinMax) {
448 computeMinMax();
449 setComputeMinMax(false);
450 }
451 return fMaxTime;
452 }
453
454 /**
455 * Computes the minimum and maximum time between consecutive messages within the frame.
456 */
457 protected void computeMaxMinTime() {
458 if (!fInitSDMin) {
459 return;
460 }
461
462 List<SDTimeEvent> timeArray = buildTimeArray();
463
464 if ((timeArray == null) || timeArray.isEmpty()) {
465 return;
466 }
467 for (int i = 0; i < timeArray.size(); i++) {
468 SDTimeEvent m = timeArray.get(i);
469
470 if (m.getTime().compareTo(fMaxSDTime) > 0) {
471 fMaxSDTime = m.getTime();
472 }
473
474 if ((m.getTime().compareTo(fMinSDTime) < 0) || fInitSDMin) {
475 fMinSDTime = m.getTime();
476 fInitSDMin = false;
477 }
478 }
479 }
480
481 /**
482 * Returns the minimum time between consecutive messages.
483 *
484 * @return the minimum time between consecutive messages
485 */
486 public ITmfTimestamp getSDMinTime() {
487 computeMaxMinTime();
488 return fMinSDTime;
489 }
490
491 /**
492 * Returns the maximum time between consecutive messages.
493 *
494 * @return the maximum time between consecutive messages
495 */
496 public ITmfTimestamp getSDMaxTime() {
497 computeMaxMinTime();
498 return fMaxSDTime;
499 }
500
501 /**
502 * Browse all the GraphNode to compute the min and max times store in the Frame
503 */
504 protected void computeMinMax() {
505 List<SDTimeEvent> timeArray = buildTimeArray();
506
507 if ((timeArray == null) || timeArray.isEmpty()) {
508 return;
509 }
510 for (int i = 0; i < timeArray.size() - 1; i++) {
511 SDTimeEvent m1 = timeArray.get(i);
512 SDTimeEvent m2 = timeArray.get(i + 1);
513
514 updateMinMax(m1, m2);
515 }
516 }
517
518 /**
519 * Updates the minimum and maximum time between consecutive message within the frame based on the given values.
520 *
521 * @param m1 A first SD time event.
522 * @param m2 A second SD time event.
523 */
524 protected void updateMinMax(SDTimeEvent m1, SDTimeEvent m2) {
525 ITmfTimestamp delta = m2.getTime().getDelta(m1.getTime());
526 if (fComputeMinMax) {
527 fMinTime = delta;
528 if (fMinTime.compareTo(TmfTimestamp.ZERO) < 0) {
529 fMinTime = new TmfTimestamp(0, m1.getTime().getScale());
530 }
531 fMaxTime = fMinTime;
532 setComputeMinMax(false);
533 }
534
535 if ((delta.compareTo(fMinTime) < 0) && (delta.compareTo(TmfTimestamp.ZERO) > 0)) {
536 fMinTime = delta;
537 }
538
539 if ((delta.compareTo(fMaxTime) > 0) && (delta.compareTo(TmfTimestamp.ZERO) > 0)) {
540 fMaxTime = delta;
541 }
542 }
543
544 /**
545 * Builds the time array based on the list of graph nodes.
546 *
547 * @return the time array else empty list.
548 */
549 protected List<SDTimeEvent> buildTimeArray() {
550 if (!hasChildren()) {
551 return new ArrayList<>();
552 }
553
554 Iterator<String> it = getForwardSortMap().keySet().iterator();
555 List<SDTimeEvent> timeArray = new ArrayList<>();
556 while (it.hasNext()) {
557 String nodeType = it.next();
558 List<GraphNode> list = checkNotNull(getNodeMap().get(nodeType));
559 for (int i = 0; i < list.size(); i++) {
560 Object timedNode = list.get(i);
561 if ((timedNode instanceof ITimeRange) && ((ITimeRange) timedNode).hasTimeInfo()) {
562 int event = list.get(i).getStartOccurrence();
563 ITmfTimestamp time = ((ITimeRange) list.get(i)).getStartTime();
564 SDTimeEvent f = new SDTimeEvent(time, event, (ITimeRange) list.get(i));
565 timeArray.add(f);
566 if (event != list.get(i).getEndOccurrence()) {
567 event = (list.get(i)).getEndOccurrence();
568 time = ((ITimeRange) list.get(i)).getEndTime();
569 f = new SDTimeEvent(time, event, (ITimeRange) list.get(i));
570 timeArray.add(f);
571 }
572 }
573 }
574 }
575 return timeArray;
576 }
577
578 @Override
579 public String getArrayId() {
580 return null;
581 }
582
583 @Override
584 public boolean contains(int x, int y) {
585 return false;
586 }
587
588 /**
589 * @return true if frame has time info else false
590 */
591 public boolean hasTimeInfo() {
592 return fHasTimeInfo;
593 }
594
595 /**
596 * Sets the flag whether the frame has time info or not
597 *
598 * @param hasTimeInfo
599 * true if frame has time info else false
600 */
601 public void setHasTimeInfo(boolean hasTimeInfo) {
602 fHasTimeInfo = hasTimeInfo;
603 }
604
605 /**
606 * Sets the flag for minimum and maximum computation.
607 *
608 * @param computeMinMax
609 * true if mininum and maximum time needs to be calculated else false
610 */
611 public void setComputeMinMax(boolean computeMinMax) {
612 fComputeMinMax = computeMinMax;
613 }
614
615 /**
616 * Sets the initialization flag for SD minimum.
617 *
618 * @param initSDMin
619 * the flag to set
620 */
621 public void setInitSDMin(boolean initSDMin) {
622 fInitSDMin = initSDMin;
623 }
624 }
This page took 0.045624 seconds and 4 git commands to generate.