Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java')
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java245
1 files changed, 245 insertions, 0 deletions
diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java
new file mode 100644
index 0000000000..f32cc5c5b9
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *
+ * Modifications:
+ * 2010-07-16 Yuriy Vashchuk - Base class simplification. Redraw bug correction.
+ * Double Buffering implementation.
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.events.PaintEvent;
+
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * <b><u>HistogramCanvasPaintListener</u></b>
+ * <p>
+ * Implementation of a PaintListener for the specific need of the ParentHistogramCanvas.
+ * <p>
+ * The difference with the default one is that this one take a content that is the power of 2 higher
+ * than the display size.<p>
+ *
+ * When it is time to draw, it takes the closest power of 2 smaller than the canvas size; it is then easy to
+ * concatenate the interval as they are both power of 2.<p>
+ * The difference between the power of 2 and the not-power-of-2 canvas size is then filled by drawing bar that are
+ * slightly larger every (power/canvasSize) interval.<p>
+ */
+public class ParentHistogramCanvasPaintListener extends HistogramCanvasPaintListener
+{
+ private static ParentHistogramCanvas parentCanvas = null;
+
+ /**
+ * ParentHistogramCanvasPaintListener constructor
+ *
+ * @param newCanvas Related canvas
+ */
+ public ParentHistogramCanvasPaintListener(ParentHistogramCanvas newCanvas) {
+ parentCanvas = newCanvas;
+ }
+
+ // *** VERIFY ***
+ // Is it good to put this synchronized?
+ //
+ /**
+ * Draw the histogram bars in the canvas.<p>
+ * This drawing function expect the content to be the power of 2 higher than the canvas size.
+ * The bars size will be slightly dynamic to fill the gap between the power and the canvas size.<p>
+ *
+ * Note : This draw function is somewhat heavier than the default one.
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ @Override
+ public synchronized void drawHistogram(GC imageGC, Image image) {
+ final HistogramContent tmpContent = parentCanvas.getHistogramContent();
+ final int tmpBarWidth = tmpContent.getBarsWidth();
+
+ imageGC.setBackground(parentCanvas.getDisplay().getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR));
+
+ // Calculate the closest power of 2 just smaller than the canvas size
+ final int closestPowerToCanvas = (int)Math.pow(2, Math.floor( Math.log( image.getBounds().width ) / Math.log(2.0) ));
+
+ // Make sure the canvas didn't change size, it which case we need to recalculate our heights
+ recalculateHeightIfCanvasSizeChanged();
+
+ // Calculate the factor of difference between canvas and the power
+ final double factor = (double)image.getBounds().width / (double)closestPowerToCanvas;
+ // Calculate how many interval will need to be concatenated into one pixel
+ final int intervalDifference = (tmpContent.getNbElement() / closestPowerToCanvas)*tmpBarWidth;
+
+ // This keep a link between the position in "power" and the pixel we draw
+ // I.e. correlation between position in the power ("fake" pixels) and the position in the canvas ("real" pixels)
+ // So if pos == 30 and factor == 1.5, we know that the pixel that draw this pos is (30 * 1.5) == 45
+ int posInPower = 0;
+ int widthFilled = 0;
+
+ // Read from 0 up to the currently ready position
+ // We advance by "intervalDifference" as the bars migth not represent 1 interval only
+ int itemWidth = 0;
+ int thisElementHeight = 0;
+ for( int contentPos=0; contentPos < tmpContent.getReadyUpToPosition(); contentPos += intervalDifference ) {
+ // Width of the current item.
+ // Vary because of the difference between the power of 2 and the canvas size
+ // Ex: if power == 1024 and canvas == 1500, a bars every (1024/1500) will have a size of 2 instead of 1.
+ itemWidth = (int)( Math.ceil((double)(posInPower+1)*factor) - Math.ceil((double)posInPower*factor) );
+ itemWidth = itemWidth * tmpBarWidth;
+
+ // Concatenate all the element in the interval
+ // Ex : if power == 1024 and content == 2048, every (2048/1024)*bars_width will be concatenated
+ thisElementHeight = 0;
+ for ( int concatPos=0; concatPos<intervalDifference; concatPos++) {
+ final int updatedPos = contentPos + concatPos;
+ // Make sure we don't cross the last element available.
+ if ( updatedPos < tmpContent.getReadyUpToPosition() ) {
+ thisElementHeight += tmpContent.getElementByIndex(contentPos + concatPos).intervalHeight;
+ }
+ }
+
+ // *** NOTE ***
+ // Y Position in a canvas is REVERSED, so "0" is on top of the screen and "MAX" is on bottom.
+ // Not very instinctive, isn't it?
+
+ // Draw our rectangle
+ imageGC.fillRectangle(
+ widthFilled,
+ image.getBounds().height - thisElementHeight,
+ itemWidth,
+ thisElementHeight
+ );
+
+ // Keep in a variable how much width we filld so far
+ widthFilled += itemWidth;
+ // Keep a correlation between fake_pixel -> real_pixel,
+ // this is used to calculate the width of each element
+ posInPower++;
+ }
+ }
+
+ /*
+ * The function will make sure that the "max difference average" factor is still the same as before;
+ * if not, the heigth of the events will be recalculated.<p>
+ *
+ * The factor might change if the canvas is resized by a big factor.<p>
+ */
+ protected void recalculateHeightIfCanvasSizeChanged() {
+ final HistogramContent tmpContent = parentCanvas.getHistogramContent();
+ // We need to ajust the "maxDifferenceToAverageFactor" as the bars we draw might be slitghly larger than the value asked
+ // Each "interval" are concatenated when draw so the worst case should be :
+ // contentSize / (closest power of 2 to canvasMaxSize)
+ // Ex : if canvasSize is 1500 -> (2048 / 1024) == 2 so maxDiff should be twice larger
+ //
+ // His is set in the create content of the canvas, but we need to recalculate it
+ // here because the window might have been resized!
+ final int exp = (int)Math.floor( Math.log( (double)tmpContent.getCanvasWindowSize() ) / Math.log(2.0) );
+ final int contentSize = (int)Math.pow(2, exp);
+ final double maxBarsDiffFactor = ((double)tmpContent.getNbElement() / (double)contentSize );
+
+ // Floating point comparaison :
+ // We consider it is different if the difference is greater than 10^-3
+ if ( Math.abs(maxBarsDiffFactor - tmpContent.getMaxDifferenceToAverageFactor()) > 0.001 ) {
+ // The factor changed! That's unfortunate because it will take a while to recalculate.
+ tmpContent.setMaxDifferenceToAverageFactor(maxBarsDiffFactor);
+ tmpContent.recalculateHeightFactor();
+ tmpContent.recalculateEventHeight();
+ }
+ }
+
+ /**
+ * Function called when the canvas need to redraw.<p>
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ @Override
+ public void paintControl(PaintEvent event) {
+
+ if (parentCanvas.getSize().x > 0 && parentCanvas.getSize().y > 0) {
+ Image image = (Image) parentCanvas.getData("double-buffer-image");
+
+ // Creates new image only absolutely necessary.
+ if (image == null
+ || image.getBounds().width != parentCanvas.getBounds().width
+ || image.getBounds().height != parentCanvas.getBounds().height) {
+
+ image = new Image(
+ event.display,
+ parentCanvas.getBounds().width,
+ parentCanvas.getBounds().height
+ );
+
+ parentCanvas.setData("double-buffer-image", image);
+ }
+
+ // Initializes the graphics context of the image.
+ GC imageGC = new GC(image);
+
+ // First clear the whole canvas to have a clean section where to draw
+ clearDrawingSection(imageGC, image, parentCanvas);
+
+ // If the content is null or has rady to draw we quit the function here
+ if ( (parentCanvas.getHistogramContent() != null) && (parentCanvas.getHistogramContent().getReadyUpToPosition() != 0) ) {
+ // Call the function that draw the bars
+ drawHistogram(imageGC, image);
+
+ // If we have a selected window set to visible, call the function to draw it
+ if ( (parentCanvas.getCurrentWindow() != null) && (parentCanvas.getCurrentWindow().getSelectedWindowVisible()) ) {
+ drawSelectedWindow(
+ imageGC,
+ image
+ );
+ }
+
+ // Draws the buffer image onto the canvas.
+ event.gc.drawImage(image, 0, 0);
+ }
+
+ imageGC.dispose();
+ }
+
+ }
+
+ /**
+ * Draw the selection window in the canvas.<p>
+ * This draw a square around the selected section with a crosshair in the middle.
+ * The square cannot be smaller than "MINIMUM_WINDOW_WIDTH"
+ *
+ * @param imageGC GC content.
+ * @param image Image content.
+ */
+ public void drawSelectedWindow(GC imageGC, Image image) {
+ // Get the window position... this would fail if the window is not initialized yet
+ final int positionCenter = parentCanvas.getCurrentWindow().getWindowXPositionCenter();
+ final int positionLeft = parentCanvas.getCurrentWindow().getWindowXPositionLeft();
+ final int positionRight = parentCanvas.getCurrentWindow().getWindowXPositionRight();
+
+ final int imageHeight = image.getBounds().height;
+
+ // Draw the selection window square
+ // Attributes (color and width) of the lines
+ imageGC.setForeground(parentCanvas.getDisplay().getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR));
+ imageGC.setLineWidth(HistogramConstant.SELECTION_LINE_WIDTH);
+ imageGC.drawLine(positionLeft , 0 , positionLeft , imageHeight);
+ imageGC.drawLine(positionLeft , imageHeight, positionRight, imageHeight);
+ imageGC.drawLine(positionRight, imageHeight, positionRight, 0);
+ imageGC.drawLine(positionLeft , 0 , positionRight, 0);
+
+ // Draw the crosshair section
+ imageGC.setBackground(parentCanvas.getDisplay().getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR));
+ imageGC.fillOval(
+ positionCenter,
+ imageHeight / 2,
+ HistogramConstant.SELECTION_CROSSHAIR_LENGTH,
+ HistogramConstant.SELECTION_CROSSHAIR_LENGTH
+ );
+ }
+
+}

Back to the top