1 /*****************************************************************************
2 * Copyright (c) 2007, 2014 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
.internal
.tmf
.ui
.Messages
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalManager
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimestampFormatUpdateSignal
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimePreferences
;
29 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.Resolution
;
30 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
31 import org
.eclipse
.swt
.SWT
;
32 import org
.eclipse
.swt
.events
.MouseEvent
;
33 import org
.eclipse
.swt
.events
.MouseListener
;
34 import org
.eclipse
.swt
.events
.MouseMoveListener
;
35 import org
.eclipse
.swt
.events
.PaintEvent
;
36 import org
.eclipse
.swt
.graphics
.GC
;
37 import org
.eclipse
.swt
.graphics
.Point
;
38 import org
.eclipse
.swt
.graphics
.Rectangle
;
39 import org
.eclipse
.swt
.widgets
.Composite
;
42 * Implementation of the scale for the time graph view.
44 * This goes above the "gantt chart" area.
47 * @author Alvaro Sanchez-Leon
48 * @author Patrick Tasse
50 public class TimeGraphScale
extends TimeGraphBaseControl
implements
51 MouseListener
, MouseMoveListener
{
53 private static final long MICROSEC_IN_NS
= 1000;
54 private static final long MILLISEC_IN_NS
= 1000000;
55 private static final long SEC_IN_NS
= 1000000000;
56 private static final long MIN_IN_NS
= 60 * SEC_IN_NS
;
57 private static final long HOUR_IN_NS
= 60 * MIN_IN_NS
;
58 private static final long DAY_IN_NS
= 24 * HOUR_IN_NS
;
59 private static final long MONTH_IN_NS
= 31 * DAY_IN_NS
; // upper limit
60 private static final long YEAR_IN_NS
= 366 * DAY_IN_NS
; // upper limit
62 private static final double LOG10_1
= Math
.log10(1);
63 private static final double LOG10_2
= Math
.log10(2);
64 private static final double LOG10_3
= Math
.log10(3);
65 private static final double LOG10_5
= Math
.log10(5);
67 private static final Calendar GREGORIAN_CALENDAR
= Calendar
.getInstance();
69 private static final TimeDraw TIMEDRAW_NANOSEC
= new TimeDrawNanosec();
70 private static final TimeDraw TIMEDRAW_MICROSEC
= new TimeDrawMicrosec();
71 private static final TimeDraw TIMEDRAW_MILLISEC
= new TimeDrawMillisec();
72 private static final TimeDraw TIMEDRAW_SEC
= new TimeDrawSec();
73 private static final TimeDraw TIMEDRAW_ABS_NANOSEC
= new TimeDrawAbsNanoSec();
74 private static final TimeDraw TIMEDRAW_ABS_MICROSEC
= new TimeDrawAbsMicroSec();
75 private static final TimeDraw TIMEDRAW_ABS_MILLISEC
= new TimeDrawAbsMillisec();
76 private static final TimeDraw TIMEDRAW_ABS_SEC
= new TimeDrawAbsSec();
77 private static final TimeDraw TIMEDRAW_ABS_MIN
= new TimeDrawAbsMin();
78 private static final TimeDraw TIMEDRAW_ABS_HRS
= new TimeDrawAbsHrs();
79 private static final TimeDraw TIMEDRAW_ABS_DAY
= new TimeDrawAbsDay();
80 private static final TimeDraw TIMEDRAW_ABS_MONTH
= new TimeDrawAbsMonth();
81 private static final TimeDraw TIMEDRAW_ABS_YEAR
= new TimeDrawAbsYear();
82 private static final TimeDraw TIMEDRAW_NUMBER
= new TimeDrawNumber();
83 private static final TimeDraw TIMEDRAW_CYCLES
= new TimeDrawCycles();
85 private static final int DRAG_EXTERNAL
= -1;
86 private static final int NO_BUTTON
= 0;
87 private static final int LEFT_BUTTON
= 1;
89 private ITimeDataProvider fTimeProvider
;
90 private int fDragState
= NO_BUTTON
;
91 private int fDragX0
= 0;
92 private int fDragX
= 0;
93 private long fTime0bak
;
94 private long fTime1bak
;
95 private boolean fIsInUpdate
;
99 * Standard constructor
102 * The parent composite object
104 * The color scheme to use
106 public TimeGraphScale(Composite parent
, TimeGraphColorScheme colors
) {
107 super(parent
, colors
, SWT
.NO_BACKGROUND
| SWT
.NO_FOCUS
| SWT
.DOUBLE_BUFFERED
);
108 TmfSignalManager
.register(this);
109 addMouseListener(this);
110 addMouseMoveListener(this);
111 TimeDraw
.updateTimeZone();
115 public void dispose() {
116 TmfSignalManager
.deregister(this);
121 * Assign the time provider for this scale
123 * @param timeProvider
124 * The provider to use
126 public void setTimeProvider(ITimeDataProvider timeProvider
) {
127 fTimeProvider
= timeProvider
;
131 * Get the time provider used by this scale
133 * @return The time provider
136 public ITimeDataProvider
getTimeProvider() {
137 return fTimeProvider
;
141 public Point
computeSize(int wHint
, int hHint
, boolean changed
) {
142 return super.computeSize(wHint
, fHeight
, changed
);
146 * Set the height of the scale
151 public void setHeight(int height
) {
152 this.fHeight
= height
;
156 * Set the drag range to paint decorators
159 * The begin x-coordinate
161 * The end x-coordinate
164 public void setDragRange(int begin
, int end
) {
165 if (NO_BUTTON
== fDragState
|| DRAG_EXTERNAL
== fDragState
) {
166 fDragX0
= begin
- fTimeProvider
.getNameSpace();
167 fDragX
= end
- fTimeProvider
.getNameSpace();
168 if (begin
>= 0 || end
>= 0) {
169 fDragState
= DRAG_EXTERNAL
;
171 fDragState
= NO_BUTTON
;
177 private long calcTimeDelta(int width
, double pixelsPerNanoSec
) {
179 double minDelta
= (pixelsPerNanoSec
== 0) ? YEAR_IN_NS
: width
/ pixelsPerNanoSec
;
181 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
182 if (minDelta
> 6 * MONTH_IN_NS
) {
184 } else if (minDelta
> 3 * MONTH_IN_NS
) {
185 unit
= 6 * MONTH_IN_NS
;
186 } else if (minDelta
> 10 * DAY_IN_NS
) {
188 } else if (minDelta
> 12 * HOUR_IN_NS
) {
190 } else if (minDelta
> 3 * HOUR_IN_NS
) {
191 unit
= 6 * HOUR_IN_NS
;
192 } else if (minDelta
> 30 * MIN_IN_NS
) {
194 } else if (minDelta
> 10 * MIN_IN_NS
) {
195 unit
= 15 * MIN_IN_NS
;
196 } else if (minDelta
> 30 * SEC_IN_NS
) {
198 } else if (minDelta
> 20 * SEC_IN_NS
) {
199 unit
= 30 * SEC_IN_NS
;
200 } else if (minDelta
<= 1) {
205 double log
= Math
.log10(minDelta
/ unit
);
206 long pow10
= (long) log
;
207 double remainder
= log
- pow10
;
208 if (remainder
< LOG10_1
) {
209 timeDelta
= (long) Math
.pow(10, pow10
) * unit
;
210 } else if (remainder
< LOG10_2
) {
211 timeDelta
= 2 * (long) Math
.pow(10, pow10
) * unit
;
212 } else if (remainder
< LOG10_3
&& unit
>= HOUR_IN_NS
&& unit
< YEAR_IN_NS
) {
213 timeDelta
= 3 * (long) Math
.pow(10, pow10
) * unit
;
214 } else if (remainder
< LOG10_5
) {
215 timeDelta
= 5 * (long) Math
.pow(10, pow10
) * unit
;
217 timeDelta
= 10 * (long) Math
.pow(10, pow10
) * unit
;
219 if (timeDelta
<= 0) {
225 TimeDraw
getTimeDraw(long timeDelta
) {
227 if (fTimeProvider
!= null) {
228 switch (fTimeProvider
.getTimeFormat()) {
230 if (timeDelta
>= YEAR_IN_NS
) {
231 timeDraw
= TIMEDRAW_ABS_YEAR
;
232 } else if (timeDelta
>= MONTH_IN_NS
) {
233 timeDraw
= TIMEDRAW_ABS_MONTH
;
234 } else if (timeDelta
>= DAY_IN_NS
) {
235 timeDraw
= TIMEDRAW_ABS_DAY
;
236 } else if (timeDelta
>= HOUR_IN_NS
) {
237 timeDraw
= TIMEDRAW_ABS_HRS
;
238 } else if (timeDelta
>= MIN_IN_NS
) {
239 timeDraw
= TIMEDRAW_ABS_MIN
;
240 } else if (timeDelta
>= SEC_IN_NS
) {
241 timeDraw
= TIMEDRAW_ABS_SEC
;
242 } else if (timeDelta
>= MILLISEC_IN_NS
) {
243 timeDraw
= TIMEDRAW_ABS_MILLISEC
;
244 } else if (timeDelta
>= MICROSEC_IN_NS
) {
245 timeDraw
= TIMEDRAW_ABS_MICROSEC
;
247 timeDraw
= TIMEDRAW_ABS_NANOSEC
;
251 return TIMEDRAW_NUMBER
;
253 return TIMEDRAW_CYCLES
;
259 if (timeDelta
>= SEC_IN_NS
) {
260 timeDraw
= TIMEDRAW_SEC
;
261 } else if (timeDelta
>= MILLISEC_IN_NS
) {
262 timeDraw
= TIMEDRAW_MILLISEC
;
263 } else if (timeDelta
>= MICROSEC_IN_NS
) {
264 timeDraw
= TIMEDRAW_MICROSEC
;
266 timeDraw
= TIMEDRAW_NANOSEC
;
272 void paint(Rectangle rect
, PaintEvent e
) {
274 if (fIsInUpdate
|| null == fTimeProvider
) {
279 gc
.fillRectangle(rect
);
281 long time0
= fTimeProvider
.getTime0();
282 long time1
= fTimeProvider
.getTime1();
283 int leftSpace
= fTimeProvider
.getNameSpace();
284 int timeSpace
= fTimeProvider
.getTimeSpace();
286 gc
.setBackground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_BACKGROUND
));
287 gc
.setForeground(getColorScheme().getColor(TimeGraphColorScheme
.TOOL_FOREGROUND
));
288 Rectangle rect0
= new Rectangle(0, 0, 0, 0);
289 Utils
.init(rect0
, rect
);
291 // draw top left area
292 rect0
.width
= leftSpace
;
295 Rectangle absHeaderRect
= new Rectangle(rect0
.x
, rect0
.y
, rect0
.width
, rect0
.height
);
299 // prepare and draw right rect of the timescale
300 rect0
.x
+= leftSpace
;
301 rect0
.width
= rect
.width
- leftSpace
;
303 // draw bottom border and erase all other area
304 gc
.drawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
- 1,
305 rect
.y
+ rect
.height
- 1);
307 gc
.fillRectangle(rect0
);
309 if (time1
<= time0
|| timeSpace
< 2) {
313 int numDigits
= calculateDigits(time0
, time1
);
315 int labelWidth
= gc
.getCharWidth('0') * numDigits
;
316 double pixelsPerNanoSec
= (timeSpace
<= RIGHT_MARGIN
) ?
0 :
317 (double) (timeSpace
- RIGHT_MARGIN
) / (time1
- time0
);
318 long timeDelta
= calcTimeDelta(labelWidth
, pixelsPerNanoSec
);
320 TimeDraw timeDraw
= getTimeDraw(timeDelta
);
322 // draw range decorators
323 if (DRAG_EXTERNAL
== fDragState
) {
324 int x1
= leftSpace
+ Math
.min(fDragX0
, fDragX
);
325 int x2
= leftSpace
+ Math
.max(fDragX0
, fDragX
);
326 drawRangeDecorators(rect0
, gc
, x1
, x2
);
330 long selectionBegin
= fTimeProvider
.getSelectionBegin();
331 long selectionEnd
= fTimeProvider
.getSelectionEnd();
332 x1
= leftSpace
+ (int) ((selectionBegin
- time0
) * pixelsPerNanoSec
);
333 x2
= leftSpace
+ (int) ((selectionEnd
- time0
) * pixelsPerNanoSec
);
334 drawRangeDecorators(rect0
, gc
, x1
, x2
);
337 if (rect0
.isEmpty()) {
341 // draw time scale ticks
343 rect0
.height
= rect
.height
- 4;
344 rect0
.width
= labelWidth
;
347 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
348 time
= floorToCalendar(time0
, timeDelta
);
350 time
= (time0
/ timeDelta
) * timeDelta
;
356 int y
= rect0
.y
+ rect0
.height
;
358 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
359 timeDraw
.drawAbsHeader(gc
, time
, absHeaderRect
);
363 int x
= rect
.x
+ leftSpace
+ (int) (Math
.floor((time
- time0
) * pixelsPerNanoSec
));
364 if (x
>= rect
.x
+ leftSpace
+ rect
.width
- rect0
.width
) {
367 if (x
>= rect
.x
+ leftSpace
) {
368 gc
.drawLine(x
, y
, x
, y
+ 4);
370 if (x
+ rect0
.width
<= rect
.x
+ rect
.width
) {
371 timeDraw
.draw(gc
, time
, rect0
);
374 if (pixelsPerNanoSec
== 0 || time
> Long
.MAX_VALUE
- timeDelta
|| timeDelta
== 0) {
377 if (fTimeProvider
!= null && fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
378 if (timeDelta
>= YEAR_IN_NS
) {
379 long millis
= time
/ MILLISEC_IN_NS
;
380 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
381 GREGORIAN_CALENDAR
.add(Calendar
.YEAR
, (int) (timeDelta
/ YEAR_IN_NS
));
382 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
383 time
= millis
* MILLISEC_IN_NS
;
384 } else if (timeDelta
>= MONTH_IN_NS
) {
385 long millis
= time
/ MILLISEC_IN_NS
;
386 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
387 GREGORIAN_CALENDAR
.add(Calendar
.MONTH
, (int) (timeDelta
/ MONTH_IN_NS
));
388 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
389 time
= millis
* MILLISEC_IN_NS
;
390 } else if (timeDelta
>= DAY_IN_NS
) {
391 long millis
= time
/ MILLISEC_IN_NS
;
392 GREGORIAN_CALENDAR
.setTime(new Date(millis
));
393 GREGORIAN_CALENDAR
.add(Calendar
.DAY_OF_MONTH
, (int) (timeDelta
/ DAY_IN_NS
));
394 millis
= GREGORIAN_CALENDAR
.getTimeInMillis();
395 time
= millis
* MILLISEC_IN_NS
;
405 private static void drawRangeDecorators(Rectangle rect
, GC gc
, int x1
, int x2
) {
406 int y1
= rect
.y
+ rect
.height
- 9;
407 int y2
= rect
.y
+ rect
.height
- 5;
408 int ym
= (y1
+ y2
) / 2;
411 gc
.drawLine(x1
- 3, y1
, x1
- 3, y2
);
412 gc
.drawLine(x1
- 4, y1
, x1
- 2, y1
);
413 gc
.drawLine(x1
, y1
, x1
, y2
);
415 if (x2
>= rect
.x
&& x2
- x1
> 3) {
417 gc
.drawLine(x2
- 2, y1
, x2
- 2, y2
);
418 gc
.drawLine(x2
- 3, y1
, x2
- 1, y1
);
420 if (x2
>= rect
.x
&& x2
- x1
> 0) {
421 gc
.drawLine(x2
+ 1, y1
, x2
+ 3, y1
);
422 gc
.drawLine(x2
+ 3, y1
, x2
+ 3, ym
);
423 gc
.drawLine(x2
+ 1, ym
, x2
+ 3, ym
);
424 gc
.drawLine(x2
+ 1, ym
, x2
+ 1, y2
);
425 gc
.drawLine(x2
+ 1, y2
, x2
+ 3, y2
);
429 private static long floorToCalendar(long time
, long timeDelta
) {
432 if (timeDelta
>= YEAR_IN_NS
) {
433 GREGORIAN_CALENDAR
.setTime(new Date(ret
/ MILLISEC_IN_NS
));
434 int year
= GREGORIAN_CALENDAR
.get(Calendar
.YEAR
);
435 int yearDelta
= (int) (timeDelta
/ YEAR_IN_NS
);
436 year
= (year
/ yearDelta
) * yearDelta
;
437 GREGORIAN_CALENDAR
.set(Calendar
.YEAR
, year
);
438 GREGORIAN_CALENDAR
.set(Calendar
.MONTH
, 0); // January 1st of year
439 GREGORIAN_CALENDAR
.set(Calendar
.DAY_OF_MONTH
, 1);
440 GREGORIAN_CALENDAR
.set(Calendar
.HOUR_OF_DAY
, 0);
441 GREGORIAN_CALENDAR
.set(Calendar
.MINUTE
, 0);
442 GREGORIAN_CALENDAR
.set(Calendar
.SECOND
, 0);
443 GREGORIAN_CALENDAR
.set(Calendar
.MILLISECOND
, 0);
444 ret
= GREGORIAN_CALENDAR
.getTimeInMillis() * MILLISEC_IN_NS
;
445 } else if (timeDelta
>= MONTH_IN_NS
) {
446 GREGORIAN_CALENDAR
.setTime(new Date(ret
/ MILLISEC_IN_NS
));
447 int month
= GREGORIAN_CALENDAR
.get(Calendar
.MONTH
);
448 int monthDelta
= (int) (timeDelta
/ MONTH_IN_NS
);
449 month
= (month
/ monthDelta
) * monthDelta
;
450 GREGORIAN_CALENDAR
.set(Calendar
.MONTH
, month
);
451 GREGORIAN_CALENDAR
.set(Calendar
.DAY_OF_MONTH
, 1); // 1st of month
452 GREGORIAN_CALENDAR
.set(Calendar
.HOUR_OF_DAY
, 0);
453 GREGORIAN_CALENDAR
.set(Calendar
.MINUTE
, 0);
454 GREGORIAN_CALENDAR
.set(Calendar
.SECOND
, 0);
455 GREGORIAN_CALENDAR
.set(Calendar
.MILLISECOND
, 0);
456 ret
= GREGORIAN_CALENDAR
.getTimeInMillis() * MILLISEC_IN_NS
;
458 long offset
= GREGORIAN_CALENDAR
.getTimeZone().getOffset(ret
/ MILLISEC_IN_NS
) * MILLISEC_IN_NS
;
460 ret
= (ret
/ timeDelta
) * timeDelta
;
466 private int calculateDigits(long time0
, long time1
) {
468 long timeRange
= time1
- time0
;
470 if (fTimeProvider
.getTimeFormat() == TimeFormat
.CALENDAR
) {
471 // Calculate the number of digits to represent the minutes provided
475 if (timeRange
< 10000) {
476 // HH:11:222:333:444__
478 } else if (timeRange
< 10000000) {
483 long sec
= time1
/ SEC_IN_NS
;
484 numDigits
= Long
.toString(sec
).length();
485 int thousandGroups
= (numDigits
- 1) / 3;
486 numDigits
+= thousandGroups
;
487 numDigits
+= 12; // .000 000 000
488 if (fTimeProvider
.getTimeFormat() == TimeFormat
.CYCLES
) {
489 numDigits
+= Messages
.Utils_ClockCyclesUnit
.length();
497 public void mouseDown(MouseEvent e
) {
498 getParent().setFocus();
499 if (fDragState
== NO_BUTTON
&& null != fTimeProvider
) {
500 int x
= e
.x
- fTimeProvider
.getNameSpace();
501 if (LEFT_BUTTON
== e
.button
&& x
> 0) {
503 fDragState
= LEFT_BUTTON
;
507 } else if (x
> getSize().x
- fTimeProvider
.getNameSpace()) {
508 x
= getSize().x
- fTimeProvider
.getNameSpace();
512 fTime0bak
= fTimeProvider
.getTime0();
513 fTime1bak
= fTimeProvider
.getTime1();
518 public void mouseUp(MouseEvent e
) {
519 if (e
.button
== LEFT_BUTTON
&& fDragState
== LEFT_BUTTON
) {
521 fDragState
= NO_BUTTON
;
523 // Notify time provider to check the need for listener notification
524 if (fDragX
!= fDragX0
&& fTimeProvider
.getTime0() != fTimeProvider
.getTime1()) {
525 fTimeProvider
.setStartFinishTimeNotify(fTimeProvider
.getTime0(), fTimeProvider
.getTime1());
531 public void mouseMove(MouseEvent e
) {
532 if (fDragX0
< 0 || fDragState
== NO_BUTTON
|| fTimeProvider
== null) {
535 Point size
= getSize();
536 int leftSpace
= fTimeProvider
.getNameSpace();
537 int x
= e
.x
- leftSpace
;
538 if (LEFT_BUTTON
== fDragState
) {
539 if (x
> 0 && size
.x
> leftSpace
&& fDragX
!= x
) {
541 if (fTimeProvider
.getTime0() == fTimeProvider
.getTime1()) {
544 long interval
= (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ fDragX
));
545 if (interval
== Long
.MAX_VALUE
) {
546 fTimeProvider
.setStartFinishTime(fTime0bak
, Long
.MAX_VALUE
);
548 long time1
= fTime0bak
+ (long) ((fTime1bak
- fTime0bak
) * ((double) fDragX0
/ fDragX
));
549 fTimeProvider
.setStartFinishTime(fTime0bak
, time1
);
556 public void mouseDoubleClick(MouseEvent e
) {
557 if (e
.button
== 1 && null != fTimeProvider
&& fTimeProvider
.getTime0() != fTimeProvider
.getTime1() && (e
.stateMask
& SWT
.BUTTON_MASK
) == 0) {
558 fTimeProvider
.resetStartFinishTime();
559 fTimeProvider
.notifyStartFinishTime();
560 fTime0bak
= fTimeProvider
.getTime0();
561 fTime1bak
= fTimeProvider
.getTime1();
566 * Update the display to use the updated timestamp format
568 * @param signal the incoming signal
572 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal
) {
573 TimeDraw
.updateTimeZone();
574 Utils
.updateTimeZone();
579 abstract class TimeDraw
{
580 protected static final long MICROSEC_IN_NS
= 1000;
581 protected static final long MILLISEC_IN_NS
= 1000000;
582 protected static final long MILLISEC_IN_US
= 1000;
583 protected static final long SEC_IN_NS
= 1000000000;
584 protected static final long SEC_IN_MS
= 1000;
585 private static final String S
= "" ; //$NON-NLS-1$
586 private static final String S0
= "0" ; //$NON-NLS-1$
587 private static final String S00
= "00"; //$NON-NLS-1$
588 protected static final long PAD_1000
= 1000;
589 protected static final SimpleDateFormat SEC_FORMAT_HEADER
= new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$
590 protected static final SimpleDateFormat SEC_FORMAT
= new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
591 protected static final SimpleDateFormat MIN_FORMAT_HEADER
= new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$
592 protected static final SimpleDateFormat MIN_FORMAT
= new SimpleDateFormat("HH:mm"); //$NON-NLS-1$
593 protected static final SimpleDateFormat HOURS_FORMAT_HEADER
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
594 protected static final SimpleDateFormat HOURS_FORMAT
= new SimpleDateFormat("MMM dd HH:mm"); //$NON-NLS-1$
595 protected static final SimpleDateFormat DAY_FORMAT_HEADER
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
596 protected static final SimpleDateFormat DAY_FORMAT
= new SimpleDateFormat("MMM dd"); //$NON-NLS-1$
597 protected static final SimpleDateFormat MONTH_FORMAT
= new SimpleDateFormat("yyyy MMM"); //$NON-NLS-1$
598 protected static final SimpleDateFormat YEAR_FORMAT
= new SimpleDateFormat("yyyy"); //$NON-NLS-1$
600 protected static final SimpleDateFormat formatArray
[] = {
601 SEC_FORMAT
, SEC_FORMAT_HEADER
, MIN_FORMAT
, MIN_FORMAT_HEADER
,
602 HOURS_FORMAT
, HOURS_FORMAT_HEADER
, DAY_FORMAT
, DAY_FORMAT_HEADER
, MONTH_FORMAT
, YEAR_FORMAT
606 * Updates the timezone using the preferences.
608 public static void updateTimeZone() {
609 final TimeZone timeZone
= TmfTimePreferences
.getInstance().getTimeZone();
610 for (SimpleDateFormat sdf
: formatArray
) {
611 sdf
.setTimeZone(timeZone
);
615 static String
sep(long n
) {
616 StringBuilder retVal
= new StringBuilder();
617 String s
= Long
.toString(n
);
618 for (int i
= 0; i
< s
.length(); i
++) {
619 int pos
= s
.length() - i
- 1;
620 retVal
.append(s
.charAt(i
));
621 if (pos
% 3 == 0 && pos
!= 0) {
625 return retVal
.toString();
628 static String
pad(long n
) {
632 } else if (n
< 100) {
640 public abstract int draw(GC gc
, long time
, Rectangle rect
);
643 * Override to draw absolute time header. This is for the time information
644 * not shown in the draw of each tick
650 * @param absHeaderRect
653 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle absHeaderRect
) {
657 class TimeDrawSec
extends TimeDraw
{
659 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
660 long sec
= nanosec
/ SEC_IN_NS
;
661 return Utils
.drawText(gc
, sep(sec
), rect
, true);
665 class TimeDrawMillisec
extends TimeDraw
{
667 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
668 long millisec
= nanosec
/ MILLISEC_IN_NS
;
669 long ms
= millisec
% PAD_1000
;
670 long sec
= millisec
/ SEC_IN_MS
;
671 return Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
), rect
, true); //$NON-NLS-1$
675 class TimeDrawMicrosec
extends TimeDraw
{
677 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
678 long microsec
= nanosec
/ MICROSEC_IN_NS
;
679 long us
= microsec
% PAD_1000
;
680 long millisec
= microsec
/ MILLISEC_IN_US
;
681 long ms
= millisec
% PAD_1000
;
682 long sec
= millisec
/ SEC_IN_MS
;
683 return Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
) + " " + pad(us
), rect
, true); //$NON-NLS-1$ //$NON-NLS-2$
687 class TimeDrawNanosec
extends TimeDraw
{
689 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
690 long ns
= nanosec
% PAD_1000
;
691 long microsec
= nanosec
/ MICROSEC_IN_NS
;
692 long us
= microsec
% PAD_1000
;
693 long millisec
= microsec
/ MILLISEC_IN_US
;
694 long ms
= millisec
% PAD_1000
;
695 long sec
= millisec
/ SEC_IN_MS
;
696 return Utils
.drawText(gc
, sep(sec
) + "." + pad(ms
) + " " + pad(us
) + " " + pad(ns
), rect
, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
700 class TimeDrawAbsYear
extends TimeDraw
{
702 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
703 String stime
= YEAR_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
704 return Utils
.drawText(gc
, stime
, rect
, true);
708 class TimeDrawAbsMonth
extends TimeDraw
{
710 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
711 String stime
= MONTH_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
712 return Utils
.drawText(gc
, stime
, rect
, true);
716 class TimeDrawAbsDay
extends TimeDraw
{
718 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
719 String stime
= DAY_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
720 return Utils
.drawText(gc
, stime
, rect
, true);
724 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
725 String header
= DAY_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
726 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
727 if (headerwidth
<= rect
.width
) {
728 rect
.x
+= (rect
.width
- headerwidth
);
729 Utils
.drawText(gc
, header
, rect
, true);
734 class TimeDrawAbsHrs
extends TimeDraw
{
736 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
737 String stime
= HOURS_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
738 return Utils
.drawText(gc
, stime
, rect
, true);
742 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
743 String header
= HOURS_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
744 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
745 if (headerwidth
<= rect
.width
) {
746 rect
.x
+= (rect
.width
- headerwidth
);
747 Utils
.drawText(gc
, header
, rect
, true);
752 class TimeDrawAbsMin
extends TimeDraw
{
754 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
755 String stime
= MIN_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
756 return Utils
.drawText(gc
, stime
, rect
, true);
760 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
761 String header
= MIN_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
762 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
763 if (headerwidth
<= rect
.width
) {
764 rect
.x
+= (rect
.width
- headerwidth
);
765 Utils
.drawText(gc
, header
, rect
, true);
770 class TimeDrawAbsSec
extends TimeDraw
{
772 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
773 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
774 return Utils
.drawText(gc
, stime
, rect
, true);
778 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
779 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
780 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
781 if (headerwidth
<= rect
.width
) {
782 rect
.x
+= (rect
.width
- headerwidth
);
783 Utils
.drawText(gc
, header
, rect
, true);
788 class TimeDrawAbsMillisec
extends TimeDraw
{
790 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
791 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
792 String ns
= Utils
.formatNs(nanosec
, Resolution
.MILLISEC
);
793 return Utils
.drawText(gc
, stime
+ "." + ns
, rect
, true); //$NON-NLS-1$
797 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
798 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
799 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
800 if (headerwidth
<= rect
.width
) {
801 rect
.x
+= (rect
.width
- headerwidth
);
802 Utils
.drawText(gc
, header
, rect
, true);
807 class TimeDrawAbsMicroSec
extends TimeDraw
{
809 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
810 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
811 String micr
= Utils
.formatNs(nanosec
, Resolution
.MICROSEC
);
812 return Utils
.drawText(gc
, stime
+ "." + micr
, rect
, true); //$NON-NLS-1$
816 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
817 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
818 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
819 if (headerwidth
<= rect
.width
) {
820 rect
.x
+= (rect
.width
- headerwidth
);
821 Utils
.drawText(gc
, header
, rect
, true);
826 class TimeDrawAbsNanoSec
extends TimeDraw
{
828 public int draw(GC gc
, long nanosec
, Rectangle rect
) {
829 String stime
= SEC_FORMAT
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
830 String ns
= Utils
.formatNs(nanosec
, Resolution
.NANOSEC
);
831 return Utils
.drawText(gc
, stime
+ "." + ns
, rect
, true); //$NON-NLS-1$
835 public void drawAbsHeader(GC gc
, long nanosec
, Rectangle rect
) {
836 String header
= SEC_FORMAT_HEADER
.format(new Date(nanosec
/ MILLISEC_IN_NS
));
837 int headerwidth
= gc
.stringExtent(header
).x
+ 4;
838 if (headerwidth
<= rect
.width
) {
839 rect
.x
+= (rect
.width
- headerwidth
);
840 Utils
.drawText(gc
, header
, rect
, true);
845 class TimeDrawNumber
extends TimeDraw
{
847 public int draw(GC gc
, long time
, Rectangle rect
) {
848 String stime
= NumberFormat
.getInstance().format(time
);
849 return Utils
.drawText(gc
, stime
, rect
, true);
853 class TimeDrawCycles
extends TimeDraw
{
855 public int draw(GC gc
, long time
, Rectangle rect
) {
856 String stime
= Utils
.formatTime(time
, TimeFormat
.CYCLES
, Resolution
.SECONDS
);
857 return Utils
.drawText(gc
, stime
, rect
, true);