Add process and syscall labels to Control Flow and Resources views
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / timegraph / widgets / Utils.java
1 /*****************************************************************************
2 * Copyright (c) 2007, 2008 Intel Corporation, 2009, 2012 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 * Intel Corporation - Initial API and implementation
10 * Ruslan A. Scherbakov, Intel - Initial API and implementation
11 * Alvaro Sanchez-Leon - Udpated for TMF
12 * Patrick Tasse - Refactoring
13 *
14 *****************************************************************************/
15
16 package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets;
17
18 import java.text.SimpleDateFormat;
19 import java.util.Date;
20 import java.util.Iterator;
21
22 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
23 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
24 import org.eclipse.swt.graphics.Color;
25 import org.eclipse.swt.graphics.Device;
26 import org.eclipse.swt.graphics.GC;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.graphics.Rectangle;
29 import org.eclipse.swt.widgets.Display;
30
31 /**
32 * General utilities and definitions used by the time graph widget
33 *
34 * @version 1.0
35 * @author Alvaro Sanchez-Leon
36 * @author Patrick Tasse
37 */
38 public class Utils {
39
40 /** Time format for dates and timestamp */
41 public enum TimeFormat {
42 /** Relative to the start of the trace */
43 RELATIVE,
44 /** Absolute timestamp (ie, relative to the Unix epoch) */
45 ABSOLUTE
46 }
47
48 static public final int IMG_THREAD_RUNNING = 0;
49 static public final int IMG_THREAD_SUSPENDED = 1;
50 static public final int IMG_THREAD_STOPPED = 2;
51 static public final int IMG_METHOD_RUNNING = 3;
52 static public final int IMG_METHOD = 4;
53 static public final int IMG_NUM = 5;
54
55 static public final Object[] _empty = new Object[0];
56
57 public static enum Resolution {
58 SECONDS, MILLISEC, MICROSEC, NANOSEC
59 }
60
61 static private final SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
62 static private final SimpleDateFormat sdateformat = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
63
64 static Rectangle clone(Rectangle source) {
65 return new Rectangle(source.x, source.y, source.width, source.height);
66 }
67
68 /**
69 * Initialize a Rectangle object to default values (all equal to 0)
70 *
71 * @param rect
72 * The Rectangle to initialize
73 */
74 static public void init(Rectangle rect) {
75 rect.x = 0;
76 rect.y = 0;
77 rect.width = 0;
78 rect.height = 0;
79 }
80
81 /**
82 * Initialize a Rectangle object with all the given values
83 *
84 * @param rect
85 * The Rectangle object to initialize
86 * @param x
87 * The X coordinate
88 * @param y
89 * The Y coordinate
90 * @param width
91 * The width of the rectangle
92 * @param height
93 * The height of the rectangle
94 */
95 static public void init(Rectangle rect, int x, int y, int width, int height) {
96 rect.x = x;
97 rect.y = y;
98 rect.width = width;
99 rect.height = height;
100 }
101
102 /**
103 * Initialize a Rectangle object to another existing Rectangle's values.
104 *
105 * @param rect
106 * The Rectangle to initialize
107 * @param source
108 * The reference Rectangle to copy
109 */
110 static public void init(Rectangle rect, Rectangle source) {
111 rect.x = source.x;
112 rect.y = source.y;
113 rect.width = source.width;
114 rect.height = source.height;
115 }
116
117 /**
118 * Reduce the size of a given rectangle by the given amounts.
119 *
120 * @param rect
121 * The rectangle to modify
122 * @param x
123 * The reduction in width
124 * @param y
125 * The reduction in height
126 */
127 static public void deflate(Rectangle rect, int x, int y) {
128 rect.x += x;
129 rect.y += y;
130 rect.width -= x + x;
131 rect.height -= y + y;
132 }
133
134 /**
135 * Increase the size of a given rectangle by the given amounts.
136 *
137 * @param rect
138 * The rectangle to modify
139 * @param x
140 * The augmentation in width
141 * @param y
142 * The augmentation in height
143 */
144 static public void inflate(Rectangle rect, int x, int y) {
145 rect.x -= x;
146 rect.y -= y;
147 rect.width += x + x;
148 rect.height += y + y;
149 }
150
151 static void dispose(Color col) {
152 if (null != col) {
153 col.dispose();
154 }
155 }
156
157 /**
158 * Get the resulting color from a mix of two existing ones for a given
159 * display.
160 *
161 * @param display
162 * The display device (which might affect the color conversion)
163 * @param c1
164 * The first color
165 * @param c2
166 * The second color
167 * @param w1
168 * The gamma level for color 1
169 * @param w2
170 * The gamma level for color 2
171 * @return The resulting color
172 */
173 static public Color mixColors(Device display, Color c1, Color c2, int w1,
174 int w2) {
175 return new Color(display, (w1 * c1.getRed() + w2 * c2.getRed())
176 / (w1 + w2), (w1 * c1.getGreen() + w2 * c2.getGreen())
177 / (w1 + w2), (w1 * c1.getBlue() + w2 * c2.getBlue())
178 / (w1 + w2));
179 }
180
181 /**
182 * Get the system color with the given ID.
183 *
184 * @param id
185 * The color ID
186 * @return The resulting color
187 */
188 static public Color getSysColor(int id) {
189 Color col = Display.getCurrent().getSystemColor(id);
190 return new Color(col.getDevice(), col.getRGB());
191 }
192
193 /**
194 * Get the resulting color from a mix of two existing ones for the current
195 * display.
196 *
197 * @param col1
198 * The first color
199 * @param col2
200 * The second color
201 * @param w1
202 * The gamma level for color 1
203 * @param w2
204 * The gamma level for color 2
205 * @return The resulting color
206 */
207 static public Color mixColors(Color col1, Color col2, int w1, int w2) {
208 return mixColors(Display.getCurrent(), col1, col2, w1, w2);
209 }
210
211 /**
212 * Draw text in a rectangle.
213 *
214 * @param gc
215 * The SWT GC object
216 * @param text
217 * The text to draw
218 * @param rect
219 * The rectangle object which is being drawn
220 * @param transp
221 * Should we transpose the color
222 * @return The X coordinate where we have written
223 */
224 static public int drawText(GC gc, String text, Rectangle rect, boolean transp) {
225 Point size = gc.stringExtent(text);
226 gc.drawText(text, rect.x, rect.y, transp);
227 return size.x;
228 }
229
230 /**
231 * Draw text at a given location.
232 *
233 * @param gc
234 * The SWT GC object
235 * @param text
236 * The text to draw
237 * @param x
238 * The X coordinate of the starting point
239 * @param y
240 * the Y coordinate of the starting point
241 * @param transp
242 * Should we transpose the color
243 * @return The X coordinate where we have written
244 */
245 static public int drawText(GC gc, String text, int x, int y, boolean transp) {
246 Point size = gc.stringExtent(text);
247 gc.drawText(text, x, y, transp);
248 return size.x;
249 }
250
251 /**
252 * Draw text in a rectangle, trimming the text to prevent exceeding the specified width.
253 *
254 * @param gc
255 * The SWT GC object
256 * @param text
257 * The string to be drawn
258 * @param x
259 * The x coordinate of the top left corner of the rectangular area where the text is to be drawn
260 * @param y
261 * The y coordinate of the top left corner of the rectangular area where the text is to be drawn
262 * @param width
263 * The width of the area to be drawn
264 * @param isCentered
265 * If <code>true</code> the text will be centered in the available width if space permits
266 * @param isTransparent
267 * If <code>true</code> the background will be transparent, otherwise it will be opaque
268 * @return The number of characters written
269 *
270 * @since 2.0
271 */
272 static public int drawText(GC gc, String text, int x, int y, int width, boolean isCentered, boolean isTransparent) {
273 int len = text.length();
274 int textWidth = 0;
275 while (len > 0) {
276 textWidth = gc.stringExtent(text.substring(0, len)).x;
277 if (textWidth <= width) {
278 break;
279 }
280 isCentered = false;
281 len--;
282 }
283 if (len > 0) {
284 if (isCentered) {
285 x += (width - textWidth) / 2;
286 }
287 gc.drawText(text.substring(0, len), x, y, isTransparent);
288 }
289 return len;
290 }
291
292 /**
293 * Formats time in format: MM:SS:NNN
294 *
295 * @param time time
296 * @param format 0: MMMM:ss:nnnnnnnnn, 1: HH:MM:ss MMM.mmmm.nnn
297 * @param resolution the resolution
298 * @return the formatted time
299 */
300 static public String formatTime(long time, TimeFormat format, Resolution resolution) {
301 // if format is absolute (Calendar)
302 if (format == TimeFormat.ABSOLUTE) {
303 return formatTimeAbs(time, resolution);
304 }
305
306 StringBuffer str = new StringBuffer();
307 boolean neg = time < 0;
308 if (neg) {
309 time = -time;
310 str.append('-');
311 }
312
313 long sec = (long) (time * 1E-9);
314 // TODO: Expand to make it possible to select the minute, second, nanosecond format
315 //printing minutes is suppressed just sec and ns
316 // if (sec / 60 < 10)
317 // str.append('0');
318 // str.append(sec / 60);
319 // str.append(':');
320 // sec %= 60;
321 // if (sec < 10)
322 // str.append('0');
323 str.append(sec);
324 String ns = formatNs(time, resolution);
325 if (!ns.equals("")) { //$NON-NLS-1$
326 str.append('.');
327 str.append(ns);
328 }
329
330 return str.toString();
331 }
332
333 /**
334 * From input time in nanoseconds, convert to Date format YYYY-MM-dd
335 *
336 * @param absTime
337 * The source time, in ns
338 * @return the formatted date
339 */
340 public static String formatDate(long absTime) {
341 String sdate = sdateformat.format(new Date((long) (absTime * 1E-6)));
342 return sdate;
343 }
344
345 /**
346 * Formats time in ns to Calendar format: HH:MM:SS MMM.mmm.nnn
347 *
348 * @param time
349 * The source time, in ns
350 * @param res
351 * The resolution to use
352 * @return the formatted time
353 */
354 static public String formatTimeAbs(long time, Resolution res) {
355 StringBuffer str = new StringBuffer();
356
357 // format time from nanoseconds to calendar time HH:MM:SS
358 String stime = stimeformat.format(new Date((long) (time * 1E-6)));
359 str.append(stime);
360 str.append('.');
361 // append the Milliseconds, MicroSeconds and NanoSeconds as specified in
362 // the Resolution
363 str.append(formatNs(time, res));
364 return str.toString();
365 }
366
367 /**
368 * Obtains the remainder fraction on unit Seconds of the entered value in
369 * nanoseconds. e.g. input: 1241207054171080214 ns The number of fraction
370 * seconds can be obtained by removing the last 9 digits: 1241207054 the
371 * fractional portion of seconds, expressed in ns is: 171080214
372 *
373 * @param time
374 * The source time in ns
375 * @param res
376 * The Resolution to use
377 * @return the formatted nanosec
378 */
379 public static String formatNs(long time, Resolution res) {
380 StringBuffer str = new StringBuffer();
381 boolean neg = time < 0;
382 if (neg) {
383 time = -time;
384 }
385
386 // The following approach could be used although performance
387 // decreases in half.
388 // String strVal = String.format("%09d", time);
389 // String tmp = strVal.substring(strVal.length() - 9);
390
391 long ns = time;
392 ns %= 1000000000;
393 if (ns < 10) {
394 str.append("00000000"); //$NON-NLS-1$
395 } else if (ns < 100) {
396 str.append("0000000"); //$NON-NLS-1$
397 } else if (ns < 1000) {
398 str.append("000000"); //$NON-NLS-1$
399 } else if (ns < 10000) {
400 str.append("00000"); //$NON-NLS-1$
401 } else if (ns < 100000) {
402 str.append("0000"); //$NON-NLS-1$
403 } else if (ns < 1000000) {
404 str.append("000"); //$NON-NLS-1$
405 } else if (ns < 10000000) {
406 str.append("00"); //$NON-NLS-1$
407 } else if (ns < 100000000) {
408 str.append("0"); //$NON-NLS-1$
409 }
410 str.append(ns);
411
412 if (res == Resolution.MILLISEC) {
413 return str.substring(0, 3);
414 } else if (res == Resolution.MICROSEC) {
415 return str.substring(0, 6);
416 } else if (res == Resolution.NANOSEC) {
417 return str.substring(0, 9);
418 }
419 return ""; //$NON-NLS-1$
420 }
421
422 /**
423 * FIXME Currently does nothing.
424 *
425 * @param opt
426 * The option name
427 * @param def
428 * The option value
429 * @param min
430 * The minimal accepted value
431 * @param max
432 * The maximal accepted value
433 * @return The value that was read
434 */
435 static public int loadIntOption(String opt, int def, int min, int max) {
436 // int val =
437 // TraceUIPlugin.getDefault().getPreferenceStore().getInt(opt);
438 // if (0 == val)
439 // val = def;
440 // if (val < min)
441 // val = min;
442 // if (val > max)
443 // val = max;
444 return def;
445 }
446
447 /**
448 * FIXME currently does nothing
449 *
450 * @param opt
451 * The option name
452 * @param val
453 * The option value
454 */
455 static public void saveIntOption(String opt, int val) {
456 // TraceUIPlugin.getDefault().getPreferenceStore().setValue(opt, val);
457 }
458
459 static ITimeEvent getFirstEvent(ITimeGraphEntry entry) {
460 if (null == entry || ! entry.hasTimeEvents()) {
461 return null;
462 }
463 Iterator<ITimeEvent> iterator = entry.getTimeEventsIterator();
464 if (iterator != null && iterator.hasNext()) {
465 return iterator.next();
466 }
467 return null;
468 }
469
470 /**
471 * N means: <list> <li>-1: Previous Event</li> <li>0: Current Event</li> <li>
472 * 1: Next Event</li> <li>2: Previous Event when located in a non Event Area
473 * </list>
474 *
475 * @param entry
476 * @param time
477 * @param n
478 * @return
479 */
480 static ITimeEvent findEvent(ITimeGraphEntry entry, long time, int n) {
481 if (null == entry || ! entry.hasTimeEvents()) {
482 return null;
483 }
484 Iterator<ITimeEvent> iterator = entry.getTimeEventsIterator();
485 if (iterator == null) {
486 return null;
487 }
488 ITimeEvent nextEvent = null;
489 ITimeEvent currEvent = null;
490 ITimeEvent prevEvent = null;
491
492 while (iterator.hasNext()) {
493 nextEvent = iterator.next();
494 long nextStartTime = nextEvent.getTime();
495
496 if (nextStartTime > time) {
497 break;
498 }
499
500 if (currEvent == null || currEvent.getTime() != nextStartTime) {
501 prevEvent = currEvent;
502 currEvent = nextEvent;
503 }
504 }
505
506 if (n == -1) { //previous
507 if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) {
508 return prevEvent;
509 }
510 return currEvent;
511 } else if (n == 0) { //current
512 if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) {
513 return currEvent;
514 }
515 return null;
516 } else if (n == 1) { //next
517 if (nextEvent != null && nextEvent.getTime() > time) {
518 return nextEvent;
519 }
520 return null;
521 } else if (n == 2) { //current or previous when in empty space
522 return currEvent;
523 }
524
525 return null;
526 }
527
528 /**
529 * Pretty-print a method signature.
530 *
531 * @param sig
532 * The original signature
533 * @return The pretty signature
534 */
535 static public String fixMethodSignature(String sig) {
536 int pos = sig.indexOf('(');
537 if (pos >= 0) {
538 String ret = sig.substring(0, pos);
539 sig = sig.substring(pos);
540 sig = sig + " " + ret; //$NON-NLS-1$
541 }
542 return sig;
543 }
544
545 /**
546 * Restore an original method signature from a pretty-printed one.
547 *
548 * @param sig
549 * The pretty-printed signature
550 * @return The original method signature
551 */
552 static public String restoreMethodSignature(String sig) {
553 String ret = ""; //$NON-NLS-1$
554 int pos = sig.indexOf('(');
555 if (pos >= 0) {
556 ret = sig.substring(0, pos);
557 sig = sig.substring(pos + 1);
558 }
559 pos = sig.indexOf(')');
560 if (pos >= 0) {
561 sig = sig.substring(0, pos);
562 }
563 String args[] = sig.split(","); //$NON-NLS-1$
564 StringBuffer result = new StringBuffer("("); //$NON-NLS-1$
565 for (int i = 0; i < args.length; i++) {
566 String arg = args[i].trim();
567 if (arg.length() == 0 && args.length == 1) {
568 break;
569 }
570 result.append(getTypeSignature(arg));
571 }
572 result.append(")").append(getTypeSignature(ret)); //$NON-NLS-1$
573 return result.toString();
574 }
575
576 /**
577 * Get the mangled type information from an array of types.
578 *
579 * @param type
580 * The types to convert. See method implementation for what it
581 * expects.
582 * @return The mangled string of types
583 */
584 static public String getTypeSignature(String type) {
585 int dim = 0;
586 for (int j = 0; j < type.length(); j++) {
587 if (type.charAt(j) == '[') {
588 dim++;
589 }
590 }
591 int pos = type.indexOf('[');
592 if (pos >= 0) {
593 type = type.substring(0, pos);
594 }
595 StringBuffer sig = new StringBuffer(""); //$NON-NLS-1$
596 for (int j = 0; j < dim; j++)
597 {
598 sig.append("["); //$NON-NLS-1$
599 }
600 if (type.equals("boolean")) { //$NON-NLS-1$
601 sig.append('Z');
602 } else if (type.equals("byte")) { //$NON-NLS-1$
603 sig.append('B');
604 } else if (type.equals("char")) { //$NON-NLS-1$
605 sig.append('C');
606 } else if (type.equals("short")) { //$NON-NLS-1$
607 sig.append('S');
608 } else if (type.equals("int")) { //$NON-NLS-1$
609 sig.append('I');
610 } else if (type.equals("long")) { //$NON-NLS-1$
611 sig.append('J');
612 } else if (type.equals("float")) { //$NON-NLS-1$
613 sig.append('F');
614 } else if (type.equals("double")) { //$NON-NLS-1$
615 sig.append('D');
616 } else if (type.equals("void")) { //$NON-NLS-1$
617 sig.append('V');
618 }
619 else {
620 sig.append('L').append(type.replace('.', '/')).append(';');
621 }
622 return sig.toString();
623 }
624
625 /**
626 * Compare two doubles together.
627 *
628 * @param d1
629 * First double
630 * @param d2
631 * Second double
632 * @return 1 if they are different, and 0 if they are *exactly* the same.
633 * Because of the way doubles are stored, it's possible for the
634 * same number obtained in two different ways to actually look
635 * different.
636 */
637 static public int compare(double d1, double d2) {
638 if (d1 > d2) {
639 return 1;
640 }
641 if (d1 < d2) {
642 return 1;
643 }
644 return 0;
645 }
646
647 /**
648 * Compare two character strings alphabetically. This is simply a wrapper
649 * around String.compareToIgnoreCase but that will handle cases where
650 * strings can be null
651 *
652 * @param s1
653 * The first string
654 * @param s2
655 * The second string
656 * @return A number below, equal, or greater than zero if the first string
657 * is smaller, equal, or bigger (alphabetically) than the second
658 * one.
659 */
660 static public int compare(String s1, String s2) {
661 if (s1 != null && s2 != null) {
662 return s1.compareToIgnoreCase(s2);
663 }
664 if (s1 != null) {
665 return 1;
666 }
667 if (s2 != null) {
668 return -1;
669 }
670 return 0;
671 }
672 }
This page took 0.045278 seconds and 6 git commands to generate.