From b59134e1685ff4bc0dcd29554bd1b45f066a3b8c Mon Sep 17 00:00:00 2001 From: William Bourque Date: Thu, 1 Apr 2010 00:09:39 +0000 Subject: [PATCH] Draft of a HistogramView, in process of merging into the TimeFrameView --- .../ui/views/histogram/HistogramContent.java | 786 +++--------------- .../ui/views/histogram/HistogramElement.java | 28 +- .../ui/views/histogram/HistogramRequest.java | 230 ++--- .../histogram/HistogramSelectedWindow.java | 211 +---- .../ui/views/histogram/HistogramView.java | 149 +++- .../lttng/ui/views/histogram/TraceCanvas.java | 170 ++++ .../histogram/TraceCanvasPaintListener.java | 131 +++ 7 files changed, 618 insertions(+), 1087 deletions(-) create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvas.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvasPaintListener.java diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramContent.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramContent.java index 0959def0b6..8f83b483f5 100644 --- a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramContent.java +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramContent.java @@ -1,234 +1,100 @@ -/******************************************************************************* - * 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 - *******************************************************************************/ package org.eclipse.linuxtools.lttng.ui.views.histogram; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; -/** - * HistogramContent - *

- * This class hold the content that will be used to draw the Histograms. - *

- */ public class HistogramContent { - // Start and end time of the content - protected long startTime = 0L; - protected long endTime = 0L; - - // Some information about the content - // Most of them are required to calculate position and/or draw - // Make sure they stay consistent! - protected long elementsTimeInterval = 1L; - protected double heightFactor = 100.0; - protected long heighestEventCount = 0L; - protected int maxHeight = 0; - protected int canvasWindowSize = 0; - protected int barsWidth = 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 - protected double maxDifferenceToAverage = HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE; - // This is a factor we might apply on the max difference to average, as example if we concatenate interval together - protected double maxDifferenceFactor = 1.0; - - // By default we will only consider element up to this position - protected int readyUpToPosition = 0; - - // The average number of events in the content - // Note : this IS needed to draw - protected int averageNumberOfEvents = 0; - - // This is to draw the selected event of the TMF framework in another color - // Set the 0 to ignore - protected long selectedEventTimeInWindow = -1L; - - // The table that hold the elements - protected HistogramElement[] elementTable; - - - /** - * 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 newBarWidth, int newMaxHeight) { - this(tableSize, newCanvasSize, newBarWidth, newMaxHeight, HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE); - } + final static double MAX_DIFFERENCE_TO_AVERAGE = 2.0; + + private Long startTime = 0L; + private Long endTime = 0L; + + private Long intervalTime = 0L; + private Double heightFactor = 0.0; + private Long heighestEventCount = 0L; + private Integer maxHeight = 0; + + private Integer readyUpToPosition = 0; + private Integer fullWindowSize = 0; + + private Integer averageNumberOfEvents = 0; - /** - * 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 newBarWidth, int newMaxHeight, double newDiffToAverage) { - canvasWindowSize = newCanvasSize; - barsWidth = newBarWidth; + private HistogramElement[] elementTable; + + public HistogramContent(int tableSize, int newWindowsSize, int newMaxHeight) { + fullWindowSize = newWindowsSize; 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.

- * 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]; for ( int x=0; x - */ - public void clearContentData() { + public void resetContentData() { startTime = 0L; endTime = 0L; - elementsTimeInterval = 1L; - heightFactor = 100.0; + intervalTime = 0L; + heightFactor = 0.0; heighestEventCount = 0L; readyUpToPosition = 0; + + cleanTable(); } - /** - * Reset the data in the elements table.

- * NOTE : For this to be consistent and usuable, "startTime", "endTime" and "intervalTime" need to be set already. - */ - public void resetTable() { + public void cleanTable() { for ( int x=0; x - * Start and EndTime will be used to calculate elementsTimeInterval.

- * - * @param newStartTime The new start time to use - * @param newEndTime The new stop time to use - */ - public void resetTable(long newStartTime, long newEndTime) { - recalculateElementsTimeInterval(newStartTime, newEndTime); - resetTable(newStartTime, newEndTime, elementsTimeInterval); - } - - /** - * Reset the data in the elements table.

- * elementsTimeInterval will be set to the one give, use this for fixed interval.

- * - * @param newStartTime The new start time to use - * @param newEndTime The new stop time to use - * @param newTimeInterval The new time interval to use - */ - public void resetTable(long newStartTime, long newEndTime, long newTimeInterval) { - - startTime = newStartTime; - endTime = newEndTime; - recalculateElementsTimeInterval(newStartTime, newEndTime); - + public void printTable() { for ( int x=0; x " + elementTable[x].intervalNbEvents + ":" + elementTable[x].intervalHeight); } } - /** - * Clear (zeroed) the data in the elements table.

- * NOTE : Unlike reset, this does not recalculate the content, - * so it should be done either by hand or by calling reset table after. - */ - public void clearTable() { - for ( int x=0; x (MAX_DIFFERENCE_TO_AVERAGE * averageNumberOfEvents) ) { + heightFactor = (double)maxHeight/( MAX_DIFFERENCE_TO_AVERAGE * (double)averageNumberOfEvents); } - } - - /** - * Print all HistogramContent attributes, but the elements table. - */ - public void printContentInfo() { - System.out.println("startTime : " + startTime); - System.out.println("endTime : " + endTime ); - System.out.println(); - System.out.println("intervalTime : " + elementsTimeInterval); - System.out.println("heightFactor : " + heightFactor); - System.out.println("heighestEventCount : " + heighestEventCount); - System.out.println(); - System.out.println("readyUpToPosition : " + readyUpToPosition); - } - - /** - * Print the data in the elements table.

- */ - public void printTable() { + else { + heightFactor = (double)maxHeight/(double)getHeighestEventCount(); + } + for ( int x=0; x " + elementTable[x].intervalNbEvents + ":" + elementTable[x].intervalHeight + " (" + elementTable[x].firstIntervalTimestamp + ")"); + elementTable[x].intervalHeight = (int)(elementTable[x].intervalNbEvents * heightFactor); } } - /** - * Getter for the timestamp of the selected event in the window.

- * - * @return The time of the event. - */ - public long getSelectedEventTimeInWindow() { - return selectedEventTimeInWindow; + /* + // *** VERIFY *** + // We don't need to expose the table, do we ? + public HistogramElement[] getElementTable() { + return elementTable; } + */ - /** - * Setter for the timestamp of the selected event in the window.

- * - * This allow to pinpoint a certain event or position in the window. - * Set to 0 or lower to ignore. - * - * @param newPosition The new event time. - */ - public void setSelectedEventTimeInWindow(long newTime) { - this.selectedEventTimeInWindow = newTime; + public int getNbElement() { + return elementTable.length; } - /** - * Get an element in the table by its index.

- * Null is returned if the index is out of range.

- * 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) ) { @@ -238,548 +104,158 @@ public class HistogramContent { return returnedElement; } - /** - * Return the closest element to a X position on the canvas.

- * Note : canvasWindowSize need to be set correctly here, otherwise unexpected element might be returned.

- *

- * NOTE : This ALWAYS 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 closest element found. - */ - public HistogramElement getClosestElementFromXPosition(int position) { + + public HistogramElement getElementFromXPosition(int position) { + + HistogramElement returnedElement = null; - int index = (int)Math.round((double)elementTable.length * ((double)position / (double)canvasWindowSize) ); + int index = (int)( ((double)elementTable.length)*((double)position/(double)fullWindowSize) ); - // 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); - } - return elementTable[index]; - } - - /** - * Return the closest element's timestamp to a X position on the canvas.

- * Note : canvasWindowSize need to be set correctly here, otherwise unexpected timestamp might be returned.

- *

- * NOTE : This ALWAYS return a timestamp; - * If calculation lead outside the table, the first or the last timestamp will be returned. - * - * @param position The X position we are looking at (0 < pos < canvasWidth) - * - * @return The closest timestamp found. - */ - public long getClosestTimestampFromXPosition(int position) { - return getClosestElementFromXPosition(position).firstIntervalTimestamp; - } - - /** - * Return the X position (relative to the canvas) of a certain element.

- * Note : canvasWindowSize need to be set correctly here, otherwise unexpected element might be returned.

- * - * NOTE : This ALWAYS 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 closest found element. - */ - public int getXPositionFromElement(HistogramElement targetElement) { - return (int)Math.round( ((double)targetElement.index / (double)elementTable.length)*(double)canvasWindowSize ); + /* + System.out.println("position " + position); + System.out.println("fullWindowSize " + fullWindowSize); + System.out.println("index " + index); + */ + + returnedElement = elementTable[index]; + + return returnedElement; } - /** - * Return the closest element to a timestamp (long) given.

- * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected element might be returned.

- *

- * NOTE : This ALWAYS 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 closest element found. - */ - public HistogramElement getClosestElementFromTimestamp(long timestamp) { - int index = (int)Math.round( (double)(timestamp - startTime)/(double)elementsTimeInterval ); + public HistogramElement getElementFromTimestamp(TmfTimestamp timestamp) { + + HistogramElement returnedElement = null; + + int index = (int)( (timestamp.getValue() - 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); - } - return elementTable[index]; + /* + System.out.println("timestamp " + timestamp); + System.out.println("intervalTime " + intervalTime); + System.out.println("index " + index); + */ + + returnedElement = elementTable[index]; + + return returnedElement; } - /** - * Return the closest X position to a timestamp (long) given.

- * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected position might be returned.

- *

- * NOTE : This ALWAYS return a position; - * If calculation lead outside the table, the first or the last position will be returned. - * - * @param timestamp The timestamp (in nanosecond, as long) of the element we are looking for (startTime < timestamp < endTime) - * - * @return The closest position found. - */ - public int getClosestXPositionFromTimestamp(long timestamp) { - return getXPositionFromElement(getClosestElementFromTimestamp(timestamp)); - } - /** - * Return the closest element to an element and a time interval to this element.

- * 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.

- * - * @param targetElement The element we compare the interval with. - * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element. - * - * @return The closest found element, or null if given data are wrong. - */ - public HistogramElement getClosestElementByElementAndTimeInterval(HistogramElement targetElement, long intervalToElement) { + public HistogramElement getClosestElementByTimeInterval(HistogramElement targetElement, Long intervalToElement) { - // 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; + HistogramElement returnedElement = null; - return getClosestElementFromTimestamp(elementTime); - } - - /** - * Return the closest element to an element's timestamp (as long) and a time interval to this element.

- * 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.

- * - * @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 closest 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); + if ( targetElement != null) { + 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; + } + + /* + System.out.println("targetElement.position " + targetElement.position); + System.out.println("intervalTime " + intervalTime); + System.out.println("intervalToElement " + intervalToElement); + System.out.println("elementTime " + elementTime); + System.out.println("newPos " + newPos); + */ + + returnedElement = elementTable[newPos]; + } - return getXPositionFromElement(newElement); + return returnedElement; } - /** - * Return the closest element to an element's position and a time interval to this element.

- * 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.

- * - * @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 closest found element, or null if given data are wrong. - */ - public int getXPositionByPositionAndTimeInterval(int targetPosition, long intervalToElement) { - HistogramElement targetElement = getClosestElementFromXPosition(targetPosition); - HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement); + public int getXPositionFromElement(HistogramElement targetElement) { + + int returnedPosition = (int)( ((double)targetElement.position / (double)elementTable.length)*(double)fullWindowSize ); - return getXPositionFromElement(newElement); + return returnedPosition; } - /** - * Getter for the number of element.

- * 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.

- * - * 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.

- * - * 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.

- * - * 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 0 ) { - nbInterval++; - } - } - else { - nbInterval++; - } - - totalNbEvents += elementTable[x].intervalNbEvents; - } - // Calculate the average here - averageNumberOfEvents = (int)Math.round((double)totalNbEvents / (double)nbInterval); - } - - /** - * Getter for the start time of the content.

- * - * @return The start time we currently use. - */ - public long getStartTime() { + public Long getStartTime() { return startTime; } - /** - * Setter for the start time of the content.

- * 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) { + public void setStartTime(Long newStartTime) { this.startTime = newStartTime; } - /** - * Getter for the end time of the content.

- * - * @return The end time we currently use. - */ - public long getEndTime() { + public Long getEndTime() { return endTime; } - - /** - * Setter for the end time of the content.

- * 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) { + + public void setEndTime(Long newEndTime) { this.endTime = newEndTime; } - /** - * Getter for the complete time interval of the content.

- * 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

- * 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.

- * Note : height = "nb events in interval" * heightFactor - * - * @return Height factor currently used. - */ - public double getHeightFactor() { + public Double getHeightFactor() { return heightFactor; } - /** - * Recalculate the height factor of the element table.

- * Assume values of "maxHeight", "heighestEventCount" or "averageNumberOfEvents" are set correctly. - */ - public void recalculateHeightFactor() { - // Recalculate the new HeightFactor for the element; - // the highest bar will get "maxHeight" and other bar a fraction of it. - double diffToConsider = (maxDifferenceToAverage * maxDifferenceFactor * (double)barsWidth); - - if ( heighestEventCount > (long)(diffToConsider * (double)averageNumberOfEvents) ) { - heightFactor = (double)maxHeight/( diffToConsider * (double)averageNumberOfEvents); - } - else { - heightFactor = (double)maxHeight/(double)heighestEventCount; - } - } - - /** - * Recalculate the height of each bar in the elements table.

- * This assume "heightFactor" is already set correctly.

- * - * NOTE : if "maxHeight", "heighestEventCount" or "averageNumberOfEvents" changes, - * recalculateHeightFactor() should be recalled. - */ - public void recalculateEventHeight() { - // Recalculate the height of the bars up to "readyUpToPosition" - for ( int x=0; x - * Unlike recalculateEventHeight(), this only recalculate for the given range, not the whole table. - * - */ - public void recalculateEventHeightInInterval(int startPosition, int stopPosition) { - // Basic error checking on start : should be bigger than 0 - if ( startPosition < 0 ) { - startPosition = 0; - } - - // Basic error checking on start : should be smaller than length - 1 - if ( stopPosition >= elementTable.length) { - stopPosition = (elementTable.length-1); - } - - // Recalculate the height of the bars from startPosition to stopPosition - for ( int x=startPosition; x - * 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 int getCanvasWindowSize() { - return canvasWindowSize; + public void setHeightFactor(Double newheightFactor) { + this.heightFactor = newheightFactor; } - /** - * Set a new full size of the canvas.

- * This is used for the positionnal calculation so should be consistent with the real canvas size. - * - * @param newSize New canvas size; - */ - public void setCanvasWindowSize(int newSize) { - canvasWindowSize = newSize; - } - /** - * Getter for the heighest event count recorded so far for an interval.

- * - * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee. - * - * @return Current heighestEventCount - */ - public long getHeighestEventCount() { + public Long getHeighestEventCount() { return heighestEventCount; } - /** - * Setter for setHeighestEventCount.

- * - * 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.

- * - * 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 heighestEventCount ) { - this.heighestEventCount = elementTable[x].intervalNbEvents; - } - } + public void setHeighestEventCount(Long newheighestEventCount) { + this.heighestEventCount = newheighestEventCount; } - /** - * Getter for the max height of a bar in the content.

- * - * @return maximum height for a bar we currently use. - */ - public int getMaxHeight() { + public Integer getMaxHeight() { return maxHeight; } - - /** - * Setter for maxHeight.

- * - * 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(int maxHeight) { + + public void setMaxHeight(Integer maxHeight) { this.maxHeight = maxHeight; } - /** - * Getter for the max difference to the average height a bar can have.

- * 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.

- * 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; - } - - - /** - * Getter for a factor applied to the max difference to the average height a bar can have.

- * This is muliplied to maxDifferenceToAverage. Set to value 1.0 to ignore. - * - * Note : this is useful if you concatenate some intervals to gether but want the average to be consistent - * - * @return maximum difference to the average we currently use. - */ - public double getMaxDifferenceToAverageFactor() { - return maxDifferenceFactor; - } - - /** - * Setter for a factor applied to the max difference to the average height a bar can have.

- * - * 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. - * Note : setting to 0 will cause bar to have a zero size... use 1.0 to desactivate - * - * @param newFactor The new factor to use. - */ - public void setMaxDifferenceToAverageFactor(double newFactor) { - maxDifferenceFactor = newFactor; - } - - - /** - * Getter for the interval time of each interval.

- * This is usually "(EndTime - StartTime) / NbElement" - * - * @return Currently used interval time. - */ - public long getElementsTimeInterval() { - return elementsTimeInterval; - } - - - /** - * Setter for the interval time of each interval.

- * - * 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 setElementsTimeInterval(long newInterval) { - this.elementsTimeInterval = newInterval; - } - - - /** - * Calculate the correct time interval of each element from the given time.

- * - * @return The complete time interval - */ - public void recalculateElementsTimeInterval(long startTime, long endTime) { - long tmpInterval = (long)Math.ceil((double)(endTime - startTime)/ (double)getNbElement()); - - if ( tmpInterval <= 0 ) { - tmpInterval = 1L; - } - - this.elementsTimeInterval = tmpInterval; - } - - - /** - * Getter for readyUpToPosition.

- * 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.

- * 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; } - /** - * Getter for the bar width.

- * This is needed by the paint listener usually. - * - * @return current bars width; - */ - public int getBarsWidth() { - return barsWidth; + + public Long getIntervalTime() { + return intervalTime; } - /** - * Setter for the bar width.

- * Setting this to 0 will hide all the bar in the histogram. - * - * @param newBarsWidth new bars width; - */ - public void setBarsWidth(int newBarsWidth) { - this.barsWidth = newBarsWidth; + public void setIntervalTime(Long newInterval) { + this.intervalTime = newInterval; } } diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java index eb907d4a9c..3a64c2f23a 100644 --- a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java @@ -1,27 +1,9 @@ -/******************************************************************************* - * 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 - *******************************************************************************/ package org.eclipse.linuxtools.lttng.ui.views.histogram; -/** - * HistogramElement - *

- * This is used by the content to keep its data. - * It would be a struct if such a thing would exist in java. - *

- * Each "element" should represent a certain time interval - */ public class HistogramElement { - public int index = 0; // Position of the element in the table (table index, obviously) - public long firstIntervalTimestamp = 0L; // The first timestamp recorded for this interval - public long intervalNbEvents = 0L; // Number of events recorded in this interval - public int intervalHeight = 0; // Height (in the canvas) of this element. Should be smaller than the canvas height. + public Integer position = 0; + public Long firstIntervalTimestamp = 0L; + public Long intervalNbEvents = 0L; + public Integer intervalHeight = 0; + public Boolean isInSelectedWindow = false; } diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java index 34d00572fb..3f3bc6c8e2 100644 --- a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java @@ -1,77 +1,39 @@ -/******************************************************************************* - * 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 - *******************************************************************************/ package org.eclipse.linuxtools.lttng.ui.views.histogram; import org.eclipse.linuxtools.lttng.event.LttngEvent; import org.eclipse.linuxtools.tmf.event.TmfEvent; import org.eclipse.linuxtools.tmf.event.TmfTimeRange; import org.eclipse.linuxtools.tmf.request.TmfEventRequest; +import org.eclipse.swt.widgets.Display; -/** - * HistogramRequest - *

- * Request class, to perform a request to TMF for the histograms. - *

- */ public class HistogramRequest extends TmfEventRequest { - protected HistogramContent histogramContent = null; - protected int lastInterval = 0; - protected long lastRangeTime = 0L; - protected long nbEventsInInterval = 0L; + final static int MAX_EVENTS_PER_REQUEST = 1; + final static int REDRAW_EVERY_NB_EVENTS = 10000; - protected int nbIntervalNotEmpty = 1; - protected int nbEventRead = 0; + private HistogramContent histogramContent = null; - protected int lastDrawPosition = 0; + private int lastPos = 0; + private long lastRangeTime = 0L; + private long nbEventsInRange = 1; - protected HistogramCanvas parentCanvas = null; + private int nbPosNotEmpty = 1; + private int nbEventRead = 0; - /** - * Constructor for HistogramRequest.

- * Prepare the request in TMF and reset the histogram content. - * - * @param range Range of the request. - * @param nbRequested Nb events requested. Can be "Infinity" for all. - * @param newParentCanvas HistogramCanvas related to the request. - * @param timeInterval Time interval to consider (i.e. : 1 interval is 1 bar in the histogram) - * - * @see org.eclipse.linuxtools.tmf.request.TmfEventRequest - */ - public HistogramRequest(TmfTimeRange range, int nbRequested, HistogramCanvas newParentCanvas, long timeInterval) { - super((Class)LttngEvent.class, range, nbRequested, HistogramConstant.MAX_EVENTS_PER_READ); - - // *** FIXME *** - // This does not work! The request won't be processed or the number of events returned is wrong! - // We cannot use this ! - //super((Class)dataType, range); + private TraceCanvas parentCanvas = null; + + @SuppressWarnings("unchecked") + public HistogramRequest(Class dataType, TmfTimeRange range, int nbRequested, HistogramContent newContent, TraceCanvas newParentCanvas) { + super((Class)dataType, range, nbRequested, MAX_EVENTS_PER_REQUEST); + histogramContent = newContent; parentCanvas = newParentCanvas; - histogramContent = parentCanvas.getHistogramContent(); - - // Reset the content of the HistogramContent... the given data better be valid or this will fail. - histogramContent.clearContentData(); - histogramContent.resetTable(range.getStartTime().getValue(), range.getEndTime().getValue(), timeInterval); - lastRangeTime = range.getStartTime().getValue(); + lastRangeTime = histogramContent.getStartTime(); - // Notify the UI even before the request started, so we set the timestamp already. - parentCanvas.notifyParentUpdatedInformationAsynchronously(); + histogramContent.resetContentData(); } - - /** - * HandleData function : will be called by TMF each time a new event is receive for the request.

- * Calculation for the content is done here. - */ + @Override public void handleData() { TmfEvent[] result = getData(); @@ -79,159 +41,73 @@ public class HistogramRequest extends TmfEventRequest { evt[0] = (result.length > 0) ? result[0] : null; - // *** FIXME *** - // *** EVIL BUG *** - // The request by timerange only does not work! (see constructor above) - // However, the request with number of events will loop until it reach its number or EOF - // We have to filter out ourself the extra useless events! - // - if (evt[0] != null) { - + if ( evt[0] != null ) { LttngEvent tmpEvent = (LttngEvent)evt[0]; - // This check is linked to the evil fix mentionned above - if ( ( tmpEvent.getTimestamp().getValue() >= histogramContent.getStartTime() ) && - ( tmpEvent.getTimestamp().getValue() <= histogramContent.getEndTime() ) ) - { - - // Distance (in time) between this event and the last one we read - long distance = ( tmpEvent.getTimestamp().getValue() - lastRangeTime ); + long distance = ( tmpEvent.getTimestamp().getValue() - lastRangeTime ); + + if ( distance > histogramContent.getIntervalTime() ) { - // Check if we changed of interval (the distance is higher than the interval time) - if ( distance > histogramContent.getElementsTimeInterval() ) { - - histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval; - lastRangeTime = tmpEvent.getTimestamp().getValue(); - - // * NOTE * - // We can skip several interval at once, so we need to find what was our interval now - lastInterval = (int)((lastRangeTime - histogramContent.getStartTime()) / histogramContent.getElementsTimeInterval() ); - - // *** HACK *** - // Because of the threads, weird phenomenons seem to happen here, like a position after the - // element range because another request was issued. - // This enforce the position but may result in slightly inconsistent result (i.e. a weird misplaced bar sometime). - if ( lastInterval < 0 ) { - lastInterval = 0; - } - else if ( lastInterval >= histogramContent.getNbElement() ) { - lastInterval = (histogramContent.getNbElement()-1); - } - - // * NOTE * - // 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); - - nbIntervalNotEmpty++; - nbEventsInInterval = 1L; - } - // We are still in the same interval, just keep counting - else { - nbEventsInInterval++; - } + histogramContent.getElementByIndex(lastPos).intervalNbEvents = nbEventsInRange; + lastRangeTime = tmpEvent.getTimestamp().getValue(); - if ( nbEventsInInterval > histogramContent.getHeighestEventCount() ) { - histogramContent.setHeighestEventCount(nbEventsInInterval); - } - nbEventRead++; + lastPos = (int)((lastRangeTime - histogramContent.getStartTime()) / histogramContent.getIntervalTime() ); + histogramContent.getElementByIndex(lastPos).firstIntervalTimestamp = lastRangeTime; + + histogramContent.setReadyUpToPosition(lastPos); - // Call an asynchronous redraw every REDRAW_EVERY_NB_EVENTS events - // That way we don't need to wait until to end to have something on the screen - if ( nbEventRead % HistogramConstant.REDRAW_EVERY_NB_EVENTS == 0 ) { - redrawAsyncronously(); + nbPosNotEmpty++; + nbEventsInRange = 1; + } + else { + nbEventsInRange++; + if ( nbEventsInRange > histogramContent.getHeighestEventCount() ) { + histogramContent.setHeighestEventCount(nbEventsInRange); } - } - } - // We got a null event! This mean we reach the end of the request. - // Save the last interval we had, so we won't miss the very last events at the end. - else { - // Save the last events - histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval; - // We reached the end of the request, so assume we fill up the content as well - histogramContent.setReadyUpToPosition(histogramContent.getNbElement()); + } + + nbEventRead++; - // If the interval wasn't null, count this as a "non empty" interval - if (nbEventsInInterval > 0) { - nbIntervalNotEmpty++; + if ( nbEventRead % REDRAW_EVERY_NB_EVENTS == 0 ) { + redrawAsyncronously(); } - } + + } } - /** - * Function that is called when the request completed (successful or not).

- * Update information and redraw the screen. - */ @Override public void handleCompleted() { - parentCanvas.notifyParentUpdatedInformationAsynchronously(); redrawAsyncronously(); } - /** - * Function that is called when the request completed successfully.

- */ @Override public void handleSuccess() { - // Nothing different from completed. } - /** - * Function that is called when the request completed in failure.

- */ @Override public void handleFailure() { - // Nothing different from cancel. } - /** - * Function that is called when the request was cancelled.

- * Redraw and set the requestCompleted flag to true; - */ @Override public void handleCancel() { - redrawAsyncronously(); } - /** - * Update the HistogramContent with the latest information.

- * This will perform some calculation that might be a bit harsh so it should'nt be called too often. - */ + public void updateEventsInfo() { - // *** 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 = (int)Math.ceil((double)nbEventRead / (double)nbIntervalNotEmpty); - } - else { - averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)histogramContent.getNbElement()); - } - - histogramContent.setAverageNumberOfEvents(averageNumberOfEvents); - - // It is possible that the height factor didn't change; - // If not, we only need to redraw the updated section, no the whole content - // Save the actual height, recalculate the height and check if there was any changes - double previousHeightFactor = histogramContent.getHeightFactor(); - histogramContent.recalculateHeightFactor(); - if ( histogramContent.getHeightFactor() != previousHeightFactor ) { - histogramContent.recalculateEventHeight(); - } - else { - histogramContent.recalculateEventHeightInInterval(lastDrawPosition, histogramContent.getReadyUpToPosition()); - } - - lastDrawPosition = histogramContent.getReadyUpToPosition(); + int averageNumberOfEvents = nbEventRead / nbPosNotEmpty; + histogramContent.setAverageNumberOfEvents(averageNumberOfEvents); + histogramContent.recalculateEventHeight(); } - /** - * Perform an asynchonous redraw of the screen. - */ public void redrawAsyncronously() { updateEventsInfo(); - // Canvas redraw is already asynchronous - parentCanvas.redrawAsynchronously(); + + Display display = parentCanvas.getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentCanvas.redraw(); + } + }); } } diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java index 562da82b90..e8bd21c7b7 100644 --- a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java @@ -1,212 +1,7 @@ -/******************************************************************************* - * 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 - *******************************************************************************/ package org.eclipse.linuxtools.lttng.ui.views.histogram; -/** - * HistogramSelectedWindow - *

- * Selection window represent the selected section of the trace in the HistogramCanvas. - *

- * The selected window have 3 important attributes : - *

- * The dimension are then deduced from the first 2 values. - * This mean the window is always a perfectly symetrical rectangle. - */ public class HistogramSelectedWindow { - - protected int windowCenterPosition = 0; - protected long windowTimeWidth = 0L; - - protected Boolean isSelectedWindowVisible = false; - - protected HistogramContent histogramContent = null; - - /** - * Default constructor for HistogramSelectedWindow.

- * 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.

- * 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; - windowCenterPosition = centralPosition; - windowTimeWidth = newWindowWidth; - } - - /** - * Getter for the HistogramContent used by the window.

- * - * @return HistogramContent tied to this selection window. - */ - public HistogramContent getTraceContent() { - return histogramContent; - } - - /** - * Setter for the HistogramContent used by the window.

- * 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.

- * - * @return true if the window is visible (will be draw), false otherwise - */ - public boolean getSelectedWindowVisible() { - return isSelectedWindowVisible; - } - - /** - * Setter for the window visibility.

- * 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).

- * 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; - } - - - /** - * Getter for the central position of the window.

- * - * @return Center X position of this window on the canvas. - */ - public int getWindowXPositionCenter() { - return windowCenterPosition; - } - - /** - * Setter for the central position of the window.

- * The new position need to be valid on the canvas (0 to canvasWidth). - * - * @param newPosCenter The new central position. - */ - public void setWindowXPositionCenter(int newPosCenter) { - this.windowCenterPosition = newPosCenter; - } - - /** - * Getter for the left border of the window.

- * 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 getWindowXPositionLeft() { - - // If the timewidth is too small, we would pick the same position as the center one. - // To avoid this, we take a "full interval" when the window size is too small - if ( windowTimeWidth < histogramContent.getElementsTimeInterval() ) { - // Use intervalTime and not intervalTime/2 to make sure we step into the next interval - // Otherwise, if we are in the beginning of an interval, adding IntervalTime/2 could lead us into the same one - // The rounding operation will then return a correct position - return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, -(histogramContent.getElementsTimeInterval() ) ); - } - else { - return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, -(windowTimeWidth / 2) ); - } - } - - /** - * Getter for the right border of the window.

- * 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 getWindowXPositionRight() { - // If the timewidth is too small, we would pick the same position as the center one. - // To avoid this, we take a "full interval" when the window size is too small - if ( windowTimeWidth < histogramContent.getElementsTimeInterval() ) { - // Use intervalTime and not intervalTime/2 to make sure we step into the next interval - // Otherwise, if we are in the beginning of an interval, adding IntervalTime/2 could lead us into the same one - // The rounding operation will then return a correct position - return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, +(histogramContent.getElementsTimeInterval() ) ); - } - else { - return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, +(windowTimeWidth / 2) ); - } - - } - - /** - * Getter for the timestamp of left border of the window.

- * 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 getTimestampOfLeftPosition() { - return histogramContent.getClosestElementFromXPosition( getWindowXPositionLeft() ).firstIntervalTimestamp; - } - - /** - * Getter for the timestamp of the center of the window.

- * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong. - * - * @return The center timestamp of the window, or 0 if it cannot compute it. - */ - public long getTimestampOfCenterPosition() { - return histogramContent.getClosestElementFromXPosition( getWindowXPositionCenter() ).firstIntervalTimestamp; - } - - /** - * Getter for the timestamp of right border of the window.

- * 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 getTimestampOfRightPosition() { - return histogramContent.getClosestElementFromXPosition( getWindowXPositionRight() ).firstIntervalTimestamp; - } + public int selectionLeft = 0; + public int selectionCenter = 0; + public int selectionRight = 0; } diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java index 4de5699b4a..c6eb642ef2 100644 --- a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java @@ -7,46 +7,147 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Francois Chouinard - Initial API and implementation + * William Bourque - Initial API and implementation *******************************************************************************/ package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.event.LttngTimestamp; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.experiment.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.experiment.TmfExperimentUpdatedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.ui.views.TmfView; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.part.ViewPart; -/** - * HistogramView - *

- * TODO: Implement me. Please. - */ -public class HistogramView extends ViewPart { +public class HistogramView extends TmfView { public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.histogram"; - - /** - * - */ + + + private HistogramRequest dataBackgroundFullRequest = null; + private TraceCanvas fullTraceCanvas = null; + + private HistogramRequest selectedWindowRequest = null; + private TraceCanvas selectedWindowCanvas = null; + public HistogramView() { - // TODO Auto-generated constructor stub + super(ID); } - - /* (non-Javadoc) - * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) - */ + + @Override public void createPartControl(Composite parent) { - // TODO Auto-generated method stub - + + Composite folderGroup = new Composite(parent, SWT.NONE); + +// GridLayout gl = new GridLayout(); +// gl.marginHeight = 0; +// gl.marginWidth = 0; +// folderGroup.setLayout(gl); + + folderGroup.setSize(parent.getDisplay().getBounds().width, parent.getDisplay().getBounds().height); + folderGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); + + fullTraceCanvas = new TraceCanvas(folderGroup, SWT.NONE, 2, 50); + + +// GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false); +// gd.heightHint = 50; +// fullTraceCanvas.setLayoutData(gd); + + fullTraceCanvas.redraw(); } + - /* (non-Javadoc) - * @see org.eclipse.ui.part.WorkbenchPart#setFocus() - */ + @SuppressWarnings("unchecked") @Override public void setFocus() { - // TODO Auto-generated method stub - + + TmfExperiment tmpExperiment = (TmfExperiment)TmfExperiment.getCurrentExperiment(); + + if ( (dataBackgroundFullRequest == null) && (tmpExperiment != null) ) { + // Create a new time range from "start" to "end" + // That way, we will get "everything" in the trace + LttngTimestamp ts1 = new LttngTimestamp( tmpExperiment.getStartTime() ); + LttngTimestamp ts2 = new LttngTimestamp( tmpExperiment.getEndTime() ); + TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2); + dataBackgroundFullRequest = performRequest(tmpExperiment, fullTraceCanvas, tmpRange); + + fullTraceCanvas.redraw(); + } } + + + @SuppressWarnings("unchecked") + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + fullTraceCanvas.getHistogramContent().resetContentData(); + fullTraceCanvas.resetSelectedWindow(); + + TmfExperiment tmpExperiment = (TmfExperiment)signal.getExperiment(); + + // Create a new time range from "start" to "end" + // That way, we will get "everything" in the trace + //LttngTimestamp ts1 = new LttngTimestamp( tmpExperiment.getStartTime() ); + //LttngTimestamp ts2 = new LttngTimestamp( tmpExperiment.getEndTime() ); + LttngTimestamp ts1 = new LttngTimestamp( tmpExperiment.getStartTime() ); + LttngTimestamp ts2 = new LttngTimestamp( tmpExperiment.getEndTime() ); + TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2); + + dataBackgroundFullRequest = performRequest(tmpExperiment, fullTraceCanvas, tmpRange); + + fullTraceCanvas.redraw(); + } + + // *** VERIFY *** + // this function is synchronized, is it a good idea? + public synchronized HistogramRequest performRequest(TmfExperiment experiment, TraceCanvas targetCanvas, TmfTimeRange newRange) { + + HistogramRequest returnedRequest = null; + + // The content holder we will use + HistogramContent content = targetCanvas.getHistogramContent(); + + // We use integer.MAX_VALUE because we want to make sure we get every events + returnedRequest = new HistogramRequest(LttngEvent.class, newRange, Integer.MAX_VALUE, content, targetCanvas ); + + content.setStartTime( experiment.getStartTime().getValue() ); + content.setEndTime( experiment.getEndTime().getValue() ); + + // Set a (dynamic) time interval + content.setIntervalTime( (content.getEndTime() - content.getStartTime()) / content.getNbElement() ); + + // *** VERIFY *** + // This would enable "fixed interval" instead of dynamic one. + // + //content.setIntervalTime((long)(0.001 * (double)1000000000)); + + experiment.sendRequest(returnedRequest); + + return returnedRequest; + } + + @TmfSignalHandler + public void experimentUpdated(TmfExperimentUpdatedSignal signal) { + System.out.println("experimentUpdated"); + + // *** TODO *** + // Update the histogram if the time changed + // + + } + + + @TmfSignalHandler + public void currentTimeUpdated(TmfTimeSynchSignal signal) { + System.out.println("currentTimeUpdated"); + } } diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvas.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvas.java new file mode 100644 index 0000000000..25974c271e --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvas.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; + +public class TraceCanvas extends Canvas implements MouseMoveListener, MouseListener, FocusListener +//public class TraceCanvas extends Canvas implements FocusListener, KeyListener, MouseMoveListener, MouseListener, MouseWheelListener, ControlListener, SelectionListener, MouseTrackListener, TraverseListener +{ + + public Long BIDON_VARIABLE_WINDOW_SIZE = (long)(0.1 * 1000000000L); // 0.1 seconds + + + final static int DEFAULT_WIDTH_PER_COL = 2; + final static int DEFAULT_MAX_HEIGHT_PER_COL = 50; + + private HistogramContent histogramContent = null; + + private TraceCanvasPaintListener paintListener = null; + + private int columnWidth = DEFAULT_WIDTH_PER_COL; + private int columnMaxHeight = DEFAULT_MAX_HEIGHT_PER_COL; + + public TraceCanvas(Composite parent, int style) { + this(parent, style, DEFAULT_WIDTH_PER_COL, DEFAULT_MAX_HEIGHT_PER_COL); + } + + public TraceCanvas(Composite parent, int style, int widthPerColumn, int columnHeight) { + super (parent, style); + + columnWidth = widthPerColumn; + columnMaxHeight = columnHeight; + + setSize(parent.getDisplay().getBounds().width, columnHeight); + + //int viewWidth = getParent().computeSize(SWT.DEFAULT,SWT.DEFAULT).x; + //System.out.println("*************** X " + viewWidth); + + int viewWidth = parent.getDisplay().getBounds().width; + + histogramContent = new HistogramContent( viewWidth / widthPerColumn, viewWidth, columnMaxHeight); + + addNeededListeners(); + } + + public void addNeededListeners() { + paintListener = new TraceCanvasPaintListener(getHistogramContent(), getColumnWidth(), getColumnMaxHeight() ); + + this.addPaintListener( paintListener ); + this.addMouseListener(this); + this.addMouseMoveListener(this); + this.addFocusListener(this); + + /* + this.addControlListener(this); + this.addKeyListener(this); + this.addMouseWheelListener(this); + this.addMouseTrackListener(this); + this.addTraverseListener(this); + */ + } + + public void resetSelectedWindow() { + paintListener.setSelectedWindow(null); + } + + public boolean positionMouseCursor(MouseEvent e) { + + boolean returnedValue = false; + + if ( histogramContent.getIntervalTime() != 0 ) { + int centralPos = e.x; + HistogramElement centralElement = histogramContent.getElementFromXPosition(centralPos); + HistogramElement leftElement = histogramContent.getClosestElementByTimeInterval(centralElement, -(BIDON_VARIABLE_WINDOW_SIZE / 2) ); + HistogramElement rightElement = histogramContent.getClosestElementByTimeInterval(centralElement, +(BIDON_VARIABLE_WINDOW_SIZE / 2) ); + + /* + System.out.println("X : " + e.x); + System.out.println("Y : " + e.y); + System.out.println("CENTRAL : " + centralElement.firstIntervalTimestamp); + System.out.println("LEFT : " + leftElement.firstIntervalTimestamp); + System.out.println("RIGHT : " + rightElement.firstIntervalTimestamp); + */ + + HistogramSelectedWindow tmpSelection = new HistogramSelectedWindow(); + tmpSelection.selectionCenter = histogramContent.getXPositionFromElement(centralElement); + tmpSelection.selectionLeft = histogramContent.getXPositionFromElement(leftElement); + tmpSelection.selectionRight = histogramContent.getXPositionFromElement(rightElement); + + paintListener.setSelectedWindow(tmpSelection); + + returnedValue = true; + + redraw(); + } + + return returnedValue; + } + + public void notifyTimeWindowChanged() { + // *** TODO *** + // Notify framework that the windows changed! + + System.out.println("NOTIFICATION"); + } + + public HistogramContent getHistogramContent() { + return histogramContent; + } + + public int getColumnWidth() { + return columnWidth; + } + + public int getColumnMaxHeight() { + return columnMaxHeight; + } + + public boolean isWindowMoving = false; + + public void mouseDown(MouseEvent e) { + isWindowMoving = true; + + positionMouseCursor(e); + } + + public void mouseUp(MouseEvent e) { + if ( positionMouseCursor(e) ) { + notifyTimeWindowChanged(); + } + + isWindowMoving = false; + } + + public void mouseMove(MouseEvent e) { + if ( isWindowMoving == true ) { + positionMouseCursor(e); + } + } + + public void mouseDoubleClick(MouseEvent e) { + System.out.println("mouseDoubleClick"); + } + + + public void focusGained(FocusEvent e) { + System.out.println("focusGained"); + } + + public void focusLost(FocusEvent e) { + System.out.println("focusLost"); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvasPaintListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvasPaintListener.java new file mode 100644 index 0000000000..7b7528f9f3 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TraceCanvasPaintListener.java @@ -0,0 +1,131 @@ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Rectangle; + +public class TraceCanvasPaintListener implements PaintListener { + + private final static int EMPTY_BACKGROUND_COLOR = SWT.COLOR_WHITE; + private final static int HISTOGRAM_BARS_COLOR = SWT.COLOR_DARK_CYAN; + private final static int SELECTION_WINDOW_COLOR = SWT.COLOR_RED; + + private final static int SELECTION_LINE_WIDTH = 2; + private final static int SELECTION_CROSSHAIR_LENGTH = 3; + + private HistogramContent histogramContent = null; + private HistogramSelectedWindow selectedWindow = null; + + private int columnWidth = 0; + private int columnHeight = 0; + + public TraceCanvasPaintListener(HistogramContent newHistogramContent, int newBarWidth, int newBarHeight) { + columnWidth = newBarWidth; + columnHeight = newBarHeight; + histogramContent = newHistogramContent; + } + + public void paintControl(PaintEvent e) { + + clearDrawingSection(e); + + if ( (histogramContent == null) || (histogramContent.getReadyUpToPosition() == 0) ) { + return; + } + + if ( (e.height != columnHeight) && (columnHeight != 0) ) { + columnHeight = e.height; + } + + drawHistogram(e); + + if ( selectedWindow != null) { + drawSelectedWindow(e); + } + } + + public void clearDrawingSection(PaintEvent e) { + e.gc.setBackground(e.display.getSystemColor(EMPTY_BACKGROUND_COLOR)); + Rectangle allSection = new Rectangle(0, 0, e.width, e.height); + e.gc.fillRectangle(allSection); + e.gc.drawRectangle(allSection); + } + + // *** VERIFY *** + // Is it good to put this synchronized? + // + public synchronized void drawHistogram(PaintEvent e) { + e.gc.setBackground(e.display.getSystemColor(HISTOGRAM_BARS_COLOR)); + Rectangle allSection = new Rectangle(0, 0, histogramContent.getReadyUpToPosition()*columnWidth, e.height); + e.gc.fillRectangle(allSection); + e.gc.drawRectangle(allSection); + + e.gc.setForeground(e.display.getSystemColor(EMPTY_BACKGROUND_COLOR)); + e.gc.setBackground(e.display.getSystemColor(EMPTY_BACKGROUND_COLOR)); + + for ( int x=0; x