Final modifications to HistogramView before integration in TimeframeView (bugid=308695)
authorWilliam Bourque <william.bourque@polymtl.ca>
Fri, 9 Apr 2010 19:54:37 +0000 (19:54 +0000)
committerWilliam Bourque <william.bourque@polymtl.ca>
Fri, 9 Apr 2010 19:54:37 +0000 (19:54 +0000)
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvas.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasFocusListener.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasPaintListener.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramConstant.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramContent.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java
org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java

index 6d2780794e85ae5c89f2c23255104d3a6af21fd7..b51e4e05d365e578785c3271701bcd28f87cccbb 100644 (file)
@@ -94,8 +94,7 @@ public class HistogramCanvas extends Canvas
                // paintlistener need to know about the new content...
                // This is nowhere near elegant, change me.
                paintListener.setHistogramContent(histogramContent);
-               paintListener.setColumnWidth(widthPerBar);
-               paintListener.setColumnHeight(barsHeight);
+               paintListener.setBarWidth(widthPerBar);
                
                // New selected window, not visible by default
                createNewSelectedWindow(windowSize);
index 7da5c78a4c5c6a14bc733e6c1c2948d5ea85f9b8..4f0566f1b3121e0950bb29d0842f7414f8a1e4a3 100644 (file)
@@ -22,7 +22,6 @@ import org.eclipse.swt.events.FocusListener;
  */
 public class HistogramCanvasFocusListener implements FocusListener {
        
-       @SuppressWarnings("unused")
        private HistogramCanvas parentCanvas = null;
        
        /**
@@ -37,12 +36,12 @@ public class HistogramCanvasFocusListener implements FocusListener {
        /**
         * Function that is called when the canvas get focus.<p>
         * 
-        * Doesn't do anything yet..
+        * Redraw the screen to make sure everything is sane
         * 
         * @param event  The focus event generated.
         */
        public void focusGained(FocusEvent event) {
-               System.out.println("focusGained");
+               parentCanvas.redrawAsynchronously();
        }
        
        /**
index f215c8158adde67391561d0e89c28474f7d3e50d..39a7cc6057bd05aafa99045f7f2ae9fdc9add8c9 100644 (file)
@@ -15,122 +15,186 @@ import org.eclipse.swt.events.PaintEvent;
 import org.eclipse.swt.events.PaintListener;
 import org.eclipse.swt.graphics.Rectangle;
 
-public class HistogramCanvasPaintListener implements PaintListener {
+/**
+ * <b><u>HistogramCanvasPaintListener</u></b>
+ * <p>
+ * Implementation of a PaintListener for the need of the HistogramCanvas
+ * <p> 
+ */
+public class HistogramCanvasPaintListener implements PaintListener 
+{
        private HistogramContent histogramContent = null;
        private HistogramSelectedWindow selectedWindow = null;
        
-       private int columnWidth = 0;
-       private int columnHeight = 0;
+       private int barsWidth = 0;
        
+       /**
+        * HistogramCanvasPaintListener constructor
+        * 
+        * @param parentCanvas Related canvas
+        */
        public HistogramCanvasPaintListener(HistogramCanvas parentCanvas) {
                histogramContent = parentCanvas.getHistogramContent();
        }
        
-       public void paintControl(PaintEvent e) {
+       /**
+        * Function called when the canvas need to redraw.<p>
+        * 
+        * @param event  The generated paint event when redraw is called.
+        */
+       public void paintControl(PaintEvent event) {
                
-               clearDrawingSection(e);
+               // First clear the whole canvas to have a clean section where to draw
+               clearDrawingSection(event);
                
+               // If the content is null or has rady to draw we quit the function here
                if ( (histogramContent == null) || (histogramContent.getReadyUpToPosition() == 0) ) {
                        return;
                }
                
-               if ( (e.height != columnHeight) && (columnHeight != 0) ) {
-                       columnHeight = e.height;
-               }
-               
-               drawHistogram(e);
+               // Call the function that draw the bars
+               drawHistogram(event);
                
+               // If we have a selected window set to visible, call the function to draw it
                if ( (selectedWindow != null) && (selectedWindow.getSelectedWindowVisible() == true) ) {
-                       drawSelectedWindow(e);
+                       drawSelectedWindow(event);
                }
        }
        
-       public void clearDrawingSection(PaintEvent e) {
-               e.gc.setForeground(e.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
-               e.gc.setBackground(e.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
-               Rectangle allSection = new Rectangle(0, 0, e.width, e.height);
-               e.gc.fillRectangle(allSection);
-               e.gc.drawRectangle(allSection);
+       /**
+        * Clear the drawing section of the canvas<p>
+        * This paint the whole background in EMPTY_BACKGROUND_COLOR, so we have something clean to draw on.
+        * 
+        * @param event The generated paint event when redraw is called.
+        */
+       public void clearDrawingSection(PaintEvent event) {
+               event.gc.setForeground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+               event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+               Rectangle allSection = new Rectangle(0, 0, event.width, event.height);
+               event.gc.fillRectangle(allSection);
+               event.gc.drawRectangle(allSection);
        }
        
+       
        // *** VERIFY ***
        // Is it good to put this synchronized?
        //
-       public synchronized void drawHistogram(PaintEvent e) {
-           e.gc.setForeground(e.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
-               Rectangle allSection = new Rectangle(0, 0, histogramContent.getReadyUpToPosition()*columnWidth, e.height);
-               e.gc.fillRectangle(allSection);
-               e.gc.drawRectangle(allSection);
+       /**
+        * Draw the histogram bars in the canvas.<p>
+        * Use existing elements in HistogramContent to draw bars on the cancas; 
+        *      the element table in content need to be populated and have consistent value.  
+        * 
+        * @param event The generated paint event when redraw is called.
+        */
+       public synchronized void drawHistogram(PaintEvent event) {
+               // This will be the color for all the bars that wil be draw below.
+               event.gc.setBackground(event.display.getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR));
+               
+               // *** 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?
                
-           e.gc.setBackground(e.display.getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR));
+               // Draw a bar from the left (pos X=0) until the pos=(NbBars*barWidth). If space is left, it will be blanked after.
            for ( int x=0; x<histogramContent.getReadyUpToPosition(); x++) {
-               Rectangle rect = new Rectangle(columnWidth*x, columnHeight - histogramContent.getElementByIndex(x).intervalHeight, columnWidth, histogramContent.getElementByIndex(x).intervalHeight);
-                       
-               e.gc.fillRectangle(rect);
+               Rectangle rect = new Rectangle(barsWidth*x, event.height - histogramContent.getElementByIndex(x).intervalHeight, barsWidth, histogramContent.getElementByIndex(x).intervalHeight);
+               event.gc.fillRectangle(rect);
            }
            
-           e.gc.setBackground(e.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
-           Rectangle rect = new Rectangle(columnWidth*histogramContent.getNbElement(), 0, e.width, columnHeight);
-               e.gc.fillRectangle(rect);
+           // Clear the remaining space in the canvas (if any) so it appears clean.
+           event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+           Rectangle rect = new Rectangle(barsWidth*histogramContent.getNbElement(), 0, event.width, event.height);
+           event.gc.fillRectangle(rect);
        }
        
-       public void drawSelectedWindow(PaintEvent e) {
-               
-               e.gc.setForeground(e.display.getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR));
-           e.gc.setBackground(e.display.getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR));
-               
-               e.gc.setLineWidth(HistogramConstant.SELECTION_LINE_WIDTH);
+       /**
+        * Draw the selection window in the canvas.<p>
+        * This draw a square ober the selected section with a crosshair in the middle.
+        * The square cannot be smaller than "MINIMUM_WINDOW_WIDTH"
+        * 
+        * @param event The generated paint event when redraw is called.
+        */
+       public void drawSelectedWindow(PaintEvent event) {
+               // Attributes (color and width) of the lines
+               event.gc.setForeground(event.display.getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR));
+               event.gc.setLineWidth(HistogramConstant.SELECTION_LINE_WIDTH);
            
+               // Get the window position... this would fail if the window is not initialized yet
                int positionCenter = selectedWindow.getWindowCenterXPosition();
                int positionLeft = selectedWindow.getWindowPositionLeft();
                int positionRight = selectedWindow.getWindowPositionRight();
                
+               // Minimal size verification.
                if ( (positionRight - positionLeft) < HistogramConstant.MINIMUM_WINDOW_WIDTH ) {
                        positionLeft  = positionCenter - (HistogramConstant.MINIMUM_WINDOW_WIDTH/2);
                        positionRight = positionCenter + (HistogramConstant.MINIMUM_WINDOW_WIDTH/2);
                }
                
-               e.gc.drawLine(positionLeft , 0       , positionLeft , e.height);
-           e.gc.drawLine(positionLeft , e.height, positionRight, e.height);
-           e.gc.drawLine(positionRight, e.height, positionRight, 0);
-           e.gc.drawLine(positionLeft , 0       , positionRight, 0);
+               // Draw the selection window square
+               event.gc.drawLine(positionLeft , 0               , positionLeft , event.height);
+               event.gc.drawLine(positionLeft , event.height, positionRight, event.height);
+               event.gc.drawLine(positionRight, event.height, positionRight, 0);
+               event.gc.drawLine(positionLeft , 0               , positionRight, 0);
            
-           
-           e.gc.drawLine(positionCenter + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, e.height/2, positionCenter - HistogramConstant.SELECTION_CROSSHAIR_LENGTH, e.height/2);
-           e.gc.drawLine(positionCenter, (e.height/2) + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, positionCenter, (e.height/2) - HistogramConstant.SELECTION_CROSSHAIR_LENGTH);
+               // Draw the crosshair section
+               event.gc.drawLine(positionCenter + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, event.height/2, positionCenter - HistogramConstant.SELECTION_CROSSHAIR_LENGTH, event.height/2);
+               event.gc.drawLine(positionCenter, (event.height/2) + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, positionCenter, (event.height/2) - HistogramConstant.SELECTION_CROSSHAIR_LENGTH);
        }
        
-       
+       /**
+        * Getter for the histogram content used by this paint listener.
+        * 
+        * @return Histogram content currently tied to this paint listener
+        */
        public HistogramContent getHistogramContent() {
                return histogramContent;
        }
        
+       /**
+        * Setter for the histogram content used by this paint listener.<p>
+        * The new content will be displayed upon the next redraw (assuming the content is populated).
+        * 
+        * @return Histogram content currently tied to this paint listener
+        */
        public void setHistogramContent(HistogramContent newhistogramContent) {
                this.histogramContent = newhistogramContent;
        }
        
-       public int getColumnWidth() {
-               return columnWidth;
+       /**
+        * Getter for the bars witdh of this paint listener.
+        * 
+        * @return Bars width we will use during draw. 
+        */
+       public int getBarWidth() {
+               return barsWidth;
        }
        
-       public void setColumnWidth(int newcolumnWidth) {
-               this.columnWidth = newcolumnWidth;
+       /**
+        * Getter for the bars witdh of this paint listener.<p>
+        * NOTE : This MUST be set before any draw is done.
+        * 
+        * @param newBarsWidth  The new width to use for the bars
+        */
+       public void setBarWidth(int newBarsWidth) {
+               this.barsWidth = newBarsWidth;
        }
        
-       public int getColumnHeight() {
-               return columnHeight;
+       /**
+        * Getter for the selection window used by this paint listener
+        * 
+        * @return The selection window tied to this paint listener
+        */
+       public HistogramSelectedWindow getSelectedWindow() {
+               return selectedWindow;
        }
        
-       public void setColumnHeight(int newcolumnHeight) {
-               this.columnHeight = newcolumnHeight;
-       }
-
+       /**
+        * Setter for the selection window used by this paint listener.<p>
+        * NOTE : a null selectedWindow or a selectedWindow with visible == false will be ignored (i.e. : not draw).
+        * 
+        * @param newSelectedWindow     The new selection window
+        */
        public void setSelectedWindow(HistogramSelectedWindow newSelectedWindow) {
                this.selectedWindow = newSelectedWindow;
        }
-
-       public HistogramSelectedWindow getSelectedWindow() {
-               return selectedWindow;
-       }
        
 }
index 86cda89b266f882d7a6aebda366f16ba47c785e1..56d7d48057e74d1081c5f09f5b162e9f525ed09d 100644 (file)
@@ -23,10 +23,11 @@ public interface HistogramConstant {
        // Constants relative to requests
        final static int MAX_EVENTS_PER_READ = 1;
        final static int REDRAW_EVERY_NB_EVENTS = 10000;
+       final static boolean SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE = true;
        
        
        // Constant relative to the content
-       final static double DEFAULT_DIFFERENCE_TO_AVERAGE = 100.0;
+       final static double DEFAULT_DIFFERENCE_TO_AVERAGE = 1000.0;
        
        
        
index 1acac38bd37249d22a639ff1fa23a1a56eca952f..5dfd0caa318fa81b91d0beaed8491cf2da2ff6d9 100644 (file)
  *******************************************************************************/
 package org.eclipse.linuxtools.lttng.ui.views.histogram;
 
-import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
 
+/**
+ * <b><u>HistogramContent</u></b>
+ * <p>
+ * This class hold the content that will be used to draw the Histograms.
+ * <p>
+ */
 public class HistogramContent {
        
        private Long    startTime = 0L;
@@ -22,27 +27,53 @@ public class HistogramContent {
        private Double  heightFactor = 0.0;
        private Long    heighestEventCount = 0L;
        private Integer maxHeight        = 0;
+       
+       // This value is used to calculate at which point we should "cut" bar that are too tall.
+       // Default value is large enought so that no bar should be cut
        private Double  maxDifferenceToAverage = HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE;
        
        private Integer readyUpToPosition = 0;
-       private Integer fullWindowSize = 0;
+       private Integer canvasFullSize = 0;
        
        private Integer averageNumberOfEvents = 0;
        
        private HistogramElement[] elementTable;
        
-       public HistogramContent(int tableSize, int newWindowsSize, int newMaxHeight) {
-               this(tableSize, newWindowsSize, newMaxHeight, HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE);
-       }
-       
-       public HistogramContent(int tableSize, int newWindowsSize, int newMaxHeight, double newDiffToAverage) {
-               fullWindowSize = newWindowsSize;
+       /**
+        * Default constructor for the HistogramContent.
+        * 
+        * @param tableSize                     The size ofthe element table that will be created.
+        * @param newCanvasSize         The full size of the canvas. Used for positionning; need to be consistent with canvas.
+        * @param newMaxHeight          The maximum height of a bar, usually same as the height of the canvas.
+        */
+       public HistogramContent(int tableSize, int newCanvasSize, int newMaxHeight) {
+               this(tableSize, newCanvasSize, newMaxHeight, HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE);
+       }
+       
+       /**
+        * Default constructor for the HistogramContent.
+        * 
+        * @param tableSize                     The size ofthe element table that will be created.
+        * @param newCanvasSize         The full size of the canvas. Used for positionning; need to be consistent with canvas.
+        * @param newMaxHeight          The maximum height of a bar, usually same as the height of the canvas.
+        * @param newDiffToAverage  This value at which point we "cut" bar that are too tall.
+        */
+       public HistogramContent(int tableSize, int newCanvasSize, int newMaxHeight, double newDiffToAverage) {
+               canvasFullSize = newCanvasSize;
                maxHeight = newMaxHeight;
                maxDifferenceToAverage = newDiffToAverage;
                
+               // Create a new element table from the above value
+               // The table will not get initialized until resetTable() is called. 
                createNewTable(tableSize);
        }
        
+       /**
+        * Create a new table to hold the content element.<p>
+        * Note that the table is not initialized (and so unusable) until resetTable() is called.
+        * 
+        * @param newTableSize  The size (number of element) of the table.
+        */
        public void createNewTable(int newTableSize) {
                elementTable = new HistogramElement[newTableSize];
                
@@ -52,6 +83,9 @@ public class HistogramContent {
                }
        }
        
+       /**
+        * Reset all HistogramContent attributes, but keep the elements table untouched.<p>
+        */
        public void resetContentData() {
                startTime = 0L;
                endTime = 0L;
@@ -63,6 +97,10 @@ public class HistogramContent {
                readyUpToPosition = 0;
        }
        
+       /**
+        * Reset the data in the elements table.<p>
+        * NOTE : For this to be consistent and usuable, "startTime" and "intervalTime" need to be set.
+        */
        public void resetTable() {
                for ( int x=0; x<elementTable.length; x++) {
                        elementTable[x].position = x;
@@ -72,6 +110,9 @@ public class HistogramContent {
                }
        }
        
+       /**
+        * Print all HistogramContent attributes, but the elements table.
+        */
        public void printContentInfo() {
                System.out.println("startTime          : " + startTime);
                System.out.println("endTime            : " + endTime );
@@ -83,32 +124,25 @@ public class HistogramContent {
                System.out.println("readyUpToPosition  : " + readyUpToPosition);
        }
        
+       /**
+        * Print the data in the elements table.<p>
+        */
        public void printTable() {
                for ( int x=0; x<elementTable.length; x++) {
                        System.out.println("X:" + x + " -> " + elementTable[x].intervalNbEvents + ":" + elementTable[x].intervalHeight);
                }
        }
        
-       public void recalculateEventHeight() {
-               
-               if ( getHeighestEventCount() > (maxDifferenceToAverage * averageNumberOfEvents) ) {
-                       heightFactor = (double)maxHeight/( maxDifferenceToAverage * (double)averageNumberOfEvents);
-               }
-               else {
-                       heightFactor = (double)maxHeight/(double)getHeighestEventCount();
-               }
-               
-               for ( int x=0; x<elementTable.length; x++) {
-                       elementTable[x].intervalHeight = (int)(elementTable[x].intervalNbEvents * heightFactor);
-               }
-       }
-       
-       public int getNbElement() {
-               return elementTable.length;
-       }
-       
+       /**
+        * Get an element in the table by its index.<p>
+        * Null is returned if the index is out of range.<p>
+        * Note that you can get an element past "readyUpToPosition", the index is NOT tested against it. 
+        * 
+        * @param index The index of the element (0 < index < nbElement)
+        * 
+        * @return The element found or null if the index is wrong.
+        */
        public HistogramElement getElementByIndex(int index) {
-               
                HistogramElement returnedElement = null;
                
                if ( (index >= 0) && (index < elementTable.length) ) {
@@ -118,13 +152,22 @@ public class HistogramContent {
                return returnedElement;
        }
        
-       
-       public HistogramElement getElementFromXPosition(int position) {
+       /**
+        * Return the closest element to a X position on the canvas.<p>
+        * Note : canvasFullSize need to be set correctly here, otherwise unexpected element might be returned.<p>
+        * <p>
+        * NOTE : This <b>ALWAYS</b> return an element; 
+        *              If calculation lead outside the table, the first or the last element will be returned.  
+        * 
+        * @param position  The X position we are looking at (0 < pos < canvasWidth) 
+        * 
+        * @return      The <i>closest</i> element found.
+        */
+       public HistogramElement getClosestElementFromXPosition(int position) {
                
-               HistogramElement returnedElement = null;
-               
-               int index = (int)(  ((double)elementTable.length)*((double)position/(double)fullWindowSize) );
+               int index = (int)(  ((double)elementTable.length)*((double)position/(double)canvasFullSize) );
                
+               // If we are out of bound, return the closest border (first or last element)
                if ( index < 0) {
                        index = 0;
                }
@@ -132,156 +175,398 @@ public class HistogramContent {
                        index = (elementTable.length -1);
                }
                
-               returnedElement = elementTable[index];
-               
-               return returnedElement;
-       }
-       
-       public HistogramElement getElementFromTimestamp(TmfTimestamp timestamp) {
-               
-               HistogramElement returnedElement = null;
-               
-               int index = (int)( (timestamp.getValue() - startTime)/intervalTime );
+               return elementTable[index];
+       }
+       
+       /**
+        * Return the X position (relative to the canvas) of a certain element.<p>
+        * Note : canvasFullSize need to be set correctly here, otherwise unexpected element might be returned.<p>
+        * 
+        * NOTE : This <b>ALWAYS</b> return an element; 
+        *              If calculation lead outside the table, the first or the last element will be returned.
+        * 
+        * @param targetElement         The element we are looking to find the position 
+        * 
+        * @return                                      The <i>closest</i> found element. 
+        */
+       public int getXPositionFromElement(HistogramElement targetElement) {
+               return (int)( ((double)targetElement.position / (double)elementTable.length)*(double)canvasFullSize );
+       }
+       
+       /**
+        * Return the closest element to a timestamp (long) given.<p>
+        * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected element might be returned.<p>
+        * <p>
+        * NOTE : This <b>ALWAYS</b> return an element; 
+        *              If calculation lead outside the table, the first or the last element will be returned.  
+        * 
+        * @param timestamp  The timestamp (in nanosecond, as long) of the element we are looking for (startTime < timestamp < endTime) 
+        * 
+        * @return      The <i>closest</i> element found.
+        */
+       public HistogramElement getClosestElementFromTimestamp(long timestamp) {
+               int index = (int)( (timestamp - startTime)/intervalTime );
                
+               // If we are out of bound, return the closest border (first or last element)
                if ( index < 0) {
                        index = 0;
                }
+               else if ( index >= elementTable.length ) {
+                       index = (elementTable.length -1);
+               }
                
-               returnedElement = elementTable[index];
-               
-               return returnedElement;
-       }
-       
-       
+               return elementTable[index];
+       }
+       
+       /**
+        * Return the closest element to an element and a time interval to this element.<p>
+        * The time interval can be negative or positive (before or after the element).
+        * 
+        * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.<p>
+        * 
+        * @param targetElement                 The element we compare the interval with.
+        * @param intervalToElement             Time negative or positive time interval (in nanosecond) to this element. 
+        * 
+        * @return      The <i>closest</i> found element, or null if given data are wrong.
+        */
        public HistogramElement getClosestElementByElementAndTimeInterval(HistogramElement targetElement, Long intervalToElement) {
                
-               HistogramElement returnedElement = null;
+               // Get the timestamp of the target element
+               // This should always be valid as long the table is initialized
+               Long elementTime = targetElement.firstIntervalTimestamp;
+               elementTime = elementTime + intervalToElement;
                
-               if ( (targetElement != null) && (intervalTime > 0) ) {
-                       Long elementTime = targetElement.position * intervalTime;
-                       
-                       elementTime = elementTime + intervalToElement;
-                       
-                       int newPos = (int)(elementTime / intervalTime );
-                       
-                       if ( newPos < 0 ) {
-                               newPos = 0;
-                       }
-                       
-                       if ( newPos >= elementTable.length ) {
-                               newPos = elementTable.length - 1;
-                       }
-                       
-                       returnedElement = elementTable[newPos];
-               }
+               return getClosestElementFromTimestamp(elementTime);
+       }
+       
+       /**
+        * Return the closest element to an element's timestamp (as long) and a time interval to this element.<p>
+        * The time interval can be negative or positive (before or after the element).
+        * 
+        * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.<p>
+        * 
+        * @param timestamp                             The timestamp (in nanoseconds, as long) of the element we want to compare from.
+        * @param intervalToElement             Time negative or positive time interval (in nanosecond) to this element. 
+        * 
+        * @return      The <i>closest</i> found element, or null if given data are wrong.
+        */
+       public int getClosestElementByTimestampAndTimeInterval(Long timestamp, Long intervalToElement) {
+               HistogramElement targetElement = getClosestElementFromTimestamp(timestamp);
+               HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement);
                
-               return returnedElement;
-       }
-       
+               return getXPositionFromElement(newElement);
+       }
+       
+       /**
+        * Return the closest element to an element's position and a time interval to this element.<p>
+        * The time interval can be negative or positive (before or after the element).
+        * 
+        * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.<p>
+        * 
+        * @param targetPosition                The position (relative to the canvas) of the element we want to compare from.
+        * @param intervalToElement             Time negative or positive time interval (in nanosecond) to this element.
+        * 
+        * @return      The <i>closest</i> found element, or null if given data are wrong.
+        */
        public int getXPositionByPositionAndTimeInterval(int targetPosition, Long intervalToElement) {
-               int returnedValue = 0;
+               HistogramElement targetElement = getClosestElementFromXPosition(targetPosition);
+               HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement);
                
-               HistogramElement targetElement = getElementFromXPosition(targetPosition);
-               
-               if ( targetElement != null ) {
-                       HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement);
-                       
-                       if ( newElement != null ) {
-                               returnedValue = getXPositionFromElement(newElement);
-                       }
-               }
-               
-               return returnedValue;
+               return  getXPositionFromElement(newElement);
        }
        
-       
-       public int getXPositionFromElement(HistogramElement targetElement) {
-               
-               int returnedPosition = (int)( ((double)targetElement.position / (double)elementTable.length)*(double)fullWindowSize );
-               
-               return returnedPosition;
+       /**
+        * Getter for the number of element.<p>
+        * The same as the value of tableSize given at construction.
+        * 
+        * @return The number of element in the elements table.
+        */
+       public int getNbElement() {
+               return elementTable.length;
        }
        
-       
+       /**
+        * Getter for the average number of events by interval in the content.<p>
+        * 
+        * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee.
+        * 
+        * @return      Average number of events we currently use in
+        */
        public int getAverageNumberOfEvents() {
                return averageNumberOfEvents;
        }
        
+       /**
+        * Setter for averageNumberOfEvents.<p>
+        * 
+        * Note : this is used in some drawing calculation so make sure this number make sense.
+        * Note : you might want to call recalculateEventHeight() if you change this.
+        * 
+        * @param newAverageNumberOfEvents      The new average number of events to use.
+        */
        public void setAverageNumberOfEvents(int newAverageNumberOfEvents) {
                this.averageNumberOfEvents = newAverageNumberOfEvents;
        }
        
+       /**
+        * Recalculate the average number of events by time interval.<p>
+        * 
+        * Note : This run over all the element so this is quite cpu intensive, use with care. 
+        */
+       public void recalculateAverageNumberOfEvents() {
+               
+               int nbInterval = 0;
+               int totalNbEvents = 0;
+               
+               // Go over the element up to readyUpToPosition (further position might not be ready)
+               for ( int x=0; x<readyUpToPosition; x++) {
+                       // Skip the empty interval if we were asked to do so.
+                       if ( HistogramConstant.SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE ) {
+                               if ( elementTable[x].intervalNbEvents > 0 ) {
+                               nbInterval++;
+                               }
+               }
+               else {
+                       nbInterval++;
+               }
+                       
+                       totalNbEvents += elementTable[x].intervalNbEvents;
+               }
+               // Calculate the average here
+               averageNumberOfEvents = totalNbEvents / nbInterval;
+       }
+       
+       /**
+        * Getter for the start time of the content.<p>
+        * 
+        * @return The start time we currently use.
+        */
        public Long getStartTime() {
                return startTime;
        }
        
+       /**
+        * Setter for the start time of the content.<p>
+        * Note : You probably want to call "resetTable()" if you change this, otherwise data might be inconsistent.
+        * 
+        * @param newStartTime  the new start time
+        */
        public void setStartTime(Long newStartTime) {
                this.startTime = newStartTime;
        }
        
        
+       /**
+        * Getter for the end time of the content.<p>
+        * 
+        * @return The end time we currently use.
+        */
        public Long getEndTime() {
                return endTime;
        }
-
+       
+       // *** TODO ***
+       // Implement a way to "compress" a table if the endtime change.
+       // That way, the end time could change without having to reset the table data.
+       /**
+        * Setter for the end time of the content.<p>
+        * Note : You probably want to call "resetTable()" if you change this, otherwise data might be inconsistent.
+        * 
+        * @param newStartTime  the new end time
+        */
        public void setEndTime(Long newEndTime) {
                this.endTime = newEndTime;
        }
        
+       /**
+        * Getter for the complete time interval of the content.<p>
+        * Note : This return "endTime" minus "startTime", unlike getReadyTimeInterval() it won't check the actual time of elements.  
+        * 
+        * @return      The complete time interval
+        */
        public Long getCompleteTimeInterval() {
                return ( endTime - startTime );
        }
        
+       /**
+        * Getter for the time interval for the element between first and readyUpToPosition<p>
+        * Note : This return element[readyPosition].time - element[first].time , not the full interval like getCompleteTimeInterval()
+        * 
+        * @return      The time interval of the position that are ready.
+        */
+       public Long getReadyTimeInterval() {
+               return ( elementTable[readyUpToPosition].firstIntervalTimestamp - elementTable[0].firstIntervalTimestamp );
+       }
+       
+       /**
+        * Getter for the height factor of the bar.<p>
+        * Note : height =  "nb events in interval" * heightFactor
+        * 
+        * @return      Height factor currently used. 
+        */
        public Double getHeightFactor() {
                return heightFactor;
        }
        
-       public void setHeightFactor(Double newheightFactor) {
-               this.heightFactor = newheightFactor;
+       /**
+        * Recalculate the height of each bar in the elements table.<p>
+        * Need to be called at least once, or when value of "maxHeight", "heighestEventCount" or "averageNumberOfEvents" changes.
+        */
+       public void recalculateEventHeight() {
+               
+               // Recalculate the new HeightFactor for the element; 
+               //              the highest bar will get "maxHeight" and other bar a fraction of it.
+               // If a maxDifferenceToAverage exist, this is considered here 
+               if ( heighestEventCount > (maxDifferenceToAverage * averageNumberOfEvents) ) {
+                       heightFactor = (double)maxHeight/( maxDifferenceToAverage * (double)averageNumberOfEvents);
+               }
+               else {
+                       heightFactor = (double)maxHeight/(double)heighestEventCount;
+               }
+               
+               // Recalculate the height of the bars up to "readyUpToPosition"
+               for ( int x=0; x<readyUpToPosition; x++) {
+                       elementTable[x].intervalHeight = (int)(elementTable[x].intervalNbEvents * heightFactor);
+               }
        }
        
-       
+       // *** TODO ***
+       // It is not possible for now to resize the canvas without creating a new content.
+       // We need to implement this somehow.
+       /**
+        * Getter for the full size of the canvas.<p>
+        * This is used for the positionnal calculation so should be consistent with the real canvas size.
+        * 
+        * @return      Size of the canvas we currently use.
+        */
+       public Integer getCanvasFullSize() {
+               return canvasFullSize;
+       }
+       
+       /**
+        * Getter for the heighest event count recorded so far for an interval.<p>
+        * 
+        * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee.
+        * 
+        * @return Current heighestEventCount
+        */
        public Long getHeighestEventCount() {
                return heighestEventCount;
        }
        
-       public void setHeighestEventCount(Long newheighestEventCount) {
-               this.heighestEventCount = newheighestEventCount;
+       /**
+        * Setter for setHeighestEventCount.<p>
+        * 
+        * Note : this is used in some drawing calculation so make sure this number make sense.
+        * Note : you might want to call recalculateEventHeight() if you change this.
+        * 
+        * @param newHeighestEventCount Heighest event count for a single interval.
+        */
+       public void setHeighestEventCount(Long newHeighestEventCount) {
+               this.heighestEventCount = newHeighestEventCount;
+       }
+       
+       /**
+        * Recalculate the heightest event count for a single time interval.<p>
+        * 
+        * Note : This run over all the element so this is quite cpu intensive, use with care. 
+        */
+       public void recalculateHeighestEventCount() {
+               // Go over the element up to readyUpToPosition (further position might not be ready)
+               for ( int x=0; x<readyUpToPosition; x++) {
+                       if ( elementTable[x].intervalNbEvents > heighestEventCount ) {
+                               this.heighestEventCount = elementTable[x].intervalNbEvents;
+                       }
+               }
        }
        
+       /**
+        * Getter for the max height of a bar in the content.<p>
+        * 
+        * @return      maximum height for a bar we currently use.
+        */
        public Integer getMaxHeight() {
                return maxHeight;
        }
-
+       
+       /**
+        * Setter for maxHeight.<p>
+        * 
+        * Note : this is used in some drawing calculation so make sure this number make sense.
+        * Note : you might want to call recalculateEventHeight() if you change this.
+        * 
+        * @param maxHeight     The new maximum height for a bar to use.
+        */
        public void setMaxHeight(Integer maxHeight) {
                this.maxHeight = maxHeight;
        }
        
-       
+       /**
+        * Getter for the max difference to the average height a bar can have.<p>
+        * This determine at which point a bar too tall is "cut". Set a very large value (like 1000.0) to ignore.
+        * 
+        * @return      maximum difference to the average we currently use.
+        */
        public Double getMaxDifferenceToAverage() {
                return maxDifferenceToAverage;
        }
        
+       /**
+        * Setter for the max difference to the average height a bar can have.<p>
+        * This determine at which point a bar too tall is "cut". Set a very large value (like 1000.0) to ignore.
+        * 
+        * Note : this is used in some drawing calculation so make sure this number make sense.
+        * Note : you might want to call recalculateEventHeight() if you change this.
+        * 
+        * @param newDiffToAverage      The new maximum difference to the average to use.
+        */
        public void setMaxDifferenceToAverage(Double newDiffToAverage) {
                maxDifferenceToAverage = newDiffToAverage;
        }
        
        
-       public int getReadyUpToPosition() {
-               return readyUpToPosition;
-       }
-
-       public void setReadyUpToPosition(int newReadyUpToPosition) {
-               this.readyUpToPosition = newReadyUpToPosition;
-       }
-       
-       
+       /**
+        * Getter for the interval time of each interval.<p>
+        * This is usually "(EndTime - StartTime) / NbElement"
+        * 
+        * @return      Currently used interval time.
+        */
        public Long getIntervalTime() {
                return intervalTime;
        }
        
+       
+       /**
+        * Setter for the interval time of each interval.<p>
+        * 
+        * Note : this is used in some drawing calculation so make sure this number make sense.
+        * Note : you migth want to call resetTable() to to fill the element's table again if you change this.
+        * 
+        * @return New interval time.
+        */
        public void setIntervalTime(Long newInterval) {
                this.intervalTime = newInterval;
        }
        
+       
+       /**
+        * Getter for readyUpToPosition.<p>
+        * This should tell to which point the content is filled, calculated and ready to use.
+        * 
+        * @return Last position processed so far.
+        */
+       public int getReadyUpToPosition() {
+               return readyUpToPosition;
+       }
+       
+       /**
+        * Setter for readyUpToPosition.<p>
+        * Set a new point (position) up to where the content is filled, calculated and ready to use. 
+        * 
+        * @param newReadyUpToPosition  The new position to use.
+        */
+       public void setReadyUpToPosition(int newReadyUpToPosition) {
+               this.readyUpToPosition = newReadyUpToPosition;
+       }
+       
 }
index a78332df6c153c2889518301674948177ddecf29..aea49993834fbd88a7e96e1fae257790c06dc1c0 100644 (file)
@@ -17,10 +17,11 @@ package org.eclipse.linuxtools.lttng.ui.views.histogram;
  * This is used by the content to keep its data. 
  * It would be a struct if such a thing would exist in java. 
  * <p>
+ * Each "element" should represent a certain time interval
  */
 public class HistogramElement {
-       public Integer position = 0;
-       public Long firstIntervalTimestamp = 0L;
-       public Long intervalNbEvents = 0L;
-       public Integer intervalHeight = 0;
+       public Integer position = 0;                            // Position of the element in the table (table index, usually)
+       public Long firstIntervalTimestamp = 0L;        // The first timestamp recorded for this interval 
+       public Long intervalNbEvents = 0L;                      // Number of events recorded in this interval
+       public Integer intervalHeight = 0;                      // Height (in the canvas) of this element. Should be smaller than the canvas height.
 }
index 8f79b277f0dcff23c47357dc9dd6efb47bc8f68a..3c7e72771e5341219748bc52f3015ce1c2a3ae87 100644 (file)
@@ -116,7 +116,7 @@ public class HistogramRequest extends TmfEventRequest<LttngEvent> {
                                        }
                                        
                                        // * NOTE * 
-                                       // We save the time we have. This mean only the FIRST time read in an interval will be saved. 
+                                       // We save the time we have here. This mean only the FIRST time read in an interval will be saved. 
                                        histogramContent.getElementByIndex(lastInterval).firstIntervalTimestamp = lastRangeTime;
                                        histogramContent.setReadyUpToPosition(lastInterval);
                                        
@@ -193,10 +193,19 @@ public class HistogramRequest extends TmfEventRequest<LttngEvent> {
        
     /**
         * Update the HistogramContent with the latest information.<p>
-        * This will perform some calculation that might be a bit harsh so it shouldnt be called too often.
+        * This will perform some calculation that might be a bit harsh so it should'nt be called too often.
         */
     public void updateEventsInfo() {
-       int averageNumberOfEvents = nbEventRead / nbIntervalNotEmpty;
+       // *** Note *** 
+       // The average number of event is calculated while skipping empty interval if asked
+       int averageNumberOfEvents = 0;
+       if ( HistogramConstant.SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE ) {
+               averageNumberOfEvents = nbEventRead / nbIntervalNotEmpty;
+       }
+       else {
+               averageNumberOfEvents = nbEventRead / histogramContent.getNbElement();
+       }
+       
                histogramContent.setAverageNumberOfEvents(averageNumberOfEvents);
                histogramContent.recalculateEventHeight();
     }
index 0e9d6900008a2637768ecab385423752ac9d81c2..70a4b031e799ce40f1a19dc9fa1868629750c9b4 100644 (file)
  *******************************************************************************/
 package org.eclipse.linuxtools.lttng.ui.views.histogram;
 
+/**
+ * <b><u>HistogramSelectedWindow</u></b>
+ * <p>
+ * Selection window represent the selected section of the trace in the HistogramCanvas.
+ * <p>
+ * The selected window have 3 important attributes : 
+ * <ul>
+ * <li>Its central position
+ * <li>Its time width
+ * <li>Its visibility (to determine if we should draw it or not)
+ * </ul>
+ * The dimension are then deduced from the first 2 values.
+ * This mean the window is always a perfectly symetrical rectangle.
+ */
 public class HistogramSelectedWindow {
        
        private int windowCenterXPosition = 0;
@@ -19,68 +33,149 @@ public class HistogramSelectedWindow {
        private boolean isSelectedWindowVisible = false;
        
        private HistogramContent histogramContent = null;
-
+       
+       /**
+        * Default constructor for HistogramSelectedWindow.<p>
+        * Position and TimeWidth are both set to 0
+        * 
+        * @param newTraceContent       HistogramContent to read window's data from
+        */
        public HistogramSelectedWindow(HistogramContent newTraceContent) {
                histogramContent = newTraceContent;
        }
        
+       /**
+        * Default constructor for HistogramSelectedWindow.<p>
+        * Position and TimeWidth are set to given value.
+        * 
+        * @param newTraceContent       HistogramContent to read window's data from
+        * @param centralPosition       Central X Position of the selection window in the canvas (0 to canvasWidth)
+        * @param newWindowWidth        Time width (size) of the window. (0 or greater)
+        */
        public HistogramSelectedWindow(HistogramContent newTraceContent, int centralPosition, long newWindowWidth) {
                histogramContent = newTraceContent;
                windowCenterXPosition = centralPosition;
                windowTimeWidth = newWindowWidth;
        }
        
-
+       /** 
+        * Getter for the HistogramContent used by the window.<p>
+        * 
+        * @return HistogramContent tied to this selection window.
+        */
+       public HistogramContent getTraceContent() {
+               return histogramContent;
+       }
+       
+       /**
+        * Setter for the HistogramContent used by the window.<p>
+        * This need to be a valid, initialized HistogramContent;
+        *      the data in the content are needed for positionning the window.
+        * 
+        * @param newTraceContent  A new HistogramContent
+        */
+       public void setTraceContent(HistogramContent newTraceContent) {
+               this.histogramContent = newTraceContent;
+       }
+       
+       
+       /**
+        * Getter for the window visibility.<p>
+        * 
+        * @return true if the window is visible (will be draw), false otherwise
+        */
        public boolean getSelectedWindowVisible() {
                return isSelectedWindowVisible;
        }
        
+       /**
+        * Setter for the window visibility.<p>
+        * True means the window will be draw, false that it will be hidden.
+        * 
+        * @param newIsSelectedWindowVisible    The visibility value
+        */
        public void setSelectedWindowVisible(boolean newIsSelectedWindowVisible) {
                this.isSelectedWindowVisible = newIsSelectedWindowVisible;
        }
-
        
+       
+       /**
+        * Getter for the window time width (size)
+        * 
+        * @return Window time width (size)
+        */
        public long getWindowTimeWidth() {
                return windowTimeWidth;
        }
        
+       /**
+        * Setter for the window time width (size).<p>
+        * Width need to be a time (in nanoseconds) that's coherent to the data we are looking at.
+        * 
+        * @param newWindowTimeWidth    The new time width
+        */
        public void setWindowTimeWidth(long newWindowTimeWidth) {
                this.windowTimeWidth = newWindowTimeWidth;
        }
        
-
-       public HistogramContent getTraceContent() {
-               return histogramContent;
-       }
-       
-       public void setTraceContent(HistogramContent newTraceContent) {
-               this.histogramContent = newTraceContent;
-       }
-       
        
+       /**
+        * Getter for the central position of the window.<p>
+        * 
+        * @return Center X position of this window on the canvas.
+        */
        public int getWindowCenterXPosition() {
                return windowCenterXPosition;
        }
        
+       /**
+        * Setter for the central position of the window.<p>
+        * The new position need to be valid on the canvas (0 to canvasWidth).
+        * 
+        * @param newPosCenter  The new central position.
+        */
        public void setWindowCenterXPosition(int newPosCenter) {
                this.windowCenterXPosition = newPosCenter;
        }
        
        
+       /**
+        * Getter for the left border of the window.<p>
+        * Compute the position from the HistogramContent data; may return 0 if the content data are wrong.  
+        * 
+        * @return The left position of the window, or 0 if it cannot compute it. 
+        */
        public int getWindowPositionLeft() {
                return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterXPosition, -(windowTimeWidth / 2) );
        }
        
+       /**
+        * Getter for the right border of the window.<p>
+        * Compute the position from the HistogramContent data; may return 0 if the content data are wrong.  
+        * 
+        * @return The right position of the window, or 0 if it cannot compute it. 
+        */
        public int getWindowPositionRight() {
                return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterXPosition, +(windowTimeWidth / 2) );
        }
        
+       /**
+        * Getter for the timestamp of left border of the window.<p>
+        * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong.  
+        * 
+        * @return  The left timestamp of the window, or 0 if it cannot compute it. 
+        */
        public long getTimestampLeft() {
-               return histogramContent.getElementFromXPosition( getWindowPositionLeft() ).firstIntervalTimestamp;
+               return histogramContent.getClosestElementFromXPosition( getWindowPositionLeft() ).firstIntervalTimestamp;
        }
        
+       /**
+        * Getter for the timestamp of right border of the window.<p>
+        * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong.  
+        * 
+        * @return  The right timestamp of the window, or 0 if it cannot compute it. 
+        */
        public long getTimestampRight() {
-               return histogramContent.getElementFromXPosition( getWindowPositionRight() ).firstIntervalTimestamp;
+               return histogramContent.getClosestElementFromXPosition( getWindowPositionRight() ).firstIntervalTimestamp;
        }
-       
 }
This page took 0.040061 seconds and 5 git commands to generate.