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 NO_BUTTON
= 0;
84 private static final int LEFT_BUTTON
= 1;
85 private static final int RIGHT_BUTTON
= 3;
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
;
143 private long calcTimeDelta(int width
, double pixelsPerNanoSec
) {
145 double minDelta
= (pixelsPerNanoSec
== 0) ? YEAR_IN_NS
: width
/ pixelsPerNanoSec
;
147 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
148 if (minDelta
> 6 * MONTH_IN_NS
) {
150 } else if (minDelta
> 3 * MONTH_IN_NS
) {
151 unit
= 6 * MONTH_IN_NS
;
152 } else if (minDelta
> 10 * DAY_IN_NS
) {
154 } else if (minDelta
> 12 * HOUR_IN_NS
) {
156 } else if (minDelta
> 3 * HOUR_IN_NS
) {
157 unit
= 6 * HOUR_IN_NS
;
158 } else if (minDelta
> 30 * MIN_IN_NS
) {
160 } else if (minDelta
> 10 * MIN_IN_NS
) {
161 unit
= 15 * MIN_IN_NS
;
162 } else if (minDelta
> 30 * SEC_IN_NS
) {
164 } else if (minDelta
> 20 * SEC_IN_NS
) {
165 unit
= 30 * SEC_IN_NS
;
166 } else if (minDelta
<= 1) {
171 double log
= Math
.log10(minDelta
/ unit
);
172 long pow10
= (long) log
;
173 double remainder
= log
- pow10
;
174 if (remainder
< LOG10_1
) {
175 timeDelta
= (long) Math
.pow(10, pow10
) * unit
;
176 } else if (remainder
< LOG10_2
) {
177 timeDelta
= 2 * (long) Math
.pow(10, pow10
) * unit
;
178 } else if (remainder
< LOG10_3
&& unit
>= HOUR_IN_NS
&& unit
< YEAR_IN_NS
) {
179 timeDelta
= 3 * (long) Math
.pow(10, pow10
) * unit
;
180 } else if (remainder
< LOG10_5
) {
181 timeDelta
= 5 * (long) Math
.pow(10, pow10
) * unit
;
183 timeDelta
= 10 * (long) Math
.pow(10, pow10
) * unit
;
185 if (timeDelta
<= 0) {
191 TimeDraw
getTimeDraw(long timeDelta
) {
193 if (fTimeProvider
!= null) {
195 if (fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
196 if (timeDelta
>= YEAR_IN_NS
) {
197 timeDraw
= TIMEDRAW_ABS_YEAR
;
198 } else if (timeDelta
>= MONTH_IN_NS
) {
199 timeDraw
= TIMEDRAW_ABS_MONTH
;
200 } else if (timeDelta
>= DAY_IN_NS
) {
201 timeDraw
= TIMEDRAW_ABS_DAY
;
202 } else if (timeDelta
>= HOUR_IN_NS
) {
203 timeDraw
= TIMEDRAW_ABS_HRS
;
204 } else if (timeDelta
>= MIN_IN_NS
) {
205 timeDraw
= TIMEDRAW_ABS_MIN
;
206 } else if (timeDelta
>= SEC_IN_NS
) {
207 timeDraw
= TIMEDRAW_ABS_SEC
;
208 } else if (timeDelta
>= MILLISEC_IN_NS
) {
209 timeDraw
= TIMEDRAW_ABS_MILLISEC
;
210 } else if (timeDelta
>= MICROSEC_IN_NS
) {
211 timeDraw
= TIMEDRAW_ABS_MICROSEC
;
213 timeDraw
= TIMEDRAW_ABS_NANOSEC
;
216 } else if (fTimeProvider
.getTimeFormat() == TimeFormat
.NUMBER
) {
217 timeDraw
= TIMEDRAW_NUMBER
;
222 if (timeDelta
>= SEC_IN_NS
) {
223 timeDraw
= TIMEDRAW_SEC
;
224 } else if (timeDelta
>= MILLISEC_IN_NS
) {
225 timeDraw
= TIMEDRAW_MILLISEC
;
226 } else if (timeDelta
>= MICROSEC_IN_NS
) {
227 timeDraw
= TIMEDRAW_MICROSEC
;
229 timeDraw
= TIMEDRAW_NANOSEC
;
235 void paint(Rectangle rect
, PaintEvent e
) {
237 if (fIsInUpdate
|| null == fTimeProvider
) {
242 gc
.fillRectangle(rect
);
244 long time0
= fTimeProvider
.getTime0();
245 long time1
= fTimeProvider
.getTime1();
246 long selectedTime
= fTimeProvider
.getSelectedTime();
247 int leftSpace
= fTimeProvider
.getNameSpace();
248 int timeSpace
= fTimeProvider
.getTimeSpace();
250 gc
.setBackground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_BACKGROUND
));
251 gc
.setForeground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_FOREGROUND
));
252 Rectangle rect0
= new Rectangle(0, 0, 0, 0);
253 Utils
.init(rect0
, rect
);
255 // draw top left area
256 rect0
.width
= leftSpace
;
259 Rectangle absHeaderRect
= new Rectangle(rect0
.x
, rect0
.y
, rect0
.width
, rect0
.height
);
263 // prepare and draw right rect of the timescale
264 rect0
.x
+= leftSpace
;
265 rect0
.width
= rect
.width
- leftSpace
;
267 // draw bottom border and erase all other area
268 gc
.drawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
- 1,
269 rect
.y
+ rect
.height
- 1);
271 gc
.fillRectangle(rect0
);
273 if (RIGHT_BUTTON
== fDragState
&& null != fTimeProvider
) {
274 // draw selected zoom region background
275 gc
.setBackground(getColorScheme().getBkColor(true, false, true));
276 if (fDragX0
< fDragX
) {
277 gc
.fillRectangle(new Rectangle(leftSpace
+ fDragX0
, rect0
.y
, fDragX
- fDragX0
, rect0
.height
));
278 } else if (fDragX0
> fDragX
) {
279 gc
.fillRectangle(new Rectangle(leftSpace
+ fDragX
, rect0
.y
, fDragX0
- fDragX
, rect0
.height
));
283 if (time1
<= time0
|| timeSpace
< 2) {
287 int numDigits
= calculateDigits(time0
, time1
);
289 int labelWidth
= gc
.getCharWidth('0') * numDigits
;
290 double pixelsPerNanoSec
= (timeSpace
<= RIGHT_MARGIN
) ?
0 :
291 (double) (timeSpace
- RIGHT_MARGIN
) / (time1
- time0
);
292 long timeDelta
= calcTimeDelta(labelWidth
, pixelsPerNanoSec
);
294 TimeDraw timeDraw
= getTimeDraw(timeDelta
);
296 // draw selected zoom region lines
297 if (RIGHT_BUTTON
== fDragState
&& null != fTimeProvider
) {
298 gc
.drawLine(leftSpace
+ fDragX0
, rect
.y
, leftSpace
+ fDragX0
, rect
.y
+ rect
.height
);
299 gc
.drawLine(leftSpace
+ fDragX
, rect
.y
, leftSpace
+ fDragX
, rect
.y
+ rect
.height
);
302 if (rect0
.isEmpty()) {
306 // draw selected time
307 int x
= rect0
.x
+ (int) ((selectedTime
- time0
) * pixelsPerNanoSec
);
308 if (x
>= rect0
.x
&& x
< rect0
.x
+ rect0
.width
) {
309 gc
.setForeground(getColorScheme().getColor(TimeGraphColorScheme
.SELECTED_TIME
));
310 gc
.drawLine(x
, rect0
.y
+ rect0
.height
- 6, x
, rect0
.y
312 gc
.setForeground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_FOREGROUND
));
315 // draw time scale ticks
317 rect0
.height
= rect
.height
- 4;
318 rect0
.width
= labelWidth
;
321 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
322 time
= floorToCalendar(time0
, timeDelta
);
324 time
= (time0
/ timeDelta
) * timeDelta
;
330 int y
= rect0
.y
+ rect0
.height
;
332 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
333 timeDraw
.drawAbsHeader(gc
, time
, absHeaderRect
);
337 x
= rect
.x
+ leftSpace
+ (int) (Math
.floor((time
- time0
) * pixelsPerNanoSec
));
338 if (x
>= rect
.x
+ leftSpace
+ rect
.width
- rect0
.width
) {
341 if (x
>= rect
.x
+ leftSpace
) {
342 gc
.drawLine(x
, y
, x
, y
+ 4);
344 if (x
+ rect0
.width
<= rect
.x
+ rect
.width
) {
345 timeDraw
.draw(gc
, time
, rect0
);
348 if (pixelsPerNanoSec
== 0 || time
> Long
.MAX_VALUE
- timeDelta
|| timeDelta
== 0) {
351 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
352 if (timeDelta
>= YEAR_IN_NS
) {
353 long millis
= time
/ MILLISEC_IN_NS
;
354 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
355 GREGORIAN_CALENDAR
.add(Calendar
.YEAR
, (int) (timeDelta
/ YEAR_IN_NS
));
356 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
357 time
= millis
* MILLISEC_IN_NS
;
358 } else if (timeDelta
>= MONTH_IN_NS
) {
359 long millis
= time
/ MILLISEC_IN_NS
;
360 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
361 GREGORIAN_CALENDAR
.add(Calendar
.MONTH
, (int) (timeDelta
/ MONTH_IN_NS
));
362 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
363 time
= millis
* MILLISEC_IN_NS
;
364 } else if (timeDelta
>= DAY_IN_NS
) {
365 long millis
= time
/ MILLISEC_IN_NS
;
366 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
367 GREGORIAN_CALENDAR
.add(Calendar
.DAY_OF_MONTH
, (int) (timeDelta
/ DAY_IN_NS
));
368 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
369 time
= millis
* MILLISEC_IN_NS
;
379 private static long floorToCalendar(long time
, long timeDelta
) {
382 if (timeDelta
>= YEAR_IN_NS
) {
383 GREGORIAN_CALENDAR
.setTime(new Date(ret
/ MILLISEC_IN_NS
));
384 int year
= GREGORIAN_CALENDAR
.get(Calendar
.YEAR
);
385 int yearDelta
= (int) (timeDelta
/ YEAR_IN_NS
);
386 year
= (year
/ yearDelta
) * yearDelta
;
387 GREGORIAN_CALENDAR
.set(Calendar
.YEAR
, year
);
388 GREGORIAN_CALENDAR
.set(Calendar
.MONTH
, 0); // January 1st of year
389 GREGORIAN_CALENDAR
.set(Calendar
.DAY_OF_MONTH
, 1);
390 GREGORIAN_CALENDAR
.set(Calendar
.HOUR_OF_DAY
, 0);
391 GREGORIAN_CALENDAR
.set(Calendar
.MINUTE
, 0);
392 GREGORIAN_CALENDAR
.set(Calendar
.SECOND
, 0);
393 GREGORIAN_CALENDAR
.set(Calendar
.MILLISECOND
, 0);
394 ret
= GREGORIAN_CALENDAR
.getTimeInMillis() * MILLISEC_IN_NS
;
395 } else if (timeDelta
>= MONTH_IN_NS
) {
396 GREGORIAN_CALENDAR
.setTime(new Date(ret
/ MILLISEC_IN_NS
));
397 int month
= GREGORIAN_CALENDAR
.get(Calendar
.MONTH
);
398 int monthDelta
= (int) (timeDelta
/ MONTH_IN_NS
);
399 month
= (month
/ monthDelta
) * monthDelta
;
400 GREGORIAN_CALENDAR
.set(Calendar
.MONTH
, month
);
401 GREGORIAN_CALENDAR
.set(Calendar
.DAY_OF_MONTH
, 1); // 1st of month
402 GREGORIAN_CALENDAR
.set(Calendar
.HOUR_OF_DAY
, 0);
403 GREGORIAN_CALENDAR
.set(Calendar
.MINUTE
, 0);
404 GREGORIAN_CALENDAR
.set(Calendar
.SECOND
, 0);
405 GREGORIAN_CALENDAR
.set(Calendar
.MILLISECOND
, 0);
406 ret
= GREGORIAN_CALENDAR
.getTimeInMillis() * MILLISEC_IN_NS
;
408 long offset
= GREGORIAN_CALENDAR
.getTimeZone().getOffset(ret
/ MILLISEC_IN_NS
) * MILLISEC_IN_NS
;
410 ret
= (ret
/ timeDelta
) * timeDelta
;
416 private int calculateDigits(long time0
, long time1
) {
418 long timeRange
= time1
- time0
;
420 if (fTimeProvider
.getTimeFormat().equals(TimeFormat
.CALENDAR
)) {
421 // Calculate the number of digits to represent the minutes provided
425 if (timeRange
< 10000) {
426 // HH:11:222:333:444__
428 } else if (timeRange
< 10000000) {
433 long sec
= time1
/ SEC_IN_NS
;
434 numDigits
= Long
.toString(sec
).length();
435 int thousandGroups
= (numDigits
- 1) / 3;
436 numDigits
+= thousandGroups
;
437 numDigits
+= 12; // .000 000 000
444 public void mouseDown(MouseEvent e
) {
445 getParent().setFocus();
446 if (fDragState
== NO_BUTTON
&& null != fTimeProvider
) {
447 int x
= e
.x
- fTimeProvider
.getNameSpace();
448 if (LEFT_BUTTON
== e
.button
&& x
> 0) {
450 fDragState
= LEFT_BUTTON
;
451 } else if (RIGHT_BUTTON
== e
.button
) {
452 fDragState
= RIGHT_BUTTON
;
456 } else if (x
> getSize().x
- fTimeProvider
.getNameSpace()) {
457 x
= getSize().x
- fTimeProvider
.getNameSpace();
461 fTime0bak
= fTimeProvider
.getTime0();
462 fTime1bak
= fTimeProvider
.getTime1();
467 public void mouseUp(MouseEvent e
) {
468 if (e
.button
== LEFT_BUTTON
&& fDragState
== LEFT_BUTTON
) {
470 fDragState
= NO_BUTTON
;
472 // Notify time provider to check the need for listener notification
473 if (fDragX
!= fDragX0
&& fTimeProvider
.getTime0() != fTimeProvider
.getTime1()) {
474 fTimeProvider
.setStartFinishTimeNotify(fTimeProvider
.getTime0(), fTimeProvider
.getTime1());
476 } else if (e
.button
== RIGHT_BUTTON
&& fDragState
== RIGHT_BUTTON
&& null != fTimeProvider
) {
477 fDragState
= NO_BUTTON
;
478 if (fDragX0
== fDragX
|| fTimeProvider
.getTime0() == fTimeProvider
.getTime1()) {
482 int timeSpace
= fTimeProvider
.getTimeSpace();
483 int leftSpace
= fTimeProvider
.getNameSpace();
484 int x
= Math
.max(0, e
.x
- leftSpace
);
487 if (fDragX0
> fDragX
) { // drag right to left
491 long time0
= fTime0bak
+ (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ timeSpace
));
492 long time1
= fTime0bak
+ (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX
/ timeSpace
));
494 fTimeProvider
.setStartFinishTimeNotify(time0
, time1
);
495 fTime0bak
= fTimeProvider
.getTime0();
496 fTime1bak
= fTimeProvider
.getTime1();
502 public void mouseMove(MouseEvent e
) {
503 if (fDragX0
< 0 || fDragState
== NO_BUTTON
|| fTimeProvider
== null) {
506 Point size
= getSize();
507 int leftSpace
= fTimeProvider
.getNameSpace();
508 int timeSpace
= fTimeProvider
.getTimeSpace();
509 int x
= e
.x
- leftSpace
;
510 if (LEFT_BUTTON
== fDragState
) {
511 if (x
> 0 && size
.x
> leftSpace
&& fDragX
!= x
) {
513 if (fTimeProvider
.getTime0() == fTimeProvider
.getTime1()) {
516 long interval
= (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ fDragX
));
517 if (interval
== Long
.MAX_VALUE
) {
518 fTimeProvider
.setStartFinishTime(fTime0bak
, Long
.MAX_VALUE
);
520 long time1
= fTime0bak
+ (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ fDragX
));
521 fTimeProvider
.setStartFinishTime(fTime0bak
, time1
);
524 } else if (RIGHT_BUTTON
== fDragState
) {
527 } else if (x
> timeSpace
) {
537 public void mouseDoubleClick(MouseEvent e
) {
538 if (e
.button
== 1 && null != fTimeProvider
&& fTimeProvider
.getTime0() != fTimeProvider
.getTime1() && (e
.stateMask
& SWT
.BUTTON_MASK
) == 0) {
539 fTimeProvider
.resetStartFinishTime();
540 fTimeProvider
.notifyStartFinishTime();
541 fTime0bak
= fTimeProvider
.getTime0();
542 fTime1bak
= fTimeProvider
.getTime1();
547 * Update the display to use the updated timestamp format
549 * @param signal the incoming signal
553 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal
) {
554 TimeDraw
.updateTimeZone();
555 Utils
.updateTimeZone();
560 abstract class TimeDraw
{
561 protected static final long MICROSEC_IN_NS
= 1000;
562 protected static final long MILLISEC_IN_NS
= 1000000;
563 protected static final long MILLISEC_IN_US
= 1000;
564 protected static final long SEC_IN_NS
= 1000000000;
565 protected static final long SEC_IN_MS
= 1000;
566 private static final String S
= "" ; //$NON-NLS-1$
567 private static final String S0
= "0" ; //$NON-NLS-1$
568 private static final String S00
= "00"; //$NON-NLS-1$
569 protected static final long PAD_1000
= 1000;
570 protected static final SimpleDateFormat SEC_FORMAT_HEADER
= new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$
571 protected static final SimpleDateFormat SEC_FORMAT
= new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
572 protected static final SimpleDateFormat MIN_FORMAT_HEADER
= new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$
573 protected static final SimpleDateFormat MIN_FORMAT
= new SimpleDateFormat("HH:mm"); //$NON-NLS-1$
574 protected static final SimpleDateFormat HOURS_FORMAT_HEADER
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
575 protected static final SimpleDateFormat HOURS_FORMAT
= new SimpleDateFormat("MMM dd HH:mm"); //$NON-NLS-1$
576 protected static final SimpleDateFormat DAY_FORMAT_HEADER
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
577 protected static final SimpleDateFormat DAY_FORMAT
= new SimpleDateFormat("MMM dd"); //$NON-NLS-1$
578 protected static final SimpleDateFormat MONTH_FORMAT
= new SimpleDateFormat("yyyy MMM"); //$NON-NLS-1$
579 protected static final SimpleDateFormat YEAR_FORMAT
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
581 protected static final SimpleDateFormat formatArray
[] = {
582 SEC_FORMAT
, SEC_FORMAT_HEADER
, MIN_FORMAT
, MIN_FORMAT_HEADER
,
583 HOURS_FORMAT
, HOURS_FORMAT_HEADER
, DAY_FORMAT
, DAY_FORMAT_HEADER
, MONTH_FORMAT
, YEAR_FORMAT
587 * Updates the timezone using the preferences.
589 public static void updateTimeZone() {
590 final TimeZone timeZone
= TmfTimePreferences
.getInstance().getTimeZone();
591 for (SimpleDateFormat sdf
: formatArray
) {
592 sdf
.setTimeZone(timeZone
);
596 static String
sep(long n
) {
597 StringBuilder retVal
= new StringBuilder();
598 String s
= Long
.toString(n
);
599 for (int i
= 0; i
< s
.length(); i
++) {
600 int pos
= s
.length() - i
- 1;
601 retVal
.append(s
.charAt(i
));
602 if (pos
% 3 == 0 && pos
!= 0) {
606 return retVal
.toString();
609 static String
pad(long n
) {
613 } else if (n
< 100) {
621 public abstract void draw(GC gc
, long time
, Rectangle rect
);
624 * Override to draw absolute time header. This is for the time information
625 * not shown in the draw of each tick
631 * @param absHeaderRect
634 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle absHeaderRect
) {
638 class TimeDrawSec
extends TimeDraw
{
640 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
641 long sec
= nanosec
/ SEC_IN_NS
;
642 Utils
.drawText(gc
, sep(sec
), rect
, true);
646 class TimeDrawMillisec
extends TimeDraw
{
648 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
649 long millisec
= nanosec
/ MILLISEC_IN_NS
;
650 long ms
= millisec
% PAD_1000
;
651 long sec
= millisec
/ SEC_IN_MS
;
652 Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
), rect
, true); //$NON-NLS-1$
656 class TimeDrawMicrosec
extends TimeDraw
{
658 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
659 long microsec
= nanosec
/ MICROSEC_IN_NS
;
660 long us
= microsec
% PAD_1000
;
661 long millisec
= microsec
/ MILLISEC_IN_US
;
662 long ms
= millisec
% PAD_1000
;
663 long sec
= millisec
/ SEC_IN_MS
;
664 Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
) + " " + pad(us
), rect
, true); //$NON-NLS-1$ //$NON-NLS-2$
668 class TimeDrawNanosec
extends TimeDraw
{
670 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
671 long ns
= nanosec
% PAD_1000
;
672 long microsec
= nanosec
/ MICROSEC_IN_NS
;
673 long us
= microsec
% PAD_1000
;
674 long millisec
= microsec
/ MILLISEC_IN_US
;
675 long ms
= millisec
% PAD_1000
;
676 long sec
= millisec
/ SEC_IN_MS
;
677 Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
) + " " + pad(us
) + " " + pad(ns
), rect
, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
681 class TimeDrawAbsYear
extends TimeDraw
{
683 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
684 String stime
= YEAR_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
685 Utils
.drawText(gc
, stime
, rect
, true);
689 class TimeDrawAbsMonth
extends TimeDraw
{
691 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
692 String stime
= MONTH_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
693 Utils
.drawText(gc
, stime
, rect
, true);
697 class TimeDrawAbsDay
extends TimeDraw
{
699 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
700 String stime
= DAY_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
701 Utils
.drawText(gc
, stime
, rect
, true);
705 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
706 String header
= DAY_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
707 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
708 if (headerwidth
<= rect
.width
) {
709 rect
.x
+= (rect
.width
- headerwidth
);
710 Utils
.drawText(gc
, header
, rect
, true);
715 class TimeDrawAbsHrs
extends TimeDraw
{
717 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
718 String stime
= HOURS_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
719 Utils
.drawText(gc
, stime
, rect
, true);
723 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
724 String header
= HOURS_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
725 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
726 if (headerwidth
<= rect
.width
) {
727 rect
.x
+= (rect
.width
- headerwidth
);
728 Utils
.drawText(gc
, header
, rect
, true);
733 class TimeDrawAbsMin
extends TimeDraw
{
735 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
736 String stime
= MIN_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
737 Utils
.drawText(gc
, stime
, rect
, true);
741 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
742 String header
= MIN_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
743 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
744 if (headerwidth
<= rect
.width
) {
745 rect
.x
+= (rect
.width
- headerwidth
);
746 Utils
.drawText(gc
, header
, rect
, true);
751 class TimeDrawAbsSec
extends TimeDraw
{
753 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
754 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
755 Utils
.drawText(gc
, stime
, rect
, true);
759 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
760 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
761 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
762 if (headerwidth
<= rect
.width
) {
763 rect
.x
+= (rect
.width
- headerwidth
);
764 Utils
.drawText(gc
, header
, rect
, true);
769 class TimeDrawAbsMillisec
extends TimeDraw
{
771 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
772 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
773 String ns
= Utils
.formatNs(nanosec
, Resolution
.MILLISEC
);
775 Utils
.drawText(gc
, stime
+ "." + ns
, rect
, true); //$NON-NLS-1$
779 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
780 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
781 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
782 if (headerwidth
<= rect
.width
) {
783 rect
.x
+= (rect
.width
- headerwidth
);
784 Utils
.drawText(gc
, header
, rect
, true);
789 class TimeDrawAbsMicroSec
extends TimeDraw
{
791 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
792 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
793 String micr
= Utils
.formatNs(nanosec
, Resolution
.MICROSEC
);
794 Utils
.drawText(gc
, stime
+ "." + micr
, rect
, true); //$NON-NLS-1$
798 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
799 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
800 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
801 if (headerwidth
<= rect
.width
) {
802 rect
.x
+= (rect
.width
- headerwidth
);
803 Utils
.drawText(gc
, header
, rect
, true);
808 class TimeDrawAbsNanoSec
extends TimeDraw
{
810 public void draw(GC gc
, long nanosec
, Rectangle rect
) {
811 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
812 String ns
= Utils
.formatNs(nanosec
, Resolution
.NANOSEC
);
813 Utils
.drawText(gc
, stime
+ "." + ns
, rect
, true); //$NON-NLS-1$
817 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
818 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
819 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
820 if (headerwidth
<= rect
.width
) {
821 rect
.x
+= (rect
.width
- headerwidth
);
822 Utils
.drawText(gc
, header
, rect
, true);
827 class TimeDrawNumber
extends TimeDraw
{
829 public void draw(GC gc
, long time
, Rectangle rect
) {
830 String stime
= NumberFormat
.getInstance().format(time
);
831 Utils
.drawText(gc
, stime
, rect
, true);