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