Commit | Line | Data |
---|---|---|
b0d3496e | 1 | /*****************************************************************************\r |
a5823d5f | 2 | * Copyright (c) 2007, 2008, 2010 Intel Corporation and others.\r |
b0d3496e ASL |
3 | * All rights reserved. This program and the accompanying materials\r |
4 | * are made available under the terms of the Eclipse Public License v1.0\r | |
5 | * which accompanies this distribution, and is available at\r | |
6 | * http://www.eclipse.org/legal/epl-v10.html\r | |
7 | *\r | |
8 | * Contributors:\r | |
9 | * Intel Corporation - Initial API and implementation\r | |
10 | * Ruslan A. Scherbakov, Intel - Initial API and implementation\r | |
11 | * Alvaro Sanchex-Leon - Udpated for TMF\r | |
12 | *\r | |
13 | * $Id: TimeScaleCtrl.java,v 1.5 2008/06/16 21:04:49 jkubasta Exp $ \r | |
14 | *****************************************************************************/\r | |
15 | \r | |
2fa130b8 | 16 | package org.eclipse.linuxtools.internal.lttng.ui.viewers.timeAnalysis.widgets;\r |
b0d3496e ASL |
17 | \r |
18 | import java.text.SimpleDateFormat;\r | |
a5823d5f | 19 | import java.util.Calendar;\r |
b0d3496e | 20 | import java.util.Date;\r |
a5823d5f | 21 | import java.util.GregorianCalendar;\r |
b0d3496e | 22 | \r |
2fa130b8 PT |
23 | import org.eclipse.linuxtools.internal.lttng.ui.viewers.timeAnalysis.Messages;\r |
24 | import org.eclipse.linuxtools.internal.lttng.ui.viewers.timeAnalysis.widgets.Utils.Resolution;\r | |
b0d3496e ASL |
25 | import org.eclipse.swt.SWT;\r |
26 | import org.eclipse.swt.events.MouseEvent;\r | |
27 | import org.eclipse.swt.events.MouseListener;\r | |
28 | import org.eclipse.swt.events.MouseMoveListener;\r | |
29 | import org.eclipse.swt.events.PaintEvent;\r | |
30 | import org.eclipse.swt.graphics.GC;\r | |
31 | import org.eclipse.swt.graphics.Point;\r | |
32 | import org.eclipse.swt.graphics.Rectangle;\r | |
33 | import org.eclipse.swt.widgets.Composite;\r | |
34 | \r | |
35 | public class TimeScaleCtrl extends TraceCtrl implements MouseListener,\r | |
36 | MouseMoveListener {\r | |
37 | \r | |
38 | public TimeScaleCtrl(Composite parent, TraceColorScheme colors) {\r | |
39 | super(parent, colors, SWT.NO_BACKGROUND | SWT.NO_FOCUS\r | |
40 | | SWT.DOUBLE_BUFFERED);\r | |
41 | addMouseListener(this);\r | |
42 | addMouseMoveListener(this);\r | |
43 | }\r | |
44 | \r | |
a5823d5f ASL |
45 | private static final long SEC_IN_NS = 1000000000;\r |
46 | private static final long MIN_IN_NS = 60 * SEC_IN_NS;\r | |
47 | private static final long HOUR_IN_NS = 60 * MIN_IN_NS;\r | |
48 | private static final long DAY_IN_NS = 24 * HOUR_IN_NS;\r | |
49 | private static final long MONTH_IN_NS = 31 * DAY_IN_NS; // upper limit\r | |
50 | private static final long YEAR_IN_NS = 366 * DAY_IN_NS; // upper limit\r | |
51 | \r | |
52 | private static final double LOG10_1 = Math.log10(1);\r | |
53 | private static final double LOG10_2 = Math.log10(2);\r | |
54 | private static final double LOG10_3 = Math.log10(3);\r | |
55 | private static final double LOG10_5 = Math.log10(5);\r | |
56 | \r | |
7ad12be3 | 57 | private static final Calendar GREGORIAN_CALENDAR = GregorianCalendar.getInstance();\r |
a5823d5f | 58 | \r |
b0d3496e ASL |
59 | private ITimeDataProvider _timeProvider;\r |
60 | private int _dragState = 0;\r | |
61 | private int _dragX0 = 0;\r | |
62 | private int _dragX = 0;\r | |
63 | private long _time0bak;\r | |
64 | private long _time1bak;\r | |
65 | private boolean _isInUpdate;\r | |
66 | private Rectangle _rect0 = new Rectangle(0, 0, 0, 0);\r | |
a5823d5f | 67 | private int _height;\r |
b0d3496e ASL |
68 | \r |
69 | public void setTimeProvider(ITimeDataProvider timeProvider) {\r | |
70 | _timeProvider = timeProvider;\r | |
71 | }\r | |
72 | \r | |
73 | private long _timeDelta;\r | |
74 | \r | |
a5823d5f ASL |
75 | @Override\r |
76 | public Point computeSize(int wHint, int hHint, boolean changed) {\r | |
77 | return super.computeSize(wHint, _height, changed);\r | |
78 | }\r | |
79 | \r | |
80 | public void setHeight(int height) {\r | |
81 | this._height = height;\r | |
82 | }\r | |
83 | \r | |
84 | private void calcTimeDelta(int width, double pixelsPerNanoSec) {\r | |
8b9fa226 | 85 | double minDelta = (double) ((pixelsPerNanoSec == 0) ? YEAR_IN_NS : width / pixelsPerNanoSec);\r |
a5823d5f ASL |
86 | long unit = 1;\r |
87 | if (_timeProvider != null && _timeProvider.isCalendarFormat()) {\r | |
88 | if (minDelta > 6 * MONTH_IN_NS) {\r | |
89 | unit = YEAR_IN_NS;\r | |
90 | } else if (minDelta > 3 * MONTH_IN_NS) {\r | |
91 | unit = 6 * MONTH_IN_NS;\r | |
92 | } else if (minDelta > 10 * DAY_IN_NS) {\r | |
93 | unit = MONTH_IN_NS;\r | |
94 | } else if (minDelta > 12 * HOUR_IN_NS) {\r | |
95 | unit = DAY_IN_NS;\r | |
96 | } else if (minDelta > 3 * HOUR_IN_NS) {\r | |
97 | unit = 6 * HOUR_IN_NS;\r | |
98 | } else if (minDelta > 30 * MIN_IN_NS) {\r | |
99 | unit = HOUR_IN_NS;\r | |
100 | } else if (minDelta > 10 * MIN_IN_NS) {\r | |
101 | unit = 15 * MIN_IN_NS;\r | |
102 | } else if (minDelta > 30 * SEC_IN_NS) {\r | |
103 | unit = MIN_IN_NS;\r | |
104 | } else if (minDelta > 20 * SEC_IN_NS) {\r | |
105 | unit = 30 * SEC_IN_NS;\r | |
ce62370f FC |
106 | } else if (minDelta <= 1) {\r |
107 | _timeDelta = 1;\r | |
108 | return;\r | |
a5823d5f ASL |
109 | }\r |
110 | }\r | |
111 | double log = Math.log10((double) minDelta / unit);\r | |
112 | long pow10 = (long) log;\r | |
113 | double remainder = log - pow10;\r | |
114 | if (remainder < LOG10_1) {\r | |
115 | _timeDelta = (long) Math.pow(10, pow10) * unit;\r | |
116 | } else if (remainder < LOG10_2) {\r | |
117 | _timeDelta = 2 * (long) Math.pow(10, pow10) * unit;\r | |
118 | } else if (remainder < LOG10_3 && unit >= HOUR_IN_NS && unit < YEAR_IN_NS) {\r | |
119 | _timeDelta = 3 * (long) Math.pow(10, pow10) * unit;\r | |
120 | } else if (remainder < LOG10_5) {\r | |
121 | _timeDelta = 5 * (long) Math.pow(10, pow10) * unit;\r | |
122 | } else {\r | |
123 | _timeDelta = 10 * (long) Math.pow(10, pow10) * unit;\r | |
124 | }\r | |
125 | }\r | |
126 | \r | |
127 | private static TimeDraw TIMEDRAW_NANOSEC = new TimeDrawNanosec();\r | |
128 | private static TimeDraw TIMEDRAW_MICROSEC = new TimeDrawMicrosec();\r | |
129 | private static TimeDraw TIMEDRAW_MILLISEC = new TimeDrawMillisec();\r | |
130 | private static TimeDraw TIMEDRAW_SEC = new TimeDrawSec();\r | |
131 | private static TimeDraw TIMEDRAW_ABS_NANOSEC = new TimeDrawAbsNanoSec();\r | |
132 | private static TimeDraw TIMEDRAW_ABS_MICROSEC = new TimeDrawAbsMicroSec();\r | |
133 | private static TimeDraw TIMEDRAW_ABS_MILLISEC = new TimeDrawAbsMillisec();\r | |
134 | private static TimeDraw TIMEDRAW_ABS_SEC = new TimeDrawAbsSec();\r | |
135 | private static TimeDraw TIMEDRAW_ABS_MIN = new TimeDrawAbsMin();\r | |
136 | private static TimeDraw TIMEDRAW_ABS_HRS = new TimeDrawAbsHrs();\r | |
137 | private static TimeDraw TIMEDRAW_ABS_DAY = new TimeDrawAbsDay();\r | |
138 | private static TimeDraw TIMEDRAW_ABS_MONTH = new TimeDrawAbsMonth();\r | |
139 | private static TimeDraw TIMEDRAW_ABS_YEAR = new TimeDrawAbsYear();\r | |
b0d3496e ASL |
140 | \r |
141 | TimeDraw getTimeDraw(long timeDelta) {\r | |
142 | TimeDraw timeDraw;\r | |
a5823d5f ASL |
143 | if (_timeProvider != null && _timeProvider.isCalendarFormat()) {\r |
144 | if (timeDelta >= YEAR_IN_NS)\r | |
145 | timeDraw = TIMEDRAW_ABS_YEAR;\r | |
146 | else if (timeDelta >= MONTH_IN_NS)\r | |
147 | timeDraw = TIMEDRAW_ABS_MONTH;\r | |
148 | else if (timeDelta >= DAY_IN_NS)\r | |
149 | timeDraw = TIMEDRAW_ABS_DAY;\r | |
150 | else if (timeDelta >= HOUR_IN_NS)\r | |
151 | timeDraw = TIMEDRAW_ABS_HRS;\r | |
152 | else if (timeDelta >= MIN_IN_NS)\r | |
153 | timeDraw = TIMEDRAW_ABS_MIN;\r | |
154 | else if (timeDelta >= SEC_IN_NS)\r | |
155 | timeDraw = TIMEDRAW_ABS_SEC;\r | |
156 | else if (timeDelta >= 1000000)\r | |
157 | timeDraw = TIMEDRAW_ABS_MILLISEC;\r | |
158 | else if (timeDelta >= 1000)\r | |
159 | timeDraw = TIMEDRAW_ABS_MICROSEC;\r | |
160 | else\r | |
161 | timeDraw = TIMEDRAW_ABS_NANOSEC;\r | |
162 | return timeDraw;\r | |
b0d3496e ASL |
163 | }\r |
164 | if (timeDelta >= 1000000000)\r | |
a5823d5f | 165 | timeDraw = TIMEDRAW_SEC;\r |
b0d3496e | 166 | else if (timeDelta >= 1000000)\r |
a5823d5f | 167 | timeDraw = TIMEDRAW_MILLISEC;\r |
b0d3496e | 168 | else if (timeDelta >= 1000)\r |
a5823d5f | 169 | timeDraw = TIMEDRAW_MICROSEC;\r |
b0d3496e | 170 | else\r |
a5823d5f | 171 | timeDraw = TIMEDRAW_NANOSEC;\r |
b0d3496e ASL |
172 | return timeDraw;\r |
173 | }\r | |
174 | \r | |
4e3aa37d | 175 | @Override\r |
b0d3496e ASL |
176 | void paint(Rectangle rect, PaintEvent e) {\r |
177 | \r | |
178 | if (_isInUpdate || null == _timeProvider)\r | |
179 | return;\r | |
180 | \r | |
181 | GC gc = e.gc;\r | |
a5823d5f ASL |
182 | gc.fillRectangle(rect);\r |
183 | \r | |
b0d3496e ASL |
184 | long time0 = _timeProvider.getTime0();\r |
185 | long time1 = _timeProvider.getTime1();\r | |
186 | long selectedTime = _timeProvider.getSelectedTime();\r | |
187 | int leftSpace = _timeProvider.getNameSpace();\r | |
188 | int timeSpace = _timeProvider.getTimeSpace();\r | |
a5823d5f ASL |
189 | \r |
190 | gc.setBackground(_colors.getColor(TraceColorScheme.TOOL_BACKGROUND));\r | |
191 | gc.setForeground(_colors.getColor(TraceColorScheme.TOOL_FOREGROUND));\r | |
b0d3496e ASL |
192 | Utils.init(_rect0, rect);\r |
193 | \r | |
194 | // draw top left area\r | |
195 | _rect0.width = leftSpace;\r | |
196 | _rect0.x += 4;\r | |
197 | _rect0.width -= 4;\r | |
198 | if (_rect0.width > 0) {\r | |
7995b722 | 199 | Utils.drawText(gc, Messages.TimeScaleCtrl_Timescale + ":", _rect0, true); //$NON-NLS-1$\r |
b0d3496e | 200 | }\r |
7995b722 | 201 | int messageWidth = gc.stringExtent(Messages.TimeScaleCtrl_Timescale + ":").x + 4; //$NON-NLS-1$\r |
a5823d5f | 202 | Rectangle absHeaderRect = new Rectangle(_rect0.x + messageWidth, _rect0.y, _rect0.width - messageWidth, _rect0.height);\r |
b0d3496e ASL |
203 | _rect0.x -= 4;\r |
204 | _rect0.width += 4;\r | |
a5823d5f | 205 | \r |
b0d3496e ASL |
206 | // prepare and draw right rect of the timescale\r |
207 | _rect0.x += leftSpace;\r | |
208 | _rect0.width = rect.width - leftSpace;\r | |
a5823d5f | 209 | \r |
b0d3496e ASL |
210 | // draw bottom border and erase all other area\r |
211 | gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width - 1,\r | |
a5823d5f | 212 | rect.y + rect.height - 1);\r |
b0d3496e ASL |
213 | _rect0.height--;\r |
214 | gc.fillRectangle(_rect0);\r | |
a5823d5f ASL |
215 | \r |
216 | if (time1 <= time0 || timeSpace < 2) {\r | |
217 | return;\r | |
218 | }\r | |
219 | \r | |
220 | int numDigits = calculateDigits(time0, time1);\r | |
221 | \r | |
222 | int labelWidth = gc.getCharWidth('0') * numDigits;\r | |
8b9fa226 ASL |
223 | double pixelsPerNanoSec = (timeSpace <= RIGHT_MARGIN) ? 0 :\r |
224 | (double) (timeSpace - RIGHT_MARGIN) / (time1 - time0);\r | |
a5823d5f ASL |
225 | calcTimeDelta(labelWidth, pixelsPerNanoSec);\r |
226 | \r | |
227 | TimeDraw timeDraw = getTimeDraw(_timeDelta);\r | |
228 | \r | |
229 | // draw zoom rectangle\r | |
230 | if (3 == _dragState && null != _timeProvider) {\r | |
231 | if (_dragX0 < _dragX) {\r | |
232 | gc.drawRectangle(leftSpace + _dragX0, rect.y, _dragX - _dragX0 - 1, rect.height - 8);\r | |
233 | } else if (_dragX0 > _dragX) {\r | |
234 | gc.drawRectangle(leftSpace + _dragX, rect.y, _dragX0 - _dragX - 1, rect.height - 8);\r | |
235 | }\r | |
236 | }\r | |
b0d3496e ASL |
237 | \r |
238 | if (_rect0.isEmpty())\r | |
239 | return;\r | |
240 | \r | |
241 | // draw selected time\r | |
a5823d5f | 242 | int x = _rect0.x + (int) ((double)(selectedTime - time0) * pixelsPerNanoSec);\r |
b0d3496e ASL |
243 | if (x >= _rect0.x && x < _rect0.x + _rect0.width) {\r |
244 | gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME));\r | |
245 | gc.drawLine(x, _rect0.y + _rect0.height - 6, x, _rect0.y\r | |
246 | + _rect0.height);\r | |
247 | gc\r | |
248 | .setForeground(_colors\r | |
249 | .getColor(TraceColorScheme.TOOL_FOREGROUND));\r | |
250 | }\r | |
251 | \r | |
252 | // draw time scale ticks\r | |
253 | _rect0.y = rect.y;\r | |
254 | _rect0.height = rect.height - 4;\r | |
255 | _rect0.width = labelWidth;\r | |
a5823d5f ASL |
256 | \r |
257 | long time;\r | |
258 | if (_timeProvider != null && _timeProvider.isCalendarFormat()) {\r | |
259 | time = floorToCalendar(time0, _timeDelta);\r | |
260 | } else {\r | |
261 | time = (long) (Math.ceil((double) time0 / _timeDelta) * _timeDelta);\r | |
262 | }\r | |
263 | \r | |
b0d3496e ASL |
264 | // long t = (long) (time * 1000000000);\r |
265 | int y = _rect0.y + _rect0.height;\r | |
a5823d5f ASL |
266 | \r |
267 | if (_timeProvider != null && _timeProvider.isCalendarFormat()) {\r | |
268 | timeDraw.drawAbsHeader(gc, time, absHeaderRect);\r | |
269 | }\r | |
270 | \r | |
b0d3496e | 271 | while (true) {\r |
a5823d5f | 272 | x = rect.x + leftSpace + (int) (Math.floor((time - time0) * pixelsPerNanoSec));\r |
b0d3496e ASL |
273 | if (x >= rect.x + leftSpace + rect.width - _rect0.width) {\r |
274 | break;\r | |
275 | }\r | |
276 | if (x >= rect.x + leftSpace) {\r | |
277 | gc.drawLine(x, y, x, y + 4);\r | |
278 | _rect0.x = x;\r | |
279 | if (x + _rect0.width <= rect.x + rect.width)\r | |
a5823d5f ASL |
280 | timeDraw.draw(gc, time, _rect0);\r |
281 | }\r | |
8fc205cb | 282 | if (pixelsPerNanoSec == 0 || time > Long.MAX_VALUE - _timeDelta || _timeDelta == 0) {\r |
a5823d5f | 283 | break;\r |
b0d3496e | 284 | }\r |
a5823d5f ASL |
285 | time += _timeDelta;\r |
286 | if (_timeProvider != null && _timeProvider.isCalendarFormat()) {\r | |
287 | if (_timeDelta >= YEAR_IN_NS) {\r | |
288 | GREGORIAN_CALENDAR.setTime(new Date(time / 1000000));\r | |
289 | GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year\r | |
290 | GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1);\r | |
291 | time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000;\r | |
292 | } else if (_timeDelta >= MONTH_IN_NS) {\r | |
293 | GREGORIAN_CALENDAR.setTime(new Date(time / 1000000));\r | |
294 | GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month\r | |
295 | time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000;\r | |
296 | }\r | |
297 | }\r | |
b0d3496e ASL |
298 | }\r |
299 | }\r | |
300 | \r | |
a5823d5f ASL |
301 | private long floorToCalendar(long time, long timeDelta) {\r |
302 | if (_timeDelta >= YEAR_IN_NS) {\r | |
303 | GREGORIAN_CALENDAR.setTime(new Date(time / 1000000));\r | |
304 | int year = GREGORIAN_CALENDAR.get(Calendar.YEAR);\r | |
305 | int yearDelta = (int) (timeDelta / YEAR_IN_NS);\r | |
306 | year = (year / yearDelta) * yearDelta;\r | |
307 | GREGORIAN_CALENDAR.set(Calendar.YEAR, year);\r | |
308 | GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year\r | |
309 | GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1);\r | |
310 | GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0);\r | |
311 | GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0);\r | |
312 | GREGORIAN_CALENDAR.set(Calendar.SECOND, 0);\r | |
313 | GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0);\r | |
314 | time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000;\r | |
315 | } else if (_timeDelta >= MONTH_IN_NS) {\r | |
316 | GREGORIAN_CALENDAR.setTime(new Date(time / 1000000));\r | |
317 | int month = GREGORIAN_CALENDAR.get(Calendar.MONTH);\r | |
318 | int monthDelta = (int) (timeDelta / MONTH_IN_NS);\r | |
319 | month = (month / monthDelta) * monthDelta;\r | |
320 | GREGORIAN_CALENDAR.set(Calendar.MONTH, month);\r | |
321 | GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month\r | |
322 | GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0);\r | |
323 | GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0);\r | |
324 | GREGORIAN_CALENDAR.set(Calendar.SECOND, 0);\r | |
325 | GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0);\r | |
326 | time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000;\r | |
327 | } else {\r | |
328 | time = (time / timeDelta) * timeDelta;\r | |
329 | }\r | |
330 | return time;\r | |
331 | }\r | |
332 | \r | |
b0d3496e ASL |
333 | private int calculateDigits(long time0, long time1) {\r |
334 | int numDigits = 5;\r | |
335 | long timeRange = time1 - time0;\r | |
336 | \r | |
337 | if (_timeProvider.isCalendarFormat()) {\r | |
338 | // Calculate the number of digits to represent the minutes provided\r | |
339 | // 11:222\r | |
340 | // HH:mm:ss\r | |
a5823d5f | 341 | numDigits += 8;\r |
b0d3496e ASL |
342 | if (timeRange < 10000) {\r |
343 | // HH:11:222:333:444__\r | |
344 | numDigits += 10;\r | |
345 | } else if (timeRange < 10000000) {\r | |
346 | // HH:11:222:333__\r | |
347 | numDigits += 6;\r | |
348 | }\r | |
349 | } else {\r | |
350 | // Calculate the number of digits to represent the minutes provided\r | |
351 | long min = (long) ((time1 * 1E-9) / 60); // to sec then to minutes\r | |
352 | String strMinutes = String.valueOf(min);\r | |
353 | // 11:222\r | |
354 | if (strMinutes != null) {\r | |
355 | numDigits += strMinutes.length();\r | |
356 | } else {\r | |
357 | numDigits += 2;\r | |
358 | }\r | |
359 | if (timeRange < 10000) {\r | |
360 | // 11:222:333:444__\r | |
361 | numDigits += 8;\r | |
362 | } else if (timeRange < 10000000) {\r | |
363 | // 11:222:333__\r | |
364 | numDigits += 4;\r | |
365 | }\r | |
366 | }\r | |
367 | \r | |
368 | // Trace.debug("timeRange: " + timeRange + " numDigits: " + numDigits);\r | |
369 | return numDigits;\r | |
370 | }\r | |
371 | \r | |
d4011df2 | 372 | @Override\r |
b0d3496e | 373 | public void mouseDown(MouseEvent e) {\r |
a5823d5f ASL |
374 | if (_dragState == 0 && null != _timeProvider) {\r |
375 | if (1 == e.button) {\r | |
376 | setCapture(true);\r | |
377 | _dragState = 1;\r | |
378 | } else if (3 == e.button) {\r | |
379 | _dragState = 3;\r | |
380 | }\r | |
381 | int x = e.x - _timeProvider.getNameSpace();\r | |
382 | if (x < 0) {\r | |
383 | x = 0;\r | |
384 | } else if (x > getSize().x - _timeProvider.getNameSpace()) {\r | |
385 | x = getSize().x - _timeProvider.getNameSpace();\r | |
386 | }\r | |
387 | _dragX = _dragX0 = x;\r | |
388 | _time0bak = _timeProvider.getTime0();\r | |
389 | _time1bak = _timeProvider.getTime1();\r | |
390 | }\r | |
b0d3496e ASL |
391 | }\r |
392 | \r | |
d4011df2 | 393 | @Override\r |
b0d3496e | 394 | public void mouseUp(MouseEvent e) {\r |
a5823d5f | 395 | if (e.button == 1 && _dragState == 1) {\r |
b0d3496e ASL |
396 | setCapture(false);\r |
397 | _dragState = 0;\r | |
8b9fa226 ASL |
398 | \r |
399 | // Notify time provider to check the need for listener notification\r | |
400 | if (_dragX != _dragX0) {\r | |
401 | _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1());\r | |
402 | }\r | |
a5823d5f ASL |
403 | } else if (e.button == 3 && _dragState == 3 && null != _timeProvider) {\r |
404 | _dragState = 0;\r | |
405 | if (_dragX0 == _dragX) {\r | |
b0d3496e ASL |
406 | return;\r |
407 | }\r | |
a5823d5f | 408 | int timeSpace = _timeProvider.getTimeSpace();\r |
b0d3496e ASL |
409 | int leftSpace = _timeProvider.getNameSpace();\r |
410 | int x = e.x - leftSpace;\r | |
a5823d5f | 411 | if (timeSpace > 0) {\r |
b0d3496e | 412 | _dragX = x;\r |
a5823d5f ASL |
413 | if (_dragX0 > _dragX) { // drag right to left\r |
414 | _dragX = _dragX0;\r | |
415 | _dragX0 = x;\r | |
416 | }\r | |
417 | long time0 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX0 / timeSpace));\r | |
418 | long time1 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX / timeSpace));\r | |
79a3a76e | 419 | \r |
8b9fa226 | 420 | _timeProvider.setStartFinishTimeNotify(time0, time1);\r |
a5823d5f ASL |
421 | _time0bak = _timeProvider.getTime0();\r |
422 | _time1bak = _timeProvider.getTime1();\r | |
b0d3496e ASL |
423 | }\r |
424 | }\r | |
425 | }\r | |
426 | \r | |
d4011df2 | 427 | @Override\r |
b0d3496e | 428 | public void mouseMove(MouseEvent e) {\r |
f9a8715c | 429 | if (_dragX0 < 0 || _dragState == 0 || _timeProvider == null) {\r |
b0d3496e ASL |
430 | return;\r |
431 | }\r | |
432 | Point size = getSize();\r | |
a5823d5f ASL |
433 | int leftSpace = _timeProvider.getNameSpace();\r |
434 | int timeSpace = _timeProvider.getTimeSpace();\r | |
435 | int x = e.x - leftSpace;\r | |
f9a8715c | 436 | if (1 == _dragState) {\r |
b0d3496e ASL |
437 | if (x > 0 && size.x > leftSpace && _dragX != x) {\r |
438 | _dragX = x;\r | |
a5823d5f | 439 | long time1 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX0 / _dragX));\r |
b0d3496e ASL |
440 | _timeProvider.setStartFinishTime(_time0bak, time1);\r |
441 | }\r | |
f9a8715c | 442 | } else if (3 == _dragState) {\r |
a5823d5f ASL |
443 | if (x < 0) {\r |
444 | _dragX = 0;\r | |
445 | } else if (x > timeSpace) {\r | |
446 | _dragX = timeSpace;\r | |
447 | } else {\r | |
448 | _dragX = x;\r | |
449 | }\r | |
450 | redraw();\r | |
b0d3496e ASL |
451 | }\r |
452 | }\r | |
453 | \r | |
d4011df2 | 454 | @Override\r |
b0d3496e ASL |
455 | public void mouseDoubleClick(MouseEvent e) {\r |
456 | if (null != _timeProvider) {\r | |
457 | _timeProvider.resetStartFinishTime();\r | |
a5823d5f ASL |
458 | _time0bak = _timeProvider.getTime0();\r |
459 | _time1bak = _timeProvider.getTime1();\r | |
b0d3496e ASL |
460 | }\r |
461 | }\r | |
462 | }\r | |
463 | \r | |
464 | abstract class TimeDraw {\r | |
3b38ea61 FC |
465 | static String S = ":" ; //$NON-NLS-1$\r |
466 | static String S0 = ":0" ; //$NON-NLS-1$\r | |
467 | static String S00 = ":00"; //$NON-NLS-1$\r | |
468 | protected static final SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$\r | |
469 | protected static final SimpleDateFormat stimeformatheader = new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$\r | |
470 | protected static final SimpleDateFormat sminformat = new SimpleDateFormat("HH:mm"); //$NON-NLS-1$\r | |
471 | protected static final SimpleDateFormat sminformatheader = new SimpleDateFormat("yyyy MMM dd"); //$NON-NLS-1$\r | |
472 | protected static final SimpleDateFormat shrsformat = new SimpleDateFormat("MMM dd HH:mm"); //$NON-NLS-1$\r | |
473 | protected static final SimpleDateFormat shrsformatheader = new SimpleDateFormat("yyyy"); //$NON-NLS-1$\r | |
474 | protected static final SimpleDateFormat sdayformat = new SimpleDateFormat("MMM dd"); //$NON-NLS-1$\r | |
475 | protected static final SimpleDateFormat sdayformatheader = new SimpleDateFormat("yyyy"); //$NON-NLS-1$\r | |
476 | protected static final SimpleDateFormat smonthformat = new SimpleDateFormat("yyyy MMM"); //$NON-NLS-1$\r | |
477 | protected static final SimpleDateFormat syearformat = new SimpleDateFormat("yyyy"); //$NON-NLS-1$\r | |
b0d3496e ASL |
478 | \r |
479 | static String pad(long n) {\r | |
480 | String s = S;\r | |
481 | if (n < 10)\r | |
482 | s = S00;\r | |
483 | else if (n < 100)\r | |
484 | s = S0;\r | |
485 | return s + n;\r | |
486 | }\r | |
487 | \r | |
a5823d5f | 488 | public abstract void draw(GC gc, long time, Rectangle rect);\r |
b0d3496e | 489 | \r |
a5823d5f ASL |
490 | public void drawAbsHeader(GC gc, long time, Rectangle absHeaderRect) {\r |
491 | // Override to draw absolute time header\r | |
492 | // This is for the time information not shown in the draw of each tick\r | |
493 | }\r | |
494 | \r | |
b0d3496e ASL |
495 | public abstract String hint();\r |
496 | }\r | |
497 | \r | |
498 | class TimeDrawSec extends TimeDraw {\r | |
3b38ea61 | 499 | static String _hint = "sec"; //$NON-NLS-1$\r |
b0d3496e | 500 | \r |
4e3aa37d | 501 | @Override\r |
b0d3496e ASL |
502 | public void draw(GC gc, long time, Rectangle rect) {\r |
503 | time /= 1000000000;\r | |
3b38ea61 | 504 | Utils.drawText(gc, time + "", rect, true); //$NON-NLS-1$\r |
b0d3496e ASL |
505 | }\r |
506 | \r | |
4e3aa37d | 507 | @Override\r |
b0d3496e ASL |
508 | public String hint() {\r |
509 | return _hint;\r | |
510 | }\r | |
511 | }\r | |
512 | \r | |
513 | class TimeDrawMillisec extends TimeDraw {\r | |
3b38ea61 | 514 | static String _hint = "s:ms"; //$NON-NLS-1$\r |
b0d3496e | 515 | \r |
4e3aa37d | 516 | @Override\r |
b0d3496e ASL |
517 | public void draw(GC gc, long time, Rectangle rect) {\r |
518 | time /= 1000000;\r | |
519 | long ms = time % 1000;\r | |
520 | time /= 1000;\r | |
521 | Utils.drawText(gc, time + pad(ms), rect, true);\r | |
522 | }\r | |
523 | \r | |
4e3aa37d | 524 | @Override\r |
b0d3496e ASL |
525 | public String hint() {\r |
526 | return _hint;\r | |
527 | }\r | |
528 | }\r | |
529 | \r | |
530 | class TimeDrawMicrosec extends TimeDraw {\r | |
3b38ea61 | 531 | static String _hint = "s:ms:mcs"; //$NON-NLS-1$\r |
b0d3496e | 532 | \r |
4e3aa37d | 533 | @Override\r |
b0d3496e ASL |
534 | public void draw(GC gc, long time, Rectangle rect) {\r |
535 | time /= 1000;\r | |
536 | long mcs = time % 1000;\r | |
537 | time /= 1000;\r | |
538 | long ms = time % 1000;\r | |
539 | time /= 1000;\r | |
540 | Utils.drawText(gc, time + pad(ms) + pad(mcs), rect, true);\r | |
541 | }\r | |
542 | \r | |
4e3aa37d | 543 | @Override\r |
b0d3496e ASL |
544 | public String hint() {\r |
545 | return _hint;\r | |
546 | }\r | |
547 | }\r | |
548 | \r | |
549 | class TimeDrawNanosec extends TimeDraw {\r | |
3b38ea61 | 550 | static String _hint = "s:ms:mcs:ns"; //$NON-NLS-1$\r |
b0d3496e | 551 | \r |
4e3aa37d | 552 | @Override\r |
b0d3496e ASL |
553 | public void draw(GC gc, long time, Rectangle rect) {\r |
554 | long ns = time % 1000;\r | |
555 | time /= 1000;\r | |
556 | long mcs = time % 1000;\r | |
557 | time /= 1000;\r | |
558 | long ms = time % 1000;\r | |
559 | time /= 1000;\r | |
560 | Utils.drawText(gc, time + pad(ms) + pad(mcs) + pad(ns), rect, true);\r | |
561 | }\r | |
562 | \r | |
4e3aa37d | 563 | @Override\r |
b0d3496e ASL |
564 | public String hint() {\r |
565 | return _hint;\r | |
566 | }\r | |
567 | }\r | |
568 | \r | |
a5823d5f | 569 | class TimeDrawAbsYear extends TimeDraw {\r |
3b38ea61 | 570 | static String _hint = "YYYY"; //$NON-NLS-1$\r |
b0d3496e | 571 | \r |
a5823d5f ASL |
572 | @Override\r |
573 | public void draw(GC gc, long time, Rectangle rect) {\r | |
574 | String stime = syearformat.format(new Date((long) (time / 1000000)));\r | |
575 | Utils.drawText(gc, stime, rect, true);\r | |
576 | }\r | |
b0d3496e | 577 | \r |
a5823d5f ASL |
578 | @Override\r |
579 | public String hint() {\r | |
580 | return _hint;\r | |
581 | }\r | |
582 | }\r | |
583 | \r | |
584 | class TimeDrawAbsMonth extends TimeDraw {\r | |
3b38ea61 | 585 | static String _hint = "YYYY Mmm"; //$NON-NLS-1$\r |
a5823d5f ASL |
586 | \r |
587 | @Override\r | |
588 | public void draw(GC gc, long time, Rectangle rect) {\r | |
589 | String stime = smonthformat.format(new Date((long) (time / 1000000)));\r | |
590 | Utils.drawText(gc, stime, rect, true);\r | |
591 | }\r | |
592 | \r | |
593 | @Override\r | |
594 | public String hint() {\r | |
595 | return _hint;\r | |
596 | }\r | |
597 | }\r | |
598 | \r | |
599 | class TimeDrawAbsDay extends TimeDraw {\r | |
3b38ea61 | 600 | static String _hint = "Mmm dd"; //$NON-NLS-1$\r |
a5823d5f ASL |
601 | \r |
602 | @Override\r | |
603 | public void draw(GC gc, long time, Rectangle rect) {\r | |
604 | String stime = sdayformat.format(new Date((long) (time / 1000000)));\r | |
605 | Utils.drawText(gc, stime, rect, true);\r | |
606 | }\r | |
607 | \r | |
608 | @Override\r | |
609 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
610 | String header = sdayformatheader.format(new Date((long) (time / 1000000)));\r | |
611 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
612 | if (headerwidth <= rect.width) {\r | |
613 | rect.x += (rect.width - headerwidth);\r | |
614 | Utils.drawText(gc, header, rect, true);\r | |
615 | }\r | |
616 | }\r | |
617 | \r | |
618 | @Override\r | |
619 | public String hint() {\r | |
620 | return _hint;\r | |
621 | }\r | |
622 | }\r | |
623 | \r | |
624 | class TimeDrawAbsHrs extends TimeDraw {\r | |
3b38ea61 | 625 | static String _hint = "Mmm dd HH:mm"; //$NON-NLS-1$\r |
a5823d5f ASL |
626 | \r |
627 | @Override\r | |
628 | public void draw(GC gc, long time, Rectangle rect) {\r | |
629 | String stime = shrsformat.format(new Date((long) (time / 1000000)));\r | |
630 | Utils.drawText(gc, stime, rect, true);\r | |
631 | }\r | |
632 | \r | |
633 | @Override\r | |
634 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
635 | String header = shrsformatheader.format(new Date((long) (time / 1000000)));\r | |
636 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
637 | if (headerwidth <= rect.width) {\r | |
638 | rect.x += (rect.width - headerwidth);\r | |
639 | Utils.drawText(gc, header, rect, true);\r | |
640 | }\r | |
641 | }\r | |
642 | \r | |
643 | @Override\r | |
644 | public String hint() {\r | |
645 | return _hint;\r | |
646 | }\r | |
647 | }\r | |
648 | \r | |
649 | class TimeDrawAbsMin extends TimeDraw {\r | |
3b38ea61 | 650 | static String _hint = "HH:mm"; //$NON-NLS-1$\r |
a5823d5f ASL |
651 | \r |
652 | @Override\r | |
653 | public void draw(GC gc, long time, Rectangle rect) {\r | |
654 | String stime = sminformat.format(new Date((long) (time / 1000000)));\r | |
655 | Utils.drawText(gc, stime, rect, true);\r | |
656 | }\r | |
657 | \r | |
658 | @Override\r | |
659 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
660 | String header = sminformatheader.format(new Date((long) (time / 1000000)));\r | |
661 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
662 | if (headerwidth <= rect.width) {\r | |
663 | rect.x += (rect.width - headerwidth);\r | |
664 | Utils.drawText(gc, header, rect, true);\r | |
665 | }\r | |
666 | }\r | |
667 | \r | |
668 | \r | |
669 | @Override\r | |
670 | public String hint() {\r | |
671 | return _hint;\r | |
672 | }\r | |
673 | }\r | |
674 | \r | |
675 | class TimeDrawAbsSec extends TimeDraw {\r | |
3b38ea61 | 676 | static String _hint = "HH:mm:ss"; //$NON-NLS-1$\r |
a5823d5f ASL |
677 | \r |
678 | @Override\r | |
679 | public void draw(GC gc, long time, Rectangle rect) {\r | |
680 | String stime = stimeformat.format(new Date((long) (time / 1000000)));\r | |
681 | Utils.drawText(gc, stime, rect, true);\r | |
682 | }\r | |
683 | \r | |
684 | @Override\r | |
685 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
686 | String header = stimeformatheader.format(new Date((long) (time / 1000000)));\r | |
687 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
688 | if (headerwidth <= rect.width) {\r | |
689 | rect.x += (rect.width - headerwidth);\r | |
690 | Utils.drawText(gc, header, rect, true);\r | |
691 | }\r | |
692 | }\r | |
693 | \r | |
694 | @Override\r | |
695 | public String hint() {\r | |
696 | return _hint;\r | |
697 | }\r | |
b0d3496e ASL |
698 | }\r |
699 | \r | |
700 | class TimeDrawAbsMillisec extends TimeDraw {\r | |
3b38ea61 | 701 | static String _hint = "HH:ss:ms"; //$NON-NLS-1$\r |
b0d3496e | 702 | \r |
4e3aa37d | 703 | @Override\r |
b0d3496e | 704 | public void draw(GC gc, long time, Rectangle rect) {\r |
a5823d5f | 705 | String stime = stimeformat.format(new Date((long) (time / 1000000)));\r |
b0d3496e ASL |
706 | String ns = Utils.formatNs(time, Resolution.MILLISEC);\r |
707 | \r | |
3b38ea61 | 708 | Utils.drawText(gc, stime + " " + ns, rect, true); //$NON-NLS-1$\r |
b0d3496e ASL |
709 | }\r |
710 | \r | |
a5823d5f ASL |
711 | @Override\r |
712 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
713 | String header = stimeformatheader.format(new Date((long) (time / 1000000)));\r | |
714 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
715 | if (headerwidth <= rect.width) {\r | |
716 | rect.x += (rect.width - headerwidth);\r | |
717 | Utils.drawText(gc, header, rect, true);\r | |
718 | }\r | |
719 | }\r | |
720 | \r | |
4e3aa37d | 721 | @Override\r |
b0d3496e ASL |
722 | public String hint() {\r |
723 | return _hint;\r | |
724 | }\r | |
725 | }\r | |
726 | \r | |
727 | class TimeDrawAbsMicroSec extends TimeDraw {\r | |
3b38ea61 | 728 | static String _hint = "HH:ss:ms:mcs"; //$NON-NLS-1$\r |
b0d3496e | 729 | \r |
4e3aa37d | 730 | @Override\r |
b0d3496e | 731 | public void draw(GC gc, long time, Rectangle rect) {\r |
a5823d5f | 732 | String stime = stimeformat.format(new Date((long) (time / 1000000)));\r |
b0d3496e | 733 | String micr = Utils.formatNs(time, Resolution.MICROSEC);\r |
3b38ea61 | 734 | Utils.drawText(gc, stime + " " + micr, rect, true); //$NON-NLS-1$\r |
b0d3496e ASL |
735 | }\r |
736 | \r | |
a5823d5f ASL |
737 | @Override\r |
738 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
739 | String header = stimeformatheader.format(new Date((long) (time / 1000000)));\r | |
740 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
741 | if (headerwidth <= rect.width) {\r | |
742 | rect.x += (rect.width - headerwidth);\r | |
743 | Utils.drawText(gc, header, rect, true);\r | |
744 | }\r | |
745 | }\r | |
746 | \r | |
4e3aa37d | 747 | @Override\r |
b0d3496e ASL |
748 | public String hint() {\r |
749 | return _hint;\r | |
750 | }\r | |
751 | }\r | |
752 | \r | |
753 | class TimeDrawAbsNanoSec extends TimeDraw {\r | |
3b38ea61 | 754 | static String _hint = "HH:ss:ms:mcs:ns"; //$NON-NLS-1$\r |
b0d3496e | 755 | \r |
4e3aa37d | 756 | @Override\r |
b0d3496e | 757 | public void draw(GC gc, long time, Rectangle rect) {\r |
a5823d5f | 758 | String stime = stimeformat.format(new Date((long) (time / 1000000)));\r |
b0d3496e | 759 | String ns = Utils.formatNs(time, Resolution.NANOSEC);\r |
3b38ea61 | 760 | Utils.drawText(gc, stime + " " + ns, rect, true); //$NON-NLS-1$\r |
b0d3496e ASL |
761 | }\r |
762 | \r | |
a5823d5f ASL |
763 | @Override\r |
764 | public void drawAbsHeader(GC gc, long time, Rectangle rect) {\r | |
765 | String header = stimeformatheader.format(new Date((long) (time / 1000000)));\r | |
766 | int headerwidth = gc.stringExtent(header).x + 4;\r | |
767 | if (headerwidth <= rect.width) {\r | |
768 | rect.x += (rect.width - headerwidth);\r | |
769 | Utils.drawText(gc, header, rect, true);\r | |
770 | }\r | |
771 | }\r | |
772 | \r | |
4e3aa37d | 773 | @Override\r |
b0d3496e ASL |
774 | public String hint() {\r |
775 | return _hint;\r | |
776 | }\r | |
777 | }\r |