Commit | Line | Data |
---|---|---|
b0d3496e | 1 | /*****************************************************************************\r |
79a3a76e | 2 | * Copyright (c) 2007, 2008 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 | |
16 | package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets;\r | |
17 | \r | |
18 | import java.text.SimpleDateFormat;\r | |
b0d3496e | 19 | import java.util.Date;\r |
b0d3496e ASL |
20 | \r |
21 | import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages;\r | |
22 | import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.Utils.Resolution;\r | |
23 | import org.eclipse.swt.SWT;\r | |
24 | import org.eclipse.swt.events.MouseEvent;\r | |
25 | import org.eclipse.swt.events.MouseListener;\r | |
26 | import org.eclipse.swt.events.MouseMoveListener;\r | |
27 | import org.eclipse.swt.events.PaintEvent;\r | |
28 | import org.eclipse.swt.graphics.GC;\r | |
29 | import org.eclipse.swt.graphics.Point;\r | |
30 | import org.eclipse.swt.graphics.Rectangle;\r | |
31 | import org.eclipse.swt.widgets.Composite;\r | |
32 | \r | |
33 | public class TimeScaleCtrl extends TraceCtrl implements MouseListener,\r | |
34 | MouseMoveListener {\r | |
35 | \r | |
36 | public TimeScaleCtrl(Composite parent, TraceColorScheme colors) {\r | |
37 | super(parent, colors, SWT.NO_BACKGROUND | SWT.NO_FOCUS\r | |
38 | | SWT.DOUBLE_BUFFERED);\r | |
39 | addMouseListener(this);\r | |
40 | addMouseMoveListener(this);\r | |
41 | }\r | |
42 | \r | |
b0d3496e ASL |
43 | private ITimeDataProvider _timeProvider;\r |
44 | private int _dragState = 0;\r | |
45 | private int _dragX0 = 0;\r | |
46 | private int _dragX = 0;\r | |
47 | private long _time0bak;\r | |
48 | private long _time1bak;\r | |
49 | private boolean _isInUpdate;\r | |
50 | private Rectangle _rect0 = new Rectangle(0, 0, 0, 0);\r | |
b0d3496e ASL |
51 | \r |
52 | public void setTimeProvider(ITimeDataProvider timeProvider) {\r | |
53 | _timeProvider = timeProvider;\r | |
54 | }\r | |
55 | \r | |
79a3a76e | 56 | private double _timeDeltaD;\r |
b0d3496e ASL |
57 | private long _timeDelta;\r |
58 | \r | |
79a3a76e FC |
59 | private void calcTimeDelta(int width, double K) {\r |
60 | long D[] = { 1, 2, 5, };\r | |
61 | long pow = 1;\r | |
62 | double powD = 1;\r | |
63 | long td = pow;\r | |
64 | double tdD = powD;\r | |
65 | double dx = tdD * K;\r | |
66 | int i = 0;\r | |
67 | while (dx < width) {\r | |
68 | td = D[i] * pow;\r | |
69 | tdD = D[i] * powD;\r | |
70 | dx = tdD * K;\r | |
71 | i++;\r | |
72 | if (i == 3) {\r | |
73 | i = 0;\r | |
74 | pow *= 10;\r | |
75 | powD *= 10;\r | |
76 | }\r | |
77 | }\r | |
78 | _timeDeltaD = tdD;\r | |
79 | _timeDelta = td;\r | |
80 | // Trace.debug("Width: " + width + " K: " + K + " Time Delta: "\r | |
81 | // + _timeDelta);\r | |
82 | }\r | |
83 | \r | |
84 | static private TimeDraw _tds[] = new TimeDraw[] { new TimeDrawSec(),\r | |
85 | new TimeDrawMillisec(), new TimeDrawMicrosec(),\r | |
86 | new TimeDrawNanosec(), new TimeDrawAbsSec(),\r | |
87 | new TimeDrawAbsMillisec(), new TimeDrawAbsMicroSec(),\r | |
88 | new TimeDrawAbsNanoSec() };\r | |
b0d3496e ASL |
89 | \r |
90 | TimeDraw getTimeDraw(long timeDelta) {\r | |
91 | TimeDraw timeDraw;\r | |
79a3a76e FC |
92 | if (_timeProvider != null) {\r |
93 | if (_timeProvider.isCalendarFormat()) {\r | |
94 | if (timeDelta >= 1000000000)\r | |
95 | timeDraw = _tds[4];\r | |
96 | else if (timeDelta >= 1000000)\r | |
97 | timeDraw = _tds[5];\r | |
98 | else if (timeDelta >= 1000)\r | |
99 | timeDraw = _tds[6];\r | |
100 | else\r | |
101 | timeDraw = _tds[7];\r | |
102 | return timeDraw;\r | |
103 | }\r | |
b0d3496e ASL |
104 | }\r |
105 | if (timeDelta >= 1000000000)\r | |
79a3a76e | 106 | timeDraw = _tds[0];\r |
b0d3496e | 107 | else if (timeDelta >= 1000000)\r |
79a3a76e | 108 | timeDraw = _tds[1];\r |
b0d3496e | 109 | else if (timeDelta >= 1000)\r |
79a3a76e | 110 | timeDraw = _tds[2];\r |
b0d3496e | 111 | else\r |
79a3a76e | 112 | timeDraw = _tds[3];\r |
b0d3496e ASL |
113 | return timeDraw;\r |
114 | }\r | |
115 | \r | |
b0d3496e ASL |
116 | void paint(Rectangle rect, PaintEvent e) {\r |
117 | \r | |
118 | if (_isInUpdate || null == _timeProvider)\r | |
119 | return;\r | |
120 | \r | |
121 | GC gc = e.gc;\r | |
b0d3496e | 122 | if (null == _timeProvider) {\r |
79a3a76e | 123 | gc.fillRectangle(rect);\r |
b0d3496e ASL |
124 | return;\r |
125 | }\r | |
126 | \r | |
79a3a76e FC |
127 | gc.setBackground(_colors.getColor(TraceColorScheme.TOOL_BACKGROUND));\r |
128 | gc.setForeground(_colors.getColor(TraceColorScheme.TOOL_FOREGROUND));\r | |
b0d3496e ASL |
129 | long time0 = _timeProvider.getTime0();\r |
130 | long time1 = _timeProvider.getTime1();\r | |
131 | long selectedTime = _timeProvider.getSelectedTime();\r | |
132 | int leftSpace = _timeProvider.getNameSpace();\r | |
133 | int timeSpace = _timeProvider.getTimeSpace();\r | |
79a3a76e FC |
134 | \r |
135 | if (time1 <= time0 || timeSpace < 2) {\r | |
136 | gc.fillRectangle(rect);\r | |
137 | return;\r | |
138 | }\r | |
139 | \r | |
140 | int numDigits = calculateDigits(time0, time1);\r | |
141 | \r | |
b0d3496e | 142 | Utils.init(_rect0, rect);\r |
79a3a76e FC |
143 | int labelWidth = gc.getCharWidth('0') * numDigits;\r |
144 | double K = 1;\r | |
145 | if (rect.width - leftSpace > 0) {\r | |
146 | K = (double) timeSpace / (time1 - time0);\r | |
147 | calcTimeDelta(labelWidth, K);\r | |
148 | }\r | |
b0d3496e | 149 | \r |
79a3a76e FC |
150 | TimeDraw timeDraw = getTimeDraw(_timeDelta);\r |
151 | \r | |
b0d3496e ASL |
152 | // draw top left area\r |
153 | _rect0.width = leftSpace;\r | |
79a3a76e | 154 | gc.fillRectangle(_rect0);\r |
b0d3496e ASL |
155 | _rect0.x += 4;\r |
156 | _rect0.width -= 4;\r | |
157 | if (_rect0.width > 0) {\r | |
79a3a76e FC |
158 | // TODO: Check if we really need that piece of code... \r |
159 | // if (false && rect.width - leftSpace > 0)\r | |
160 | // Utils.drawText(gc, Messages._Timescale + ": "\r | |
161 | // + timeDraw.hint(), _rect0, true);\r | |
162 | // else\r | |
163 | Utils.drawText(gc, Messages._Timescale + ":", _rect0, true);\r | |
b0d3496e | 164 | }\r |
b0d3496e ASL |
165 | _rect0.x -= 4;\r |
166 | _rect0.width += 4;\r | |
79a3a76e | 167 | \r |
b0d3496e ASL |
168 | // prepare and draw right rect of the timescale\r |
169 | _rect0.x += leftSpace;\r | |
170 | _rect0.width = rect.width - leftSpace;\r | |
79a3a76e | 171 | \r |
b0d3496e ASL |
172 | // draw bottom border and erase all other area\r |
173 | gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width - 1,\r | |
79a3a76e | 174 | rect.y + rect.height - 1);\r |
b0d3496e ASL |
175 | _rect0.height--;\r |
176 | gc.fillRectangle(_rect0);\r | |
b0d3496e ASL |
177 | \r |
178 | if (_rect0.isEmpty())\r | |
179 | return;\r | |
180 | \r | |
181 | // draw selected time\r | |
79a3a76e | 182 | int x = _rect0.x + (int) ((selectedTime - time0) * K);\r |
b0d3496e ASL |
183 | if (x >= _rect0.x && x < _rect0.x + _rect0.width) {\r |
184 | gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME));\r | |
185 | gc.drawLine(x, _rect0.y + _rect0.height - 6, x, _rect0.y\r | |
186 | + _rect0.height);\r | |
187 | gc\r | |
188 | .setForeground(_colors\r | |
189 | .getColor(TraceColorScheme.TOOL_FOREGROUND));\r | |
190 | }\r | |
191 | \r | |
192 | // draw time scale ticks\r | |
193 | _rect0.y = rect.y;\r | |
194 | _rect0.height = rect.height - 4;\r | |
195 | _rect0.width = labelWidth;\r | |
79a3a76e | 196 | long time = (long) (Math.floor(time0 / _timeDeltaD) * _timeDeltaD);\r |
b0d3496e | 197 | // long t = (long) (time * 1000000000);\r |
79a3a76e | 198 | long t = time;\r |
b0d3496e | 199 | int y = _rect0.y + _rect0.height;\r |
b0d3496e | 200 | while (true) {\r |
79a3a76e | 201 | x = rect.x + leftSpace + (int) ((time - time0) * K);\r |
b0d3496e ASL |
202 | if (x >= rect.x + leftSpace + rect.width - _rect0.width) {\r |
203 | break;\r | |
204 | }\r | |
205 | if (x >= rect.x + leftSpace) {\r | |
206 | gc.drawLine(x, y, x, y + 4);\r | |
207 | _rect0.x = x;\r | |
208 | if (x + _rect0.width <= rect.x + rect.width)\r | |
79a3a76e | 209 | timeDraw.draw(gc, t, _rect0);\r |
b0d3496e | 210 | }\r |
79a3a76e FC |
211 | time += _timeDeltaD;\r |
212 | t += _timeDelta;\r | |
b0d3496e ASL |
213 | }\r |
214 | }\r | |
215 | \r | |
b0d3496e ASL |
216 | private int calculateDigits(long time0, long time1) {\r |
217 | int numDigits = 5;\r | |
218 | long timeRange = time1 - time0;\r | |
219 | \r | |
220 | if (_timeProvider.isCalendarFormat()) {\r | |
221 | // Calculate the number of digits to represent the minutes provided\r | |
222 | // 11:222\r | |
223 | // HH:mm:ss\r | |
79a3a76e | 224 | numDigits += 5;\r |
b0d3496e ASL |
225 | if (timeRange < 10000) {\r |
226 | // HH:11:222:333:444__\r | |
227 | numDigits += 10;\r | |
228 | } else if (timeRange < 10000000) {\r | |
229 | // HH:11:222:333__\r | |
230 | numDigits += 6;\r | |
231 | }\r | |
232 | } else {\r | |
233 | // Calculate the number of digits to represent the minutes provided\r | |
234 | long min = (long) ((time1 * 1E-9) / 60); // to sec then to minutes\r | |
235 | String strMinutes = String.valueOf(min);\r | |
236 | // 11:222\r | |
237 | if (strMinutes != null) {\r | |
238 | numDigits += strMinutes.length();\r | |
239 | } else {\r | |
240 | numDigits += 2;\r | |
241 | }\r | |
242 | if (timeRange < 10000) {\r | |
243 | // 11:222:333:444__\r | |
244 | numDigits += 8;\r | |
245 | } else if (timeRange < 10000000) {\r | |
246 | // 11:222:333__\r | |
247 | numDigits += 4;\r | |
248 | }\r | |
249 | }\r | |
250 | \r | |
251 | // Trace.debug("timeRange: " + timeRange + " numDigits: " + numDigits);\r | |
252 | return numDigits;\r | |
253 | }\r | |
254 | \r | |
255 | public void mouseDown(MouseEvent e) {\r | |
79a3a76e FC |
256 | if (1 == e.button && null != _timeProvider) {\r |
257 | setCapture(true);\r | |
258 | _dragState = 1;\r | |
259 | }\r | |
260 | // Window adjustment allowed using mouse button three.\r | |
261 | _dragX = _dragX0 = e.x - _timeProvider.getNameSpace();\r | |
262 | _time0bak = _timeProvider.getTime0();\r | |
263 | _time1bak = _timeProvider.getTime1();\r | |
b0d3496e ASL |
264 | }\r |
265 | \r | |
266 | public void mouseUp(MouseEvent e) {\r | |
79a3a76e | 267 | if (1 == _dragState) {\r |
b0d3496e ASL |
268 | setCapture(false);\r |
269 | _dragState = 0;\r | |
79a3a76e FC |
270 | }\r |
271 | \r | |
272 | if (3 == e.button && null != _timeProvider) {\r | |
273 | if (_dragX0 < 0) {\r | |
b0d3496e ASL |
274 | return;\r |
275 | }\r | |
79a3a76e FC |
276 | Point size = getSize();\r |
277 | \r | |
b0d3496e ASL |
278 | int leftSpace = _timeProvider.getNameSpace();\r |
279 | int x = e.x - leftSpace;\r | |
79a3a76e | 280 | if (x > 0 && size.x > leftSpace && _dragX != x) {\r |
b0d3496e | 281 | _dragX = x;\r |
79a3a76e FC |
282 | long time0 = _time0bak + ((_time1bak - _time0bak) * _dragX0)\r |
283 | / (size.x - leftSpace);\r | |
284 | long time1 = _time0bak + ((_time1bak - _time0bak) * _dragX)\r | |
285 | / (size.x - leftSpace);\r | |
286 | \r | |
287 | _timeProvider.setStartFinishTime(time0, time1);\r | |
b0d3496e ASL |
288 | }\r |
289 | }\r | |
290 | }\r | |
291 | \r | |
292 | public void mouseMove(MouseEvent e) {\r | |
79a3a76e | 293 | if (_dragX0 < 0) {\r |
b0d3496e ASL |
294 | return;\r |
295 | }\r | |
296 | Point size = getSize();\r | |
b0d3496e | 297 | if (1 == _dragState && null != _timeProvider) {\r |
79a3a76e FC |
298 | int leftSpace = _timeProvider.getNameSpace();\r |
299 | int x = e.x - leftSpace;\r | |
b0d3496e ASL |
300 | if (x > 0 && size.x > leftSpace && _dragX != x) {\r |
301 | _dragX = x;\r | |
79a3a76e FC |
302 | long time1 = _time0bak + ((_time1bak - _time0bak) * _dragX0)\r |
303 | / _dragX;\r | |
b0d3496e ASL |
304 | _timeProvider.setStartFinishTime(_time0bak, time1);\r |
305 | }\r | |
b0d3496e ASL |
306 | }\r |
307 | }\r | |
308 | \r | |
309 | public void mouseDoubleClick(MouseEvent e) {\r | |
310 | if (null != _timeProvider) {\r | |
311 | _timeProvider.resetStartFinishTime();\r | |
b0d3496e ASL |
312 | }\r |
313 | }\r | |
314 | }\r | |
315 | \r | |
316 | abstract class TimeDraw {\r | |
317 | static String S = ":";\r | |
318 | static String S0 = ":0";\r | |
319 | static String S00 = ":00";\r | |
79a3a76e | 320 | protected SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss");\r |
b0d3496e ASL |
321 | \r |
322 | static String pad(long n) {\r | |
323 | String s = S;\r | |
324 | if (n < 10)\r | |
325 | s = S00;\r | |
326 | else if (n < 100)\r | |
327 | s = S0;\r | |
328 | return s + n;\r | |
329 | }\r | |
330 | \r | |
79a3a76e | 331 | public abstract void draw(GC gc, long time, Rectangle rect);\r |
b0d3496e | 332 | \r |
b0d3496e ASL |
333 | public abstract String hint();\r |
334 | }\r | |
335 | \r | |
336 | class TimeDrawSec extends TimeDraw {\r | |
337 | static String _hint = "sec";\r | |
338 | \r | |
b0d3496e ASL |
339 | public void draw(GC gc, long time, Rectangle rect) {\r |
340 | time /= 1000000000;\r | |
341 | Utils.drawText(gc, time + "", rect, true);\r | |
342 | }\r | |
343 | \r | |
b0d3496e ASL |
344 | public String hint() {\r |
345 | return _hint;\r | |
346 | }\r | |
347 | }\r | |
348 | \r | |
349 | class TimeDrawMillisec extends TimeDraw {\r | |
350 | static String _hint = "s:ms";\r | |
351 | \r | |
b0d3496e ASL |
352 | public void draw(GC gc, long time, Rectangle rect) {\r |
353 | time /= 1000000;\r | |
354 | long ms = time % 1000;\r | |
355 | time /= 1000;\r | |
356 | Utils.drawText(gc, time + pad(ms), rect, true);\r | |
357 | }\r | |
358 | \r | |
b0d3496e ASL |
359 | public String hint() {\r |
360 | return _hint;\r | |
361 | }\r | |
362 | }\r | |
363 | \r | |
364 | class TimeDrawMicrosec extends TimeDraw {\r | |
365 | static String _hint = "s:ms:mcs";\r | |
366 | \r | |
b0d3496e ASL |
367 | public void draw(GC gc, long time, Rectangle rect) {\r |
368 | time /= 1000;\r | |
369 | long mcs = time % 1000;\r | |
370 | time /= 1000;\r | |
371 | long ms = time % 1000;\r | |
372 | time /= 1000;\r | |
373 | Utils.drawText(gc, time + pad(ms) + pad(mcs), rect, true);\r | |
374 | }\r | |
375 | \r | |
b0d3496e ASL |
376 | public String hint() {\r |
377 | return _hint;\r | |
378 | }\r | |
379 | }\r | |
380 | \r | |
381 | class TimeDrawNanosec extends TimeDraw {\r | |
382 | static String _hint = "s:ms:mcs:ns";\r | |
383 | \r | |
b0d3496e ASL |
384 | public void draw(GC gc, long time, Rectangle rect) {\r |
385 | long ns = time % 1000;\r | |
386 | time /= 1000;\r | |
387 | long mcs = time % 1000;\r | |
388 | time /= 1000;\r | |
389 | long ms = time % 1000;\r | |
390 | time /= 1000;\r | |
391 | Utils.drawText(gc, time + pad(ms) + pad(mcs) + pad(ns), rect, true);\r | |
392 | }\r | |
393 | \r | |
b0d3496e ASL |
394 | public String hint() {\r |
395 | return _hint;\r | |
396 | }\r | |
397 | }\r | |
398 | \r | |
79a3a76e FC |
399 | class TimeDrawAbsSec extends TimeDraw {\r |
400 | static String _hint = "HH:mm:ss";\r | |
b0d3496e | 401 | \r |
79a3a76e FC |
402 | public void draw(GC gc, long time, Rectangle rect) {\r |
403 | String stime = stimeformat.format(new Date((long) (time * 1E-6)));\r | |
404 | Utils.drawText(gc, stime, rect, true);\r | |
405 | }\r | |
b0d3496e | 406 | \r |
79a3a76e FC |
407 | public String hint() {\r |
408 | return _hint;\r | |
409 | }\r | |
b0d3496e ASL |
410 | }\r |
411 | \r | |
412 | class TimeDrawAbsMillisec extends TimeDraw {\r | |
413 | static String _hint = "HH:ss:ms";\r | |
414 | \r | |
b0d3496e | 415 | public void draw(GC gc, long time, Rectangle rect) {\r |
79a3a76e | 416 | String stime = stimeformat.format(new Date((long) (time * 1E-6)));\r |
b0d3496e ASL |
417 | String ns = Utils.formatNs(time, Resolution.MILLISEC);\r |
418 | \r | |
419 | Utils.drawText(gc, stime + " " + ns, rect, true);\r | |
420 | }\r | |
421 | \r | |
b0d3496e ASL |
422 | public String hint() {\r |
423 | return _hint;\r | |
424 | }\r | |
425 | }\r | |
426 | \r | |
427 | class TimeDrawAbsMicroSec extends TimeDraw {\r | |
428 | static String _hint = "HH:ss:ms:mcs";\r | |
429 | \r | |
b0d3496e | 430 | public void draw(GC gc, long time, Rectangle rect) {\r |
79a3a76e | 431 | String stime = stimeformat.format(new Date((long) (time * 1E-6)));\r |
b0d3496e ASL |
432 | String micr = Utils.formatNs(time, Resolution.MICROSEC);\r |
433 | Utils.drawText(gc, stime + " " + micr, rect, true);\r | |
434 | }\r | |
435 | \r | |
b0d3496e ASL |
436 | public String hint() {\r |
437 | return _hint;\r | |
438 | }\r | |
439 | }\r | |
440 | \r | |
441 | class TimeDrawAbsNanoSec extends TimeDraw {\r | |
442 | static String _hint = "HH:ss:ms:mcs:ns";\r | |
443 | \r | |
b0d3496e | 444 | public void draw(GC gc, long time, Rectangle rect) {\r |
79a3a76e | 445 | String stime = stimeformat.format(new Date((long) (time * 1E-6)));\r |
b0d3496e ASL |
446 | String ns = Utils.formatNs(time, Resolution.NANOSEC);\r |
447 | Utils.drawText(gc, stime + " " + ns, rect, true);\r | |
448 | }\r | |
449 | \r | |
b0d3496e ASL |
450 | public String hint() {\r |
451 | return _hint;\r | |
452 | }\r | |
453 | }\r |