sysperfana/memspyext/com.nokia.s60tools.swmtanalyser/src/com/nokia/s60tools/swmtanalyser/ui/graphs/LinearIssuesGraph.java
author Jussi Ryoma <ext-jussi.s.ryoma@nokia.com>
Tue, 24 Aug 2010 14:01:48 +0300
changeset 16 72f198be1c1d
parent 7 8e12a575a9b5
permissions -rw-r--r--
Crash Analyser Carbide Extension 1.4.0

/*
* 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;
	}	
	

}