sysperfana/memspyext/com.nokia.s60tools.swmtanalyser/src/com/nokia/s60tools/swmtanalyser/ui/graphs/LinearIssuesGraph.java
changeset 7 8e12a575a9b5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/memspyext/com.nokia.s60tools.swmtanalyser/src/com/nokia/s60tools/swmtanalyser/ui/graphs/LinearIssuesGraph.java	Wed Apr 21 20:01:08 2010 +0300
@@ -0,0 +1,812 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+package com.nokia.s60tools.swmtanalyser.ui.graphs;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.FlowLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.draw2d.Polyline;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Transform;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ScrollBar;
+
+import com.nokia.s60tools.swmtanalyser.analysers.ResultElements;
+import com.nokia.s60tools.swmtanalyser.data.ParsedData;
+import com.nokia.s60tools.swmtanalyser.model.SWMTLogReaderUtils;
+import com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph.EventTypes;
+import com.nokia.s60tools.ui.IImageProvider;
+import com.nokia.s60tools.ui.actions.CopyImageToClipboardAction;
+import com.nokia.s60tools.util.debug.DbgUtility;
+
+/**
+ * Graph to be shown in Analysis tab.
+ */
+public class LinearIssuesGraph extends ZoomableGraph implements MouseMoveListener, IImageProvider {
+	
+	private static DecimalFormat MBformat = new DecimalFormat("#####.0");
+	private static DecimalFormat Bytes_Format = new DecimalFormat("#####.##");
+	
+	private HashMap<ResultElements, Polyline> pointsData = new HashMap<ResultElements, Polyline>();
+	
+	private Composite parentComposite;
+	private FigureCanvas yAxis;
+	private FigureCanvas numberAxis;
+	private FigureCanvas figureCanvas;
+	private int[] timeSamples;
+	private ArrayList<ResultElements> selectedIssues;
+	private boolean scalingNeeded;
+	
+	private double visY;
+	private int maxBytes = 10;
+	private int maxCount = 10;
+	private double scale = 1.0;
+	private int timeOffset = 0;
+	
+	/**
+	 * Construction
+	 * @param composite
+	 */
+	public LinearIssuesGraph(Composite composite)
+	{
+		this.parentComposite = composite;
+	}
+	
+	/**
+	 * Draw the area
+	 */
+	public void constructGraphArea()
+	{		
+		if(parentComposite == null)
+			return;
+		
+		Control [] children = parentComposite.getChildren();
+		
+		if(children != null)
+		{
+			for(Control child:children)
+				child.dispose();
+		}
+
+		calculateMultiplier();
+	    scalingNeeded = true;
+		
+		Composite parent = new Composite(parentComposite, SWT.NONE);
+		parent.setLayout(new FormLayout());
+			
+		yAxis = new FigureCanvas(parent);
+				
+		numberAxis = new FigureCanvas(parent);
+		figureCanvas = new FigureCanvas(parent);
+		FormData formData = new FormData();
+		formData.top = new FormAttachment(0);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(0);
+		formData.width  = 50;
+		numberAxis.setLayoutData(formData);
+		
+		formData = new FormData();
+		formData.top = new FormAttachment(0);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(numberAxis);
+		formData.width  = 60;
+		yAxis.setLayoutData(formData);
+		
+		formData = new FormData();
+		formData.top = new FormAttachment(0);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(yAxis, 0, SWT.RIGHT);
+		formData.right  = new FormAttachment(100);
+		
+		figureCanvas.setLayoutData(formData);
+			
+		yAxis.setBackground(ColorConstants.white);
+		numberAxis.setBackground(ColorConstants.white);
+		
+		yAxis.addPaintListener(new PaintListener()
+		{
+			public void paintControl(PaintEvent event) {
+				GC localGC = event.gc;
+				
+				org.eclipse.swt.graphics.Rectangle rect = figureCanvas.getClientArea();
+				
+				visY  = rect.height - CommonGraphConstants.XLEGENDSPACE;
+						
+				double yIncrement = visY / 10;
+				int previousBottom = 0;
+				
+				double multiplier = GraphsUtils.prettyMaxBytes(maxBytes)/visY;
+				
+				for (int k = 10; k >= 0; k--)
+				{
+					// location for the value indicator is k * 1/10 the height of the display
+					int y = (int) (visY - (yIncrement * k));
+				
+					int bytes = (int)(yIncrement * multiplier) * k;
+					String legend = "";
+					
+					if (maxBytes < 10000)
+					{
+						legend += bytes + " B"; //$NON-NLS-1$
+					}
+					else if (maxBytes <= 500 * 1024)
+					{
+						legend += (bytes / 1024) + " KB"; //$NON-NLS-1$
+					}
+					else
+					{
+						legend +=  MBformat.format(((float) bytes / (1024 * 1024)))  + " MB"; //$NON-NLS-1$
+					}
+										
+					Point extent = localGC.stringExtent(legend);
+					
+					localGC.drawLine(CommonGraphConstants.YLEGENDSPACE - 3, (int)y + 1, 60, (int)y + 1);
+					
+					if (y >= previousBottom)
+					{
+						localGC.drawString(legend, 60 - extent.x -2, (int)y);
+						previousBottom = (int)y + extent.y;
+					}
+				}
+				localGC.setLineWidth(2);
+				localGC.drawLine(CommonGraphConstants.YLEGENDSPACE, 0, 60, rect.height);
+							
+				final Image image = GraphsUtils.getDoubleYAxisVerticalLabel("Bytes");
+				
+			    localGC.setAdvanced(true);
+			    final org.eclipse.swt.graphics.Rectangle rect2 = image.getBounds();
+		        Transform transform = new Transform(Display.getDefault());
+
+		        transform.translate(rect2.height / 2f, rect2.width / 2f);
+		        transform.rotate(-90);
+		        transform.translate(-rect2.width / 2f, -rect2.height / 2f);
+
+		        localGC.setTransform(transform);
+		        localGC.drawImage(image, -(int)visY/3, 1);
+		        
+		        transform.dispose();
+		        localGC.dispose();
+			}
+		});
+		
+		numberAxis.addPaintListener(new PaintListener()
+		{
+			public void paintControl(PaintEvent event) {
+				
+				GC localGC = event.gc;
+				org.eclipse.swt.graphics.Rectangle rect = figureCanvas.getClientArea();
+				visY  = rect.height - CommonGraphConstants.XLEGENDSPACE;
+				double yIncrement = visY / 10;
+				int previousBottom = 0;
+				double multiplier = GraphsUtils.roundToNearestNumber(maxCount)/visY;
+				for (int k = 10; k >= 0; k--)
+				{
+					// location for the value indicator is k * 1/10 the height of the display
+					int y = (int) (visY - (yIncrement * k));
+					int yValue = (int)(yIncrement * multiplier) * k;
+					String legend = yValue + "";
+					Point extent = localGC.stringExtent(legend);
+					localGC.drawLine(50 - 3, (int)y + 1, 50, (int)y + 1);
+					if (y >= previousBottom)
+					{
+						localGC.drawString(legend, 50 - extent.x -2, (int)y);
+						previousBottom = (int)y + extent.y;
+					}
+				}
+				localGC.setLineWidth(2);
+				localGC.drawLine(50, 0, 50, rect.height);
+				
+				final Image image = GraphsUtils.getDoubleYAxisVerticalLabel("Count");
+				localGC.setAdvanced(true);
+			    final org.eclipse.swt.graphics.Rectangle rect2 = image.getBounds();
+		        Transform transform = new Transform(Display.getDefault());
+
+		        transform.translate(rect2.height / 2f, rect2.width / 2f);
+		        transform.rotate(-90);
+		        transform.translate(-rect2.width / 2f, -rect2.height / 2f);
+
+		        localGC.setTransform(transform);
+		        localGC.drawImage(image, -(int)visY/3, 10);
+		        
+		        transform.dispose();
+		        localGC.dispose();
+		        
+			}
+		});
+		
+		
+		figureCanvas.setBackground(ColorConstants.white);
+		Panel panel = new Panel()
+		{
+			public void paint(Graphics graphics)
+			{
+//				DbgUtility.println(DbgUtility.PRIORITY_LOOP, "LinearIssuesGraph/Panel/paint START");
+				
+				drawBackGroundLines(figureCanvas,graphics);
+				paintData(graphics);
+				
+//				DbgUtility.println(DbgUtility.PRIORITY_LOOP, "LinearIssuesGraph/Panel/paint END");				
+			}
+		};
+		
+		panel.setLayoutManager(new FlowLayout());
+		figureCanvas.setContents(panel);
+		figureCanvas.addMouseMoveListener(this);
+		
+		final ScrollBar horizontalBar = figureCanvas.getHorizontalBar();
+		horizontalBar.addSelectionListener(new SelectionListener()
+		{
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			
+			}
+
+			public void widgetSelected(SelectionEvent event) {
+				timeOffset = figureCanvas.getViewport().getViewLocation().x;
+				figureCanvas.redraw();
+			}
+			
+		});
+		
+		figureCanvas.addControlListener(new ControlAdapter()
+		{
+			public void controlResized(ControlEvent e) {
+				horizontalBar.setPageIncrement(figureCanvas.getBounds().width);
+				
+				if(scalingNeeded)
+				{
+					zoomGraph();
+					scalingNeeded = false;
+				}
+				//setNewSize();
+				yAxis.redraw();
+				numberAxis.redraw();
+				figureCanvas.redraw();
+				
+			}
+		});
+	
+		zoomGraph();
+		figureCanvas.redraw();
+		hookContextMenu();
+		parentComposite.layout(true);
+	}
+	
+	/**
+	 * Draw background lines on the canvas
+	 * @param canvas
+	 * @param graphics
+	 */
+	public void drawBackGroundLines(FigureCanvas canvas, Graphics graphics)
+	{
+		Rectangle canvasRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
+	  	graphics.setForegroundColor(new Color(Display.getDefault(), new RGB(200, 200, 200)));
+	 	graphics.setBackgroundColor(new Color(Display.getDefault(), new RGB(170,170,170)));
+		
+	  	int height = canvas.getClientArea().height;
+	  	int width = canvas.getClientArea().width;
+	  	
+	  	graphics.fillRectangle(new Rectangle(canvasRect.x,0,width, height-50));
+	  	
+	    double visY = height - CommonGraphConstants.XLEGENDSPACE;
+				
+		int k = 0;
+		
+		for (float y = 0; k <= 10; y += visY * 10000 / 100001, k++)
+		{
+			for(int x = canvasRect.x; x <= canvasRect.x + canvasRect.width; x += 5)
+			{
+				if ((x / 5) % 2 == 0) graphics.drawLine(x, ((int)y) + 1, x + 5, ((int)y) + 1);
+			}
+		}
+		
+		graphics.setForegroundColor(new Color(Display.getDefault(), new RGB(100, 100, 100)));
+		graphics.setBackgroundColor(new Color(Display.getDefault(),new RGB(255, 255, 255)));
+		
+		// horizontal lines
+		if (width > 0)
+		{
+			for (int x = 0; x <= canvasRect.x + canvasRect.width; x += 50)
+			{	
+				if (x % 100 == 0)
+					graphics.setForegroundColor(new Color(Display.getDefault(), new RGB(100, 100, 100)));
+				else
+					graphics.setForegroundColor(new Color(Display.getDefault(),new RGB(200, 200, 200)));
+				
+				for (int y = 0; y < height; y += 5)
+				{
+					if ((y / 5) % 2 == 0)
+						graphics.drawLine(x, y, x, y + 5);
+				}
+				
+			}
+		}
+		
+		graphics.setForegroundColor(new Color(Display.getDefault(), new RGB(100, 100, 100)));
+		graphics.setBackgroundColor(new Color(Display.getDefault(),new RGB(255, 255, 255)));
+		
+		for (int x = 0; x <= canvasRect.x + canvasRect.width; x += 50)
+		{
+			double time = (double) x;
+			TimeObject timeObj = new TimeObject(time, scale);
+			graphics.drawString(timeObj.getHourMinutesAndSeconds(), x + 5, height - 13);
+			if(timeObj.hasDays()){
+				graphics.drawString(timeObj.getDays(), x + 5, height - 26);
+			}
+		}
+		Image img = GraphsUtils.getDoubleYAxisVerticalLabel(GenericGraph.TIME_X_AXIS_LABEL);
+		graphics.drawImage(img, width/2, height-30);
+
+	}
+	
+	private void paintData(Graphics graphics)
+	{
+		DbgUtility.println(DbgUtility.PRIORITY_LOOP, this.getClass().getSimpleName() + "/paintData START");
+		
+		try
+		{
+			Rectangle canvasRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
+		
+			if(this.selectedIssues == null || selectedIssues.size() == 0)
+				return;
+		
+			int [] listX = timeSamples;
+			int k = 0;
+		
+			calculateMultiplier();
+				
+			// Storing original graphics settings
+			Color origColor = graphics.getForegroundColor();
+			int origLineWidth = graphics.getLineWidth();
+			// Setting line width for drawing the graph
+			graphics.setLineWidth(CommonGraphConstants.DEFAULT_GRAPH_LINE_WIDTH);				
+		
+			for(ResultElements item:selectedIssues)
+			{
+				long [] valuesToBePlotted = item.getEventValues();
+			
+				if(valuesToBePlotted == null)
+					continue;
+			
+				double visY = canvasRect.height - CommonGraphConstants.XLEGENDSPACE;
+				double multiplier = 1;
+				
+				EventTypes eventType = GraphsUtils.getMappedEvent(item.getEvent());
+					
+				switch (eventType)
+				{
+					case NO_OF_FILES:
+					case NO_OF_PSHANDLES:
+					case HEAP_ALLOC_CELL_COUNT:
+					case HEAP_FREE_CELL_COUNT:
+					case SYSTEM_DATA:
+						multiplier = GraphsUtils.roundToNearestNumber(maxCount)/visY;
+						break;
+					default:
+						multiplier = GraphsUtils.prettyMaxBytes(maxBytes)/visY;
+						break;
+				}
+			
+				List<Point> pointsList = new ArrayList<Point>();
+				 
+				for (int i = 0; i < valuesToBePlotted.length; i++)
+				{
+			    	// Showing only positive values
+			    	if(valuesToBePlotted[i] > 0){
+			    		int scaledXPoint = (int)(listX[i]/scale);
+			    		int scaledYPoint = (int) (visY - valuesToBePlotted[i] /multiplier);;
+				    	Point p = new Point(scaledXPoint, scaledYPoint);
+				    	pointsList.add(p);			    		
+			    	}
+				}
+			 
+				// Converting point list into integer array for drawing
+				int[] points = GraphsUtils.convertPointListToIntArray(pointsList);
+				
+				graphics.setForegroundColor(item.getColor());
+				
+				// Drawing graph
+				graphics.drawPolyline(points);				
+				// Drawing markers to the data points
+				GraphsUtils.drawMarkers(graphics, points);
+			
+				Polyline line = new Polyline();
+				line.setPoints(new PointList(points));
+				pointsData.put(item, line);
+					
+				k++;
+			}
+
+			// Restoring original settings
+			graphics.setForegroundColor(origColor);
+			graphics.setLineWidth(origLineWidth);
+
+		}catch(Exception e){
+			e.printStackTrace();
+		}
+	}
+	
+	private void calculateMultiplier()
+	{
+		maxCount = 10;
+		maxBytes = 10;
+		
+		if(selectedIssues == null)
+			return;
+		
+		for(ResultElements item:selectedIssues)
+		{
+			long [] valuesToBePlotted = item.getEventValues();
+		
+			if(valuesToBePlotted == null)
+				return;
+			
+			int maxValue = (int)calculateMaxValue(valuesToBePlotted);
+			
+			EventTypes eventType = GraphsUtils.getMappedEvent(item.getEvent());
+			
+			switch (eventType)
+			{
+				case NO_OF_FILES:
+				case NO_OF_PSHANDLES:
+				case HEAP_ALLOC_CELL_COUNT:
+				case HEAP_FREE_CELL_COUNT:
+				case SYSTEM_DATA:
+					if(maxValue > maxCount)
+						maxCount = maxValue;
+					break;
+				default:
+					if(maxValue > maxBytes)
+						maxBytes = maxValue;
+					break;
+			}
+		}
+		
+	}
+	/**
+	 * Adds Pop-Up menu items on th graph area.
+	 *
+	 */
+	private void hookContextMenu() {
+		MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+		menuMgr.setRemoveAllWhenShown(true);
+		menuMgr.addMenuListener(new IMenuListener() {
+			public void menuAboutToShow(IMenuManager manager) {
+				fillContextMenu(manager);
+			}
+        });
+	    Menu menu = menuMgr.createContextMenu(figureCanvas);
+	    figureCanvas.setMenu(menu);
+	}
+	
+	protected void fillContextMenu(IMenuManager manager) {
+		zoomIn = new Action()
+		{
+			public void run()
+			{
+				zoomIn();
+			}
+			{
+				this.setText(ZOOM_IN_CONTEXT_MENU_TITLE);
+			}
+		};
+		
+		zoomOut = new Action()
+		{
+			public void run()
+			{
+				zoomOut();
+			}
+			{
+				this.setText(ZOOM_OUT_CONTEXT_MENU_TITLE);
+			}
+		};
+		IAction showEntireGraph = new Action()
+		{
+			public void run()
+			{
+				zoomGraph();
+			}
+			{
+				this.setText(CommonGraphConstants.SHOW_ENTIRE_GRAPH_CONTEXT_MENU_ITEM_TITLE);
+			}
+		};
+		
+		IAction saveGraph = new Action()
+		{
+			public void run()
+			{
+				GraphsUtils.saveGraph(parentComposite);
+			}
+			{
+				this.setText(CommonGraphConstants.SAVE_GRAPH_CONTEXT_MENU_ITEM_TITLE);
+			}
+		};
+		
+		copy = new CopyImageToClipboardAction(this);		
+
+		manager.add(zoomIn);
+		manager.add(new Separator());
+		manager.add(zoomOut);
+		manager.add(new Separator());
+		manager.add(showEntireGraph);
+		manager.add(saveGraph);
+		manager.add(copy);
+
+		// Finally updating action states
+		updateViewActionEnabledStates();
+
+	}
+
+	/**
+	 * Sets enabled/disabled states for actions commands
+	 * on this view, based on the current application state.
+	 * This method should be called whenever an operation is
+	 * started or stopped that might have effect on action 
+	 * button states.
+	 */
+	private void updateViewActionEnabledStates() {
+		// Zoom In
+		setEnableState(zoomIn, !(this.scale == GraphsUtils.nextScale(scale, false)));
+		
+		// Zoom Out
+		boolean zoomOutEnableCondition1 = !(this.scale == GraphsUtils.nextScale(scale, true));
+		int width = figureCanvas.getClientArea().width;		
+		int lastTimeSample = timeSamples[timeSamples.length - 1];
+		boolean zoomOutEnableCondition2 = !(lastTimeSample / this.scale <= width);
+		setEnableState(zoomOut, zoomOutEnableCondition1 && zoomOutEnableCondition2);		
+	}
+
+	
+	/* (non-Javadoc)
+	 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.ZoomableGraph#zoomIn()
+	 */
+	protected void zoomIn()
+	{
+		DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "LinearIssuesGraph - Zoom In");
+		//Preconditions checked already in updateViewActionEnabledStates
+		this.scale = GraphsUtils.nextScale(scale, false);
+		figureCanvas.redraw();
+		setNewSize();
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.ZoomableGraph#zoomOut()
+	 */
+	protected void zoomOut()
+	{
+		DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "LinearIssuesGraph - Zoom Out");
+		//Preconditions checked already in updateViewActionEnabledStates
+		this.scale = GraphsUtils.nextScale(this.scale, true);
+		setNewSize();
+	
+	}
+	/**
+	 * This method zoom in the graph area to the maximum possible scale
+	 * and then zooms out, so that it fits in the canvas area
+	 */
+	public void zoomGraph()
+	{		
+		int width = figureCanvas.getClientArea().width;
+		
+		if(width <=0)
+			return;
+		
+		double new_scale = this.scale;
+		
+		double prevNew  = new_scale;
+		
+		int lastSampleTime = timeSamples[timeSamples.length - 1];
+		//first zoom in until it is too big to fit
+		while (lastSampleTime / new_scale <= width){
+			new_scale = GraphsUtils.nextScale(new_scale, false);
+			
+			if(prevNew == new_scale)
+				break;
+			
+			prevNew = new_scale;
+			
+		}
+		// now zoom out until it just fits
+		while (lastSampleTime / new_scale > width){
+			new_scale = GraphsUtils.nextScale(new_scale, true);
+			
+			if(prevNew == new_scale)
+				break;
+			
+			prevNew = new_scale;
+		}
+		
+		if (new_scale == this.scale)
+			return;
+	
+		this.scale = new_scale;
+		
+		setNewSize();
+	}
+	
+	
+	/**
+	 * This method sets the size of the panel, when scale is changed.  
+	 * When graph extends beyond visible area, horizontal scroll bar appears automatically.
+	 *
+	 */
+	private void setNewSize()
+	{
+		int lastSample = timeSamples[timeSamples.length - 1];
+		
+		int prefSize = (int)(lastSample/scale);
+	
+		timeOffset = 0;	
+		Panel panel = (Panel)(figureCanvas.getContents());
+		panel.setPreferredSize(prefSize + 100, 0);
+		
+		if (prefSize >= figureCanvas.getClientArea().width) {
+			timeOffset = figureCanvas.getViewport().getViewLocation().x;
+	    	panel.setSize(prefSize + 100, 0);
+	    }
+		
+	}
+
+	/**
+	 * Set issues that user has been selected
+	 * @param selectedIssues
+	 */
+	public void setSelectedIssues(ArrayList<ResultElements> selectedIssues) {
+		this.selectedIssues = selectedIssues;
+	}
+	
+	/**
+	 * Set parsed data
+	 * @param logsData
+	 */
+	public void setLogData(ParsedData logsData)
+	{
+		SWMTLogReaderUtils utils = new SWMTLogReaderUtils();
+		timeSamples = utils.getTimeIntervalsFromLogData(logsData);
+	}
+	
+	private long calculateMaxValue(long [] values)
+	{
+		long maxValue = 0;
+		
+		for(int i=0; i<values.length; i++)
+		{
+			if(values[i] > maxValue)
+				maxValue = values[i];
+		}
+		
+		return maxValue;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void mouseMove(MouseEvent event) {
+		int x = event.x;
+		int y = event.y;
+		
+		if(y > (int)visY)
+			figureCanvas.setToolTipText(null);
+		
+		String text = "";
+		double xValue = x + timeOffset;
+		int scaledX = (int)(xValue * scale);
+		double valY = visY - y;
+					
+		double count_multiplier = GraphsUtils.roundToNearestNumber(maxCount)/visY;
+		double bytes_multiplier = GraphsUtils.prettyMaxBytes(maxBytes)/visY;
+		
+		String scaledY_1 = getFormattedValues(valY * bytes_multiplier);
+		int scaledY_2 = (int)(Math.round((valY * count_multiplier)));
+		
+		text += scaledX + "s " + scaledY_1 + " , " + scaledY_2 ;
+		
+		if(selectedIssues != null)
+		{
+			for(ResultElements item:selectedIssues)
+			{
+				Polyline line = pointsData.get(item);
+		
+				if(line != null && line.containsPoint(x, y))
+				{
+					text += "\n" + item.getItemName();
+					text +=  " -- " + item.getEvent();
+				}
+			}
+		}
+					
+		figureCanvas.setToolTipText(text);
+		figureCanvas.redraw();
+	}
+	
+	/**
+	 * 
+	 * @param bytes represents value to be formatted.
+	 * @return formatted value 
+	 */
+	private String getFormattedValues(double bytes)
+	{
+		String scaledY = "";
+		
+		if (bytes < 10000)
+		{
+			scaledY += Bytes_Format.format(bytes) + " B"; //$NON-NLS-1$
+		}
+		else if (bytes <= 500 * 1024)
+		{
+			scaledY += Bytes_Format.format(bytes / 1024) + " KB"; //$NON-NLS-1$
+		}
+		else
+		{
+			scaledY +=  MBformat.format(((float) bytes / (1024 * 1024)))  + " MB"; //$NON-NLS-1$
+		}
+		
+		return scaledY;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.s60tools.swmtanalyser.ui.actions.IImageProvider#getImage()
+	 */
+	public Image getImage() {
+		return new Image(Display.getCurrent(), parentComposite.getClientArea().width, parentComposite.getClientArea().height);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.s60tools.swmtanalyser.ui.actions.IImageProvider#getDrawable()
+	 */
+	public Drawable getDrawable() {
+		return parentComposite;
+	}	
+	
+
+}