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