Commit | Line | Data |
---|---|---|
8e1f81f1 | 1 | /***************************************************************************** |
8910dea2 | 2 | * Copyright (c) 2007, 2016 Intel Corporation, Ericsson |
8e1f81f1 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: | |
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 | |
c1cd9635 | 13 | * Marc-Andre Laperle - Add time zone preference |
8e1f81f1 PT |
14 | *****************************************************************************/ |
15 | ||
2bdf0193 | 16 | package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets; |
8e1f81f1 | 17 | |
026664b7 | 18 | import java.text.NumberFormat; |
8e1f81f1 | 19 | import java.text.SimpleDateFormat; |
55d1fc96 | 20 | import java.util.ArrayList; |
8e1f81f1 PT |
21 | import java.util.Calendar; |
22 | import java.util.Date; | |
6dcc38b9 | 23 | import java.util.List; |
c1cd9635 | 24 | import java.util.TimeZone; |
8e1f81f1 | 25 | |
8e1f81f1 PT |
26 | import org.eclipse.swt.SWT; |
27 | import org.eclipse.swt.events.MouseEvent; | |
28 | import org.eclipse.swt.events.MouseListener; | |
29 | import org.eclipse.swt.events.MouseMoveListener; | |
30 | import org.eclipse.swt.events.PaintEvent; | |
31 | import org.eclipse.swt.graphics.GC; | |
32 | import org.eclipse.swt.graphics.Point; | |
33 | import org.eclipse.swt.graphics.Rectangle; | |
34 | import org.eclipse.swt.widgets.Composite; | |
3573a01c | 35 | import org.eclipse.swt.widgets.Control; |
1d46761c | 36 | import org.eclipse.tracecompass.common.core.math.SaturatedArithmetic; |
2bdf0193 AM |
37 | import org.eclipse.tracecompass.internal.tmf.ui.Messages; |
38 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; | |
39 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; | |
40 | import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal; | |
41 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimePreferences; | |
42 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution; | |
43 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; | |
8e1f81f1 | 44 | |
6dcc38b9 MK |
45 | import com.google.common.collect.ImmutableList; |
46 | ||
8e1f81f1 PT |
47 | /** |
48 | * Implementation of the scale for the time graph view. | |
49 | * | |
50 | * This goes above the "gantt chart" area. | |
51 | * | |
52 | * @version 1.0 | |
53 | * @author Alvaro Sanchez-Leon | |
54 | * @author Patrick Tasse | |
55 | */ | |
56 | public class TimeGraphScale extends TimeGraphBaseControl implements | |
57 | MouseListener, MouseMoveListener { | |
58 | ||
83dcfe09 | 59 | private static final int BASE_10 = 10; |
83dcfe09 MK |
60 | private static final int Y_OFFSET = 4; |
61 | ||
62 | private static final int MIN_SECOND_FACTOR = 20; | |
63 | private static final int SECOND_FACTOR = 30; | |
64 | private static final int MAX_SECOND_FACTOR = 30; | |
65 | ||
66 | private static final int MIN_MINUTE_FACTOR = 10; | |
67 | private static final int MINUTE_FACTOR = 15; | |
68 | private static final int MAX_MINUTE_FACTOR = 30; | |
69 | ||
70 | private static final int MIN_HOUR_FACTOR = 3; | |
71 | private static final int HOUR_FACTOR = 6; | |
72 | private static final int MAX_HOUR_FACTOR = 12; | |
73 | ||
74 | private static final int MAX_DAY_FACTOR = 10; | |
75 | ||
76 | private static final int MAX_MONTH_FACTOR = 6; | |
77 | private static final int MONTH_FACTOR = 6; | |
78 | private static final int MIN_MONTH_FACTOR = 3; | |
79 | ||
f1fae91f PT |
80 | private static final long MICROSEC_IN_NS = 1000; |
81 | private static final long MILLISEC_IN_NS = 1000000; | |
8e1f81f1 PT |
82 | private static final long SEC_IN_NS = 1000000000; |
83 | private static final long MIN_IN_NS = 60 * SEC_IN_NS; | |
84 | private static final long HOUR_IN_NS = 60 * MIN_IN_NS; | |
85 | private static final long DAY_IN_NS = 24 * HOUR_IN_NS; | |
86 | private static final long MONTH_IN_NS = 31 * DAY_IN_NS; // upper limit | |
87 | private static final long YEAR_IN_NS = 366 * DAY_IN_NS; // upper limit | |
88 | ||
89 | private static final double LOG10_1 = Math.log10(1); | |
90 | private static final double LOG10_2 = Math.log10(2); | |
91 | private static final double LOG10_3 = Math.log10(3); | |
92 | private static final double LOG10_5 = Math.log10(5); | |
93 | ||
94 | private static final Calendar GREGORIAN_CALENDAR = Calendar.getInstance(); | |
95 | ||
f1fae91f PT |
96 | private static final TimeDraw TIMEDRAW_NANOSEC = new TimeDrawNanosec(); |
97 | private static final TimeDraw TIMEDRAW_MICROSEC = new TimeDrawMicrosec(); | |
98 | private static final TimeDraw TIMEDRAW_MILLISEC = new TimeDrawMillisec(); | |
99 | private static final TimeDraw TIMEDRAW_SEC = new TimeDrawSec(); | |
100 | private static final TimeDraw TIMEDRAW_ABS_NANOSEC = new TimeDrawAbsNanoSec(); | |
101 | private static final TimeDraw TIMEDRAW_ABS_MICROSEC = new TimeDrawAbsMicroSec(); | |
102 | private static final TimeDraw TIMEDRAW_ABS_MILLISEC = new TimeDrawAbsMillisec(); | |
103 | private static final TimeDraw TIMEDRAW_ABS_SEC = new TimeDrawAbsSec(); | |
104 | private static final TimeDraw TIMEDRAW_ABS_MIN = new TimeDrawAbsMin(); | |
105 | private static final TimeDraw TIMEDRAW_ABS_HRS = new TimeDrawAbsHrs(); | |
106 | private static final TimeDraw TIMEDRAW_ABS_DAY = new TimeDrawAbsDay(); | |
107 | private static final TimeDraw TIMEDRAW_ABS_MONTH = new TimeDrawAbsMonth(); | |
108 | private static final TimeDraw TIMEDRAW_ABS_YEAR = new TimeDrawAbsYear(); | |
109 | private static final TimeDraw TIMEDRAW_NUMBER = new TimeDrawNumber(); | |
0fab12b0 | 110 | private static final TimeDraw TIMEDRAW_CYCLES = new TimeDrawCycles(); |
f1fae91f | 111 | |
0fcf3b09 | 112 | private static final int DRAG_EXTERNAL = -1; |
f1fae91f PT |
113 | private static final int NO_BUTTON = 0; |
114 | private static final int LEFT_BUTTON = 1; | |
f1fae91f PT |
115 | |
116 | private ITimeDataProvider fTimeProvider; | |
117 | private int fDragState = NO_BUTTON; | |
118 | private int fDragX0 = 0; | |
119 | private int fDragX = 0; | |
120 | private long fTime0bak; | |
121 | private long fTime1bak; | |
122 | private boolean fIsInUpdate; | |
123 | private int fHeight; | |
55d1fc96 | 124 | private List<Integer> fTickList = new ArrayList<>(); |
f1fae91f PT |
125 | |
126 | /** | |
127 | * Standard constructor | |
128 | * | |
129 | * @param parent | |
130 | * The parent composite object | |
131 | * @param colors | |
132 | * The color scheme to use | |
133 | */ | |
134 | public TimeGraphScale(Composite parent, TimeGraphColorScheme colors) { | |
135 | super(parent, colors, SWT.NO_BACKGROUND | SWT.NO_FOCUS | SWT.DOUBLE_BUFFERED); | |
c1cd9635 | 136 | TmfSignalManager.register(this); |
f1fae91f PT |
137 | addMouseListener(this); |
138 | addMouseMoveListener(this); | |
c1cd9635 | 139 | TimeDraw.updateTimeZone(); |
25033fef PT |
140 | addDisposeListener((e) -> { |
141 | TmfSignalManager.deregister(TimeGraphScale.this); | |
142 | }); | |
f1fae91f | 143 | } |
8e1f81f1 PT |
144 | |
145 | /** | |
146 | * Assign the time provider for this scale | |
147 | * | |
148 | * @param timeProvider | |
149 | * The provider to use | |
150 | */ | |
151 | public void setTimeProvider(ITimeDataProvider timeProvider) { | |
f1fae91f | 152 | fTimeProvider = timeProvider; |
8e1f81f1 PT |
153 | } |
154 | ||
0fab12b0 PT |
155 | /** |
156 | * Get the time provider used by this scale | |
157 | * | |
158 | * @return The time provider | |
0fab12b0 PT |
159 | */ |
160 | public ITimeDataProvider getTimeProvider() { | |
161 | return fTimeProvider; | |
162 | } | |
163 | ||
8e1f81f1 PT |
164 | @Override |
165 | public Point computeSize(int wHint, int hHint, boolean changed) { | |
f1fae91f | 166 | return super.computeSize(wHint, fHeight, changed); |
8e1f81f1 PT |
167 | } |
168 | ||
169 | /** | |
170 | * Set the height of the scale | |
171 | * | |
172 | * @param height | |
173 | * The height to use | |
174 | */ | |
175 | public void setHeight(int height) { | |
3573a01c MAL |
176 | if (fHeight != height) { |
177 | fHeight = height; | |
178 | getParent().layout(new Control[] { this }); | |
179 | } | |
8e1f81f1 PT |
180 | } |
181 | ||
0fcf3b09 PT |
182 | /** |
183 | * Set the drag range to paint decorators | |
184 | * | |
185 | * @param begin | |
186 | * The begin x-coordinate | |
187 | * @param end | |
188 | * The end x-coordinate | |
0fcf3b09 PT |
189 | */ |
190 | public void setDragRange(int begin, int end) { | |
191 | if (NO_BUTTON == fDragState || DRAG_EXTERNAL == fDragState) { | |
192 | fDragX0 = begin - fTimeProvider.getNameSpace(); | |
193 | fDragX = end - fTimeProvider.getNameSpace(); | |
194 | if (begin >= 0 || end >= 0) { | |
195 | fDragState = DRAG_EXTERNAL; | |
196 | } else { | |
197 | fDragState = NO_BUTTON; | |
198 | } | |
199 | } | |
200 | redraw(); | |
201 | } | |
202 | ||
55d1fc96 PT |
203 | /** |
204 | * Get the list of visible ticks of the time axis. | |
205 | * | |
206 | * @return the list of visible tick x-coordinates | |
207 | * @since 2.0 | |
208 | */ | |
209 | public List<Integer> getTickList() { | |
210 | return fTickList; | |
211 | } | |
212 | ||
f1fae91f PT |
213 | private long calcTimeDelta(int width, double pixelsPerNanoSec) { |
214 | long timeDelta; | |
8e1f81f1 PT |
215 | double minDelta = (pixelsPerNanoSec == 0) ? YEAR_IN_NS : width / pixelsPerNanoSec; |
216 | long unit = 1; | |
0fab12b0 | 217 | if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) { |
83dcfe09 | 218 | if (minDelta > MAX_MONTH_FACTOR * MONTH_IN_NS) { |
8e1f81f1 | 219 | unit = YEAR_IN_NS; |
83dcfe09 MK |
220 | } else if (minDelta > MIN_MONTH_FACTOR * MONTH_IN_NS) { |
221 | unit = MONTH_FACTOR * MONTH_IN_NS; | |
222 | } else if (minDelta > MAX_DAY_FACTOR * DAY_IN_NS) { | |
8e1f81f1 | 223 | unit = MONTH_IN_NS; |
83dcfe09 | 224 | } else if (minDelta > MAX_HOUR_FACTOR * HOUR_IN_NS) { |
8e1f81f1 | 225 | unit = DAY_IN_NS; |
83dcfe09 MK |
226 | } else if (minDelta > MIN_HOUR_FACTOR * HOUR_IN_NS) { |
227 | unit = HOUR_FACTOR * HOUR_IN_NS; | |
228 | } else if (minDelta > MAX_MINUTE_FACTOR * MIN_IN_NS) { | |
8e1f81f1 | 229 | unit = HOUR_IN_NS; |
83dcfe09 MK |
230 | } else if (minDelta > MIN_MINUTE_FACTOR * MIN_IN_NS) { |
231 | unit = MINUTE_FACTOR * MIN_IN_NS; | |
232 | } else if (minDelta > MAX_SECOND_FACTOR * SEC_IN_NS) { | |
8e1f81f1 | 233 | unit = MIN_IN_NS; |
83dcfe09 MK |
234 | } else if (minDelta > MIN_SECOND_FACTOR * SEC_IN_NS) { |
235 | unit = SECOND_FACTOR * SEC_IN_NS; | |
8e1f81f1 | 236 | } else if (minDelta <= 1) { |
f1fae91f PT |
237 | timeDelta = 1; |
238 | return timeDelta; | |
8e1f81f1 PT |
239 | } |
240 | } | |
241 | double log = Math.log10(minDelta / unit); | |
242 | long pow10 = (long) log; | |
243 | double remainder = log - pow10; | |
244 | if (remainder < LOG10_1) { | |
83dcfe09 | 245 | timeDelta = (long) Math.pow(BASE_10, pow10) * unit; |
8e1f81f1 | 246 | } else if (remainder < LOG10_2) { |
83dcfe09 | 247 | timeDelta = 2 * (long) Math.pow(BASE_10, pow10) * unit; |
8e1f81f1 | 248 | } else if (remainder < LOG10_3 && unit >= HOUR_IN_NS && unit < YEAR_IN_NS) { |
83dcfe09 | 249 | timeDelta = 3 * (long) Math.pow(BASE_10, pow10) * unit; |
8e1f81f1 | 250 | } else if (remainder < LOG10_5) { |
83dcfe09 | 251 | timeDelta = 5 * (long) Math.pow(BASE_10, pow10) * unit; |
8e1f81f1 | 252 | } else { |
83dcfe09 | 253 | timeDelta = 10 * (long) Math.pow(BASE_10, pow10) * unit; |
8e1f81f1 | 254 | } |
f1fae91f PT |
255 | if (timeDelta <= 0) { |
256 | timeDelta = 1; | |
f85266f3 | 257 | } |
f1fae91f | 258 | return timeDelta; |
8e1f81f1 PT |
259 | } |
260 | ||
8e1f81f1 PT |
261 | TimeDraw getTimeDraw(long timeDelta) { |
262 | TimeDraw timeDraw; | |
f1fae91f | 263 | if (fTimeProvider != null) { |
0fab12b0 PT |
264 | switch (fTimeProvider.getTimeFormat()) { |
265 | case CALENDAR: | |
026664b7 XR |
266 | if (timeDelta >= YEAR_IN_NS) { |
267 | timeDraw = TIMEDRAW_ABS_YEAR; | |
268 | } else if (timeDelta >= MONTH_IN_NS) { | |
269 | timeDraw = TIMEDRAW_ABS_MONTH; | |
270 | } else if (timeDelta >= DAY_IN_NS) { | |
271 | timeDraw = TIMEDRAW_ABS_DAY; | |
272 | } else if (timeDelta >= HOUR_IN_NS) { | |
273 | timeDraw = TIMEDRAW_ABS_HRS; | |
274 | } else if (timeDelta >= MIN_IN_NS) { | |
275 | timeDraw = TIMEDRAW_ABS_MIN; | |
276 | } else if (timeDelta >= SEC_IN_NS) { | |
277 | timeDraw = TIMEDRAW_ABS_SEC; | |
f1fae91f | 278 | } else if (timeDelta >= MILLISEC_IN_NS) { |
026664b7 | 279 | timeDraw = TIMEDRAW_ABS_MILLISEC; |
f1fae91f | 280 | } else if (timeDelta >= MICROSEC_IN_NS) { |
026664b7 XR |
281 | timeDraw = TIMEDRAW_ABS_MICROSEC; |
282 | } else { | |
283 | timeDraw = TIMEDRAW_ABS_NANOSEC; | |
284 | } | |
285 | return timeDraw; | |
0fab12b0 PT |
286 | case NUMBER: |
287 | return TIMEDRAW_NUMBER; | |
288 | case CYCLES: | |
289 | return TIMEDRAW_CYCLES; | |
290 | case RELATIVE: | |
291 | default: | |
8e1f81f1 | 292 | } |
026664b7 | 293 | |
8e1f81f1 | 294 | } |
f1fae91f | 295 | if (timeDelta >= SEC_IN_NS) { |
8e1f81f1 | 296 | timeDraw = TIMEDRAW_SEC; |
f1fae91f | 297 | } else if (timeDelta >= MILLISEC_IN_NS) { |
8e1f81f1 | 298 | timeDraw = TIMEDRAW_MILLISEC; |
f1fae91f | 299 | } else if (timeDelta >= MICROSEC_IN_NS) { |
8e1f81f1 PT |
300 | timeDraw = TIMEDRAW_MICROSEC; |
301 | } else { | |
302 | timeDraw = TIMEDRAW_NANOSEC; | |
303 | } | |
304 | return timeDraw; | |
305 | } | |
306 | ||
307 | @Override | |
308 | void paint(Rectangle rect, PaintEvent e) { | |
309 | ||
f1fae91f | 310 | if (fIsInUpdate || null == fTimeProvider) { |
8e1f81f1 PT |
311 | return; |
312 | } | |
313 | ||
314 | GC gc = e.gc; | |
315 | gc.fillRectangle(rect); | |
316 | ||
f1fae91f PT |
317 | long time0 = fTimeProvider.getTime0(); |
318 | long time1 = fTimeProvider.getTime1(); | |
f1fae91f | 319 | int timeSpace = fTimeProvider.getTimeSpace(); |
8e1f81f1 | 320 | |
f1fae91f PT |
321 | gc.setBackground(getColorScheme().getColor(TimeGraphColorScheme.TOOL_BACKGROUND)); |
322 | gc.setForeground(getColorScheme().getColor(TimeGraphColorScheme.TOOL_FOREGROUND)); | |
323 | Rectangle rect0 = new Rectangle(0, 0, 0, 0); | |
324 | Utils.init(rect0, rect); | |
8e1f81f1 | 325 | |
8e1f81f1 PT |
326 | // draw bottom border and erase all other area |
327 | gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width - 1, | |
328 | rect.y + rect.height - 1); | |
f1fae91f PT |
329 | rect0.height--; |
330 | gc.fillRectangle(rect0); | |
8e1f81f1 PT |
331 | |
332 | if (time1 <= time0 || timeSpace < 2) { | |
55d1fc96 | 333 | fTickList.clear(); |
8e1f81f1 PT |
334 | return; |
335 | } | |
336 | ||
337 | int numDigits = calculateDigits(time0, time1); | |
338 | ||
339 | int labelWidth = gc.getCharWidth('0') * numDigits; | |
340 | double pixelsPerNanoSec = (timeSpace <= RIGHT_MARGIN) ? 0 : | |
6dcc38b9 | 341 | (double) (timeSpace - RIGHT_MARGIN) / (time1 - time0); |
f1fae91f | 342 | long timeDelta = calcTimeDelta(labelWidth, pixelsPerNanoSec); |
8e1f81f1 | 343 | |
f1fae91f | 344 | TimeDraw timeDraw = getTimeDraw(timeDelta); |
8e1f81f1 | 345 | |
0fcf3b09 PT |
346 | // draw range decorators |
347 | if (DRAG_EXTERNAL == fDragState) { | |
26cf0ea8 PT |
348 | int x1 = fDragX0; |
349 | int x2 = fDragX; | |
0fcf3b09 PT |
350 | drawRangeDecorators(rect0, gc, x1, x2); |
351 | } else { | |
baf92cac AM |
352 | long selectionBegin = fTimeProvider.getSelectionBegin(); |
353 | long selectionEnd = fTimeProvider.getSelectionEnd(); | |
26cf0ea8 PT |
354 | int x1 = (int) ((selectionBegin - time0) * pixelsPerNanoSec); |
355 | int x2 = (int) ((selectionEnd - time0) * pixelsPerNanoSec); | |
0fcf3b09 | 356 | drawRangeDecorators(rect0, gc, x1, x2); |
8e1f81f1 PT |
357 | } |
358 | ||
8e1f81f1 | 359 | // draw time scale ticks |
f1fae91f | 360 | rect0.y = rect.y; |
83dcfe09 | 361 | rect0.height = rect.height - Y_OFFSET; |
f1fae91f | 362 | rect0.width = labelWidth; |
8e1f81f1 PT |
363 | |
364 | long time; | |
0fab12b0 | 365 | if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) { |
f1fae91f | 366 | time = floorToCalendar(time0, timeDelta); |
8e1f81f1 | 367 | } else { |
f1fae91f | 368 | time = (time0 / timeDelta) * timeDelta; |
8e1f81f1 | 369 | if (time != time0) { |
f1fae91f | 370 | time += timeDelta; |
8e1f81f1 PT |
371 | } |
372 | } | |
373 | ||
f1fae91f | 374 | int y = rect0.y + rect0.height; |
8e1f81f1 | 375 | |
55d1fc96 | 376 | List<Integer> tickList = new ArrayList<>(); |
8e1f81f1 | 377 | while (true) { |
26cf0ea8 PT |
378 | int x = SaturatedArithmetic.add(rect.x, (int) (Math.floor((time - time0) * pixelsPerNanoSec))); |
379 | if (x >= rect.x + rect.width - rect0.width) { | |
8e1f81f1 PT |
380 | break; |
381 | } | |
26cf0ea8 | 382 | if (x >= rect.x) { |
83dcfe09 | 383 | gc.drawLine(x, y, x, y + Y_OFFSET); |
f1fae91f PT |
384 | rect0.x = x; |
385 | if (x + rect0.width <= rect.x + rect.width) { | |
386 | timeDraw.draw(gc, time, rect0); | |
8e1f81f1 | 387 | } |
26cf0ea8 | 388 | tickList.add(x + fTimeProvider.getNameSpace()); |
8e1f81f1 | 389 | } |
f1fae91f | 390 | if (pixelsPerNanoSec == 0 || time > Long.MAX_VALUE - timeDelta || timeDelta == 0) { |
8e1f81f1 PT |
391 | break; |
392 | } | |
0fab12b0 | 393 | if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) { |
f1fae91f PT |
394 | if (timeDelta >= YEAR_IN_NS) { |
395 | long millis = time / MILLISEC_IN_NS; | |
8e1f81f1 | 396 | GREGORIAN_CALENDAR.setTime(new Date(millis)); |
f1fae91f | 397 | GREGORIAN_CALENDAR.add(Calendar.YEAR, (int) (timeDelta / YEAR_IN_NS)); |
8e1f81f1 | 398 | millis = GREGORIAN_CALENDAR.getTimeInMillis(); |
f1fae91f PT |
399 | time = millis * MILLISEC_IN_NS; |
400 | } else if (timeDelta >= MONTH_IN_NS) { | |
401 | long millis = time / MILLISEC_IN_NS; | |
8e1f81f1 | 402 | GREGORIAN_CALENDAR.setTime(new Date(millis)); |
f1fae91f | 403 | GREGORIAN_CALENDAR.add(Calendar.MONTH, (int) (timeDelta / MONTH_IN_NS)); |
8e1f81f1 | 404 | millis = GREGORIAN_CALENDAR.getTimeInMillis(); |
f1fae91f PT |
405 | time = millis * MILLISEC_IN_NS; |
406 | } else if (timeDelta >= DAY_IN_NS) { | |
407 | long millis = time / MILLISEC_IN_NS; | |
8e1f81f1 | 408 | GREGORIAN_CALENDAR.setTime(new Date(millis)); |
f1fae91f | 409 | GREGORIAN_CALENDAR.add(Calendar.DAY_OF_MONTH, (int) (timeDelta / DAY_IN_NS)); |
8e1f81f1 | 410 | millis = GREGORIAN_CALENDAR.getTimeInMillis(); |
f1fae91f | 411 | time = millis * MILLISEC_IN_NS; |
8e1f81f1 | 412 | } else { |
f1fae91f | 413 | time += timeDelta; |
8e1f81f1 PT |
414 | } |
415 | } else { | |
f1fae91f | 416 | time += timeDelta; |
8e1f81f1 PT |
417 | } |
418 | } | |
55d1fc96 | 419 | fTickList = tickList; |
8e1f81f1 PT |
420 | } |
421 | ||
0fcf3b09 PT |
422 | private static void drawRangeDecorators(Rectangle rect, GC gc, int x1, int x2) { |
423 | int y1 = rect.y + rect.height - 9; | |
424 | int y2 = rect.y + rect.height - 5; | |
425 | int ym = (y1 + y2) / 2; | |
426 | if (x1 >= rect.x) { | |
427 | // T1 | |
85203d74 PT |
428 | gc.drawLine(x1 - 2, y1, x1 - 2, y2); |
429 | gc.drawLine(x1 - 3, y1, x1 - 1, y1); | |
430 | gc.drawLine(x1 + 1, y1, x1 + 1, y2); | |
0fcf3b09 | 431 | } |
85203d74 PT |
432 | if (x2 >= rect.x && Math.abs(x2 - x1 - 2) > 3) { |
433 | // T of T2 | |
0fcf3b09 PT |
434 | gc.drawLine(x2 - 2, y1, x2 - 2, y2); |
435 | gc.drawLine(x2 - 3, y1, x2 - 1, y1); | |
436 | } | |
85203d74 PT |
437 | if (x2 >= rect.x && Math.abs(x2 - x1 + 3) > 3) { |
438 | // 2 of T2 | |
0fcf3b09 PT |
439 | gc.drawLine(x2 + 1, y1, x2 + 3, y1); |
440 | gc.drawLine(x2 + 3, y1, x2 + 3, ym); | |
441 | gc.drawLine(x2 + 1, ym, x2 + 3, ym); | |
442 | gc.drawLine(x2 + 1, ym, x2 + 1, y2); | |
443 | gc.drawLine(x2 + 1, y2, x2 + 3, y2); | |
444 | } | |
445 | } | |
446 | ||
f1fae91f | 447 | private static long floorToCalendar(long time, long timeDelta) { |
41b5c37f AM |
448 | long ret = time; |
449 | ||
f1fae91f PT |
450 | if (timeDelta >= YEAR_IN_NS) { |
451 | GREGORIAN_CALENDAR.setTime(new Date(ret / MILLISEC_IN_NS)); | |
8e1f81f1 PT |
452 | int year = GREGORIAN_CALENDAR.get(Calendar.YEAR); |
453 | int yearDelta = (int) (timeDelta / YEAR_IN_NS); | |
454 | year = (year / yearDelta) * yearDelta; | |
455 | GREGORIAN_CALENDAR.set(Calendar.YEAR, year); | |
456 | GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year | |
457 | GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); | |
458 | GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0); | |
459 | GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0); | |
460 | GREGORIAN_CALENDAR.set(Calendar.SECOND, 0); | |
461 | GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0); | |
f1fae91f PT |
462 | ret = GREGORIAN_CALENDAR.getTimeInMillis() * MILLISEC_IN_NS; |
463 | } else if (timeDelta >= MONTH_IN_NS) { | |
464 | GREGORIAN_CALENDAR.setTime(new Date(ret / MILLISEC_IN_NS)); | |
8e1f81f1 PT |
465 | int month = GREGORIAN_CALENDAR.get(Calendar.MONTH); |
466 | int monthDelta = (int) (timeDelta / MONTH_IN_NS); | |
467 | month = (month / monthDelta) * monthDelta; | |
468 | GREGORIAN_CALENDAR.set(Calendar.MONTH, month); | |
469 | GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month | |
470 | GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0); | |
471 | GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0); | |
472 | GREGORIAN_CALENDAR.set(Calendar.SECOND, 0); | |
473 | GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0); | |
f1fae91f | 474 | ret = GREGORIAN_CALENDAR.getTimeInMillis() * MILLISEC_IN_NS; |
8e1f81f1 | 475 | } else { |
f1fae91f | 476 | long offset = GREGORIAN_CALENDAR.getTimeZone().getOffset(ret / MILLISEC_IN_NS) * MILLISEC_IN_NS; |
41b5c37f AM |
477 | ret += offset; |
478 | ret = (ret / timeDelta) * timeDelta; | |
479 | ret -= offset; | |
8e1f81f1 | 480 | } |
41b5c37f | 481 | return ret; |
8e1f81f1 PT |
482 | } |
483 | ||
484 | private int calculateDigits(long time0, long time1) { | |
485 | int numDigits = 5; | |
486 | long timeRange = time1 - time0; | |
5ea5e3ab | 487 | TimeFormat timeFormat = fTimeProvider.getTimeFormat(); |
8e1f81f1 | 488 | |
5ea5e3ab | 489 | if (timeFormat == TimeFormat.CALENDAR) { |
8e1f81f1 PT |
490 | // Calculate the number of digits to represent the minutes provided |
491 | // 11:222 | |
492 | // HH:mm:ss | |
493 | numDigits += 8; | |
494 | if (timeRange < 10000) { | |
495 | // HH:11:222:333:444__ | |
496 | numDigits += 10; | |
497 | } else if (timeRange < 10000000) { | |
498 | // HH:11:222:333__ | |
499 | numDigits += 6; | |
500 | } | |
501 | } else { | |
f1fae91f | 502 | long sec = time1 / SEC_IN_NS; |
8e1f81f1 PT |
503 | numDigits = Long.toString(sec).length(); |
504 | int thousandGroups = (numDigits - 1) / 3; | |
505 | numDigits += thousandGroups; | |
506 | numDigits += 12; // .000 000 000 | |
5ea5e3ab | 507 | if (timeFormat == TimeFormat.CYCLES) { |
0fab12b0 | 508 | numDigits += Messages.Utils_ClockCyclesUnit.length(); |
5ea5e3ab MK |
509 | } else if (fTimeProvider.getTimeFormat() == TimeFormat.RELATIVE) { |
510 | numDigits += 2; // " s" | |
0fab12b0 | 511 | } |
8e1f81f1 PT |
512 | } |
513 | ||
514 | return numDigits; | |
515 | } | |
516 | ||
517 | @Override | |
518 | public void mouseDown(MouseEvent e) { | |
519 | getParent().setFocus(); | |
f1fae91f PT |
520 | if (fDragState == NO_BUTTON && null != fTimeProvider) { |
521 | int x = e.x - fTimeProvider.getNameSpace(); | |
522 | if (LEFT_BUTTON == e.button && x > 0) { | |
8e1f81f1 | 523 | setCapture(true); |
f1fae91f | 524 | fDragState = LEFT_BUTTON; |
8e1f81f1 PT |
525 | } |
526 | if (x < 0) { | |
527 | x = 0; | |
f1fae91f PT |
528 | } else if (x > getSize().x - fTimeProvider.getNameSpace()) { |
529 | x = getSize().x - fTimeProvider.getNameSpace(); | |
8e1f81f1 | 530 | } |
f1fae91f PT |
531 | fDragX = x; |
532 | fDragX0 = x; | |
533 | fTime0bak = fTimeProvider.getTime0(); | |
534 | fTime1bak = fTimeProvider.getTime1(); | |
8e1f81f1 PT |
535 | } |
536 | } | |
537 | ||
538 | @Override | |
539 | public void mouseUp(MouseEvent e) { | |
f1fae91f | 540 | if (e.button == LEFT_BUTTON && fDragState == LEFT_BUTTON) { |
8e1f81f1 | 541 | setCapture(false); |
f1fae91f | 542 | fDragState = NO_BUTTON; |
8e1f81f1 PT |
543 | |
544 | // Notify time provider to check the need for listener notification | |
f1fae91f PT |
545 | if (fDragX != fDragX0 && fTimeProvider.getTime0() != fTimeProvider.getTime1()) { |
546 | fTimeProvider.setStartFinishTimeNotify(fTimeProvider.getTime0(), fTimeProvider.getTime1()); | |
8e1f81f1 | 547 | } |
8e1f81f1 PT |
548 | } |
549 | } | |
550 | ||
551 | @Override | |
552 | public void mouseMove(MouseEvent e) { | |
f1fae91f | 553 | if (fDragX0 < 0 || fDragState == NO_BUTTON || fTimeProvider == null) { |
8e1f81f1 PT |
554 | return; |
555 | } | |
556 | Point size = getSize(); | |
f1fae91f | 557 | int leftSpace = fTimeProvider.getNameSpace(); |
8e1f81f1 | 558 | int x = e.x - leftSpace; |
f1fae91f PT |
559 | if (LEFT_BUTTON == fDragState) { |
560 | if (x > 0 && size.x > leftSpace && fDragX != x) { | |
561 | fDragX = x; | |
562 | if (fTimeProvider.getTime0() == fTimeProvider.getTime1()) { | |
8e1f81f1 PT |
563 | return; |
564 | } | |
f1fae91f | 565 | long interval = (long) ((fTime1bak - fTime0bak) * ((double) fDragX0 / fDragX)); |
8e1f81f1 | 566 | if (interval == Long.MAX_VALUE) { |
88de10c6 | 567 | fTimeProvider.setStartFinishTimeNotify(fTime0bak, Long.MAX_VALUE); |
8e1f81f1 | 568 | } else { |
f1fae91f | 569 | long time1 = fTime0bak + (long) ((fTime1bak - fTime0bak) * ((double) fDragX0 / fDragX)); |
88de10c6 | 570 | fTimeProvider.setStartFinishTimeNotify(fTime0bak, time1); |
8e1f81f1 PT |
571 | } |
572 | } | |
8e1f81f1 PT |
573 | } |
574 | } | |
575 | ||
576 | @Override | |
577 | public void mouseDoubleClick(MouseEvent e) { | |
f1fae91f PT |
578 | if (e.button == 1 && null != fTimeProvider && fTimeProvider.getTime0() != fTimeProvider.getTime1() && (e.stateMask & SWT.BUTTON_MASK) == 0) { |
579 | fTimeProvider.resetStartFinishTime(); | |
f1fae91f PT |
580 | fTime0bak = fTimeProvider.getTime0(); |
581 | fTime1bak = fTimeProvider.getTime1(); | |
8e1f81f1 PT |
582 | } |
583 | } | |
c1cd9635 | 584 | |
6dcc38b9 | 585 | /** |
c1cd9635 MAL |
586 | * Update the display to use the updated timestamp format |
587 | * | |
6dcc38b9 MK |
588 | * @param signal |
589 | * the incoming signal | |
c1cd9635 MAL |
590 | */ |
591 | @TmfSignalHandler | |
592 | public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) { | |
593 | TimeDraw.updateTimeZone(); | |
594 | Utils.updateTimeZone(); | |
595 | redraw(); | |
596 | } | |
8e1f81f1 PT |
597 | } |
598 | ||
599 | abstract class TimeDraw { | |
f1fae91f PT |
600 | protected static final long MICROSEC_IN_NS = 1000; |
601 | protected static final long MILLISEC_IN_NS = 1000000; | |
602 | protected static final long MILLISEC_IN_US = 1000; | |
603 | protected static final long SEC_IN_NS = 1000000000; | |
604 | protected static final long SEC_IN_MS = 1000; | |
6dcc38b9 MK |
605 | private static final String S = ""; //$NON-NLS-1$ |
606 | private static final String S0 = "0"; //$NON-NLS-1$ | |
f1fae91f PT |
607 | private static final String S00 = "00"; //$NON-NLS-1$ |
608 | protected static final long PAD_1000 = 1000; | |
6dcc38b9 MK |
609 | protected static final SimpleDateFormat SEC_FORMAT_HEADER = |
610 | new SimpleDateFormat("yyyy MMM dd");//$NON-NLS-1$ | |
611 | protected static final SimpleDateFormat SEC_FORMAT = | |
612 | new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$ | |
613 | protected static final SimpleDateFormat MIN_FORMAT_HEADER = | |
614 | new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$ | |
615 | protected static final SimpleDateFormat MIN_FORMAT = | |
616 | new SimpleDateFormat("HH:mm"); //$NON-NLS-1$ | |
617 | protected static final SimpleDateFormat HOURS_FORMAT_HEADER = | |
618 | new SimpleDateFormat("yyyy"); //$NON-NLS-1$ | |
619 | protected static final SimpleDateFormat HOURS_FORMAT = | |
620 | new SimpleDateFormat("MMM dd HH:mm"); //$NON-NLS-1$ | |
621 | protected static final SimpleDateFormat DAY_FORMAT_HEADER = | |
622 | new SimpleDateFormat("yyyy"); //$NON-NLS-1$ | |
623 | protected static final SimpleDateFormat DAY_FORMAT = | |
624 | new SimpleDateFormat("MMM dd"); //$NON-NLS-1$ | |
625 | protected static final SimpleDateFormat MONTH_FORMAT = | |
626 | new SimpleDateFormat("yyyy MMM"); //$NON-NLS-1$ | |
627 | protected static final SimpleDateFormat YEAR_FORMAT = | |
628 | new SimpleDateFormat("yyyy"); //$NON-NLS-1$ | |
629 | ||
630 | protected static final List<SimpleDateFormat> formats; | |
631 | static | |
632 | { | |
633 | ImmutableList.Builder<SimpleDateFormat> formatArrayBuilder = ImmutableList.<SimpleDateFormat> builder(); | |
634 | formatArrayBuilder.add(SEC_FORMAT); | |
635 | formatArrayBuilder.add(SEC_FORMAT_HEADER); | |
636 | formatArrayBuilder.add(MIN_FORMAT); | |
637 | formatArrayBuilder.add(MIN_FORMAT_HEADER); | |
638 | formatArrayBuilder.add(HOURS_FORMAT); | |
639 | formatArrayBuilder.add(HOURS_FORMAT_HEADER); | |
640 | formatArrayBuilder.add(DAY_FORMAT); | |
641 | formatArrayBuilder.add(DAY_FORMAT_HEADER); | |
642 | formatArrayBuilder.add(MONTH_FORMAT); | |
643 | formatArrayBuilder.add(YEAR_FORMAT); | |
644 | formats = formatArrayBuilder.build(); | |
645 | } | |
c1cd9635 MAL |
646 | |
647 | /** | |
648 | * Updates the timezone using the preferences. | |
649 | */ | |
650 | public static void updateTimeZone() { | |
7c34a4ea | 651 | final TimeZone timeZone = TmfTimePreferences.getTimeZone(); |
6dcc38b9 MK |
652 | for (SimpleDateFormat sdf : formats) { |
653 | synchronized (sdf) { | |
654 | sdf.setTimeZone(timeZone); | |
655 | } | |
c1cd9635 MAL |
656 | } |
657 | } | |
658 | ||
8e1f81f1 PT |
659 | static String sep(long n) { |
660 | StringBuilder retVal = new StringBuilder(); | |
661 | String s = Long.toString(n); | |
662 | for (int i = 0; i < s.length(); i++) { | |
663 | int pos = s.length() - i - 1; | |
664 | retVal.append(s.charAt(i)); | |
665 | if (pos % 3 == 0 && pos != 0) { | |
666 | retVal.append(' '); | |
667 | } | |
668 | } | |
669 | return retVal.toString(); | |
670 | } | |
671 | ||
672 | static String pad(long n) { | |
673 | String s; | |
674 | if (n < 10) { | |
675 | s = S00; | |
676 | } else if (n < 100) { | |
677 | s = S0; | |
678 | } else { | |
679 | s = S; | |
680 | } | |
681 | return s + n; | |
682 | } | |
683 | ||
0fab12b0 | 684 | public abstract int draw(GC gc, long time, Rectangle rect); |
8e1f81f1 | 685 | |
a0a88f65 | 686 | /** |
f1fae91f | 687 | * Override to draw absolute time header. This is for the time information |
a0a88f65 AM |
688 | * not shown in the draw of each tick |
689 | * | |
690 | * @param gc | |
691 | * Graphics context | |
f1fae91f PT |
692 | * @param nanosec |
693 | * time in nanosec | |
a0a88f65 AM |
694 | * @param absHeaderRect |
695 | * Header rectangle | |
696 | */ | |
f1fae91f | 697 | public void drawAbsHeader(GC gc, long nanosec, Rectangle absHeaderRect) { |
8e1f81f1 | 698 | } |
2b3be043 JCK |
699 | |
700 | protected void drawAbsHeader(GC gc, long nanosec, Rectangle rect, SimpleDateFormat dateFormat) { | |
701 | String header; | |
702 | synchronized (dateFormat) { | |
703 | header = dateFormat.format(new Date(nanosec / MILLISEC_IN_NS)); | |
704 | } | |
705 | int headerwidth = gc.stringExtent(header).x + 4; | |
706 | if (headerwidth <= rect.width) { | |
707 | rect.x += (rect.width - headerwidth); | |
708 | Utils.drawText(gc, header, rect, true); | |
709 | } | |
710 | } | |
8e1f81f1 PT |
711 | } |
712 | ||
713 | class TimeDrawSec extends TimeDraw { | |
8e1f81f1 | 714 | @Override |
0fab12b0 | 715 | public int draw(GC gc, long nanosec, Rectangle rect) { |
f1fae91f | 716 | long sec = nanosec / SEC_IN_NS; |
5ea5e3ab | 717 | return Utils.drawText(gc, sep(sec) + " s", rect, true); //$NON-NLS-1$ |
8e1f81f1 PT |
718 | } |
719 | } | |
720 | ||
721 | class TimeDrawMillisec extends TimeDraw { | |
8e1f81f1 | 722 | @Override |
0fab12b0 | 723 | public int draw(GC gc, long nanosec, Rectangle rect) { |
f1fae91f PT |
724 | long millisec = nanosec / MILLISEC_IN_NS; |
725 | long ms = millisec % PAD_1000; | |
726 | long sec = millisec / SEC_IN_MS; | |
5ea5e3ab | 727 | return Utils.drawText(gc, sep(sec) + "." + pad(ms) + " s", rect, true); //$NON-NLS-1$ //$NON-NLS-2$ |
8e1f81f1 PT |
728 | } |
729 | } | |
730 | ||
731 | class TimeDrawMicrosec extends TimeDraw { | |
8e1f81f1 | 732 | @Override |
0fab12b0 | 733 | public int draw(GC gc, long nanosec, Rectangle rect) { |
f1fae91f PT |
734 | long microsec = nanosec / MICROSEC_IN_NS; |
735 | long us = microsec % PAD_1000; | |
736 | long millisec = microsec / MILLISEC_IN_US; | |
737 | long ms = millisec % PAD_1000; | |
738 | long sec = millisec / SEC_IN_MS; | |
5ea5e3ab | 739 | return Utils.drawText(gc, sep(sec) + "." + pad(ms) + " " + pad(us) + " s", rect, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
8e1f81f1 PT |
740 | } |
741 | } | |
742 | ||
743 | class TimeDrawNanosec extends TimeDraw { | |
8e1f81f1 | 744 | @Override |
0fab12b0 | 745 | public int draw(GC gc, long nanosec, Rectangle rect) { |
f1fae91f PT |
746 | long ns = nanosec % PAD_1000; |
747 | long microsec = nanosec / MICROSEC_IN_NS; | |
748 | long us = microsec % PAD_1000; | |
749 | long millisec = microsec / MILLISEC_IN_US; | |
750 | long ms = millisec % PAD_1000; | |
751 | long sec = millisec / SEC_IN_MS; | |
5ea5e3ab | 752 | return Utils.drawText(gc, sep(sec) + "." + pad(ms) + " " + pad(us) + " " + pad(ns) + " s", rect, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
8e1f81f1 PT |
753 | } |
754 | } | |
755 | ||
756 | class TimeDrawAbsYear extends TimeDraw { | |
8e1f81f1 | 757 | @Override |
0fab12b0 | 758 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
759 | String stime; |
760 | synchronized (YEAR_FORMAT) { | |
761 | stime = YEAR_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
762 | } | |
0fab12b0 | 763 | return Utils.drawText(gc, stime, rect, true); |
8e1f81f1 | 764 | } |
8e1f81f1 PT |
765 | } |
766 | ||
767 | class TimeDrawAbsMonth extends TimeDraw { | |
8e1f81f1 | 768 | @Override |
0fab12b0 | 769 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
770 | String stime; |
771 | synchronized (MONTH_FORMAT) { | |
772 | stime = MONTH_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
773 | } | |
0fab12b0 | 774 | return Utils.drawText(gc, stime, rect, true); |
8e1f81f1 | 775 | } |
8e1f81f1 PT |
776 | } |
777 | ||
778 | class TimeDrawAbsDay extends TimeDraw { | |
8e1f81f1 | 779 | @Override |
0fab12b0 | 780 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
781 | String stime; |
782 | synchronized (DAY_FORMAT) { | |
783 | stime = DAY_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
784 | } | |
0fab12b0 | 785 | return Utils.drawText(gc, stime, rect, true); |
8e1f81f1 PT |
786 | } |
787 | ||
788 | @Override | |
f1fae91f | 789 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 790 | drawAbsHeader(gc, nanosec, rect, DAY_FORMAT_HEADER); |
8e1f81f1 | 791 | } |
8e1f81f1 PT |
792 | } |
793 | ||
794 | class TimeDrawAbsHrs extends TimeDraw { | |
8e1f81f1 | 795 | @Override |
0fab12b0 | 796 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
797 | String stime; |
798 | synchronized (HOURS_FORMAT) { | |
799 | stime = HOURS_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
800 | } | |
0fab12b0 | 801 | return Utils.drawText(gc, stime, rect, true); |
8e1f81f1 PT |
802 | } |
803 | ||
804 | @Override | |
f1fae91f | 805 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 806 | drawAbsHeader(gc, nanosec, rect, HOURS_FORMAT_HEADER); |
8e1f81f1 | 807 | } |
8e1f81f1 PT |
808 | } |
809 | ||
810 | class TimeDrawAbsMin extends TimeDraw { | |
8e1f81f1 | 811 | @Override |
0fab12b0 | 812 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
813 | String stime; |
814 | synchronized (MIN_FORMAT) { | |
815 | stime = MIN_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
816 | } | |
0fab12b0 | 817 | return Utils.drawText(gc, stime, rect, true); |
8e1f81f1 PT |
818 | } |
819 | ||
820 | @Override | |
f1fae91f | 821 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 822 | drawAbsHeader(gc, nanosec, rect, MIN_FORMAT_HEADER); |
8e1f81f1 | 823 | } |
8e1f81f1 PT |
824 | } |
825 | ||
826 | class TimeDrawAbsSec extends TimeDraw { | |
8e1f81f1 | 827 | @Override |
0fab12b0 | 828 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
829 | String stime; |
830 | synchronized (SEC_FORMAT) { | |
831 | stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
832 | } | |
0fab12b0 | 833 | return Utils.drawText(gc, stime, rect, true); |
8e1f81f1 PT |
834 | } |
835 | ||
836 | @Override | |
f1fae91f | 837 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 838 | drawAbsHeader(gc, nanosec, rect, SEC_FORMAT_HEADER); |
8e1f81f1 | 839 | } |
8e1f81f1 PT |
840 | } |
841 | ||
842 | class TimeDrawAbsMillisec extends TimeDraw { | |
8e1f81f1 | 843 | @Override |
0fab12b0 | 844 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
845 | String stime; |
846 | synchronized (SEC_FORMAT) { | |
847 | stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
848 | } | |
f1fae91f | 849 | String ns = Utils.formatNs(nanosec, Resolution.MILLISEC); |
0fab12b0 | 850 | return Utils.drawText(gc, stime + "." + ns, rect, true); //$NON-NLS-1$ |
8e1f81f1 PT |
851 | } |
852 | ||
853 | @Override | |
f1fae91f | 854 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 855 | drawAbsHeader(gc, nanosec, rect, SEC_FORMAT_HEADER); |
8e1f81f1 | 856 | } |
8e1f81f1 PT |
857 | } |
858 | ||
859 | class TimeDrawAbsMicroSec extends TimeDraw { | |
8e1f81f1 | 860 | @Override |
0fab12b0 | 861 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
862 | String stime; |
863 | synchronized (SEC_FORMAT) { | |
864 | stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
865 | } | |
f1fae91f | 866 | String micr = Utils.formatNs(nanosec, Resolution.MICROSEC); |
0fab12b0 | 867 | return Utils.drawText(gc, stime + "." + micr, rect, true); //$NON-NLS-1$ |
8e1f81f1 PT |
868 | } |
869 | ||
870 | @Override | |
f1fae91f | 871 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 872 | drawAbsHeader(gc, nanosec, rect, SEC_FORMAT_HEADER); |
8e1f81f1 | 873 | } |
8e1f81f1 PT |
874 | } |
875 | ||
876 | class TimeDrawAbsNanoSec extends TimeDraw { | |
8e1f81f1 | 877 | @Override |
0fab12b0 | 878 | public int draw(GC gc, long nanosec, Rectangle rect) { |
6dcc38b9 MK |
879 | String stime; |
880 | synchronized (SEC_FORMAT) { | |
881 | stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS)); | |
882 | } | |
f1fae91f | 883 | String ns = Utils.formatNs(nanosec, Resolution.NANOSEC); |
0fab12b0 | 884 | return Utils.drawText(gc, stime + "." + ns, rect, true); //$NON-NLS-1$ |
8e1f81f1 PT |
885 | } |
886 | ||
887 | @Override | |
f1fae91f | 888 | public void drawAbsHeader(GC gc, long nanosec, Rectangle rect) { |
2b3be043 | 889 | drawAbsHeader(gc, nanosec, rect, SEC_FORMAT_HEADER); |
8e1f81f1 | 890 | } |
8e1f81f1 | 891 | } |
026664b7 | 892 | |
026664b7 | 893 | class TimeDrawNumber extends TimeDraw { |
026664b7 | 894 | @Override |
0fab12b0 | 895 | public int draw(GC gc, long time, Rectangle rect) { |
026664b7 | 896 | String stime = NumberFormat.getInstance().format(time); |
0fab12b0 PT |
897 | return Utils.drawText(gc, stime, rect, true); |
898 | } | |
899 | } | |
900 | ||
901 | class TimeDrawCycles extends TimeDraw { | |
902 | @Override | |
903 | public int draw(GC gc, long time, Rectangle rect) { | |
904 | String stime = Utils.formatTime(time, TimeFormat.CYCLES, Resolution.SECONDS); | |
905 | return Utils.drawText(gc, stime, rect, true); | |
026664b7 | 906 | } |
2b3be043 | 907 | } |