sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/internal/ui/graph/AnalyzeToolGraph.java
changeset 15 0367d2db2c06
parent 6 f65f740e69f9
--- a/sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/internal/ui/graph/AnalyzeToolGraph.java	Tue Aug 24 12:10:03 2010 +0300
+++ b/sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/internal/ui/graph/AnalyzeToolGraph.java	Tue Aug 24 12:16:27 2010 +0300
@@ -15,6 +15,7 @@
  *
  */
 package com.nokia.s60tools.analyzetool.internal.ui.graph;
+
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.util.AbstractList;
@@ -78,10 +79,10 @@
 import com.nokia.s60tools.analyzetool.ui.ResourceVisitor;
 
 /**
- * A FigureCanvas containing the graph and X-axis area of the 
- * AnalyzeTool chart.
+ * A FigureCanvas containing the graph and X-axis area of the AnalyzeTool chart.
  */
-public class AnalyzeToolGraph extends FigureCanvas implements IMemoryActivityModelChangeListener {
+public class AnalyzeToolGraph extends FigureCanvas implements
+		IMemoryActivityModelChangeListener {
 
 	private static final int BOUNDARY_OFFSET = 3;
 	/** used for range model listener */
@@ -89,37 +90,47 @@
 	private static final int X_AXIS_HEIGHT = 50;
 	/** used for "Don't ask again" dialog */
 	private static final String PROMPT_KEY = "GraphOptimisationPrompt";//$NON-NLS-1$
-	
-	/** the scaling factor used for scaling the x-axis*/
+
+	/** the scaling factor used for scaling the x-axis */
 	private double scale = 1.0;
 
 	/** the model */
 	private IMemoryActivityModel model;
 
-	/** for synchronisation with the PropertySheet */
+	/** for synchronization with the PropertySheet */
 	private DotSelectionProvider iDotsSelecProv = new DotSelectionProvider();
 	private IWorkbenchPartSite site;
-	
+
 	/** used when user selects a dot on the graph, and moves with arrow keys */
 	private ISelection iCurrentSelectedDot = null;
-	
+
 	/** controls mouse and arrow key movements */
 	private MouseAndKeyController mc;
 	private SymReader iSymReader = null;
 	private IProject iCurrentProject = null;
 	/** Contains c++ files info for the current project. */
 	private final AbstractList<String> cppFileNames;
-	
-	/** "time ->" on axis*/
+
+	/** "time ->" on axis */
 	private Image timeImage;
 	private GraphPartServiceListener iGraphPartServiceListener;
 	private boolean optimisedDrawing;
 	private boolean userInformed;
 
+	/**
+	 * The threshold value for filtered drawing of dots. Only draw the dot if
+	 * the memory operation size is above or equals / below or equals the
+	 * threshold. Zero for no filtering.
+	 */
+	private long threshold;
+	/** indicates whether filtering is above or below the threshold */
+	private boolean aboveThreshold;
 
 	/**
 	 * Constructor
-	 * @param parent The parent composite
+	 * 
+	 * @param parent
+	 *            The parent composite
 	 */
 	public AnalyzeToolGraph(Composite parent) {
 		super(parent);
@@ -132,32 +143,40 @@
 	}
 
 	/**
-	 * Draws the graph on the canvas. Intended to be called on a paint event. 
+	 * Draws the graph on the canvas. Intended to be called on a paint event.
+	 * 
 	 * @param graphics
 	 */
 	public void paint(final Graphics graphics) {
-		if (optimisedDrawing && !userInformed){
+		if (optimisedDrawing && !userInformed) {
 			userInformed = true;
 			IPreferenceStore preferenceStore = Activator.getPreferences();
-            if (!preferenceStore.getString(PROMPT_KEY).equals(MessageDialogWithToggle.ALWAYS)) {
-                String dilaogTitle = "Optimised Graph";
-                String message = "The process contains too many memory operations to display efficiently. To optimise, only leaks will be indicated on the graph.";
-                String toggleMessage = "Don't show this again";
+			if (!preferenceStore.getString(PROMPT_KEY).equals(
+					MessageDialogWithToggle.ALWAYS)) {
+				String dilaogTitle = "Optimised Graph";
+				String message = "The process contains too many memory operations to display efficiently. To optimise, only leaks will be indicated on the graph.";
+				String toggleMessage = "Don't show this again";
 
-                MessageDialogWithToggle.openInformation(getShell(), dilaogTitle, message, toggleMessage, false, preferenceStore, PROMPT_KEY);
-            }
+				MessageDialogWithToggle.openInformation(getShell(),
+						dilaogTitle, message, toggleMessage, false,
+						preferenceStore, PROMPT_KEY);
+			}
 		}
-		Rectangle visibleRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
-		YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
+		Rectangle visibleRect = graphics.getClip(new Rectangle());
+		YConverter yConverter = new YConverter(getClientArea().height, model
+				.getHighestCumulatedMemoryAlloc());
 
-		if (model.getSelectedProcess() != null && model.getSelectedProcess().getAllocsFrees().size() > 0){
-			PointList pts = new PointList((model.getSelectedProcess().getAllocsFrees().size()*2)-1);
+		if (model.getSelectedProcess() != null
+				&& model.getSelectedProcess().getAllocsFrees().size() > 0) {
+			PointList pts = new PointList((model.getSelectedProcess()
+					.getAllocsFrees().size() * 2) - 1);
 			Point prevPt = null;
 			List<Point> dotLocations = new ArrayList<Point>();
 			List<Integer> colorDotLocations = new ArrayList<Integer>();
 
 			for (BaseInfo info : model.getSelectedProcess().getAllocsFrees()) {
-				int x_point = (int) ((info.getTime() - model.getFirstProcessTime()) / getScale());
+				int x_point = (int) ((info.getTime() - model
+						.getFirstProcessTime()) / getScale());
 				int y_point = yConverter.bytesToY(info.getTotalMem());
 
 				if (y_point < 0) {
@@ -167,9 +186,13 @@
 					pts.addPoint(x_point, prevPt.y);
 				}
 				Point nextPt = new Point(x_point, y_point);
-				if (visibleRect.contains(nextPt) && (isLeak(info) || (!optimisedDrawing && !dotLocations.contains(nextPt)))){
-					//for improved performance, only draw dots that are in visible clip area
-					//and don't draw a dot if there is one already, unless it's a leak
+				if (visibleRect.contains(nextPt)
+						&& (isLeak(info) || (!optimisedDrawing
+								&& !dotLocations.contains(nextPt) && validInThreshold(info)))) {
+					// for improved performance, only draw dots that are in
+					// visible clip area
+					// and don't draw a dot if there is one already, unless it's
+					// a leak
 					dotLocations.add(nextPt);
 					colorDotLocations.add(getColorForAllocType(info));
 				}
@@ -177,51 +200,90 @@
 				prevPt = nextPt;
 			}
 
-			if (pts.size() > 0){
+			if (pts.size() > 0) {
 				graphics.pushState();
-				
-				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_YELLOW));
+
+				graphics.setForegroundColor(Display.getDefault()
+						.getSystemColor(SWT.COLOR_DARK_YELLOW));
 				graphics.setLineWidthFloat(optimisedDrawing ? 0.5f : 2.0f);
 				graphics.drawPolyline(pts);
-				
+
 				graphics.setLineWidthFloat(optimisedDrawing ? 0.5f : 1.0f);
 				graphics.setAntialias(SWT.ON);
-				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_RED));
-				graphics.setBackgroundColor(Display.getDefault().getSystemColor(SWT.COLOR_RED));
+				graphics.setForegroundColor(Display.getDefault()
+						.getSystemColor(SWT.COLOR_RED));
+				graphics.setBackgroundColor(Display.getDefault()
+						.getSystemColor(SWT.COLOR_RED));
 				int colourCode = SWT.COLOR_RED;
 				for (int j = 0; j < dotLocations.size(); j++) {
 					Point dotLocation = dotLocations.get(j);
-					if (!optimisedDrawing && colorDotLocations.get(j) != colourCode) {
+					if (!optimisedDrawing
+							&& colorDotLocations.get(j) != colourCode) {
 						colourCode = colorDotLocations.get(j);
-						graphics.setBackgroundColor(Display.getDefault().getSystemColor(colourCode));
+						graphics.setBackgroundColor(Display.getDefault()
+								.getSystemColor(colourCode));
 					}
 					// paint the dot
-					graphics.fillOval(dotLocation.x - 2, dotLocation.y - 2,	5, 5);
+					graphics.fillOval(dotLocation.x - 2, dotLocation.y - 2, 5,
+							5);
 					if (!optimisedDrawing && colourCode == SWT.COLOR_RED) {
 						// draw a red line
-						graphics.drawLine(dotLocation.x, dotLocation.y,	dotLocation.x, yConverter.bytesToY(0));
+						graphics.drawLine(dotLocation.x, dotLocation.y,
+								dotLocation.x, yConverter.bytesToY(0));
 					}
 				}
 				graphics.popState();
 			}
 		}
 	}
-	
-	
 
 	/**
-	 * Draws the background grid on the canvas. Intended to be called on a paint event.
+	 * Returns true of the size of the alloc or free is greater or equals / less
+	 * or equals the threshold. Returns true if no threshold is set.
+	 * 
+	 * @param info
+	 *            the memory operation to check
+	 * @return
+	 */
+	private boolean validInThreshold(BaseInfo info) {
+		if (threshold <= 0
+				|| info instanceof AllocInfo
+				&& (aboveThreshold ? (((AllocInfo) info).getSizeInt() >= threshold)
+						: (((AllocInfo) info).getSizeInt() <= threshold))) {
+			return true;
+		}
+
+		if (info instanceof FreeInfo
+				&& ((aboveThreshold && ((FreeInfo) info).getSizeInt() >= threshold) || (!aboveThreshold && ((FreeInfo) info)
+						.getSizeInt() <= threshold))) {
+			// check at least one of its alloc qualifies
+			for (AllocInfo allocInfo : ((FreeInfo) info).getFreedAllocs()) {
+				if ((aboveThreshold && allocInfo.getSizeInt() >= threshold)
+						|| (!aboveThreshold && allocInfo.getSizeInt() <= threshold)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Draws the background grid on the canvas. Intended to be called on a paint
+	 * event.
+	 * 
 	 * @param graphics
 	 */
 	public void drawBackGroundLines(Graphics graphics) {
-		Rectangle canvasRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
+		Rectangle canvasRect = graphics
+				.getClip(new org.eclipse.draw2d.geometry.Rectangle());
 		graphics.setForegroundColor(ColorUtil.COLOR_100); // middle grey
 		graphics.setBackgroundColor(ColorUtil.COLOR_170); // lighter grey
 
 		int height = getClientArea().height;
 		int width = getClientArea().width;
 
-		graphics.fillRectangle(new Rectangle(canvasRect.x, 0, width, height - X_AXIS_HEIGHT));
+		graphics.fillRectangle(new Rectangle(canvasRect.x, 0, width, height
+				- X_AXIS_HEIGHT));
 
 		double visY = height - X_AXIS_HEIGHT;
 
@@ -237,13 +299,13 @@
 
 		graphics.setForegroundColor(ColorUtil.COLOR_100);
 		graphics.setBackgroundColor(ColorUtil.WHITE);
-		
-		int alignedLeftEdge = (canvasRect.x / 50)*50;
+
+		int alignedLeftEdge = (canvasRect.x / 50) * 50;
 
 		// vertical lines (one darker, one lighter vertical line in turns every
 		// 50 points in width)
 		if (width > 0) {
-			for (int x = alignedLeftEdge ; x <= canvasRect.x + canvasRect.width; x += 50) {
+			for (int x = alignedLeftEdge; x <= canvasRect.x + canvasRect.width; x += 50) {
 				if (x % 100 == 0)
 					graphics.setForegroundColor(ColorUtil.COLOR_100);
 				else
@@ -260,19 +322,23 @@
 		graphics.setBackgroundColor(ColorUtil.WHITE);
 
 		for (int x = alignedLeftEdge; x <= canvasRect.x + canvasRect.width; x += 50) {
-			String timeStringWithUnits = GraphUtils.getTimeStringWithUnits(x * scale);
+			String timeStringWithUnits = GraphUtils.getTimeStringWithUnits(x
+					* scale);
 			graphics.drawString(timeStringWithUnits, x + 5, height - 13);
 		}
-		if (timeImage == null){
-			timeImage = GraphUtils.getVerticalLabel("Time");			
+		if (timeImage == null) {
+			timeImage = GraphUtils.getVerticalLabel("Time");
 		}
 		graphics.drawImage(timeImage, width / 2, height - 30);
 	}
 
 	/**
 	 * Returns the content of the tooltip appropriate for the given coordinate
-	 * @param x the X-coordinate
-	 * @param y the Y-coordinate
+	 * 
+	 * @param x
+	 *            the X-coordinate
+	 * @param y
+	 *            the Y-coordinate
 	 * @return String containing the content of the tooltip
 	 */
 	public String getToolTipText(int x, int y) {
@@ -287,32 +353,37 @@
 
 		double timeInMs = (x * getScale());// x value in milliseconds
 
-		YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
+		YConverter yConverter = new YConverter(getClientArea().height, model
+				.getHighestCumulatedMemoryAlloc());
 		double bytes = yConverter.yToBytes(y); // y value in bytes
 
-		text.append(GraphUtils.renderTime(timeInMs)); 
+		text.append(GraphUtils.renderTime(timeInMs));
 
-		BaseInfo allocInfo = findClosestAlloc((int) timeInMs, (int) ((x - BOUNDARY_OFFSET) * getScale()), (int) ((x + BOUNDARY_OFFSET) * getScale()),
-				(int) bytes, (int) yConverter.yToBytes(y + BOUNDARY_OFFSET), (int) yConverter.yToBytes(y - BOUNDARY_OFFSET));
+		BaseInfo allocInfo = findClosestAlloc((int) timeInMs,
+				(int) ((x - BOUNDARY_OFFSET) * getScale()),
+				(int) ((x + BOUNDARY_OFFSET) * getScale()), (int) bytes,
+				(int) yConverter.yToBytes(y + BOUNDARY_OFFSET),
+				(int) yConverter.yToBytes(y - BOUNDARY_OFFSET));
 		if (allocInfo != null) {
 			text.append(String.format("%n%s: %,d B%nTotal: %,d B",
-					getMemOpString(allocInfo), 
-					Math.abs(allocInfo.getSizeInt()), 
-					allocInfo.getTotalMem()));
+					getMemOpString(allocInfo),
+					Math.abs(allocInfo.getSizeInt()), allocInfo.getTotalMem()));
 		} else {
 			text.append(", " + GraphUtils.formatBytes(bytes));
 		}
-
 		return text.toString();
 	}
-	
+
 	/**
 	 * Returns a string representation of the type of the given memory operation
-	 * @param allocInfo the memory operation to use
-	 * @return 
+	 * 
+	 * @param allocInfo
+	 *            the memory operation to use
+	 * @return
 	 */
-	private String getMemOpString(BaseInfo allocInfo){
-		return allocInfo instanceof AllocInfo ? (((AllocInfo) allocInfo).isFreed() ? "Alloc" : "Leak"  ): "Free";
+	private String getMemOpString(BaseInfo allocInfo) {
+		return allocInfo instanceof AllocInfo ? (((AllocInfo) allocInfo)
+				.isFreed() ? "Alloc" : "Leak") : "Free";
 	}
 
 	/**
@@ -331,9 +402,14 @@
 			return null;
 		}
 
-		YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
-		return findClosestAlloc((int) (x * getScale()), (int) ((x - BOUNDARY_OFFSET) * getScale()), (int) ((x + BOUNDARY_OFFSET) * getScale()),
-				(int) (yConverter.yToBytes(y)), (int) yConverter.yToBytes(y + BOUNDARY_OFFSET), (int) yConverter.yToBytes(y - BOUNDARY_OFFSET));
+		YConverter yConverter = new YConverter(getClientArea().height, model
+				.getHighestCumulatedMemoryAlloc());
+		return findClosestAlloc((int) (x * getScale()),
+				(int) ((x - BOUNDARY_OFFSET) * getScale()),
+				(int) ((x + BOUNDARY_OFFSET) * getScale()), (int) (yConverter
+						.yToBytes(y)), (int) yConverter.yToBytes(y
+						+ BOUNDARY_OFFSET), (int) yConverter.yToBytes(y
+						- BOUNDARY_OFFSET));
 	}
 
 	/**
@@ -355,13 +431,14 @@
 	 *            Right boundary for cumulative memory in bytes
 	 * @return
 	 */
-	private BaseInfo findClosestAlloc(int timeInMsMidPoint, int timeInMsBoundLeft, int timeInMsBoundRight, int bytesMidPoint, int bytesBoundLeft,
-			int bytesBoundRight) {
+	private BaseInfo findClosestAlloc(int timeInMsMidPoint,
+			int timeInMsBoundLeft, int timeInMsBoundRight, int bytesMidPoint,
+			int bytesBoundLeft, int bytesBoundRight) {
 		BaseInfo ret = null;
-		if (model.getSelectedProcess() == null){
+		if (model.getSelectedProcess() == null) {
 			return ret;
 		}
-		
+
 		int marginEnd = timeInMsBoundRight;
 		ProcessInfo process = model.getSelectedProcess();
 		AbstractList<BaseInfo> allocsFrees = process.getAllocsFrees();
@@ -370,15 +447,19 @@
 		for (BaseInfo info : allocsFrees) {
 			Long infoRelativeTime = info.getTime() - firstTime;
 			// check current alloc info is within given bounds
-			if (infoRelativeTime >= timeInMsBoundLeft && infoRelativeTime <= marginEnd && info.getTotalMem() >= bytesBoundLeft
+			if (infoRelativeTime >= timeInMsBoundLeft
+					&& infoRelativeTime <= marginEnd
+					&& info.getTotalMem() >= bytesBoundLeft
 					&& info.getTotalMem() <= bytesBoundRight) {
 				// check whether current alloc info is a better match than
 				// previously found
 				if (ret == null
-						|| (Math.abs(infoRelativeTime - timeInMsMidPoint) < Math.abs((ret.getTime() - firstTime) - timeInMsMidPoint))
-						|| ((ret.getTime() - firstTime) == infoRelativeTime && Math.abs(info.getTotalMem() - bytesMidPoint) < Math.abs(ret
-								.getTotalMem()
-								- bytesMidPoint))) {
+						|| (Math.abs(infoRelativeTime - timeInMsMidPoint) < Math
+								.abs((ret.getTime() - firstTime)
+										- timeInMsMidPoint))
+						|| ((ret.getTime() - firstTime) == infoRelativeTime && Math
+								.abs(info.getTotalMem() - bytesMidPoint) < Math
+								.abs(ret.getTotalMem() - bytesMidPoint))) {
 					ret = info;
 				}
 			} else if ((info.getTime() - firstTime) > timeInMsBoundRight) {
@@ -399,11 +480,11 @@
 	private BaseInfo findNextAlloc(BaseInfo allocInfo, boolean forward) {
 		BaseInfo ret = null;
 		ProcessInfo processInfo = model.getSelectedProcess();
-		if (processInfo == null){
+		if (processInfo == null) {
 			return ret;
 		}
-		
-		AbstractList<BaseInfo> allocsFrees = processInfo.getAllocsFrees(); 
+
+		AbstractList<BaseInfo> allocsFrees = processInfo.getAllocsFrees();
 		int i = allocsFrees.indexOf(allocInfo);
 		if (forward) {
 			if (i < allocsFrees.size() - 1) {
@@ -434,6 +515,7 @@
 
 	/**
 	 * Returns the current scaling factor for the graph's width
+	 * 
 	 * @return Scale
 	 */
 	public double getScale() {
@@ -442,7 +524,8 @@
 
 	/**
 	 * Sets the scaling factor for the graph's width
-	 * @param newScale 
+	 * 
+	 * @param newScale
 	 */
 	public void setScale(double newScale) {
 		this.scale = newScale;
@@ -450,7 +533,8 @@
 
 	/**
 	 * Returns the highest time value of the current graph in milliseconds
-	 * @return Last time 
+	 * 
+	 * @return Last time
 	 */
 	public long getLastTimeValueInMilliSeconds() {
 		return model.getLastProcessTime() - model.getFirstProcessTime();
@@ -462,24 +546,28 @@
 	 * @return
 	 */
 	private long getMaxTimeValueInMilliSeconds() {
-		return getLastTimeValueInMilliSeconds() + (int) (getLastTimeValueInMilliSeconds() * 0.01);
+		return getLastTimeValueInMilliSeconds()
+				+ (int) (getLastTimeValueInMilliSeconds() * 0.01);
 	}
 
 	/**
-	 * Adds a new model to this class 
-	 * @param newModel the IMemoryActivityModel to use
+	 * Adds a new model to this class
+	 * 
+	 * @param newModel
+	 *            the IMemoryActivityModel to use
 	 */
 	public void setInput(IMemoryActivityModel newModel) {
-		if (this.model != null){
+		if (this.model != null) {
 			this.model.removeListener(this);
 		}
+		threshold = 0; // reset threshold
 		this.model = newModel;
 		this.model.addListener(this);
 	}
 
 	/**
-	 * Creates the content of the FigureCanvas. Intended to be called
-	 * once in creating the ViewPart content. 
+	 * Creates the content of the FigureCanvas. Intended to be called once in
+	 * creating the ViewPart content.
 	 */
 	public void createContent() {
 		mc = new MouseAndKeyController();
@@ -508,7 +596,7 @@
 		horizontalBar.addSelectionListener(new SelectionListener() {
 
 			public void widgetDefaultSelected(SelectionEvent arg0) {
-				//do nothing by design
+				// do nothing by design
 			}
 
 			public void widgetSelected(SelectionEvent event) {
@@ -524,14 +612,14 @@
 				redraw();
 			}
 		});
-		
 	}
 
 	/**
 	 * Class containing code to deal with mouse and key events
-	 *
+	 * 
 	 */
-	private class MouseAndKeyController implements MouseMotionListener, MouseListener, KeyListener {
+	private class MouseAndKeyController implements MouseMotionListener,
+			MouseListener, KeyListener {
 
 		protected int mouseButton;
 		protected Point start;
@@ -559,66 +647,92 @@
 
 		public void render(Graphics graphics) {
 			graphics.pushState();
-			if (beingDragged){
-				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+			if (beingDragged) {
+				graphics.setForegroundColor(Display.getDefault()
+						.getSystemColor(SWT.COLOR_BLACK));
 				graphics.setLineWidth(1);
-				
+
 				int dragEnd = lastMouse.x;
-				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag area left edge
-				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag area right edge
-				graphics.drawRectangle(new Rectangle(dragLeftX, 0, (dragRightX-dragLeftX), getClientArea().height));
+				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag
+				// area
+				// left
+				// edge
+				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag
+				// area
+				// right
+				// edge
+				graphics.drawRectangle(new Rectangle(dragLeftX, 0,
+						(dragRightX - dragLeftX), getClientArea().height));
 			}
-			
-			if (lastShownAlloc != null){
-				
-				//for the selected dot, try to mark related allocs and free
+
+			if (lastShownAlloc != null) {
+
+				// for the selected dot, try to mark related allocs and free
 				FreeInfo freeInfo = null;
-				if (lastShownAlloc instanceof FreeInfo){
-					freeInfo = (FreeInfo)lastShownAlloc;
-				} else{
-					freeInfo = ((AllocInfo)lastShownAlloc).getFreedBy();
+				if (lastShownAlloc instanceof FreeInfo) {
+					freeInfo = (FreeInfo) lastShownAlloc;
+				} else {
+					freeInfo = ((AllocInfo) lastShownAlloc).getFreedBy();
 				}
-				if (freeInfo != null){
-					YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
-					Rectangle visibleRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
+				if (freeInfo != null) {
+					YConverter yConverter = new YConverter(
+							getClientArea().height, model
+									.getHighestCumulatedMemoryAlloc());
+					Rectangle visibleRect = graphics
+							.getClip(new org.eclipse.draw2d.geometry.Rectangle());
 					Point pfree = getLocationOnGraph(yConverter, freeInfo);
-					if (lastShownAlloc != freeInfo && visibleRect.contains(pfree)){
-						graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
-						graphics.drawLine(pfree.x+1, pfree.y+3, pfree.x+1, yConverter.bytesToY(0));
-						if (optimisedDrawing){ //draw circle as well since we don't have dots
-							graphics.drawOval(pfree.x - 2, pfree.y - 2, 5, 5);							
+					if (lastShownAlloc != freeInfo
+							&& visibleRect.contains(pfree)) {
+						graphics.setForegroundColor(Display.getDefault()
+								.getSystemColor(SWT.COLOR_DARK_GREEN));
+						graphics.drawLine(pfree.x + 1, pfree.y + 3,
+								pfree.x + 1, yConverter.bytesToY(0));
+						if (optimisedDrawing) { // draw circle as well since we
+							// don't have dots
+							graphics.drawOval(pfree.x - 2, pfree.y - 2, 5, 5);
 						}
 					}
 					for (AllocInfo freedAlloc : freeInfo.getFreedAllocs()) {
-						Point pAlloc = getLocationOnGraph(yConverter, freedAlloc);
-						if (lastShownAlloc != freedAlloc && visibleRect.contains(pAlloc)){
-							graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE));
-							graphics.drawLine(pAlloc.x+1, pAlloc.y+3, pAlloc.x+1, yConverter.bytesToY(0));
-							if (optimisedDrawing){ //draw circle as well since we don't have dots
-								graphics.drawOval(pAlloc.x - 2, pAlloc.y - 2, 5, 5);							
+						Point pAlloc = getLocationOnGraph(yConverter,
+								freedAlloc);
+						if (lastShownAlloc != freedAlloc
+								&& visibleRect.contains(pAlloc)) {
+							graphics.setForegroundColor(Display.getDefault()
+									.getSystemColor(SWT.COLOR_DARK_BLUE));
+							graphics.drawLine(pAlloc.x + 1, pAlloc.y + 3,
+									pAlloc.x + 1, yConverter.bytesToY(0));
+							if (optimisedDrawing) { // draw circle as well since
+								// we don't have dots
+								graphics.drawOval(pAlloc.x - 2, pAlloc.y - 2,
+										5, 5);
 							}
 						}
-						
+
 					}
 				}
-				//this should be the alloc that has its details displayed
-				//mark it in the graph
-				//draw a small circle around the alloc / dealloc, and a vertical line towards the X-axis
+				// this should be the alloc that has its details displayed
+				// mark it in the graph
+				// draw a small circle around the alloc / dealloc, and a
+				// vertical line towards the X-axis
 				Point p = getLocationOnGraph(lastShownAlloc);
-				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_CYAN));
+				graphics.setForegroundColor(Display.getDefault()
+						.getSystemColor(SWT.COLOR_CYAN));
 				graphics.setLineWidth(1);
 				graphics.drawOval(p.x - 2, p.y - 2, 5, 5);
-				if (optimisedDrawing || !isLeak(lastShownAlloc)){
-					graphics.drawLine(p.x+1, p.y+3, p.x+1, getClientArea().height - X_AXIS_HEIGHT);					
+				if (optimisedDrawing || !isLeak(lastShownAlloc)) {
+					graphics.drawLine(p.x + 1, p.y + 3, p.x + 1,
+							getClientArea().height - X_AXIS_HEIGHT);
 				}
 			}
 			graphics.popState();
 		}
 
 		private Point getLocationOnGraph(BaseInfo alloc) {
-			YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
+			YConverter yConverter = new YConverter(getClientArea().height,
+					model.getHighestCumulatedMemoryAlloc());
 			return getLocationOnGraph(yConverter, alloc);
 		}
+
 		private Point getLocationOnGraph(YConverter yConverter, BaseInfo alloc) {
 			int x = (int) ((alloc.getTime() - model.getFirstProcessTime()) / getScale());
 			int y = yConverter.bytesToY(alloc.getTotalMem());
@@ -637,7 +751,7 @@
 		 * .MouseEvent)
 		 */
 		public void mouseEntered(MouseEvent e) {
-			//do nothing by design
+			// do nothing by design
 		}
 
 		/*
@@ -648,7 +762,7 @@
 		 * .MouseEvent)
 		 */
 		public void mouseExited(MouseEvent e) {
-			//do nothing by design
+			// do nothing by design
 		}
 
 		/*
@@ -673,7 +787,7 @@
 		 * .MouseEvent)
 		 */
 		public void mouseMoved(MouseEvent e) {
-			//do nothing by design
+			// do nothing by design
 		}
 
 		/*
@@ -716,13 +830,20 @@
 
 				// set new scale
 				int dragEnd = me.getLocation().x;
-				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag area left edge
-				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag area right edge
+				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag
+				// area
+				// left
+				// edge
+				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag
+				// area
+				// right
+				// edge
 				int dragWindowStartTime = (int) (dragLeftX * getScale());
 
-
 				int dragWidth = dragRightX - dragLeftX;// drag area width
-				int oldVisibleWidth = getViewport().getSize().width;// visible window width
+				int oldVisibleWidth = getViewport().getSize().width;// visible
+				// window
+				// width
 				double newScale = getScale() * dragWidth / oldVisibleWidth;
 				if (newScale < 1.0) {
 					// don't allow a scale smaller than 1 millisecond per pixel
@@ -736,12 +857,13 @@
 				setScale(newScale);
 				setZoomedSize(dragLeftXScaled);
 
-				//make sure the drag window disappears
-				AnalyzeToolGraph.this.redraw();				
+				// make sure the drag window disappears
+				AnalyzeToolGraph.this.redraw();
 			} else if (me.button == 3) {
 				// mouse right click - zoom out
 
-				double maxScale = getMaxTimeValueInMilliSeconds() / getClientArea().width;
+				double maxScale = getMaxTimeValueInMilliSeconds()
+						/ getClientArea().width;
 				if (getScale() < maxScale) {
 					double newScale = GraphUtils.nextScale(getScale(), true);
 					if (getScale() != newScale) {
@@ -750,7 +872,8 @@
 						}
 
 						// get left window edge is ms to be set to after zooming
-						double leftEdgeInMs = getViewport().getViewLocation().x * getScale();
+						double leftEdgeInMs = getViewport().getViewLocation().x
+								* getScale();
 						setScale(newScale);
 						setZoomedSize((int) (leftEdgeInMs / newScale));
 					}
@@ -758,48 +881,60 @@
 			} else if (me.button == 1) {
 				BaseInfo info = findClosest(me.x, me.y);
 				if (info != null) {
-					iDotsSelecProv.setSelection(new StructuredSelection(new MemOpDescriptor(model.getFirstProcessTime(), info, iCurrentProject, iSymReader, cppFileNames, model.getCallstackManager())));
+					iDotsSelecProv
+							.setSelection(new StructuredSelection(
+									new MemOpDescriptor(model
+											.getFirstProcessTime(), info,
+											iCurrentProject, iSymReader,
+											cppFileNames, model
+													.getCallstackManager())));
 					lastShownAlloc = info;
 				}
-				}
-
 			}
-
+		}
 
 		public void keyPressed(KeyEvent ke) {
-			//do nothing by design
+			// do nothing by design
 		}
 
 		public void keyReleased(KeyEvent ke) {
 			if (ke.keycode == SWT.ARROW_RIGHT || ke.keycode == SWT.ARROW_LEFT) {
 				if (lastShownAlloc != null) {
-					BaseInfo info = findNextAlloc(lastShownAlloc, ke.keycode == SWT.ARROW_RIGHT);
+					BaseInfo info = findNextAlloc(lastShownAlloc,
+							ke.keycode == SWT.ARROW_RIGHT);
 					if (info != null) {
-						iDotsSelecProv.setSelection(new StructuredSelection(new MemOpDescriptor(model.getFirstProcessTime(), info, iCurrentProject, iSymReader, cppFileNames, model.getCallstackManager())));
+						iDotsSelecProv.setSelection(new StructuredSelection(
+								new MemOpDescriptor(
+										model.getFirstProcessTime(), info,
+										iCurrentProject, iSymReader,
+										cppFileNames, model
+												.getCallstackManager())));
 						lastShownAlloc = info;
-						
-						//if info is hidden from the visible graph area, scroll to reveal
+
+						// if info is hidden from the visible graph area, scroll
+						// to reveal
 						int x = getLocationOnGraph(info).x;
-						int leftEdge = getViewport().getHorizontalRangeModel().getValue();
-						int width = getViewport().getHorizontalRangeModel().getExtent();
-						if (x < leftEdge){
-							if (x > 10){
-								x -=10;
+						int leftEdge = getViewport().getHorizontalRangeModel()
+								.getValue();
+						int width = getViewport().getHorizontalRangeModel()
+								.getExtent();
+						if (x < leftEdge) {
+							if (x > 10) {
+								x -= 10;
 							}
 							getViewport().getHorizontalRangeModel().setValue(x);
-						} else if (x > (leftEdge + width)){
+						} else if (x > (leftEdge + width)) {
 							x -= (width - 10);
-							getViewport().getHorizontalRangeModel().setValue(x);							
+							getViewport().getHorizontalRangeModel().setValue(x);
 						}
 						AnalyzeToolGraph.this.redraw();
 					}
 				}
 			}
-
 		}
 
 		/**
-		 * resets any state
+		 * Resets any state.
 		 */
 		public void clearState() {
 			mouseButton = 0;
@@ -807,22 +942,22 @@
 			beingDragged = false;
 			lastShownAlloc = null;
 			lastMouse = null;
-			if (iDotsSelecProv != null){
-				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);				
+			if (iDotsSelecProv != null) {
+				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);
 			}
 		}
-		
 	}
-	
+
 	/**
-	 * Returns an SWT system color code depending on the type of the paramter passed.
-	 * </br> SWT.COLOR_DARK_BLUE for a alloc (that is not a leak)
-	 * </br> SWT.COLOR_RED for a leak
-	 * </br> SWT.COLOR_DARK_GREEN for a free
-	 * @param info the allocation to evaluate
+	 * Returns an SWT system color code depending on the type of the paramter
+	 * passed. </br> SWT.COLOR_DARK_BLUE for a alloc (that is not a leak) </br>
+	 * SWT.COLOR_RED for a leak </br> SWT.COLOR_DARK_GREEN for a free
+	 * 
+	 * @param info
+	 *            the allocation to evaluate
 	 * @return the appropriate SWT system color code
 	 */
-	private int getColorForAllocType(BaseInfo info){
+	private int getColorForAllocType(BaseInfo info) {
 		int color;
 		if (info instanceof AllocInfo) {
 			if (((AllocInfo) info).isFreed()) {
@@ -835,16 +970,18 @@
 		}
 		return color;
 	}
-	
+
 	/**
-	 * Returns true if the passed info is a leak, false otherwise.
-	 * AllocInfo that haven't been freed are considered leaks.
+	 * Returns true if the passed info is a leak, false otherwise. AllocInfo
+	 * that haven't been freed are considered leaks.
 	 * 
-	 * @param info the BaseInfo to test
+	 * @param info
+	 *            the BaseInfo to test
 	 * @return true if leak, false otherwise
 	 */
-	private static boolean isLeak(BaseInfo info){
-		return info instanceof AllocInfo && !(((AllocInfo) info).isFreed()) ? true : false;
+	private static boolean isLeak(BaseInfo info) {
+		return info instanceof AllocInfo && !(((AllocInfo) info).isFreed()) ? true
+				: false;
 	}
 
 	/**
@@ -870,11 +1007,15 @@
 		}
 	}
 
-	/* (non-Javadoc)
-	 * @see com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener#onProcessesAdded()
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener
+	 * #onProcessesAdded()
 	 */
 	public void onProcessesAdded() {
-		//the model is now ready to use - call a redraw on the graph
+		// the model is now ready to use - call a redraw on the graph
 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
 			public void run() {
 				mc.clearState();
@@ -884,31 +1025,39 @@
 		});
 	}
 
-	/* (non-Javadoc)
-	 * @see com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener#onProcessSelected(com.nokia.s60tools.analyzetool.engine.statistic.ProcessInfo)
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener
+	 * #onProcessSelected
+	 * (com.nokia.s60tools.analyzetool.engine.statistic.ProcessInfo)
 	 */
 	public void onProcessSelected(ProcessInfo p) {
 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
 			public void run() {
 				mc.clearState();
-				optimisedDrawing = model.getSelectedProcess().getAllocsFrees().size() > 25000 ? true : false;
+				optimisedDrawing = model.getSelectedProcess().getAllocsFrees()
+						.size() > ChartContainer.OPT_DRAWING_LIMIT ? true
+						: false;
 				userInformed = false;
 				zoomGraph();
 				redraw();
 			}
 		});
 	}
-	
+
 	@Override
 	public void dispose() {
-		//there is no dispose() entry point in this class; we may have to call this via MainView.dispose()
+		// there is no dispose() entry point in this class; we may have to call
+		// this via MainView.dispose()
 		site.setSelectionProvider(null);
 		iDotsSelecProv = null;
-		if (timeImage != null){
+		if (timeImage != null) {
 			timeImage.dispose();
 		}
 		IPartService partService = PlatformUI.getWorkbench()
-		.getActiveWorkbenchWindow().getPartService();
+				.getActiveWorkbenchWindow().getPartService();
 		partService.removePartListener(iGraphPartServiceListener);
 		iGraphPartServiceListener = null;
 		if (iSymReader != null) {
@@ -916,7 +1065,7 @@
 			iSymReader = null;
 		}
 	}
-	
+
 	private void setZoomedSize(final int newXLocation) {
 		int prefSize = (int) (getMaxTimeValueInMilliSeconds() / getScale());
 
@@ -927,106 +1076,132 @@
 		panel.setPreferredSize(prefSize, 0);
 
 		if (prefSize > getClientArea().width) {
-			getViewport().getHorizontalRangeModel().addPropertyChangeListener(new PropertyChangeListener() {
-				public void propertyChange(PropertyChangeEvent e) {
-					if (e.getPropertyName().equals(PROP_MAXIMUM)) {
-						getViewport().getHorizontalRangeModel().removePropertyChangeListener(this);
-						getViewport().getHorizontalRangeModel().setValue(newXLocation);
-					}
-				}
+			getViewport().getHorizontalRangeModel().addPropertyChangeListener(
+					new PropertyChangeListener() {
+						public void propertyChange(PropertyChangeEvent e) {
+							if (e.getPropertyName().equals(PROP_MAXIMUM)) {
+								getViewport().getHorizontalRangeModel()
+										.removePropertyChangeListener(this);
+								getViewport().getHorizontalRangeModel()
+										.setValue(newXLocation);
+							}
+						}
 
-			});
+					});
 			panel.setSize(prefSize, 0);
 
 		} else {
-			// this only works if the canvas is large enough, otherwise use property listener
-			getViewport().getHorizontalRangeModel().setValue(newXLocation); 
+			// this only works if the canvas is large enough, otherwise use
+			// property listener
+			getViewport().getHorizontalRangeModel().setValue(newXLocation);
 		}
 	}
-	
+
 	/**
-	 * DotSelectionProvider :  when a user selects a Dot on the graph, this class delivers the associated
-	 * descriptor MemOpDescriptor to the views interested in it mainly the Properties View. 
-	 *
+	 * DotSelectionProvider : when a user selects a Dot on the graph, this class
+	 * delivers the associated descriptor MemOpDescriptor to the views
+	 * interested in it mainly the Properties View.
+	 * 
 	 */
-	private class DotSelectionProvider implements ISelectionProvider, SelectionListener {
+	private class DotSelectionProvider implements ISelectionProvider,
+			SelectionListener {
 		private ListenerList iSelectionChangedListeners = new ListenerList();
 
-		/* (non-Javadoc)
-		 * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see
+		 * org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener
+		 * (org.eclipse.jface.viewers.ISelectionChangedListener)
 		 */
-		public void addSelectionChangedListener(ISelectionChangedListener listener) {
-			//TODO is there a way to allow only properties view to register.
+		public void addSelectionChangedListener(
+				ISelectionChangedListener listener) {
+			// TODO is there a way to allow only properties view to register.
 			iSelectionChangedListeners.add(listener);
-
 		}
 
-		/* (non-Javadoc)
+		/*
+		 * (non-Javadoc)
+		 * 
 		 * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
 		 */
 		public ISelection getSelection() {
 			return iCurrentSelectedDot;
 		}
 
-		/* (non-Javadoc)
-		 * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @seeorg.eclipse.jface.viewers.ISelectionProvider#
+		 * removeSelectionChangedListener
+		 * (org.eclipse.jface.viewers.ISelectionChangedListener)
 		 */
-		public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+		public void removeSelectionChangedListener(
+				ISelectionChangedListener listener) {
 			iSelectionChangedListeners.remove(listener);
-
 		}
 
-		/* (non-Javadoc)
-		 * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see
+		 * org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse
+		 * .jface.viewers.ISelection)
 		 */
 		public void setSelection(ISelection selection) {
 			iCurrentSelectedDot = selection;
-			//notify the listeners mainly the property view
+			// notify the listeners mainly the property view
 			for (final Object listenerObj : iSelectionChangedListeners
-					.getListeners())
-			{
+					.getListeners()) {
 				((ISelectionChangedListener) listenerObj)
-					.selectionChanged(new SelectionChangedEvent(this, getSelection()));
+						.selectionChanged(new SelectionChangedEvent(this,
+								getSelection()));
 			}
 		}
 
-		/* (non-Javadoc)
-		 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see
+		 * org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org
+		 * .eclipse.swt.events.SelectionEvent)
 		 */
 		public void widgetDefaultSelected(SelectionEvent event) {
 			widgetSelected(event);
-			
 		}
 
-		/* (non-Javadoc)
-		 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see
+		 * org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse
+		 * .swt.events.SelectionEvent)
 		 */
 		public void widgetSelected(SelectionEvent arg0) {
 			for (final Object listenerObj : iSelectionChangedListeners
-					.getListeners())
-			{
+					.getListeners()) {
 				((ISelectionChangedListener) listenerObj)
-					.selectionChanged(new SelectionChangedEvent(this, getSelection()));
+						.selectionChanged(new SelectionChangedEvent(this,
+								getSelection()));
 			}
-			
 		}
-
 	}
-	
-	
+
 	/**
-	 * GraphPartServiceListener is for convenience only. It serves to find an appropriate time to
-	 * add DotSelectionProvider to the part site. It also covers that case where the properties View is already
-	 * open before opening AnalyzeTool View.
-	 *
+	 * GraphPartServiceListener is for convenience only. It serves to find an
+	 * appropriate time to add DotSelectionProvider to the part site. It also
+	 * covers that case where the properties View is already open before opening
+	 * AnalyzeTool View.
+	 * 
 	 */
-	private class GraphPartServiceListener implements IPartListener, IWindowListener {
+	private class GraphPartServiceListener implements IPartListener,
+			IWindowListener {
 
 		public void partActivated(IWorkbenchPart part) {
 			if (part instanceof MainView || part instanceof PropertySheet) {
-				
+
 				site = part.getSite();
-				//set property sheet selection provider.
+				// set property sheet selection provider.
 				site.setSelectionProvider(iDotsSelecProv);
 				if (part instanceof MainView && iSymReader != null) {
 					iSymReader.reOpenCachedSymbolFiles();
@@ -1035,21 +1210,22 @@
 		}
 
 		public void partBroughtToTop(IWorkbenchPart part) {
-			//do nothing
+			// do nothing
 		}
 
 		public void partClosed(IWorkbenchPart part) {
-			//TODO this is not working. why?
-			if (part instanceof MainView || part instanceof PropertySheet) {			
+			// TODO this is not working. why?
+			if (part instanceof MainView || part instanceof PropertySheet) {
 				site = part.getSite();
-				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);	
-				//set property sheet selection provider.
+				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);
+				// set property sheet selection provider.
 				site.setSelectionProvider(null);
 			}
 		}
 
 		public void partDeactivated(IWorkbenchPart part) {
-			//the user might want to rebuild the project, so close the sumbol files
+			// the user might want to rebuild the project, so close the sumbol
+			// files
 			if (part instanceof MainView && iSymReader != null) {
 				iSymReader.closeCachedSymbolFiles();
 			}
@@ -1058,43 +1234,47 @@
 		public void partOpened(IWorkbenchPart part) {
 			if (part instanceof MainView) {
 				try {
-					part.getSite().getPage().showView("org.eclipse.ui.views.PropertySheet");//$NON-NLS-1$
+					part.getSite().getPage().showView(
+							"org.eclipse.ui.views.PropertySheet");//$NON-NLS-1$
 				} catch (PartInitException e) {
-					//just log the exception
-					Activator.getDefault().log(IStatus.ERROR, e.getMessage(), e);
+					// just log the exception
+					Activator.getDefault()
+							.log(IStatus.ERROR, e.getMessage(), e);
 				}
 			}
 		}
 
 		public void windowActivated(IWorkbenchWindow window) {
-			if (iSymReader != null && window.getActivePage().getActivePart() instanceof MainView) {
+			if (iSymReader != null
+					&& window.getActivePage().getActivePart() instanceof MainView) {
 				iSymReader.reOpenCachedSymbolFiles();
-			}			
+			}
 		}
 
 		public void windowClosed(IWorkbenchWindow window) {
-			//do nothing
-			
+			// do nothing
+
 		}
 
 		public void windowDeactivated(IWorkbenchWindow window) {
 			// the user might do a re-build from the command line
 			if (iSymReader != null) {
 				iSymReader.closeCachedSymbolFiles();
-			}		
+			}
 		}
 
 		public void windowOpened(IWorkbenchWindow window) {
-			//do nothing	
+			// do nothing
 		}
 	}
-	
+
 	/**
 	 * set a new project
+	 * 
 	 * @param aProject
 	 */
 	public void setProject(IProject aProject) {
-		if(iCurrentProject != aProject) {
+		if (iCurrentProject != aProject) {
 			iCurrentProject = aProject;
 			iSymReader = new SymReader(aProject);
 			iSymReader.loadProjectTargetsInfo();
@@ -1102,16 +1282,16 @@
 			try {
 				iCurrentProject.accept(visitor);
 			} catch (CoreException ce) {
-				//just log the exception
+				// just log the exception
 				Activator.getDefault().log(IStatus.ERROR, ce.getMessage(), ce);
 			}
 		}
 	}
-	
+
 	/**
-	 * Load all cpp files from the project
-	 * This is callback to ResourcceVisitor.
-	 *
+	 * Load all cpp files from the project. This is callback to
+	 * ResourcceVisitor.
+	 * 
 	 * @param resource
 	 */
 	public final void loadFileInfo(IResource resource) {
@@ -1124,4 +1304,21 @@
 		}
 	}
 
+	/**
+	 * Sets the threshold. Only memory operations of a size greater or equals /
+	 * lower or equals the threshold will be drawn on the graph.
+	 * 
+	 * @param value
+	 *            the threshold value in bytes
+	 * @param above
+	 *            true if filtering "above", false if "below" the threshold
+	 */
+	public void setThreshold(long value, boolean above) {
+		if (value < 0) {
+			throw new IllegalArgumentException(
+					"The threshold cannot be less than 0");
+		}
+		threshold = value;
+		aboveThreshold = above;
+	}
 }