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