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