1 /*****************************************************************************
2 * Copyright (c) 2007, 2013 Intel 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
9 * Intel Corporation - Initial API and implementation
10 * Ruslan A. Scherbakov, Intel - Initial API and implementation
11 * Alvaro Sanchez-Leon - Updated for TMF
12 * Patrick Tasse - Refactoring
13 * Marc-Andre Laperle - Add time zone preference
14 *****************************************************************************/
16 package org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
;
18 import java
.text
.NumberFormat
;
19 import java
.text
.SimpleDateFormat
;
20 import java
.util
.Calendar
;
21 import java
.util
.Date
;
22 import java
.util
.TimeZone
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalManager
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimePreferences
;
28 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.Resolution
;
29 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
30 import org
.eclipse
.swt
.SWT
;
31 import org
.eclipse
.swt
.events
.MouseEvent
;
32 import org
.eclipse
.swt
.events
.MouseListener
;
33 import org
.eclipse
.swt
.events
.MouseMoveListener
;
34 import org
.eclipse
.swt
.events
.PaintEvent
;
35 import org
.eclipse
.swt
.graphics
.GC
;
36 import org
.eclipse
.swt
.graphics
.Point
;
37 import org
.eclipse
.swt
.graphics
.Rectangle
;
38 import org
.eclipse
.swt
.widgets
.Composite
;
41 * Implementation of the scale for the time graph view.
43 * This goes above the "gantt chart" area.
46 * @author Alvaro Sanchez-Leon
47 * @author Patrick Tasse
49 public class TimeGraphScale
extends TimeGraphBaseControl
implements
50 MouseListener
, MouseMoveListener
{
52 private static final long MICROSEC_IN_NS
= 1000;
53 private static final long MILLISEC_IN_NS
= 1000000;
54 private static final long SEC_IN_NS
= 1000000000;
55 private static final long MIN_IN_NS
= 60 * SEC_IN_NS
;
56 private static final long HOUR_IN_NS
= 60 * MIN_IN_NS
;
57 private static final long DAY_IN_NS
= 24 * HOUR_IN_NS
;
58 private static final long MONTH_IN_NS
= 31 * DAY_IN_NS
; // upper limit
59 private static final long YEAR_IN_NS
= 366 * DAY_IN_NS
; // upper limit
61 private static final double LOG10_1
= Math
.log10(1);
62 private static final double LOG10_2
= Math
.log10(2);
63 private static final double LOG10_3
= Math
.log10(3);
64 private static final double LOG10_5
= Math
.log10(5);
66 private static final Calendar GREGORIAN_CALENDAR
= Calendar
.getInstance();
68 private static final TimeDraw TIMEDRAW_NANOSEC
= new TimeDrawNanosec();
69 private static final TimeDraw TIMEDRAW_MICROSEC
= new TimeDrawMicrosec();
70 private static final TimeDraw TIMEDRAW_MILLISEC
= new TimeDrawMillisec();
71 private static final TimeDraw TIMEDRAW_SEC
= new TimeDrawSec();
72 private static final TimeDraw TIMEDRAW_ABS_NANOSEC
= new TimeDrawAbsNanoSec();
73 private static final TimeDraw TIMEDRAW_ABS_MICROSEC
= new TimeDrawAbsMicroSec();
74 private static final TimeDraw TIMEDRAW_ABS_MILLISEC
= new TimeDrawAbsMillisec();
75 private static final TimeDraw TIMEDRAW_ABS_SEC
= new TimeDrawAbsSec();
76 private static final TimeDraw TIMEDRAW_ABS_MIN
= new TimeDrawAbsMin();
77 private static final TimeDraw TIMEDRAW_ABS_HRS
= new TimeDrawAbsHrs();
78 private static final TimeDraw TIMEDRAW_ABS_DAY
= new TimeDrawAbsDay();
79 private static final TimeDraw TIMEDRAW_ABS_MONTH
= new TimeDrawAbsMonth();
80 private static final TimeDraw TIMEDRAW_ABS_YEAR
= new TimeDrawAbsYear();
81 private static final TimeDraw TIMEDRAW_NUMBER
= new TimeDrawNumber();
83 private static final int DRAG_EXTERNAL
= -1;
84 private static final int NO_BUTTON
= 0;
85 private static final int LEFT_BUTTON
= 1;
87 private ITimeDataProvider fTimeProvider
;
88 private int fDragState
= NO_BUTTON
;
89 private int fDragX0
= 0;
90 private int fDragX
= 0;
91 private long fTime0bak
;
92 private long fTime1bak
;
93 private boolean fIsInUpdate
;
97 * Standard constructor
100 * The parent composite object
102 * The color scheme to use
104 public TimeGraphScale(Composite parent
, TimeGraphColorScheme colors
) {
105 super(parent
, colors
, SWT
.NO_BACKGROUND
| SWT
.NO_FOCUS
| SWT
.DOUBLE_BUFFERED
);
106 TmfSignalManager
.register(this);
107 addMouseListener(this);
108 addMouseMoveListener(this);
109 TimeDraw
.updateTimeZone();
113 public void dispose() {
114 TmfSignalManager
.deregister(this);
119 * Assign the time provider for this scale
121 * @param timeProvider
122 * The provider to use
124 public void setTimeProvider(ITimeDataProvider timeProvider
) {
125 fTimeProvider
= timeProvider
;
129 public Point
computeSize(int wHint
, int hHint
, boolean changed
) {
130 return super.computeSize(wHint
, fHeight
, changed
);
134 * Set the height of the scale
139 public void setHeight(int height
) {
140 this.fHeight
= height
;
144 * Set the drag range to paint decorators
147 * The begin x-coordinate
149 * The end x-coordinate
152 public void setDragRange(int begin
, int end
) {
153 if (NO_BUTTON
== fDragState
|| DRAG_EXTERNAL
== fDragState
) {
154 fDragX0
= begin
- fTimeProvider
.getNameSpace();
155 fDragX
= end
- fTimeProvider
.getNameSpace();
156 if (begin
>= 0 || end
>= 0) {
157 fDragState
= DRAG_EXTERNAL
;
159 fDragState
= NO_BUTTON
;
165 private long calcTimeDelta(int width
, double pixelsPerNanoSec
) {
167 double minDelta
= (pixelsPerNanoSec
== 0) ? YEAR_IN_NS
: width
/ pixelsPerNanoSec
;
169 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
170 if (minDelta
> 6 * MONTH_IN_NS
) {
172 } else if (minDelta
> 3 * MONTH_IN_NS
) {
173 unit
= 6 * MONTH_IN_NS
;
174 } else if (minDelta
> 10 * DAY_IN_NS
) {
176 } else if (minDelta
> 12 * HOUR_IN_NS
) {
178 } else if (minDelta
> 3 * HOUR_IN_NS
) {
179 unit
= 6 * HOUR_IN_NS
;
180 } else if (minDelta
> 30 * MIN_IN_NS
) {
182 } else if (minDelta
> 10 * MIN_IN_NS
) {
183 unit
= 15 * MIN_IN_NS
;
184 } else if (minDelta
> 30 * SEC_IN_NS
) {
186 } else if (minDelta
> 20 * SEC_IN_NS
) {
187 unit
= 30 * SEC_IN_NS
;
188 } else if (minDelta
<= 1) {
193 double log
= Math
.log10(minDelta
/ unit
);
194 long pow10
= (long) log
;
195 double remainder
= log
- pow10
;
196 if (remainder
< LOG10_1
) {
197 timeDelta
= (long) Math
.pow(10, pow10
) * unit
;
198 } else if (remainder
< LOG10_2
) {
199 timeDelta
= 2 * (long) Math
.pow(10, pow10
) * unit
;
200 } else if (remainder
< LOG10_3
&& unit
>= HOUR_IN_NS
&& unit
< YEAR_IN_NS
) {
201 timeDelta
= 3 * (long) Math
.pow(10, pow10
) * unit
;
202 } else if (remainder
< LOG10_5
) {
203 timeDelta
= 5 * (long) Math
.pow(10, pow10
) * unit
;
205 timeDelta
= 10 * (long) Math
.pow(10, pow10
) * unit
;
207 if (timeDelta
<= 0) {
213 TimeDraw
getTimeDraw(long timeDelta
) {
215 if (fTimeProvider
!= null) {
217 if (fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
218 if (timeDelta
>= YEAR_IN_NS
) {
219 timeDraw
= TIMEDRAW_ABS_YEAR
;
220 } else if (timeDelta
>= MONTH_IN_NS
) {
221 timeDraw
= TIMEDRAW_ABS_MONTH
;
222 } else if (timeDelta
>= DAY_IN_NS
) {
223 timeDraw
= TIMEDRAW_ABS_DAY
;
224 } else if (timeDelta
>= HOUR_IN_NS
) {
225 timeDraw
= TIMEDRAW_ABS_HRS
;
226 } else if (timeDelta
>= MIN_IN_NS
) {
227 timeDraw
= TIMEDRAW_ABS_MIN
;
228 } else if (timeDelta
>= SEC_IN_NS
) {
229 timeDraw
= TIMEDRAW_ABS_SEC
;
230 } else if (timeDelta
>= MILLISEC_IN_NS
) {
231 timeDraw
= TIMEDRAW_ABS_MILLISEC
;
232 } else if (timeDelta
>= MICROSEC_IN_NS
) {
233 timeDraw
= TIMEDRAW_ABS_MICROSEC
;
235 timeDraw
= TIMEDRAW_ABS_NANOSEC
;
238 } else if (fTimeProvider
.getTimeFormat() == TimeFormat
.NUMBER
) {
239 timeDraw
= TIMEDRAW_NUMBER
;
244 if (timeDelta
>= SEC_IN_NS
) {
245 timeDraw
= TIMEDRAW_SEC
;
246 } else if (timeDelta
>= MILLISEC_IN_NS
) {
247 timeDraw
= TIMEDRAW_MILLISEC
;
248 } else if (timeDelta
>= MICROSEC_IN_NS
) {
249 timeDraw
= TIMEDRAW_MICROSEC
;
251 timeDraw
= TIMEDRAW_NANOSEC
;
257 void paint(Rectangle rect
, PaintEvent e
) {
259 if (fIsInUpdate
|| null == fTimeProvider
) {
264 gc
.fillRectangle(rect
);
266 long time0
= fTimeProvider
.getTime0();
267 long time1
= fTimeProvider
.getTime1();
268 int leftSpace
= fTimeProvider
.getNameSpace();
269 int timeSpace
= fTimeProvider
.getTimeSpace();
271 gc
.setBackground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_BACKGROUND
));
272 gc
.setForeground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_FOREGROUND
));
273 Rectangle rect0
= new Rectangle(0, 0, 0, 0);
274 Utils
.init(rect0
, rect
);
276 // draw top left area
277 rect0
.width
= leftSpace
;
280 Rectangle absHeaderRect
= new Rectangle(rect0
.x
, rect0
.y
, rect0
.width
, rect0
.height
);
284 // prepare and draw right rect of the timescale
285 rect0
.x
+= leftSpace
;
286 rect0
.width
= rect
.width
- leftSpace
;
288 // draw bottom border and erase all other area
289 gc
.drawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
- 1,
290 rect
.y
+ rect
.height
- 1);
292 gc
.fillRectangle(rect0
);
294 if (time1
<= time0
|| timeSpace
< 2) {
298 int numDigits
= calculateDigits(time0
, time1
);
300 int labelWidth
= gc
.getCharWidth('0') * numDigits
;
301 double pixelsPerNanoSec
= (timeSpace
<= RIGHT_MARGIN
) ?
0 :
302 (double) (timeSpace
- RIGHT_MARGIN
) / (time1
- time0
);
303 long timeDelta
= calcTimeDelta(labelWidth
, pixelsPerNanoSec
);
305 TimeDraw timeDraw
= getTimeDraw(timeDelta
);
307 // draw range decorators
308 if (DRAG_EXTERNAL
== fDragState
) {
309 int x1
= leftSpace
+ Math
.min(fDragX0
, fDragX
);
310 int x2
= leftSpace
+ Math
.max(fDragX0
, fDragX
);
311 drawRangeDecorators(rect0
, gc
, x1
, x2
);
315 if (fTimeProvider
instanceof ITimeDataProvider2
) {
316 long selectionBegin
= ((ITimeDataProvider2
) fTimeProvider
).getSelectionBegin();
317 long selectionEnd
= ((ITimeDataProvider2
) fTimeProvider
).getSelectionEnd();
318 x1
= leftSpace
+ (int) ((selectionBegin
- time0
) * pixelsPerNanoSec
);
319 x2
= leftSpace
+ (int) ((selectionEnd
- time0
) * pixelsPerNanoSec
);
321 @SuppressWarnings("deprecation")
322 long selectedTime
= fTimeProvider
.getSelectedTime();
323 x1
= leftSpace
+ (int) ((selectedTime
- time0
) * pixelsPerNanoSec
);
326 drawRangeDecorators(rect0
, gc
, x1
, x2
);
329 if (rect0
.isEmpty()) {
333 // draw time scale ticks
335 rect0
.height
= rect
.height
- 4;
336 rect0
.width
= labelWidth
;
339 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
340 time
= floorToCalendar(time0
, timeDelta
);
342 time
= (time0
/ timeDelta
) * timeDelta
;
348 int y
= rect0
.y
+ rect0
.height
;
350 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
351 timeDraw
.drawAbsHeader(gc
, time
, absHeaderRect
);
355 int x
= rect
.x
+ leftSpace
+ (int) (Math
.floor((time
- time0
) * pixelsPerNanoSec
));
356 if (x
>= rect
.x
+ leftSpace
+ rect
.width
- rect0
.width
) {
359 if (x
>= rect
.x
+ leftSpace
) {
360 gc
.drawLine(x
, y
, x
, y
+ 4);
362 if (x
+ rect0
.width
<= rect
.x
+ rect
.width
) {
363 timeDraw
.draw(gc
, time
, rect0
);
366 if (pixelsPerNanoSec
== 0 || time
> Long
.MAX_VALUE
- timeDelta
|| timeDelta
== 0) {
369 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
370 if (timeDelta
>= YEAR_IN_NS
) {
371 long millis
= time
/ MILLISEC_IN_NS
;
372 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
373 GREGORIAN_CALENDAR
.add(Calendar
.YEAR
, (int) (timeDelta
/ YEAR_IN_NS
));
374 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
375 time
= millis
* MILLISEC_IN_NS
;
376 } else if (timeDelta
>= MONTH_IN_NS
) {
377 long millis
= time
/ MILLISEC_IN_NS
;
378 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
379 GREGORIAN_CALENDAR
.add(Calendar
.MONTH
, (int) (timeDelta
/ MONTH_IN_NS
));
380 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
381 time
= millis
* MILLISEC_IN_NS
;
382 } else if (timeDelta
>= DAY_IN_NS
) {
383 long millis
= time
/ MILLISEC_IN_NS
;
384 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
385 GREGORIAN_CALENDAR
.add(Calendar
.DAY_OF_MONTH
, (int) (timeDelta
/ DAY_IN_NS
));
386 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
387 time
= millis
* MILLISEC_IN_NS
;
397 private static void drawRangeDecorators(Rectangle rect
, GC gc
, int x1
, int x2
) {
398 int y1
= rect
.y
+ rect
.height
- 9;
399 int y2
= rect
.y
+ rect
.height
- 5;
400 int ym
= (y1
+ y2
) / 2;
403 gc
.drawLine(x1
- 3, y1
, x1
- 3, y2
);
404 gc
.drawLine(x1
- 4, y1
, x1
- 2, y1
);
405 gc
.drawLine(x1
, y1
, x1
, y2
);
407 if (x2
>= rect
.x
&& x2
- x1
> 3) {
409 gc
.drawLine(x2
- 2, y1
, x2
- 2, y2
);
410 gc
.drawLine(x2
- 3, y1
, x2
- 1, y1
);
412 if (x2
>= rect
.x
&& x2
- x1
> 0) {
413 gc
.drawLine(x2
+ 1, y1
, x2
+ 3, y1
);
414 gc
.drawLine(x2
+ 3, y1
, x2
+ 3, ym
);
415 gc
.drawLine(x2
+ 1, ym
, x2
+ 3, ym
);
416 gc
.drawLine(x2
+ 1, ym
, x2
+ 1, y2
);
417 gc
.drawLine(x2
+ 1, y2
, x2
+ 3, y2
);
421 private static long floorToCalendar(long time
, long timeDelta
) {
424 if (timeDelta
>= YEAR_IN_NS
) {
425 GREGORIAN_CALENDAR
.setTime(new Date(ret
/ MILLISEC_IN_NS
));
426 int year
= GREGORIAN_CALENDAR
.get(Calendar
.YEAR
);
427 int yearDelta
= (int) (timeDelta
/ YEAR_IN_NS
);
428 year
= (year
/ yearDelta
) * yearDelta
;
429 GREGORIAN_CALENDAR
.set(Calendar
.YEAR
, year
);
430 GREGORIAN_CALENDAR
.set(Calendar
.MONTH
, 0); // January 1st of year
431 GREGORIAN_CALENDAR
.set(Calendar
.DAY_OF_MONTH
, 1);
432 GREGORIAN_CALENDAR
.set(Calendar
.HOUR_OF_DAY
, 0);
433 GREGORIAN_CALENDAR
.set(Calendar
.MINUTE
, 0);
434 GREGORIAN_CALENDAR
.set(Calendar
.SECOND
, 0);
435 GREGORIAN_CALENDAR
.set(Calendar
.MILLISECOND
, 0);
436 ret
= GREGORIAN_CALENDAR
.getTimeInMillis() * MILLISEC_IN_NS
;
437 } else if (timeDelta
>= MONTH_IN_NS
) {
438 GREGORIAN_CALENDAR
.setTime(new Date(ret
/ MILLISEC_IN_NS
));
439 int month
= GREGORIAN_CALENDAR
.get(Calendar
.MONTH
);
440 int monthDelta
= (int) (timeDelta
/ MONTH_IN_NS
);
441 month
= (month
/ monthDelta
) * monthDelta
;
442 GREGORIAN_CALENDAR
.set(Calendar
.MONTH
, month
);
443 GREGORIAN_CALENDAR
.set(Calendar
.DAY_OF_MONTH
, 1); // 1st of month
444 GREGORIAN_CALENDAR
.set(Calendar
.HOUR_OF_DAY
, 0);
445 GREGORIAN_CALENDAR
.set(Calendar
.MINUTE
, 0);
446 GREGORIAN_CALENDAR
.set(Calendar
.SECOND
, 0);
447 GREGORIAN_CALENDAR
.set(Calendar
.MILLISECOND
, 0);
448 ret
= GREGORIAN_CALENDAR
.getTimeInMillis() * MILLISEC_IN_NS
;
450 long offset
= GREGORIAN_CALENDAR
.getTimeZone().getOffset(ret
/ MILLISEC_IN_NS
) * MILLISEC_IN_NS
;
452 ret
= (ret
/ timeDelta
) * timeDelta
;
458 private int calculateDigits(long time0
, long time1
) {
460 long timeRange
= time1
- time0
;
462 if (fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
463 // Calculate the number of digits to represent the minutes provided
467 if (timeRange
< 10000) {
468 // HH:11:222:333:444__
470 } else if (timeRange
< 10000000) {
475 long sec
= time1
/ SEC_IN_NS
;
476 numDigits
= Long
.toString(sec
).length();
477 int thousandGroups
= (numDigits
- 1) / 3;
478 numDigits
+= thousandGroups
;
479 numDigits
+= 12; // .000 000 000
486 public void mouseDown(MouseEvent e
) {
487 getParent().setFocus();
488 if (fDragState
== NO_BUTTON
&& null != fTimeProvider
) {
489 int x
= e
.x
- fTimeProvider
.getNameSpace();
490 if (LEFT_BUTTON
== e
.button
&& x
> 0) {
492 fDragState
= LEFT_BUTTON
;
496 } else if (x
> getSize().x
- fTimeProvider
.getNameSpace()) {
497 x
= getSize().x
- fTimeProvider
.getNameSpace();
501 fTime0bak
= fTimeProvider
.getTime0();
502 fTime1bak
= fTimeProvider
.getTime1();
507 public void mouseUp(MouseEvent e
) {
508 if (e
.button
== LEFT_BUTTON
&& fDragState
== LEFT_BUTTON
) {
510 fDragState
= NO_BUTTON
;
512 // Notify time provider to check the need for listener notification
513 if (fDragX
!= fDragX0
&& fTimeProvider
.getTime0() != fTimeProvider
.getTime1()) {
514 fTimeProvider
.setStartFinishTimeNotify(fTimeProvider
.getTime0(), fTimeProvider
.getTime1());
520 public void mouseMove(MouseEvent e
) {
521 if (fDragX0
< 0 || fDragState
== NO_BUTTON
|| fTimeProvider
== null) {
524 Point size
= getSize();
525 int leftSpace
= fTimeProvider
.getNameSpace();
526 int x
= e
.x
- leftSpace
;
527 if (LEFT_BUTTON
== fDragState
) {
528 if (x
> 0 && size
.x
> leftSpace
&& fDragX
!= x
) {
530 if (fTimeProvider
.getTime0() == fTimeProvider
.getTime1()) {
533 long interval
= (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ fDragX
));
534 if (interval
== Long
.MAX_VALUE
) {
535 fTimeProvider
.setStartFinishTime(fTime0bak
, Long
.MAX_VALUE
);
537 long time1
= fTime0bak
+ (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ fDragX
));
538 fTimeProvider
.setStartFinishTime(fTime0bak
, time1
);
545 public void mouseDoubleClick(MouseEvent e
) {
546 if (e
.button
== 1 && null != fTimeProvider
&& fTimeProvider
.getTime0() != fTimeProvider
.getTime1() && (e
.stateMask
& SWT
.BUTTON_MASK
) == 0) {
547 fTimeProvider
.resetStartFinishTime();
548 fTimeProvider
.notifyStartFinishTime();
549 fTime0bak
= fTimeProvider
.getTime0();
550 fTime1bak
= fTimeProvider
.getTime1();
555 * Update the display to use the updated timestamp format
557 * @param signal the incoming signal
561 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal
) {
562 TimeDraw
.updateTimeZone();
563 Utils
.updateTimeZone();
568 abstract class TimeDraw
{
569 protected static final long MICROSEC_IN_NS
= 1000;
570 protected static final long MILLISEC_IN_NS
= 1000000;
571 protected static final long MILLISEC_IN_US
= 1000;
572 protected static final long SEC_IN_NS
= 1000000000;
573 protected static final long SEC_IN_MS
= 1000;
574 private static final String S
= "" ; //$NON-NLS-1$
575 private static final String S0
= "0" ; //$NON-NLS-1$
576 private static final String S00
= "00"; //$NON-NLS-1$
577 protected static final long PAD_1000
= 1000;
578 protected static final SimpleDateFormat SEC_FORMAT_HEADER
= new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$
579 protected static final SimpleDateFormat SEC_FORMAT
= new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
580 protected static final SimpleDateFormat MIN_FORMAT_HEADER
= new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$
581 protected static final SimpleDateFormat MIN_FORMAT
= new SimpleDateFormat("HH:mm"); //$NON-NLS-1$
582 protected static final SimpleDateFormat HOURS_FORMAT_HEADER
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
583 protected static final SimpleDateFormat HOURS_FORMAT
= new SimpleDateFormat("MMM dd HH:mm"); //$NON-NLS-1$
584 protected static final SimpleDateFormat DAY_FORMAT_HEADER
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
585 protected static final SimpleDateFormat DAY_FORMAT
= new SimpleDateFormat("MMM dd"); //$NON-NLS-1$
586 protected static final SimpleDateFormat MONTH_FORMAT
= new SimpleDateFormat("yyyy MMM"); //$NON-NLS-1$
587 protected static final SimpleDateFormat YEAR_FORMAT
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
589 protected static final SimpleDateFormat formatArray
[] = {
590 SEC_FORMAT
, SEC_FORMAT_HEADER
, MIN_FORMAT
, MIN_FORMAT_HEADER
,
591 HOURS_FORMAT
, HOURS_FORMAT_HEADER
, DAY_FORMAT
, DAY_FORMAT_HEADER
, MONTH_FORMAT
, YEAR_FORMAT
595 * Updates the timezone using the preferences.
597 public static void updateTimeZone() {
598 final TimeZone timeZone
= TmfTimePreferences
.getInstance().getTimeZone();
599 for (SimpleDateFormat sdf
: formatArray
) {
600 sdf
.setTimeZone(timeZone
);
604 static String
sep(long n
) {
605 StringBuilder retVal
= new StringBuilder();
606 String s
= Long
.toString(n
);
607 for (int i
= 0; i
< s
.length(); i
++) {
608 int pos
= s
.length() - i
- 1;
609 retVal
.append(s
.charAt(i
));
610 if (pos
% 3 == 0 && pos
!= 0) {
614 return retVal
.toString();
617 static String
pad(long n
) {
621 } else if (n
< 100) {
629 public abstract void draw(GC gc
, long time
, Rectangle rect
);
632 * Override to draw absolute time header. This is for the time information
633 * not shown in the draw of each tick
639 * @param absHeaderRect
642 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle absHeaderRect
) {
646 class TimeDrawSec
extends TimeDraw
{
648 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
649 long sec
= nanosec
/ SEC_IN_NS
;
650 Utils
.drawText(gc
, sep(sec
), rect
, true);
654 class TimeDrawMillisec
extends TimeDraw
{
656 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
657 long millisec
= nanosec
/ MILLISEC_IN_NS
;
658 long ms
= millisec
% PAD_1000
;
659 long sec
= millisec
/ SEC_IN_MS
;
660 Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
), rect
, true); //$NON-NLS-1$
664 class TimeDrawMicrosec
extends TimeDraw
{
666 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
667 long microsec
= nanosec
/ MICROSEC_IN_NS
;
668 long us
= microsec
% PAD_1000
;
669 long millisec
= microsec
/ MILLISEC_IN_US
;
670 long ms
= millisec
% PAD_1000
;
671 long sec
= millisec
/ SEC_IN_MS
;
672 Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
) + " " + pad(us
), rect
, true); //$NON-NLS-1$ //$NON-NLS-2$
676 class TimeDrawNanosec
extends TimeDraw
{
678 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
679 long ns
= nanosec
% PAD_1000
;
680 long microsec
= nanosec
/ MICROSEC_IN_NS
;
681 long us
= microsec
% PAD_1000
;
682 long millisec
= microsec
/ MILLISEC_IN_US
;
683 long ms
= millisec
% PAD_1000
;
684 long sec
= millisec
/ SEC_IN_MS
;
685 Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
) + " " + pad(us
) + " " + pad(ns
), rect
, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
689 class TimeDrawAbsYear
extends TimeDraw
{
691 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
692 String stime
= YEAR_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
693 Utils
.drawText(gc
, stime
, rect
, true);
697 class TimeDrawAbsMonth
extends TimeDraw
{
699 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
700 String stime
= MONTH_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
701 Utils
.drawText(gc
, stime
, rect
, true);
705 class TimeDrawAbsDay
extends TimeDraw
{
707 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
708 String stime
= DAY_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
709 Utils
.drawText(gc
, stime
, rect
, true);
713 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
714 String header
= DAY_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
715 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
716 if (headerwidth
<= rect
.width
) {
717 rect
.x
+= (rect
.width
- headerwidth
);
718 Utils
.drawText(gc
, header
, rect
, true);
723 class TimeDrawAbsHrs
extends TimeDraw
{
725 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
726 String stime
= HOURS_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
727 Utils
.drawText(gc
, stime
, rect
, true);
731 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
732 String header
= HOURS_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
733 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
734 if (headerwidth
<= rect
.width
) {
735 rect
.x
+= (rect
.width
- headerwidth
);
736 Utils
.drawText(gc
, header
, rect
, true);
741 class TimeDrawAbsMin
extends TimeDraw
{
743 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
744 String stime
= MIN_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
745 Utils
.drawText(gc
, stime
, rect
, true);
749 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
750 String header
= MIN_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
751 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
752 if (headerwidth
<= rect
.width
) {
753 rect
.x
+= (rect
.width
- headerwidth
);
754 Utils
.drawText(gc
, header
, rect
, true);
759 class TimeDrawAbsSec
extends TimeDraw
{
761 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
762 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
763 Utils
.drawText(gc
, stime
, rect
, true);
767 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
768 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
769 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
770 if (headerwidth
<= rect
.width
) {
771 rect
.x
+= (rect
.width
- headerwidth
);
772 Utils
.drawText(gc
, header
, rect
, true);
777 class TimeDrawAbsMillisec
extends TimeDraw
{
779 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
780 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
781 String ns
= Utils
.formatNs(nanosec
, Resolution
.MILLISEC
);
783 Utils
.drawText(gc
, stime
+ "." + ns
, rect
, true); //$NON-NLS-1$
787 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
788 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
789 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
790 if (headerwidth
<= rect
.width
) {
791 rect
.x
+= (rect
.width
- headerwidth
);
792 Utils
.drawText(gc
, header
, rect
, true);
797 class TimeDrawAbsMicroSec
extends TimeDraw
{
799 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
800 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
801 String micr
= Utils
.formatNs(nanosec
, Resolution
.MICROSEC
);
802 Utils
.drawText(gc
, stime
+ "." + micr
, rect
, true); //$NON-NLS-1$
806 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
807 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
808 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
809 if (headerwidth
<= rect
.width
) {
810 rect
.x
+= (rect
.width
- headerwidth
);
811 Utils
.drawText(gc
, header
, rect
, true);
816 class TimeDrawAbsNanoSec
extends TimeDraw
{
818 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
819 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
820 String ns
= Utils
.formatNs(nanosec
, Resolution
.NANOSEC
);
821 Utils
.drawText(gc
, stime
+ "." + ns
, rect
, true); //$NON-NLS-1$
825 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
826 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
827 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
828 if (headerwidth
<= rect
.width
) {
829 rect
.x
+= (rect
.width
- headerwidth
);
830 Utils
.drawText(gc
, header
, rect
, true);
835 class TimeDrawNumber
extends TimeDraw
{
837 public void draw(GC gc
, long time
, Rectangle rect
) {
838 String stime
= NumberFormat
.getInstance().format(time
);
839 Utils
.drawText(gc
, stime
, rect
, true);