1 /*******************************************************************************
2 * Copyright (c) 2010, 2011 Ericsson
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
10 * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation
11 * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code
12 * Bernd Hufmann - Adapted to new model-view-controller design, display improvements
13 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.internal
.lttng
.ui
.views
.latency
.listeners
;
16 import org
.eclipse
.linuxtools
.internal
.lttng
.ui
.views
.latency
.AbstractViewer
;
17 import org
.eclipse
.linuxtools
.internal
.lttng
.ui
.views
.latency
.model
.Config
;
18 import org
.eclipse
.swt
.SWT
;
19 import org
.eclipse
.swt
.events
.PaintEvent
;
20 import org
.eclipse
.swt
.events
.PaintListener
;
21 import org
.eclipse
.swt
.graphics
.Color
;
22 import org
.eclipse
.swt
.graphics
.Font
;
23 import org
.eclipse
.swt
.graphics
.GC
;
24 import org
.eclipse
.swt
.graphics
.Image
;
25 import org
.eclipse
.swt
.graphics
.Point
;
26 import org
.eclipse
.swt
.graphics
.Rectangle
;
27 import org
.eclipse
.swt
.widgets
.Display
;
30 * <b><u>AbstractPaintListener</u></b>
32 * Abstract paint listener. Draws the graphs on the view canvas.
34 * @author Philippe Sawicki
36 public abstract class AbstractPaintListener
implements PaintListener
{
38 // ------------------------------------------------------------------------
40 // ------------------------------------------------------------------------
43 * Default colors and fonts
45 protected final Color DEFAULT_DATA_COLOR
= new Color(Display
.getDefault(), 74, 112, 139);
46 protected final static Color DEFAULT_LABEL_COLOR
= Display
.getCurrent().getSystemColor(SWT
.COLOR_BLACK
);
47 protected final static Color DEFAULT_TEXT_COLOR
= Display
.getCurrent().getSystemColor(SWT
.COLOR_DARK_GRAY
);
48 protected final static Color DEFAULT_DATA_BACKGROUND_COLOR
= Display
.getCurrent().getSystemColor(SWT
.COLOR_WHITE
);
49 protected final static Color DEFAULT_CURRENT_EVENT_COLOR
= Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
51 protected final Font DEFAULT_TITLE_FONT
= new Font(Display
.getDefault(), "Arial", 10, SWT
.BOLD
); //$NON-NLS-1$
52 protected final Font DEFAULT_VALUES_FONT
= new Font(Display
.getDefault(), "Arial", 7, SWT
.NORMAL
); //$NON-NLS-1$
53 protected final Font DEFAULT_LABEL_FONT
= new Font(Display
.getDefault(), "Arial", 8, SWT
.NORMAL
); //$NON-NLS-1$
56 * A reference to the listener's view.
58 protected AbstractViewer fViewer
;
63 protected String fGraphTitle
;
68 protected String fXAxisLabel
;
73 protected String fYAxisLabel
;
76 * Horizontal offset for the x-axis label.
78 protected int fXAxisLabelOffset
;
81 * Vertical offset for the horizontal axis offset.
83 protected int fHorizontalAxisYOffset
= 20;
88 protected int fPadding
= Config
.GRAPH_PADDING
;
93 protected Rectangle fClientArea
= new Rectangle(0, 0, 1, 1);
98 protected Color fForegroundColor
;
103 protected Color fBackgroundColor
;
106 * Data plotting color.
108 protected Color fDataColor
;
113 protected Color fLabelColor
;
118 protected Color fTextColor
;
121 * Data background color.
123 protected Color fDataBackgroundColor
;
126 * Color for current event time line.
128 protected Color fCurrentEventColor
;
131 * Original canvas font.
133 protected Font fOriginalFont
;
136 * Font for the title of the graph.
138 protected Font fTitleFont
;
141 * Font for the values on the horizontal and vertical axis.
143 protected Font fValuesFont
;
146 * Font for the horizontal and vertical labels.
148 protected Font fLabelFont
;
151 * Horizontal offset for the axis arrow.
153 protected final int ARROW_DELTA_X
= 10;
156 * Vertical offset for the axis arrow.
158 protected final int ARROW_DELTA_Y
= 4;
161 * Max horizontal distance between ticks.
163 protected final int MAX_WIDTH_BETWEEN_TICKS
= 40;
166 * Max vertical distance between ticks.
168 protected final int MAX_HEIGHT_BETWEEN_TICKS
= 30;
171 * Max characters that can be displayed on the vertical axis.
173 protected final int MAX_CHAR_VERTICAL_DISPLAY
= 5;
176 * Draw label each "drawLabelEachNTicks_" ticks.
178 protected int fDrawLabelEachNTicks
= 1;
181 * Image drawn on the canvas.
183 protected Image fImage
;
186 * Paint canvas, where the values are plotted.
188 protected GC fAxisImage
;
191 * Is the paint listener initialized ?
193 protected boolean fInitialized
= false;
198 protected Rectangle fDrawArea
;
201 * Right padding (in pixels).
203 protected int fPaddingRight
= Config
.GRAPH_PADDING
;
206 * Top padding (in pixels).
208 protected int fPaddingTop
= Config
.GRAPH_PADDING
;
211 * Vertical axis offset (in pixels).
213 protected int fVerticalAxisOffset
= 2 * Config
.GRAPH_PADDING
;
216 * Vertical axis factor for values (10^delta). When values larger than MAX_CHAR_VERTICAL_DISPLAY.
218 protected int fDelta
= 0;
221 * The barWidth of a bar
223 protected int fBarWith
= Config
.DEFAULT_HISTOGRAM_BAR_WIDTH
;
226 * Minimum value on horizontal axis
228 protected long fXMin
= -1;
231 * Maximum value on horizontal axis
233 protected long fXMax
= -1;
236 * Minimum value on vertical axis
238 protected long fYMin
= -1;
241 * Maximum value on vertical axis
243 protected long fYMax
= -1;
245 // ------------------------------------------------------------------------
247 // ------------------------------------------------------------------------
252 * A reference to the listener's view.
254 public AbstractPaintListener(AbstractViewer view
) {
256 fDataColor
= DEFAULT_DATA_COLOR
;
257 fLabelColor
= DEFAULT_LABEL_COLOR
;
258 fTextColor
= DEFAULT_TEXT_COLOR
;
259 fDataBackgroundColor
= DEFAULT_DATA_BACKGROUND_COLOR
;
260 fCurrentEventColor
= DEFAULT_CURRENT_EVENT_COLOR
;
262 fTitleFont
= DEFAULT_TITLE_FONT
;
263 fValuesFont
= DEFAULT_VALUES_FONT
;
264 fLabelFont
= DEFAULT_LABEL_FONT
;
267 // ------------------------------------------------------------------------
269 // ------------------------------------------------------------------------
272 * Returns the draw area height.
273 * @return The draw area height.
275 public double getHeight() {
276 return (fClientArea
.height
- 2.0 * fPadding
- fHorizontalAxisYOffset
- fPaddingTop
);
280 * Returns the histogram's draw area width.
281 * @return The histogram's draw area width.
283 public double getWidth() {
284 return (fClientArea
.width
- 2.0 * fPadding
- fVerticalAxisOffset
- fPaddingRight
); // width of the plot area;
288 * Returns the histogram's draw area padding.
289 * @return The histogram's draw area padding.
291 public int getPadding() {
296 * Returns the histogram's draw area top padding.
297 * @return The histogram's draw area top padding.
299 public int getPaddingTop() {
304 * Returns the histogram's vertical axis offset.
305 * @return The histogram's vertical axis offset.
307 public int getVerticalAxisOffset() {
308 return fVerticalAxisOffset
;
312 * Returns the histogram's horizontal axis offset.
313 * @return The histogram's horizontal axis offset.
315 public int getHorizontalAxisYOffset() {
316 return fHorizontalAxisYOffset
;
320 * Returns the horizontal minimum value
321 * @return The horizontal minimum value.
323 public long getXMin() {
328 * Returns the horizontal maximum value
329 * @return The horizontal maximum value.
331 public long getXMax() {
336 * Returns the horizontal minimum value
337 * @return The horizontal minimum value.
339 public long getYMin() {
344 * Returns the vertical maximum value
345 * @return The vertical maximum value.
347 public long getYMax() {
351 // ------------------------------------------------------------------------
353 // ------------------------------------------------------------------------
356 * Disposes local resources (e.g. colors or fonts)
358 public void dispose() {
359 DEFAULT_DATA_COLOR
.dispose();
360 DEFAULT_TITLE_FONT
.dispose();
361 DEFAULT_VALUES_FONT
.dispose();
362 DEFAULT_LABEL_FONT
.dispose();
367 * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
370 public void paintControl(PaintEvent e
) {
371 fClientArea
= fViewer
.getClientArea();
373 fForegroundColor
= e
.gc
.getForeground();
374 fBackgroundColor
= e
.gc
.getBackground();
375 fOriginalFont
= e
.gc
.getFont();
380 fImage
= new Image(Display
.getDefault(), fViewer
.getBounds());
382 fAxisImage
= new GC(fImage
);
384 fAxisImage
.setForeground(fForegroundColor
);
385 fAxisImage
.setBackground(fBackgroundColor
);
386 fAxisImage
.fillRectangle(fImage
.getBounds());
393 paintHorizontalAxis();
397 e
.gc
.drawImage(fImage
, 0, 0);
401 * Paints the title of the graph.
403 public void paintGraphTitle() {
404 if (fGraphTitle
!= null) {
405 fAxisImage
.setFont(fTitleFont
);
406 fAxisImage
.setForeground(fLabelColor
);
407 fAxisImage
.setBackground(fBackgroundColor
);
409 int zoomFactor
= fViewer
.getZoomFactor() / fViewer
.getZoomIncrement() + 1;
410 int labelWidth
= fAxisImage
.stringExtent(fGraphTitle
).x
;
411 // Draws the zoom factor in the title only if there is one
412 if (fViewer
.getZoomFactor() > 1)
413 fAxisImage
.drawText(fGraphTitle
+ " (" + zoomFactor
+ "x)", (fViewer
.getBounds().width
- fPadding
- labelWidth
) / 2, 0); //$NON-NLS-1$ //$NON-NLS-2$
415 fAxisImage
.drawText(fGraphTitle
, (fViewer
.getBounds().width
- fPadding
- labelWidth
) / 2, 0);
420 * Paints the background of the draw area.
422 public void paintBackground() {
423 fAxisImage
.setBackground(fDataBackgroundColor
);
425 fAxisImage
.fillRectangle(fPadding
+ fVerticalAxisOffset
, fPadding
+ fPaddingTop
, (int)getWidth() + 1, (int)getHeight());
429 * Paints the horizontal axis.
431 public void paintHorizontalAxis() {
432 fAxisImage
.setForeground(fForegroundColor
);
434 int y
= fClientArea
.height
- fPadding
- fHorizontalAxisYOffset
;
436 fAxisImage
.drawLine(fClientArea
.x
+ fPadding
+ fVerticalAxisOffset
, y
, fClientArea
.width
- fPadding
, y
);
438 paintHorizontalArrow(fClientArea
.width
- fPadding
, y
);
439 // Draw the axis graphic details only if there are some data points (i.e. do not draw the axis graphic details
440 // if the window timerange is so small that no latency can be computed, or if there are no matching events in
441 // the timerange (for example, when an experiment has many traces with a large time gap between the logged
443 if (fXMin
!= Long
.MAX_VALUE
&& fXMax
!= Long
.MIN_VALUE
&& fXMin
!= fXMax
) {
444 paintHorizontalTicks(y
);
445 paintHorizontalAxisValues(y
+ 30);
447 paintHorizontalAxisLabel(y
+ fHorizontalAxisYOffset
- 5);
451 * Paints the vertical axis.
453 public void paintVerticalAxis() {
454 fAxisImage
.setForeground(fForegroundColor
);
456 int x
= fClientArea
.x
+ fPadding
+ fVerticalAxisOffset
;
458 fAxisImage
.drawLine(x
, fPadding
, x
, fClientArea
.height
- fPadding
- fHorizontalAxisYOffset
);
460 paintVerticalArrow(x
, fClientArea
.y
+ fPadding
);
461 // Draw the axis graphic details only if there are some data points (i.e. do not draw the axis graphic details
462 // if the window timerange is so small that no latency can be computed, or if there are no matching events in
463 // the timerange (for example, when an experiment has many traces with a large time gap between the logged
465 if (fXMin
!= Long
.MAX_VALUE
&& fXMax
!= Long
.MIN_VALUE
&& fXMin
!= fXMax
) {
466 paintVerticalTicks(x
);
467 paintVerticalAxisValues(x
);
469 paintVerticalAxisLabel(x
);
473 * Paints the arrow on the horizontal axis.
475 * The x-coordinate of the point where the arrow points.
477 * The y-coordinate of the point where the arrow points.
479 public void paintHorizontalArrow(int x
, int y
) {
481 fAxisImage
.drawLine(x
- ARROW_DELTA_X
, y
- ARROW_DELTA_Y
, x
, y
);
483 fAxisImage
.drawLine(x
- ARROW_DELTA_X
, y
+ ARROW_DELTA_Y
, x
, y
);
487 * Paints the arrow on the vertical axis.
489 * The x-coordinate of the point where the arrow points.
491 * The y-coordinate of the point where the arrow points.
493 public void paintVerticalArrow(int x
, int y
) {
495 fAxisImage
.drawLine(x
- ARROW_DELTA_Y
, y
+ ARROW_DELTA_X
, x
, y
);
497 fAxisImage
.drawLine(x
+ ARROW_DELTA_Y
, y
+ ARROW_DELTA_X
, x
, y
);
501 * Paints the horizontal ticks.
503 * The y coordinate where to draw the axis.
505 public void paintHorizontalTicks(int y
) {
506 if (fXMin
>= 0L && fXMax
>= 0L) {
507 int nbTicks
= (int)(getWidth()) / MAX_WIDTH_BETWEEN_TICKS
+ 1;
509 for (int i
= 0; i
< nbTicks
; i
++) {
510 if (i
% fDrawLabelEachNTicks
== 0) {
511 int x
= i
* MAX_WIDTH_BETWEEN_TICKS
+ fPadding
+ fVerticalAxisOffset
;
512 fAxisImage
.drawLine(x
, y
, x
, y
+ 3);
519 * Paints the horizontal axis values.
521 * The y coordinate where to draw the axis.
523 public void paintHorizontalAxisValues(int y
) {
524 if (fXMin
>= 0L && fXMax
>= 0L) {
525 fAxisImage
.setForeground(fTextColor
);
526 fAxisImage
.setBackground(fBackgroundColor
);
528 double width
= getWidth();
529 int nbTicks
= ((int)getWidth()) / MAX_WIDTH_BETWEEN_TICKS
+ 1;
531 for (int i
= 0; i
< nbTicks
; i
++) {
532 if (i
% fDrawLabelEachNTicks
== 0) {
533 int x
= i
* MAX_WIDTH_BETWEEN_TICKS
+ fPadding
+ fVerticalAxisOffset
;
535 long currentValue
= (i
* MAX_WIDTH_BETWEEN_TICKS
)* (long)((fXMax
- fXMin
) / width
) + fXMin
;
536 String currentLabel
= formatStringForHorizontalAxis(currentValue
);
538 fAxisImage
.setFont(fValuesFont
);
539 fAxisImage
.drawText(currentLabel
, x
, y
- 24);
546 * Paints the horizontal axis label.
548 * The y-coordinate where to draw the label.
550 public void paintHorizontalAxisLabel(int y
) {
551 if (fXAxisLabel
!= null) {
552 fAxisImage
.setFont(fLabelFont
);
553 fAxisImage
.setForeground(fLabelColor
);
555 int labelWidth
= fAxisImage
.stringExtent(fXAxisLabel
).x
;
557 fAxisImage
.drawText(fXAxisLabel
, fClientArea
.width
- fPadding
- labelWidth
, y
);
562 * Paints the vertical axis ticks.
564 * The x-coordinate where to draw the ticks.
566 public void paintVerticalTicks(int x
) {
567 if (fYMin
!= 0L && fYMax
!= 0L) {
568 int nbTicks
= (int)(getHeight() / MAX_HEIGHT_BETWEEN_TICKS
+ 1);
570 for (int i
= 0; i
< nbTicks
; i
++) {
571 int y
= fClientArea
.height
- fPadding
- fHorizontalAxisYOffset
- i
* MAX_HEIGHT_BETWEEN_TICKS
;
572 fAxisImage
.drawLine(x
- 3, y
, x
, y
);
578 * Paints the vertical axis values.
580 * The x-coordinate where to draw the values.
582 public void paintVerticalAxisValues(int x
) {
583 if (fYMin
>= 0L && fYMax
>= 0L) {
584 fAxisImage
.setForeground(fTextColor
);
585 fAxisImage
.setBackground(fBackgroundColor
);
587 double height
= getHeight();
588 int nbTicks
= (int)(height
/ MAX_HEIGHT_BETWEEN_TICKS
+ 1);
590 // System.out.println("nbTicks = " + nbTicks);
592 for (int i
= 0; i
< nbTicks
; i
++) {
593 int y
= fClientArea
.height
- fPadding
- fHorizontalAxisYOffset
- i
* MAX_HEIGHT_BETWEEN_TICKS
;
595 long currentValue
= (i
* MAX_HEIGHT_BETWEEN_TICKS
)* (long)((fYMax
- fYMin
) / height
) + fYMin
;
596 String currentLabel
= formatStringForVerticalAxis(currentValue
);
598 fAxisImage
.setFont(fValuesFont
);
600 Point textDimensions
= fAxisImage
.stringExtent(currentLabel
);
601 fAxisImage
.drawText(currentLabel
, x
- textDimensions
.x
- 5, y
- textDimensions
.y
/ 2);
607 * Increases the bar width.
609 public void increaseBarWitdh() {
610 fBarWith
= fBarWith
<< 1;
611 if (fBarWith
> Config
.MAX_HISTOGRAM_BAR_WIDTH
) {
612 fBarWith
= Config
.MAX_HISTOGRAM_BAR_WIDTH
;
617 * Decreases the bar width.
619 public void decreaseBarWitdh() {
620 fBarWith
= fBarWith
>> 1;
621 if (fBarWith
< Config
.MIN_HISTOGRAM_BAR_WIDTH
) {
622 fBarWith
= Config
.MIN_HISTOGRAM_BAR_WIDTH
;
628 * Paints the vertical axis label.
630 * The x-coordinate where to draw the label.
632 public void paintVerticalAxisLabel(int x
) {
633 if (fYAxisLabel
!= null) {
634 fAxisImage
.setFont(fLabelFont
);
635 fAxisImage
.setForeground(fLabelColor
);
636 fAxisImage
.setBackground(fBackgroundColor
);
639 fAxisImage
.drawText(fYAxisLabel
+ " (x10^" + fDelta
+ ")", x
+ 10, fHorizontalAxisYOffset
- 5); //$NON-NLS-1$//$NON-NLS-2$
641 fAxisImage
.drawText(fYAxisLabel
, x
+ 10, fPadding
);
646 * Adds points to the graph and draws them to the canvas.
648 * The buffer of points to draw.
650 * The number of points in the buffer.
652 abstract public String
formatToolTipLabel(int x
, int y
);
655 * Method to be implemented to scale the model data to the actual screen size.
657 abstract public void scale();
660 * Called for drawing elements after points are added to the graph.
662 abstract public void paintContent();
665 * Clears the image and prepares it for redrawing.
667 public void clear() {
668 fInitialized
= false;
676 * Draw horizontal label each "nbTicks" ticks.
680 public void setDrawLabelEachNTicks(int nbTicks
) {
681 fDrawLabelEachNTicks
= nbTicks
;
685 * Sets the title of the graph.
687 * The title of the graph.
689 public void setGraphTitle(String graphTitle
) {
690 fGraphTitle
= graphTitle
;
694 * Sets the horizontal axis label.
696 * The horizontal axis label.
698 * The horizontal axis draw offset (in pixels).
700 public void setXAxisLabel(String xAxisLabel
, int offset
) {
701 fXAxisLabel
= xAxisLabel
;
702 fXAxisLabelOffset
= offset
;
706 * Sets the vertical axis label.
708 * The vertical axis label.
710 public void setYAxisLabel(String yAxisLabel
) {
711 fYAxisLabel
= yAxisLabel
;
715 * Returns a string representing the given value.
718 * The numeric value to convert to String.
719 * @return The String-formatted value.
721 public String
formatStringForHorizontalAxis(long value
) {
722 return String
.valueOf(value
);
726 * Returns a string representing the given value.
729 * The numeric value to convert to String.
730 * @return The String-formatted value.
732 public String
formatStringForVerticalAxis(long value
) {
733 return String
.valueOf(value
);