tmf: Ellipse function names that don't fit in CallStackView
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / timegraph / widgets / Utils.java
CommitLineData
6151d86c 1/*****************************************************************************
0fab12b0 2 * Copyright (c) 2007, 2014 Intel Corporation, Ericsson
6151d86c
PT
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:
c1cd9635
MAL
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 * Marc-Andre Laperle - Add time zone preference
6151d86c
PT
14 *****************************************************************************/
15
2bdf0193 16package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets;
6151d86c 17
026664b7 18import java.text.NumberFormat;
6151d86c
PT
19import java.text.SimpleDateFormat;
20import java.util.Date;
21import java.util.Iterator;
c1cd9635 22import java.util.TimeZone;
0fab12b0 23import java.util.concurrent.TimeUnit;
6151d86c 24
5b3fe39a 25import org.eclipse.jdt.annotation.NonNull;
6151d86c
PT
26import org.eclipse.swt.graphics.Color;
27import org.eclipse.swt.graphics.Device;
28import org.eclipse.swt.graphics.GC;
29import org.eclipse.swt.graphics.Point;
30import org.eclipse.swt.graphics.Rectangle;
31import org.eclipse.swt.widgets.Display;
2bdf0193
AM
32import org.eclipse.tracecompass.internal.tmf.ui.Messages;
33import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimePreferences;
34import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
35import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
6151d86c
PT
36
37/**
38 * General utilities and definitions used by the time graph widget
39 *
6151d86c
PT
40 * @author Alvaro Sanchez-Leon
41 * @author Patrick Tasse
42 */
43public class Utils {
44
f1fae91f
PT
45 private Utils() {
46 }
47
6151d86c
PT
48 /** Time format for dates and timestamp */
49 public enum TimeFormat {
50 /** Relative to the start of the trace */
51 RELATIVE,
386cf45c
AM
52
53 /**
54 * Absolute timestamp (ie, relative to the Unix epoch)
386cf45c 55 */
026664b7 56 CALENDAR,
386cf45c
AM
57
58 /**
59 * Timestamp displayed as a simple number
386cf45c 60 */
026664b7 61 NUMBER,
0fab12b0
PT
62
63 /**
64 * Timestamp displayed as cycles
0fab12b0
PT
65 */
66 CYCLES
6151d86c
PT
67 }
68
a0a88f65
AM
69 /**
70 * Timestamp resolution
71 */
72 public static enum Resolution {
73 /** seconds */
74 SECONDS,
6151d86c 75
a0a88f65
AM
76 /** milliseconds */
77 MILLISEC,
6151d86c 78
a0a88f65
AM
79 /** microseconds */
80 MICROSEC,
81
82 /** nanoseconds */
83 NANOSEC
6151d86c
PT
84 }
85
2984a466
AM
86 /**
87 * Ellipsis character, used to shorten strings that don't fit in their
88 * target area.
89 *
90 * @since 2.1
91 */
92 public static final String ELLIPSIS = "…"; //$NON-NLS-1$
93
f1fae91f
PT
94 private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
95 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
0fab12b0
PT
96 private static final long HOURS_PER_DAY = 24;
97 private static final long MIN_PER_HOUR = 60;
98 private static final long SEC_PER_MIN = 60;
f1fae91f
PT
99 private static final long SEC_IN_NS = 1000000000;
100 private static final long MILLISEC_IN_NS = 1000000;
6151d86c 101
c1cd9635
MAL
102 /**
103 * Update the time and date formats to use the current time zone
c1cd9635
MAL
104 */
105 public static void updateTimeZone() {
7c34a4ea 106 TimeZone timeZone = TmfTimePreferences.getTimeZone();
c1cd9635
MAL
107 TIME_FORMAT.setTimeZone(timeZone);
108 DATE_FORMAT.setTimeZone(timeZone);
109 }
110
6151d86c
PT
111 static Rectangle clone(Rectangle source) {
112 return new Rectangle(source.x, source.y, source.width, source.height);
113 }
114
115 /**
116 * Initialize a Rectangle object to default values (all equal to 0)
117 *
118 * @param rect
119 * The Rectangle to initialize
120 */
f1fae91f 121 public static void init(Rectangle rect) {
6151d86c
PT
122 rect.x = 0;
123 rect.y = 0;
124 rect.width = 0;
125 rect.height = 0;
126 }
127
128 /**
129 * Initialize a Rectangle object with all the given values
130 *
131 * @param rect
132 * The Rectangle object to initialize
133 * @param x
134 * The X coordinate
135 * @param y
136 * The Y coordinate
137 * @param width
138 * The width of the rectangle
139 * @param height
140 * The height of the rectangle
141 */
f1fae91f 142 public static void init(Rectangle rect, int x, int y, int width, int height) {
6151d86c
PT
143 rect.x = x;
144 rect.y = y;
145 rect.width = width;
146 rect.height = height;
147 }
148
149 /**
150 * Initialize a Rectangle object to another existing Rectangle's values.
151 *
152 * @param rect
153 * The Rectangle to initialize
154 * @param source
155 * The reference Rectangle to copy
156 */
f1fae91f 157 public static void init(Rectangle rect, Rectangle source) {
6151d86c
PT
158 rect.x = source.x;
159 rect.y = source.y;
160 rect.width = source.width;
161 rect.height = source.height;
162 }
163
164 /**
165 * Reduce the size of a given rectangle by the given amounts.
166 *
167 * @param rect
168 * The rectangle to modify
169 * @param x
170 * The reduction in width
171 * @param y
172 * The reduction in height
173 */
f1fae91f 174 public static void deflate(Rectangle rect, int x, int y) {
6151d86c
PT
175 rect.x += x;
176 rect.y += y;
177 rect.width -= x + x;
178 rect.height -= y + y;
179 }
180
181 /**
182 * Increase the size of a given rectangle by the given amounts.
183 *
184 * @param rect
185 * The rectangle to modify
186 * @param x
187 * The augmentation in width
188 * @param y
189 * The augmentation in height
190 */
f1fae91f 191 public static void inflate(Rectangle rect, int x, int y) {
6151d86c
PT
192 rect.x -= x;
193 rect.y -= y;
194 rect.width += x + x;
195 rect.height += y + y;
196 }
197
198 static void dispose(Color col) {
199 if (null != col) {
200 col.dispose();
201 }
202 }
203
204 /**
205 * Get the resulting color from a mix of two existing ones for a given
206 * display.
207 *
208 * @param display
209 * The display device (which might affect the color conversion)
210 * @param c1
211 * The first color
212 * @param c2
213 * The second color
214 * @param w1
215 * The gamma level for color 1
216 * @param w2
217 * The gamma level for color 2
218 * @return The resulting color
219 */
f1fae91f 220 public static Color mixColors(Device display, Color c1, Color c2, int w1,
6151d86c
PT
221 int w2) {
222 return new Color(display, (w1 * c1.getRed() + w2 * c2.getRed())
223 / (w1 + w2), (w1 * c1.getGreen() + w2 * c2.getGreen())
224 / (w1 + w2), (w1 * c1.getBlue() + w2 * c2.getBlue())
225 / (w1 + w2));
226 }
227
228 /**
229 * Get the system color with the given ID.
230 *
231 * @param id
232 * The color ID
233 * @return The resulting color
234 */
f1fae91f 235 public static Color getSysColor(int id) {
6151d86c
PT
236 Color col = Display.getCurrent().getSystemColor(id);
237 return new Color(col.getDevice(), col.getRGB());
238 }
239
240 /**
241 * Get the resulting color from a mix of two existing ones for the current
242 * display.
243 *
244 * @param col1
245 * The first color
246 * @param col2
247 * The second color
248 * @param w1
249 * The gamma level for color 1
250 * @param w2
251 * The gamma level for color 2
252 * @return The resulting color
253 */
f1fae91f 254 public static Color mixColors(Color col1, Color col2, int w1, int w2) {
6151d86c
PT
255 return mixColors(Display.getCurrent(), col1, col2, w1, w2);
256 }
257
258 /**
259 * Draw text in a rectangle.
260 *
261 * @param gc
262 * The SWT GC object
263 * @param text
264 * The text to draw
265 * @param rect
266 * The rectangle object which is being drawn
267 * @param transp
0fab12b0
PT
268 * If true the background will be transparent
269 * @return The width of the written text
6151d86c 270 */
f1fae91f 271 public static int drawText(GC gc, String text, Rectangle rect, boolean transp) {
6151d86c
PT
272 Point size = gc.stringExtent(text);
273 gc.drawText(text, rect.x, rect.y, transp);
274 return size.x;
275 }
276
277 /**
278 * Draw text at a given location.
279 *
280 * @param gc
281 * The SWT GC object
282 * @param text
283 * The text to draw
284 * @param x
285 * The X coordinate of the starting point
286 * @param y
287 * the Y coordinate of the starting point
288 * @param transp
0fab12b0
PT
289 * If true the background will be transparent
290 * @return The width of the written text
6151d86c 291 */
f1fae91f 292 public static int drawText(GC gc, String text, int x, int y, boolean transp) {
6151d86c
PT
293 Point size = gc.stringExtent(text);
294 gc.drawText(text, x, y, transp);
295 return size.x;
296 }
297
713a70ae
PT
298 /**
299 * Draw text in a rectangle, trimming the text to prevent exceeding the specified width.
300 *
301 * @param gc
302 * The SWT GC object
303 * @param text
304 * The string to be drawn
305 * @param x
306 * The x coordinate of the top left corner of the rectangular area where the text is to be drawn
307 * @param y
308 * The y coordinate of the top left corner of the rectangular area where the text is to be drawn
309 * @param width
310 * The width of the area to be drawn
311 * @param isCentered
312 * If <code>true</code> the text will be centered in the available width if space permits
313 * @param isTransparent
314 * If <code>true</code> the background will be transparent, otherwise it will be opaque
315 * @return The number of characters written
2984a466 316 * @deprecated Use {@link #drawText(GC, String, int, int, int, int, boolean, boolean)} instead.
713a70ae 317 */
2984a466 318 @Deprecated
f1fae91f 319 public static int drawText(GC gc, String text, int x, int y, int width, boolean isCentered, boolean isTransparent) {
5bf0ab10
MAL
320 if (width < 1) {
321 return 0;
322 }
323
713a70ae
PT
324 int len = text.length();
325 int textWidth = 0;
41b5c37f
AM
326 boolean isReallyCentered = isCentered;
327 int realX = x;
328
713a70ae
PT
329 while (len > 0) {
330 textWidth = gc.stringExtent(text.substring(0, len)).x;
331 if (textWidth <= width) {
332 break;
333 }
41b5c37f 334 isReallyCentered = false;
713a70ae
PT
335 len--;
336 }
337 if (len > 0) {
41b5c37f
AM
338 if (isReallyCentered) {
339 realX += (width - textWidth) / 2;
713a70ae 340 }
41b5c37f 341 gc.drawText(text.substring(0, len), realX, y, isTransparent);
713a70ae
PT
342 }
343 return len;
344 }
345
3bd20aa6
PT
346 /**
347 * Draw text in a rectangle, trimming the text to prevent exceeding the specified width.
348 *
349 * @param gc
350 * The SWT GC object
351 * @param text
352 * The string to be drawn
353 * @param x
354 * The x coordinate of the top left corner of the rectangular area where the text is to be drawn
355 * @param y
356 * The y coordinate of the top left corner of the rectangular area where the text is to be drawn
357 * @param width
358 * The width of the area to be drawn
359 * @param height
360 * The height of the area to be drawn
361 * @param isCentered
362 * If <code>true</code> the text will be centered in the available area if space permits
363 * @param isTransparent
364 * If <code>true</code> the background will be transparent, otherwise it will be opaque
365 * @return The number of characters written
366 * @since 2.0
367 */
368 public static int drawText(GC gc, String text, int x, int y, int width, int height, boolean isCentered, boolean isTransparent) {
2984a466 369 if (width < 1 || text.isEmpty()) {
3bd20aa6
PT
370 return 0;
371 }
372
2984a466
AM
373 String stringToDisplay;
374 int len;
375
3bd20aa6
PT
376 boolean isCenteredWidth = isCentered;
377 int realX = x;
378 int realY = y;
379
2984a466
AM
380 /* First check if the whole string fits */
381 Point textExtent = gc.textExtent(text);
382 if (textExtent.x <= width) {
383 len = text.length();
384 stringToDisplay = text;
385 } else {
386 /*
387 * The full string doesn't fit, try to find the longest one with
388 * "..." at the end that does fit.
389 *
390 * Iterate on the string length sizes, starting from 1 going up,
391 * until we find a string that does not fit. Once we do, we keep the
392 * one just before that did fit.
393 */
3bd20aa6 394 isCenteredWidth = false;
2984a466
AM
395 int prevLen = 0;
396 len = 1;
397 while (len <= text.length()) {
398 textExtent = gc.textExtent(text.substring(0, len) + ELLIPSIS);
399 if (textExtent.x > width) {
400 /*
401 * Here is the first length that does not fit, the one from
402 * the previous iteration is the one we will use.
403 */
404 len = prevLen;
405 break;
406 }
407 /* This string would fit, try the next one */
408 prevLen = len;
409 len++;
3bd20aa6 410 }
2984a466
AM
411 stringToDisplay = text.substring(0, len) + ELLIPSIS;
412 }
413
414 if (len <= 0) {
415 /* Nothing fits, we end up drawing nothing */
416 return 0;
417 }
418
419 if (isCenteredWidth) {
420 realX += (width - textExtent.x) / 2;
421 }
422 if (isCentered) {
423 realY += (height - textExtent.y) / 2 - 1;
3bd20aa6 424 }
2984a466
AM
425 gc.drawText(stringToDisplay, realX, realY, isTransparent);
426
3bd20aa6
PT
427 return len;
428 }
429
6151d86c
PT
430 /**
431 * Formats time in format: MM:SS:NNN
432 *
433 * @param time time
434 * @param format 0: MMMM:ss:nnnnnnnnn, 1: HH:MM:ss MMM.mmmm.nnn
435 * @param resolution the resolution
436 * @return the formatted time
437 */
f1fae91f 438 public static String formatTime(long time, TimeFormat format, Resolution resolution) {
0fab12b0
PT
439 switch (format) {
440 case CALENDAR:
6151d86c 441 return formatTimeAbs(time, resolution);
0fab12b0 442 case NUMBER:
026664b7 443 return NumberFormat.getInstance().format(time);
0fab12b0
PT
444 case CYCLES:
445 return NumberFormat.getInstance().format(time) + Messages.Utils_ClockCyclesUnit;
446 case RELATIVE:
447 default:
6151d86c
PT
448 }
449
450 StringBuffer str = new StringBuffer();
41b5c37f
AM
451 long t = time;
452 boolean neg = t < 0;
6151d86c 453 if (neg) {
41b5c37f 454 t = -t;
6151d86c
PT
455 str.append('-');
456 }
457
f1fae91f 458 long sec = t / SEC_IN_NS;
6151d86c 459 str.append(sec);
41b5c37f 460 String ns = formatNs(t, resolution);
6151d86c
PT
461 if (!ns.equals("")) { //$NON-NLS-1$
462 str.append('.');
463 str.append(ns);
464 }
465
466 return str.toString();
467 }
468
469 /**
470 * From input time in nanoseconds, convert to Date format YYYY-MM-dd
471 *
472 * @param absTime
473 * The source time, in ns
474 * @return the formatted date
475 */
476 public static String formatDate(long absTime) {
f1fae91f 477 String sdate = DATE_FORMAT.format(new Date(absTime / MILLISEC_IN_NS));
6151d86c
PT
478 return sdate;
479 }
480
481 /**
482 * Formats time in ns to Calendar format: HH:MM:SS MMM.mmm.nnn
483 *
484 * @param time
485 * The source time, in ns
486 * @param res
487 * The resolution to use
488 * @return the formatted time
489 */
f1fae91f 490 public static String formatTimeAbs(long time, Resolution res) {
6151d86c
PT
491 StringBuffer str = new StringBuffer();
492
493 // format time from nanoseconds to calendar time HH:MM:SS
f1fae91f 494 String stime = TIME_FORMAT.format(new Date(time / MILLISEC_IN_NS));
6151d86c
PT
495 str.append(stime);
496 str.append('.');
497 // append the Milliseconds, MicroSeconds and NanoSeconds as specified in
498 // the Resolution
499 str.append(formatNs(time, res));
500 return str.toString();
501 }
502
0fab12b0
PT
503 /**
504 * Formats time delta
505 *
506 * @param delta
507 * The time delta, in ns
508 * @param format
509 * The time format to use
510 * @param resolution
511 * The resolution to use
0fab12b0
PT
512 * @return the formatted time delta
513 */
514 public static String formatDelta(long delta, TimeFormat format, Resolution resolution) {
515 if (format == TimeFormat.CALENDAR) {
516 return formatDeltaAbs(delta, resolution);
517 }
518 return formatTime(delta, format, resolution);
519 }
520
521 /**
522 * Formats time delta in ns to Calendar format, only formatting the years,
523 * days, hours or minutes if necessary.
524 *
525 * @param delta
526 * The time delta, in ns
527 * @param resolution
528 * The resolution to use
529 * @return the formatted time delta
0fab12b0
PT
530 */
531 public static String formatDeltaAbs(long delta, Resolution resolution) {
532 StringBuffer str = new StringBuffer();
533 if (delta < 0) {
534 str.append('-');
535 }
536 long ns = Math.abs(delta);
537 long seconds = TimeUnit.NANOSECONDS.toSeconds(ns);
538 long minutes = TimeUnit.NANOSECONDS.toMinutes(ns);
539 long hours = TimeUnit.NANOSECONDS.toHours(ns);
540 long days = TimeUnit.NANOSECONDS.toDays(ns);
541 if (days > 0) {
542 str.append(days);
543 str.append("d "); //$NON-NLS-1$
544 }
545 if (hours > 0) {
546 str.append(hours % HOURS_PER_DAY);
547 str.append("h "); //$NON-NLS-1$
548 }
549 if (minutes > 0) {
550 str.append(minutes % MIN_PER_HOUR);
551 str.append("m "); //$NON-NLS-1$
552 }
553 str.append(seconds % SEC_PER_MIN);
554 str.append('.');
555 // append the ms, us and ns as specified in the resolution
556 str.append(formatNs(delta, resolution));
557 str.append("s"); //$NON-NLS-1$
558 return str.toString();
559 }
560
6151d86c
PT
561 /**
562 * Obtains the remainder fraction on unit Seconds of the entered value in
563 * nanoseconds. e.g. input: 1241207054171080214 ns The number of fraction
564 * seconds can be obtained by removing the last 9 digits: 1241207054 the
565 * fractional portion of seconds, expressed in ns is: 171080214
566 *
41b5c37f 567 * @param srcTime
6151d86c
PT
568 * The source time in ns
569 * @param res
570 * The Resolution to use
571 * @return the formatted nanosec
572 */
41b5c37f 573 public static String formatNs(long srcTime, Resolution res) {
6151d86c 574 StringBuffer str = new StringBuffer();
407bfdd5 575 long ns = Math.abs(srcTime % SEC_IN_NS);
f1fae91f
PT
576 String nanos = Long.toString(ns);
577 str.append("000000000".substring(nanos.length())); //$NON-NLS-1$
578 str.append(nanos);
6151d86c
PT
579
580 if (res == Resolution.MILLISEC) {
581 return str.substring(0, 3);
582 } else if (res == Resolution.MICROSEC) {
583 return str.substring(0, 6);
584 } else if (res == Resolution.NANOSEC) {
585 return str.substring(0, 9);
586 }
587 return ""; //$NON-NLS-1$
588 }
589
590 /**
591 * FIXME Currently does nothing.
592 *
593 * @param opt
594 * The option name
595 * @param def
596 * The option value
597 * @param min
598 * The minimal accepted value
599 * @param max
600 * The maximal accepted value
601 * @return The value that was read
602 */
f1fae91f 603 public static int loadIntOption(String opt, int def, int min, int max) {
6151d86c
PT
604 return def;
605 }
606
607 /**
608 * FIXME currently does nothing
609 *
610 * @param opt
611 * The option name
612 * @param val
613 * The option value
614 */
f1fae91f 615 public static void saveIntOption(String opt, int val) {
6151d86c
PT
616 }
617
618 static ITimeEvent getFirstEvent(ITimeGraphEntry entry) {
619 if (null == entry || ! entry.hasTimeEvents()) {
620 return null;
621 }
df2597e0 622 Iterator<? extends ITimeEvent> iterator = entry.getTimeEventsIterator();
6151d86c
PT
623 if (iterator != null && iterator.hasNext()) {
624 return iterator.next();
625 }
626 return null;
627 }
628
629 /**
bedfbbb5
XR
630 * Gets the {@link ITimeEvent} at the given time from the given
631 * {@link ITimeGraphEntry}.
6151d86c
PT
632 *
633 * @param entry
bedfbbb5 634 * a {@link ITimeGraphEntry}
6151d86c 635 * @param time
bedfbbb5 636 * a timestamp
6151d86c 637 * @param n
bedfbbb5
XR
638 * this parameter means: <list> <li>-1: Previous Event</li> <li>
639 * 0: Current Event</li> <li>
640 * 1: Next Event</li> <li>2: Previous Event when located in a non
641 * Event Area </list>
642 * @return a {@link ITimeEvent}, or <code>null</code>.
6151d86c 643 */
bedfbbb5 644 public static ITimeEvent findEvent(ITimeGraphEntry entry, long time, int n) {
6151d86c
PT
645 if (null == entry || ! entry.hasTimeEvents()) {
646 return null;
647 }
5b3fe39a 648 Iterator<@NonNull ? extends ITimeEvent> iterator = entry.getTimeEventsIterator();
6151d86c
PT
649 if (iterator == null) {
650 return null;
651 }
652 ITimeEvent nextEvent = null;
653 ITimeEvent currEvent = null;
654 ITimeEvent prevEvent = null;
655
656 while (iterator.hasNext()) {
657 nextEvent = iterator.next();
658 long nextStartTime = nextEvent.getTime();
659
660 if (nextStartTime > time) {
661 break;
662 }
663
b905d437
XR
664 if (currEvent == null || currEvent.getTime() != nextStartTime ||
665 (nextStartTime != time && currEvent.getDuration() != nextEvent.getDuration())) {
6151d86c
PT
666 prevEvent = currEvent;
667 currEvent = nextEvent;
668 }
669 }
670
671 if (n == -1) { //previous
672 if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) {
673 return prevEvent;
674 }
675 return currEvent;
676 } else if (n == 0) { //current
677 if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) {
678 return currEvent;
679 }
680 return null;
681 } else if (n == 1) { //next
682 if (nextEvent != null && nextEvent.getTime() > time) {
683 return nextEvent;
684 }
685 return null;
686 } else if (n == 2) { //current or previous when in empty space
687 return currEvent;
688 }
689
690 return null;
691 }
692
693 /**
694 * Pretty-print a method signature.
695 *
41b5c37f 696 * @param origSig
6151d86c
PT
697 * The original signature
698 * @return The pretty signature
699 */
f1fae91f 700 public static String fixMethodSignature(String origSig) {
41b5c37f 701 String sig = origSig;
6151d86c
PT
702 int pos = sig.indexOf('(');
703 if (pos >= 0) {
704 String ret = sig.substring(0, pos);
705 sig = sig.substring(pos);
706 sig = sig + " " + ret; //$NON-NLS-1$
707 }
708 return sig;
709 }
710
711 /**
712 * Restore an original method signature from a pretty-printed one.
713 *
41b5c37f 714 * @param ppSig
6151d86c
PT
715 * The pretty-printed signature
716 * @return The original method signature
717 */
f1fae91f 718 public static String restoreMethodSignature(String ppSig) {
6151d86c 719 String ret = ""; //$NON-NLS-1$
41b5c37f
AM
720 String sig = ppSig;
721
6151d86c
PT
722 int pos = sig.indexOf('(');
723 if (pos >= 0) {
724 ret = sig.substring(0, pos);
725 sig = sig.substring(pos + 1);
726 }
727 pos = sig.indexOf(')');
728 if (pos >= 0) {
729 sig = sig.substring(0, pos);
730 }
731 String args[] = sig.split(","); //$NON-NLS-1$
732 StringBuffer result = new StringBuffer("("); //$NON-NLS-1$
733 for (int i = 0; i < args.length; i++) {
734 String arg = args[i].trim();
735 if (arg.length() == 0 && args.length == 1) {
736 break;
737 }
738 result.append(getTypeSignature(arg));
739 }
740 result.append(")").append(getTypeSignature(ret)); //$NON-NLS-1$
741 return result.toString();
742 }
743
744 /**
745 * Get the mangled type information from an array of types.
746 *
41b5c37f 747 * @param typeStr
6151d86c
PT
748 * The types to convert. See method implementation for what it
749 * expects.
750 * @return The mangled string of types
751 */
41b5c37f 752 public static String getTypeSignature(String typeStr) {
6151d86c 753 int dim = 0;
41b5c37f 754 String type = typeStr;
6151d86c
PT
755 for (int j = 0; j < type.length(); j++) {
756 if (type.charAt(j) == '[') {
757 dim++;
758 }
759 }
760 int pos = type.indexOf('[');
761 if (pos >= 0) {
762 type = type.substring(0, pos);
763 }
764 StringBuffer sig = new StringBuffer(""); //$NON-NLS-1$
765 for (int j = 0; j < dim; j++)
766 {
41b5c37f 767 sig.append("["); //$NON-NLS-1$
6151d86c
PT
768 }
769 if (type.equals("boolean")) { //$NON-NLS-1$
770 sig.append('Z');
771 } else if (type.equals("byte")) { //$NON-NLS-1$
772 sig.append('B');
773 } else if (type.equals("char")) { //$NON-NLS-1$
774 sig.append('C');
775 } else if (type.equals("short")) { //$NON-NLS-1$
776 sig.append('S');
777 } else if (type.equals("int")) { //$NON-NLS-1$
778 sig.append('I');
779 } else if (type.equals("long")) { //$NON-NLS-1$
780 sig.append('J');
781 } else if (type.equals("float")) { //$NON-NLS-1$
782 sig.append('F');
783 } else if (type.equals("double")) { //$NON-NLS-1$
784 sig.append('D');
785 } else if (type.equals("void")) { //$NON-NLS-1$
786 sig.append('V');
787 }
788 else {
789 sig.append('L').append(type.replace('.', '/')).append(';');
790 }
791 return sig.toString();
792 }
793
794 /**
795 * Compare two doubles together.
796 *
797 * @param d1
798 * First double
799 * @param d2
800 * Second double
801 * @return 1 if they are different, and 0 if they are *exactly* the same.
802 * Because of the way doubles are stored, it's possible for the
803 * same number obtained in two different ways to actually look
804 * different.
805 */
f1fae91f 806 public static int compare(double d1, double d2) {
6151d86c
PT
807 if (d1 > d2) {
808 return 1;
809 }
810 if (d1 < d2) {
811 return 1;
812 }
813 return 0;
814 }
815
816 /**
817 * Compare two character strings alphabetically. This is simply a wrapper
818 * around String.compareToIgnoreCase but that will handle cases where
819 * strings can be null
820 *
821 * @param s1
822 * The first string
823 * @param s2
824 * The second string
825 * @return A number below, equal, or greater than zero if the first string
826 * is smaller, equal, or bigger (alphabetically) than the second
827 * one.
828 */
f1fae91f 829 public static int compare(String s1, String s2) {
6151d86c
PT
830 if (s1 != null && s2 != null) {
831 return s1.compareToIgnoreCase(s2);
832 }
833 if (s1 != null) {
834 return 1;
835 }
836 if (s2 != null) {
837 return -1;
838 }
839 return 0;
840 }
1053eaa6
PT
841
842 /**
843 * Calculates the square of the distance between two points.
844 *
845 * @param x1
846 * x-coordinate of point 1
847 * @param y1
848 * y-coordinate of point 1
849 * @param x2
850 * x-coordinate of point 2
851 * @param y2
852 * y-coordinate of point 2
853 *
854 * @return the square of the distance in pixels^2
1053eaa6
PT
855 */
856 public static double distance2(int x1, int y1, int x2, int y2) {
857 int dx = x2 - x1;
858 int dy = y2 - y1;
859 int d2 = dx * dx + dy * dy;
860 return d2;
861 }
862
863 /**
864 * Calculates the distance between a point and a line segment. If the point
865 * is in the perpendicular region between the segment points, return the
866 * distance from the point to its projection on the segment. Otherwise
867 * return the distance from the point to its closest segment point.
868 *
869 * @param px
870 * x-coordinate of the point
871 * @param py
872 * y-coordinate of the point
873 * @param x1
874 * x-coordinate of segment point 1
875 * @param y1
876 * y-coordinate of segment point 1
877 * @param x2
878 * x-coordinate of segment point 2
879 * @param y2
880 * y-coordinate of segment point 2
881 *
882 * @return the distance in pixels
1053eaa6
PT
883 */
884 public static double distance(int px, int py, int x1, int y1, int x2, int y2) {
885 double length2 = distance2(x1, y1, x2, y2);
886 if (length2 == 0) {
887 return Math.sqrt(distance2(px, py, x1, y1));
888 }
889 // 'r' is the ratio of the position, between segment point 1 and segment
890 // point 2, of the projection of the point on the segment
891 double r = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / length2;
892 if (r <= 0.0) {
893 // the projection is before segment point 1, return distance from
894 // the point to segment point 1
895 return Math.sqrt(distance2(px, py, x1, y1));
896 }
897 if (r >= 1.0) {
898 // the projection is after segment point 2, return distance from
899 // the point to segment point 2
900 return Math.sqrt(distance2(px, py, x2, y2));
901 }
902 // the projection is between the segment points, return distance from
903 // the point to its projection on the segment
904 int x = (int) (x1 + r * (x2 - x1));
905 int y = (int) (y1 + r * (y2 - y1));
906 return Math.sqrt(distance2(px, py, x, y));
907 }
6151d86c 908}
This page took 0.13168 seconds and 5 git commands to generate.