tmf: Update copyright headers in tmf.ui
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / histogram / Histogram.java
CommitLineData
c392540b 1/*******************************************************************************
c8422608 2 * Copyright (c) 2011, 2013 Ericsson
20ff3b75 3 *
c392540b
FC
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
20ff3b75 8 *
c392540b
FC
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
fbd124dd 11 * Bernd Hufmann - Changed to updated histogram data model
f8177ba2 12 * Francois Chouinard - Reformat histogram labels on format change
c392540b
FC
13 *******************************************************************************/
14
e0752744 15package org.eclipse.linuxtools.tmf.ui.views.histogram;
c392540b 16
f8177ba2
FC
17import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
18import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
19import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal;
3bd46eef
AM
20import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
21import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
22import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampFormat;
c392540b
FC
23import org.eclipse.linuxtools.tmf.ui.views.TmfView;
24import org.eclipse.swt.SWT;
25import org.eclipse.swt.events.ControlEvent;
26import org.eclipse.swt.events.ControlListener;
27import org.eclipse.swt.events.KeyEvent;
28import org.eclipse.swt.events.KeyListener;
29import org.eclipse.swt.events.MouseEvent;
30import org.eclipse.swt.events.MouseListener;
31import org.eclipse.swt.events.MouseTrackListener;
32import org.eclipse.swt.events.PaintEvent;
33import org.eclipse.swt.events.PaintListener;
34import org.eclipse.swt.graphics.Color;
35import org.eclipse.swt.graphics.Font;
36import org.eclipse.swt.graphics.FontData;
37import org.eclipse.swt.graphics.GC;
38import org.eclipse.swt.graphics.Image;
e60df94a 39import org.eclipse.swt.layout.FillLayout;
c392540b
FC
40import org.eclipse.swt.layout.GridData;
41import org.eclipse.swt.layout.GridLayout;
42import org.eclipse.swt.widgets.Canvas;
43import org.eclipse.swt.widgets.Composite;
44import org.eclipse.swt.widgets.Display;
45import org.eclipse.swt.widgets.Text;
46
47/**
b544077e 48 * Re-usable histogram widget.
20ff3b75 49 *
b544077e 50 * It has the following features:
c392540b
FC
51 * <ul>
52 * <li>Y-axis labels displaying min/max count values
53 * <li>X-axis labels displaying time range
54 * <li>a histogram displaying the distribution of values over time (note that
55 * the histogram might not necessarily fill the whole canvas)
56 * </ul>
57 * The widget also has 2 'markers' to identify:
58 * <ul>
59 * <li>a red dashed line over the bar that contains the currently selected event
60 * <li>a dark red dashed line that delimits the right end of the histogram (if
61 * it doesn't fill the canvas)
62 * </ul>
63 * Clicking on the histogram will select the current event at the mouse
64 * location.
65 * <p>
66 * Once the histogram is selected, there is some limited keyboard support:
67 * <ul>
68 * <li>Home: go to the first histogram bar
69 * <li>End: go to the last histogram bar
70 * <li>Left: go to the previous histogram
71 * <li>Right: go to the next histogram bar
72 * </ul>
73 * Finally, when the mouse hovers over the histogram, a tool tip showing the
74 * following information about the corresponding histogram bar time range:
75 * <ul>
76 * <li>start of the time range
77 * <li>end of the time range
78 * <li>number of events in that time range
79 * </ul>
20ff3b75 80 *
f8177ba2 81 * @version 1.1
b544077e 82 * @author Francois Chouinard
c392540b 83 */
fbd124dd 84public abstract class Histogram implements ControlListener, PaintListener, KeyListener, MouseListener, MouseTrackListener, IHistogramModelListener {
c392540b
FC
85
86 // ------------------------------------------------------------------------
87 // Constants
88 // ------------------------------------------------------------------------
89
c392540b
FC
90 // Histogram colors
91 private final Color fBackgroundColor = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
92 private final Color fCurrentEventColor = Display.getCurrent().getSystemColor(SWT.COLOR_RED);
93 private final Color fLastEventColor = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_RED);
94 private final Color fHistoBarColor = new Color(Display.getDefault(), 74, 112, 139);
95
c392540b
FC
96 // ------------------------------------------------------------------------
97 // Attributes
98 // ------------------------------------------------------------------------
99
b544077e
BH
100 /**
101 * The parent TMF view.
102 */
c392540b
FC
103 protected TmfView fParentView;
104
da7bdcbc 105 private Composite fComposite;
f8177ba2
FC
106 private Font fFont;
107
c392540b
FC
108 // Histogram text fields
109 private Text fMaxNbEventsText;
110 private Text fMinNbEventsText;
111 private Text fTimeRangeStartText;
112 private Text fTimeRangeEndText;
113
b544077e
BH
114 /**
115 * Histogram drawing area
116 */
c392540b 117 protected Canvas fCanvas;
f8177ba2 118
b544077e
BH
119 /**
120 * The histogram data model.
121 */
c392540b 122 protected final HistogramDataModel fDataModel;
f8177ba2 123
b544077e 124 /**
20ff3b75 125 * The histogram data model scaled to current resolution and screen width.
b544077e 126 */
c392540b
FC
127 protected HistogramScaledData fScaledData;
128
f8177ba2
FC
129 /**
130 * The current event value
131 */
132 protected long fCurrentEventTime = 0L;
c392540b
FC
133
134 // ------------------------------------------------------------------------
135 // Construction
136 // ------------------------------------------------------------------------
137
b544077e 138 /**
f8177ba2 139 * Full constructor.
20ff3b75 140 *
b544077e
BH
141 * @param view A reference to the parent TMF view.
142 * @param parent A parent composite
143 */
09e86496 144 public Histogram(final TmfView view, final Composite parent) {
c392540b
FC
145 fParentView = view;
146
da7bdcbc 147 fComposite = createWidget(parent);
c392540b 148 fDataModel = new HistogramDataModel();
fbd124dd 149 fDataModel.addHistogramListener(this);
c392540b
FC
150 clear();
151
152 fCanvas.addControlListener(this);
153 fCanvas.addPaintListener(this);
154 fCanvas.addKeyListener(this);
155 fCanvas.addMouseListener(this);
156 fCanvas.addMouseTrackListener(this);
f8177ba2
FC
157
158 TmfSignalManager.register(this);
c392540b
FC
159 }
160
b544077e 161 /**
f8177ba2 162 * Dispose resources and unregisters listeners.
b544077e 163 */
c392540b 164 public void dispose() {
f8177ba2
FC
165 TmfSignalManager.deregister(this);
166
c392540b 167 fHistoBarColor.dispose();
fbd124dd 168 fDataModel.removeHistogramListener(this);
c392540b
FC
169 }
170
da7bdcbc 171 private Composite createWidget(final Composite parent) {
c392540b 172
0301dc43 173 final Color labelColor = parent.getBackground();
f8177ba2 174 fFont = adjustFont(parent);
c392540b
FC
175
176 final int initalWidth = 10;
177
178 // --------------------------------------------------------------------
179 // Define the histogram
180 // --------------------------------------------------------------------
181
09e86496 182 final GridLayout gridLayout = new GridLayout();
c392540b
FC
183 gridLayout.numColumns = 3;
184 gridLayout.marginHeight = 0;
185 gridLayout.marginWidth = 0;
186 gridLayout.marginTop = 0;
187 gridLayout.horizontalSpacing = 0;
188 gridLayout.verticalSpacing = 0;
189 gridLayout.marginLeft = 0;
190 gridLayout.marginRight = 0;
09e86496 191 final Composite composite = new Composite(parent, SWT.FILL);
c392540b
FC
192 composite.setLayout(gridLayout);
193
194 // Use all the horizontal space
195 GridData gridData = new GridData();
196 gridData.horizontalAlignment = SWT.FILL;
197 gridData.verticalAlignment = SWT.FILL;
198 gridData.grabExcessHorizontalSpace = true;
199 composite.setLayoutData(gridData);
200
201 // Y-axis max event
202 gridData = new GridData();
203 gridData.horizontalAlignment = SWT.RIGHT;
204 gridData.verticalAlignment = SWT.TOP;
205 fMaxNbEventsText = new Text(composite, SWT.READ_ONLY | SWT.RIGHT);
206 fMaxNbEventsText.setFont(fFont);
207 fMaxNbEventsText.setBackground(labelColor);
208 fMaxNbEventsText.setEditable(false);
209 fMaxNbEventsText.setText("0"); //$NON-NLS-1$
210 fMaxNbEventsText.setLayoutData(gridData);
211
212 // Histogram itself
e60df94a 213 Composite canvasComposite = new Composite(composite, SWT.BORDER);
c392540b
FC
214 gridData = new GridData();
215 gridData.horizontalSpan = 2;
216 gridData.verticalSpan = 2;
217 gridData.horizontalAlignment = SWT.FILL;
218 gridData.verticalAlignment = SWT.FILL;
219 gridData.grabExcessHorizontalSpace = true;
e60df94a
PT
220 canvasComposite.setLayoutData(gridData);
221 canvasComposite.setLayout(new FillLayout());
222 fCanvas = new Canvas(canvasComposite, SWT.DOUBLE_BUFFERED);
c392540b
FC
223
224 // Y-axis min event (always 0...)
225 gridData = new GridData();
226 gridData.horizontalAlignment = SWT.RIGHT;
227 gridData.verticalAlignment = SWT.BOTTOM;
228 fMinNbEventsText = new Text(composite, SWT.READ_ONLY | SWT.RIGHT);
229 fMinNbEventsText.setFont(fFont);
230 fMinNbEventsText.setBackground(labelColor);
231 fMinNbEventsText.setEditable(false);
232 fMinNbEventsText.setText("0"); //$NON-NLS-1$
233 fMinNbEventsText.setLayoutData(gridData);
234
235 // Dummy cell
236 gridData = new GridData(initalWidth, SWT.DEFAULT);
237 gridData.horizontalAlignment = SWT.RIGHT;
238 gridData.verticalAlignment = SWT.BOTTOM;
09e86496 239 final Text dummyText = new Text(composite, SWT.READ_ONLY);
c392540b
FC
240 dummyText.setFont(fFont);
241 dummyText.setBackground(labelColor);
242 dummyText.setEditable(false);
243 dummyText.setText(""); //$NON-NLS-1$
244 dummyText.setLayoutData(gridData);
245
246 // Window range start time
247 gridData = new GridData();
248 gridData.horizontalAlignment = SWT.LEFT;
249 gridData.verticalAlignment = SWT.BOTTOM;
250 fTimeRangeStartText = new Text(composite, SWT.READ_ONLY);
251 fTimeRangeStartText.setFont(fFont);
252 fTimeRangeStartText.setBackground(labelColor);
c392540b
FC
253 fTimeRangeStartText.setLayoutData(gridData);
254
255 // Window range end time
256 gridData = new GridData();
257 gridData.horizontalAlignment = SWT.RIGHT;
258 gridData.verticalAlignment = SWT.BOTTOM;
259 fTimeRangeEndText = new Text(composite, SWT.READ_ONLY);
260 fTimeRangeEndText.setFont(fFont);
261 fTimeRangeEndText.setBackground(labelColor);
c392540b 262 fTimeRangeEndText.setLayoutData(gridData);
da7bdcbc
PT
263
264 return composite;
c392540b
FC
265 }
266
abbdd66a 267 private static Font adjustFont(final Composite composite) {
c392540b 268 // Reduce font size for a more pleasing rendering
09e86496
FC
269 final int fontSizeAdjustment = -2;
270 final Font font = composite.getFont();
271 final FontData fontData = font.getFontData()[0];
c392540b
FC
272 return new Font(font.getDevice(), fontData.getName(), fontData.getHeight() + fontSizeAdjustment, fontData.getStyle());
273 }
274
275 // ------------------------------------------------------------------------
276 // Accessors
277 // ------------------------------------------------------------------------
278
b544077e 279 /**
f8177ba2 280 * Returns the start time (equal first bucket time)
b544077e
BH
281 * @return the start time.
282 */
c392540b 283 public long getStartTime() {
fbd124dd 284 return fDataModel.getFirstBucketTime();
c392540b
FC
285 }
286
b544077e
BH
287 /**
288 * Returns the end time.
289 * @return the end time.
290 */
c392540b
FC
291 public long getEndTime() {
292 return fDataModel.getEndTime();
293 }
294
b544077e
BH
295 /**
296 * Returns the time limit (end of last bucket)
297 * @return the time limit.
298 */
c392540b
FC
299 public long getTimeLimit() {
300 return fDataModel.getTimeLimit();
301 }
09e86496 302
20ff3b75
AM
303 /**
304 * Returns a data model reference.
b544077e
BH
305 * @return data model.
306 */
fbd124dd
BH
307 public HistogramDataModel getDataModel() {
308 return fDataModel;
309 }
c392540b
FC
310
311 // ------------------------------------------------------------------------
312 // Operations
313 // ------------------------------------------------------------------------
b544077e 314 /**
20ff3b75 315 * Updates the time range.
b544077e
BH
316 * @param startTime A start time
317 * @param endTime A end time.
318 */
c392540b
FC
319 public abstract void updateTimeRange(long startTime, long endTime);
320
321 /**
322 * Clear the histogram and reset the data
323 */
324 public void clear() {
325 fDataModel.clear();
dcb3cda5
BH
326 synchronized (fDataModel) {
327 fScaledData = null;
328 }
c392540b
FC
329 }
330
331 /**
332 * Increase the histogram bucket corresponding to [timestamp]
20ff3b75
AM
333 *
334 * @param eventCount
335 * The new event count
c392540b 336 * @param timestamp
20ff3b75 337 * The latest timestamp
c392540b 338 */
09e86496 339 public void countEvent(final long eventCount, final long timestamp) {
fbd124dd 340 fDataModel.countEvent(eventCount, timestamp);
c392540b
FC
341 }
342
343 /**
344 * Sets the current event time and refresh the display
20ff3b75 345 *
c392540b 346 * @param timestamp
20ff3b75 347 * The time of the current event
c392540b 348 */
09e86496 349 public void setCurrentEvent(final long timestamp) {
74237cc3 350 fCurrentEventTime = (timestamp > 0) ? timestamp : 0;
fbd124dd 351 fDataModel.setCurrentEventNotifyListeners(timestamp);
c392540b
FC
352 }
353
354 /**
355 * Computes the timestamp of the bucket at [offset]
20ff3b75 356 *
c392540b
FC
357 * @param offset offset from the left on the histogram
358 * @return the start timestamp of the corresponding bucket
359 */
09e86496 360 public synchronized long getTimestamp(final int offset) {
c392540b
FC
361 assert offset > 0 && offset < fScaledData.fWidth;
362 try {
fbd124dd 363 return fDataModel.getFirstBucketTime() + fScaledData.fBucketDuration * offset;
09e86496 364 } catch (final Exception e) {
c392540b
FC
365 return 0; // TODO: Fix that racing condition (NPE)
366 }
367 }
368
369 /**
370 * Computes the offset of the timestamp in the histogram
20ff3b75 371 *
c392540b
FC
372 * @param timestamp the timestamp
373 * @return the offset of the corresponding bucket (-1 if invalid)
374 */
09e86496 375 public synchronized int getOffset(final long timestamp) {
20ff3b75 376 if (timestamp < fDataModel.getFirstBucketTime() || timestamp > fDataModel.getEndTime()) {
c392540b 377 return -1;
20ff3b75 378 }
fbd124dd 379 return (int) ((timestamp - fDataModel.getFirstBucketTime()) / fScaledData.fBucketDuration);
c392540b
FC
380 }
381
382 /**
383 * Move the currently selected bar cursor to a non-empty bucket.
20ff3b75 384 *
c392540b
FC
385 * @param keyCode the SWT key code
386 */
09e86496 387 protected void moveCursor(final int keyCode) {
c392540b 388
20ff3b75 389 if (fScaledData.fCurrentBucket == HistogramScaledData.OUT_OF_RANGE_BUCKET) {
c392540b 390 return;
20ff3b75 391 }
c392540b
FC
392
393 int index;
394 switch (keyCode) {
395
396 case SWT.HOME:
397 index = 0;
20ff3b75 398 while (index < fScaledData.fLastBucket && fScaledData.fData[index] == 0) {
c392540b 399 index++;
20ff3b75
AM
400 }
401 if (index < fScaledData.fLastBucket) {
c392540b 402 fScaledData.fCurrentBucket = index;
20ff3b75 403 }
c392540b
FC
404 break;
405
406 case SWT.ARROW_RIGHT:
407 index = fScaledData.fCurrentBucket + 1;
20ff3b75 408 while (index < fScaledData.fWidth && fScaledData.fData[index] == 0) {
c392540b 409 index++;
20ff3b75
AM
410 }
411 if (index < fScaledData.fLastBucket) {
c392540b 412 fScaledData.fCurrentBucket = index;
20ff3b75 413 }
c392540b
FC
414 break;
415
416 case SWT.END:
417 index = fScaledData.fLastBucket;
20ff3b75 418 while (index >= 0 && fScaledData.fData[index] == 0) {
c392540b 419 index--;
20ff3b75
AM
420 }
421 if (index >= 0) {
c392540b 422 fScaledData.fCurrentBucket = index;
20ff3b75 423 }
c392540b
FC
424 break;
425
426 case SWT.ARROW_LEFT:
427 index = fScaledData.fCurrentBucket - 1;
20ff3b75 428 while (index >= 0 && fScaledData.fData[index] == 0) {
c392540b 429 index--;
20ff3b75
AM
430 }
431 if (index >= 0) {
c392540b 432 fScaledData.fCurrentBucket = index;
20ff3b75 433 }
c392540b
FC
434 break;
435
436 default:
437 return;
438 }
439
440 updateCurrentEventTime();
441 }
442
443 /**
444 * Refresh the histogram display
445 */
fbd124dd
BH
446 @Override
447 public void modelUpdated() {
20ff3b75 448 if (!fCanvas.isDisposed() && fCanvas.getDisplay() != null) {
c392540b
FC
449 fCanvas.getDisplay().asyncExec(new Runnable() {
450 @Override
451 public void run() {
452 if (!fCanvas.isDisposed()) {
453 // Retrieve and normalize the data
09e86496
FC
454 final int canvasWidth = fCanvas.getBounds().width;
455 final int canvasHeight = fCanvas.getBounds().height;
20ff3b75 456 if (canvasWidth <= 0 || canvasHeight <= 0) {
40890fec 457 return;
20ff3b75 458 }
c392540b 459 fDataModel.setCurrentEvent(fCurrentEventTime);
f8177ba2 460 fScaledData = fDataModel.scaleTo(canvasWidth, canvasHeight, 1);
dcb3cda5 461 synchronized(fDataModel) {
0316808c
FC
462 if (fScaledData != null) {
463 fCanvas.redraw();
da7bdcbc
PT
464 if (fDataModel.getNbEvents() != 0) {
465 // Display histogram and update X-,Y-axis labels
466 fTimeRangeStartText.setText(TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getFirstBucketTime()));
467 fTimeRangeEndText.setText(TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getEndTime()));
468 } else {
469 fTimeRangeStartText.setText(""); //$NON-NLS-1$
470 fTimeRangeEndText.setText(""); //$NON-NLS-1$
471 }
0316808c
FC
472 fMaxNbEventsText.setText(Long.toString(fScaledData.fMaxValue));
473 // The Y-axis area might need to be re-sized
474 fMaxNbEventsText.getParent().layout();
475 }
09e86496 476 }
c392540b
FC
477 }
478 }
479 });
20ff3b75 480 }
c392540b
FC
481 }
482
483 // ------------------------------------------------------------------------
484 // Helper functions
485 // ------------------------------------------------------------------------
486
487 private void updateCurrentEventTime() {
09e86496 488 final long bucketStartTime = getTimestamp(fScaledData.fCurrentBucket);
c392540b
FC
489 ((HistogramView) fParentView).updateCurrentEventTime(bucketStartTime);
490 }
491
492 // ------------------------------------------------------------------------
493 // PaintListener
494 // ------------------------------------------------------------------------
b544077e
BH
495 /**
496 * Image key string for the canvas.
497 */
c392540b
FC
498 protected final String IMAGE_KEY = "double-buffer-image"; //$NON-NLS-1$
499
500 @Override
09e86496 501 public void paintControl(final PaintEvent event) {
c392540b
FC
502
503 // Get the geometry
09e86496
FC
504 final int canvasWidth = fCanvas.getBounds().width;
505 final int canvasHeight = fCanvas.getBounds().height;
c392540b
FC
506
507 // Make sure we have something to draw upon
20ff3b75 508 if (canvasWidth <= 0 || canvasHeight <= 0) {
c392540b 509 return;
20ff3b75 510 }
c392540b
FC
511
512 // Retrieve image; re-create only if necessary
513 Image image = (Image) fCanvas.getData(IMAGE_KEY);
514 if (image == null || image.getBounds().width != canvasWidth || image.getBounds().height != canvasHeight) {
515 image = new Image(event.display, canvasWidth, canvasHeight);
516 fCanvas.setData(IMAGE_KEY, image);
517 }
518
519 // Draw the histogram on its canvas
09e86496 520 final GC imageGC = new GC(image);
c392540b
FC
521 formatImage(imageGC, image);
522 event.gc.drawImage(image, 0, 0);
523 imageGC.dispose();
524 }
525
09e86496 526 private void formatImage(final GC imageGC, final Image image) {
c392540b 527
20ff3b75 528 if (fScaledData == null) {
c392540b 529 return;
20ff3b75 530 }
c392540b 531
09e86496 532 final HistogramScaledData scaledData = new HistogramScaledData(fScaledData);
c392540b
FC
533
534 try {
535 // Get drawing boundaries
09e86496
FC
536 final int width = image.getBounds().width;
537 final int height = image.getBounds().height;
c392540b
FC
538
539 // Clear the drawing area
540 imageGC.setBackground(fBackgroundColor);
541 imageGC.fillRectangle(0, 0, image.getBounds().width + 1, image.getBounds().height + 1);
542
543 // Draw the histogram bars
544 imageGC.setBackground(fHistoBarColor);
09e86496 545 final int limit = width < scaledData.fWidth ? width : scaledData.fWidth;
e6953950 546 for (int i = 0; i < limit; i++) {
e60df94a 547 final int value = (int) Math.ceil(scaledData.fData[i] * scaledData.fScalingFactor);
c392540b
FC
548 imageGC.fillRectangle(i, height - value, 1, value);
549 }
550
551 // Draw the current event bar
09e86496 552 final int currentBucket = scaledData.fCurrentBucket;
20ff3b75 553 if (currentBucket >= 0 && currentBucket < limit) {
c392540b 554 drawDelimiter(imageGC, fCurrentEventColor, height, currentBucket);
20ff3b75 555 }
c392540b
FC
556
557 // Add a dashed line as a delimiter (at the right of the last bar)
558 int lastEventIndex = limit - 1;
20ff3b75 559 while (lastEventIndex >= 0 && scaledData.fData[lastEventIndex] == 0) {
c392540b 560 lastEventIndex--;
20ff3b75 561 }
c392540b
FC
562 lastEventIndex += (lastEventIndex < limit - 1) ? 1 : 0;
563 drawDelimiter(imageGC, fLastEventColor, height, lastEventIndex);
09e86496 564 } catch (final Exception e) {
c392540b
FC
565 // Do nothing
566 }
567 }
568
abbdd66a
AM
569 private static void drawDelimiter(final GC imageGC, final Color color,
570 final int height, final int index) {
c392540b 571 imageGC.setBackground(color);
09e86496 572 final int dash = height / 4;
c392540b
FC
573 imageGC.fillRectangle(index, 0 * dash, 1, dash - 1);
574 imageGC.fillRectangle(index, 1 * dash, 1, dash - 1);
575 imageGC.fillRectangle(index, 2 * dash, 1, dash - 1);
576 imageGC.fillRectangle(index, 3 * dash, 1, height - 3 * dash);
577 }
578
579 // ------------------------------------------------------------------------
580 // KeyListener
581 // ------------------------------------------------------------------------
582
583 @Override
09e86496 584 public void keyPressed(final KeyEvent event) {
c392540b
FC
585 moveCursor(event.keyCode);
586 }
587
588 @Override
09e86496 589 public void keyReleased(final KeyEvent event) {
c392540b
FC
590 }
591
592 // ------------------------------------------------------------------------
593 // MouseListener
594 // ------------------------------------------------------------------------
595
596 @Override
09e86496 597 public void mouseDoubleClick(final MouseEvent event) {
c392540b
FC
598 }
599
600 @Override
09e86496 601 public void mouseDown(final MouseEvent event) {
c392540b
FC
602 if (fDataModel.getNbEvents() > 0 && fScaledData.fLastBucket >= event.x) {
603 fScaledData.fCurrentBucket = event.x;
604 updateCurrentEventTime();
605 }
606 }
607
608 @Override
09e86496 609 public void mouseUp(final MouseEvent event) {
c392540b
FC
610 }
611
612 // ------------------------------------------------------------------------
613 // MouseTrackListener
614 // ------------------------------------------------------------------------
615
616 @Override
09e86496 617 public void mouseEnter(final MouseEvent event) {
c392540b
FC
618 }
619
620 @Override
09e86496 621 public void mouseExit(final MouseEvent event) {
c392540b
FC
622 }
623
624 @Override
09e86496 625 public void mouseHover(final MouseEvent event) {
74237cc3 626 if (fDataModel.getNbEvents() > 0 && fScaledData != null && fScaledData.fLastBucket >= event.x) {
09e86496 627 final String tooltip = formatToolTipLabel(event.x);
c392540b 628 fCanvas.setToolTipText(tooltip);
1be49d83
PT
629 } else {
630 fCanvas.setToolTipText(null);
c392540b
FC
631 }
632 }
633
09e86496 634 private String formatToolTipLabel(final int index) {
466857f6 635 long startTime = fScaledData.getBucketStartTime(index);
09e86496 636 // negative values are possible if time values came into the model in decreasing order
20ff3b75 637 if (startTime < 0) {
fbd124dd 638 startTime = 0;
20ff3b75 639 }
466857f6 640 final long endTime = fScaledData.getBucketEndTime(index);
09e86496 641 final int nbEvents = (index >= 0) ? fScaledData.fData[index] : 0;
c392540b 642
09e86496 643 final StringBuffer buffer = new StringBuffer();
c392540b 644 buffer.append("Range = ["); //$NON-NLS-1$
f8177ba2 645 buffer.append(new TmfTimestamp(startTime, ITmfTimestamp.NANOSECOND_SCALE).toString());
c392540b 646 buffer.append(","); //$NON-NLS-1$
f8177ba2 647 buffer.append(new TmfTimestamp(endTime, ITmfTimestamp.NANOSECOND_SCALE).toString());
c392540b
FC
648 buffer.append(")\n"); //$NON-NLS-1$
649 buffer.append("Event count = "); //$NON-NLS-1$
650 buffer.append(nbEvents);
651 return buffer.toString();
652 }
653
654 // ------------------------------------------------------------------------
655 // ControlListener
656 // ------------------------------------------------------------------------
657
658 @Override
09e86496 659 public void controlMoved(final ControlEvent event) {
fbd124dd 660 fDataModel.complete();
c392540b
FC
661 }
662
663 @Override
09e86496 664 public void controlResized(final ControlEvent event) {
fbd124dd 665 fDataModel.complete();
c392540b 666 }
f8177ba2
FC
667
668 // ------------------------------------------------------------------------
669 // Signal Handlers
670 // ------------------------------------------------------------------------
671
672 /**
673 * Format the timestamp and update the display
674 *
675 * @param signal the incoming signal
676 * @since 2.0
677 */
678 @TmfSignalHandler
679 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
da7bdcbc
PT
680 if (fDataModel.getNbEvents() == 0) {
681 return;
682 }
683
f8177ba2 684 String newTS = TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getFirstBucketTime());
f8177ba2
FC
685 fTimeRangeStartText.setText(newTS);
686
687 newTS = TmfTimestampFormat.getDefaulTimeFormat().format(fDataModel.getEndTime());
f8177ba2 688 fTimeRangeEndText.setText(newTS);
f8177ba2 689
da7bdcbc 690 fComposite.layout();
f8177ba2
FC
691 }
692
c392540b 693}
This page took 0.069292 seconds and 5 git commands to generate.