sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/internal/ui/graph/AnalyzeToolGraph.java
changeset 15 0367d2db2c06
parent 6 f65f740e69f9
equal deleted inserted replaced
14:bb339882c6e9 15:0367d2db2c06
    13  *
    13  *
    14  * Description:  Definitions for the class AnalyzeToolGraph
    14  * Description:  Definitions for the class AnalyzeToolGraph
    15  *
    15  *
    16  */
    16  */
    17 package com.nokia.s60tools.analyzetool.internal.ui.graph;
    17 package com.nokia.s60tools.analyzetool.internal.ui.graph;
       
    18 
    18 import java.beans.PropertyChangeEvent;
    19 import java.beans.PropertyChangeEvent;
    19 import java.beans.PropertyChangeListener;
    20 import java.beans.PropertyChangeListener;
    20 import java.util.AbstractList;
    21 import java.util.AbstractList;
    21 import java.util.ArrayList;
    22 import java.util.ArrayList;
    22 import java.util.List;
    23 import java.util.List;
    76 import com.nokia.s60tools.analyzetool.internal.ui.util.GraphUtils;
    77 import com.nokia.s60tools.analyzetool.internal.ui.util.GraphUtils;
    77 import com.nokia.s60tools.analyzetool.ui.MainView;
    78 import com.nokia.s60tools.analyzetool.ui.MainView;
    78 import com.nokia.s60tools.analyzetool.ui.ResourceVisitor;
    79 import com.nokia.s60tools.analyzetool.ui.ResourceVisitor;
    79 
    80 
    80 /**
    81 /**
    81  * A FigureCanvas containing the graph and X-axis area of the 
    82  * A FigureCanvas containing the graph and X-axis area of the AnalyzeTool chart.
    82  * AnalyzeTool chart.
       
    83  */
    83  */
    84 public class AnalyzeToolGraph extends FigureCanvas implements IMemoryActivityModelChangeListener {
    84 public class AnalyzeToolGraph extends FigureCanvas implements
       
    85 		IMemoryActivityModelChangeListener {
    85 
    86 
    86 	private static final int BOUNDARY_OFFSET = 3;
    87 	private static final int BOUNDARY_OFFSET = 3;
    87 	/** used for range model listener */
    88 	/** used for range model listener */
    88 	private static final String PROP_MAXIMUM = "maximum"; //$NON-NLS-1$
    89 	private static final String PROP_MAXIMUM = "maximum"; //$NON-NLS-1$
    89 	private static final int X_AXIS_HEIGHT = 50;
    90 	private static final int X_AXIS_HEIGHT = 50;
    90 	/** used for "Don't ask again" dialog */
    91 	/** used for "Don't ask again" dialog */
    91 	private static final String PROMPT_KEY = "GraphOptimisationPrompt";//$NON-NLS-1$
    92 	private static final String PROMPT_KEY = "GraphOptimisationPrompt";//$NON-NLS-1$
    92 	
    93 
    93 	/** the scaling factor used for scaling the x-axis*/
    94 	/** the scaling factor used for scaling the x-axis */
    94 	private double scale = 1.0;
    95 	private double scale = 1.0;
    95 
    96 
    96 	/** the model */
    97 	/** the model */
    97 	private IMemoryActivityModel model;
    98 	private IMemoryActivityModel model;
    98 
    99 
    99 	/** for synchronisation with the PropertySheet */
   100 	/** for synchronization with the PropertySheet */
   100 	private DotSelectionProvider iDotsSelecProv = new DotSelectionProvider();
   101 	private DotSelectionProvider iDotsSelecProv = new DotSelectionProvider();
   101 	private IWorkbenchPartSite site;
   102 	private IWorkbenchPartSite site;
   102 	
   103 
   103 	/** used when user selects a dot on the graph, and moves with arrow keys */
   104 	/** used when user selects a dot on the graph, and moves with arrow keys */
   104 	private ISelection iCurrentSelectedDot = null;
   105 	private ISelection iCurrentSelectedDot = null;
   105 	
   106 
   106 	/** controls mouse and arrow key movements */
   107 	/** controls mouse and arrow key movements */
   107 	private MouseAndKeyController mc;
   108 	private MouseAndKeyController mc;
   108 	private SymReader iSymReader = null;
   109 	private SymReader iSymReader = null;
   109 	private IProject iCurrentProject = null;
   110 	private IProject iCurrentProject = null;
   110 	/** Contains c++ files info for the current project. */
   111 	/** Contains c++ files info for the current project. */
   111 	private final AbstractList<String> cppFileNames;
   112 	private final AbstractList<String> cppFileNames;
   112 	
   113 
   113 	/** "time ->" on axis*/
   114 	/** "time ->" on axis */
   114 	private Image timeImage;
   115 	private Image timeImage;
   115 	private GraphPartServiceListener iGraphPartServiceListener;
   116 	private GraphPartServiceListener iGraphPartServiceListener;
   116 	private boolean optimisedDrawing;
   117 	private boolean optimisedDrawing;
   117 	private boolean userInformed;
   118 	private boolean userInformed;
   118 
   119 
       
   120 	/**
       
   121 	 * The threshold value for filtered drawing of dots. Only draw the dot if
       
   122 	 * the memory operation size is above or equals / below or equals the
       
   123 	 * threshold. Zero for no filtering.
       
   124 	 */
       
   125 	private long threshold;
       
   126 	/** indicates whether filtering is above or below the threshold */
       
   127 	private boolean aboveThreshold;
   119 
   128 
   120 	/**
   129 	/**
   121 	 * Constructor
   130 	 * Constructor
   122 	 * @param parent The parent composite
   131 	 * 
       
   132 	 * @param parent
       
   133 	 *            The parent composite
   123 	 */
   134 	 */
   124 	public AnalyzeToolGraph(Composite parent) {
   135 	public AnalyzeToolGraph(Composite parent) {
   125 		super(parent);
   136 		super(parent);
   126 		IPartService partService = PlatformUI.getWorkbench()
   137 		IPartService partService = PlatformUI.getWorkbench()
   127 				.getActiveWorkbenchWindow().getPartService();
   138 				.getActiveWorkbenchWindow().getPartService();
   130 		PlatformUI.getWorkbench().addWindowListener(iGraphPartServiceListener);
   141 		PlatformUI.getWorkbench().addWindowListener(iGraphPartServiceListener);
   131 		cppFileNames = new ArrayList<String>();
   142 		cppFileNames = new ArrayList<String>();
   132 	}
   143 	}
   133 
   144 
   134 	/**
   145 	/**
   135 	 * Draws the graph on the canvas. Intended to be called on a paint event. 
   146 	 * Draws the graph on the canvas. Intended to be called on a paint event.
       
   147 	 * 
   136 	 * @param graphics
   148 	 * @param graphics
   137 	 */
   149 	 */
   138 	public void paint(final Graphics graphics) {
   150 	public void paint(final Graphics graphics) {
   139 		if (optimisedDrawing && !userInformed){
   151 		if (optimisedDrawing && !userInformed) {
   140 			userInformed = true;
   152 			userInformed = true;
   141 			IPreferenceStore preferenceStore = Activator.getPreferences();
   153 			IPreferenceStore preferenceStore = Activator.getPreferences();
   142             if (!preferenceStore.getString(PROMPT_KEY).equals(MessageDialogWithToggle.ALWAYS)) {
   154 			if (!preferenceStore.getString(PROMPT_KEY).equals(
   143                 String dilaogTitle = "Optimised Graph";
   155 					MessageDialogWithToggle.ALWAYS)) {
   144                 String message = "The process contains too many memory operations to display efficiently. To optimise, only leaks will be indicated on the graph.";
   156 				String dilaogTitle = "Optimised Graph";
   145                 String toggleMessage = "Don't show this again";
   157 				String message = "The process contains too many memory operations to display efficiently. To optimise, only leaks will be indicated on the graph.";
   146 
   158 				String toggleMessage = "Don't show this again";
   147                 MessageDialogWithToggle.openInformation(getShell(), dilaogTitle, message, toggleMessage, false, preferenceStore, PROMPT_KEY);
   159 
   148             }
   160 				MessageDialogWithToggle.openInformation(getShell(),
   149 		}
   161 						dilaogTitle, message, toggleMessage, false,
   150 		Rectangle visibleRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
   162 						preferenceStore, PROMPT_KEY);
   151 		YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
   163 			}
   152 
   164 		}
   153 		if (model.getSelectedProcess() != null && model.getSelectedProcess().getAllocsFrees().size() > 0){
   165 		Rectangle visibleRect = graphics.getClip(new Rectangle());
   154 			PointList pts = new PointList((model.getSelectedProcess().getAllocsFrees().size()*2)-1);
   166 		YConverter yConverter = new YConverter(getClientArea().height, model
       
   167 				.getHighestCumulatedMemoryAlloc());
       
   168 
       
   169 		if (model.getSelectedProcess() != null
       
   170 				&& model.getSelectedProcess().getAllocsFrees().size() > 0) {
       
   171 			PointList pts = new PointList((model.getSelectedProcess()
       
   172 					.getAllocsFrees().size() * 2) - 1);
   155 			Point prevPt = null;
   173 			Point prevPt = null;
   156 			List<Point> dotLocations = new ArrayList<Point>();
   174 			List<Point> dotLocations = new ArrayList<Point>();
   157 			List<Integer> colorDotLocations = new ArrayList<Integer>();
   175 			List<Integer> colorDotLocations = new ArrayList<Integer>();
   158 
   176 
   159 			for (BaseInfo info : model.getSelectedProcess().getAllocsFrees()) {
   177 			for (BaseInfo info : model.getSelectedProcess().getAllocsFrees()) {
   160 				int x_point = (int) ((info.getTime() - model.getFirstProcessTime()) / getScale());
   178 				int x_point = (int) ((info.getTime() - model
       
   179 						.getFirstProcessTime()) / getScale());
   161 				int y_point = yConverter.bytesToY(info.getTotalMem());
   180 				int y_point = yConverter.bytesToY(info.getTotalMem());
   162 
   181 
   163 				if (y_point < 0) {
   182 				if (y_point < 0) {
   164 					y_point = 0;
   183 					y_point = 0;
   165 				}
   184 				}
   166 				if (prevPt != null) {
   185 				if (prevPt != null) {
   167 					pts.addPoint(x_point, prevPt.y);
   186 					pts.addPoint(x_point, prevPt.y);
   168 				}
   187 				}
   169 				Point nextPt = new Point(x_point, y_point);
   188 				Point nextPt = new Point(x_point, y_point);
   170 				if (visibleRect.contains(nextPt) && (isLeak(info) || (!optimisedDrawing && !dotLocations.contains(nextPt)))){
   189 				if (visibleRect.contains(nextPt)
   171 					//for improved performance, only draw dots that are in visible clip area
   190 						&& (isLeak(info) || (!optimisedDrawing
   172 					//and don't draw a dot if there is one already, unless it's a leak
   191 								&& !dotLocations.contains(nextPt) && validInThreshold(info)))) {
       
   192 					// for improved performance, only draw dots that are in
       
   193 					// visible clip area
       
   194 					// and don't draw a dot if there is one already, unless it's
       
   195 					// a leak
   173 					dotLocations.add(nextPt);
   196 					dotLocations.add(nextPt);
   174 					colorDotLocations.add(getColorForAllocType(info));
   197 					colorDotLocations.add(getColorForAllocType(info));
   175 				}
   198 				}
   176 				pts.addPoint(nextPt);
   199 				pts.addPoint(nextPt);
   177 				prevPt = nextPt;
   200 				prevPt = nextPt;
   178 			}
   201 			}
   179 
   202 
   180 			if (pts.size() > 0){
   203 			if (pts.size() > 0) {
   181 				graphics.pushState();
   204 				graphics.pushState();
   182 				
   205 
   183 				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_YELLOW));
   206 				graphics.setForegroundColor(Display.getDefault()
       
   207 						.getSystemColor(SWT.COLOR_DARK_YELLOW));
   184 				graphics.setLineWidthFloat(optimisedDrawing ? 0.5f : 2.0f);
   208 				graphics.setLineWidthFloat(optimisedDrawing ? 0.5f : 2.0f);
   185 				graphics.drawPolyline(pts);
   209 				graphics.drawPolyline(pts);
   186 				
   210 
   187 				graphics.setLineWidthFloat(optimisedDrawing ? 0.5f : 1.0f);
   211 				graphics.setLineWidthFloat(optimisedDrawing ? 0.5f : 1.0f);
   188 				graphics.setAntialias(SWT.ON);
   212 				graphics.setAntialias(SWT.ON);
   189 				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_RED));
   213 				graphics.setForegroundColor(Display.getDefault()
   190 				graphics.setBackgroundColor(Display.getDefault().getSystemColor(SWT.COLOR_RED));
   214 						.getSystemColor(SWT.COLOR_RED));
       
   215 				graphics.setBackgroundColor(Display.getDefault()
       
   216 						.getSystemColor(SWT.COLOR_RED));
   191 				int colourCode = SWT.COLOR_RED;
   217 				int colourCode = SWT.COLOR_RED;
   192 				for (int j = 0; j < dotLocations.size(); j++) {
   218 				for (int j = 0; j < dotLocations.size(); j++) {
   193 					Point dotLocation = dotLocations.get(j);
   219 					Point dotLocation = dotLocations.get(j);
   194 					if (!optimisedDrawing && colorDotLocations.get(j) != colourCode) {
   220 					if (!optimisedDrawing
       
   221 							&& colorDotLocations.get(j) != colourCode) {
   195 						colourCode = colorDotLocations.get(j);
   222 						colourCode = colorDotLocations.get(j);
   196 						graphics.setBackgroundColor(Display.getDefault().getSystemColor(colourCode));
   223 						graphics.setBackgroundColor(Display.getDefault()
       
   224 								.getSystemColor(colourCode));
   197 					}
   225 					}
   198 					// paint the dot
   226 					// paint the dot
   199 					graphics.fillOval(dotLocation.x - 2, dotLocation.y - 2,	5, 5);
   227 					graphics.fillOval(dotLocation.x - 2, dotLocation.y - 2, 5,
       
   228 							5);
   200 					if (!optimisedDrawing && colourCode == SWT.COLOR_RED) {
   229 					if (!optimisedDrawing && colourCode == SWT.COLOR_RED) {
   201 						// draw a red line
   230 						// draw a red line
   202 						graphics.drawLine(dotLocation.x, dotLocation.y,	dotLocation.x, yConverter.bytesToY(0));
   231 						graphics.drawLine(dotLocation.x, dotLocation.y,
       
   232 								dotLocation.x, yConverter.bytesToY(0));
   203 					}
   233 					}
   204 				}
   234 				}
   205 				graphics.popState();
   235 				graphics.popState();
   206 			}
   236 			}
   207 		}
   237 		}
   208 	}
   238 	}
   209 	
   239 
   210 	
   240 	/**
   211 
   241 	 * Returns true of the size of the alloc or free is greater or equals / less
   212 	/**
   242 	 * or equals the threshold. Returns true if no threshold is set.
   213 	 * Draws the background grid on the canvas. Intended to be called on a paint event.
   243 	 * 
       
   244 	 * @param info
       
   245 	 *            the memory operation to check
       
   246 	 * @return
       
   247 	 */
       
   248 	private boolean validInThreshold(BaseInfo info) {
       
   249 		if (threshold <= 0
       
   250 				|| info instanceof AllocInfo
       
   251 				&& (aboveThreshold ? (((AllocInfo) info).getSizeInt() >= threshold)
       
   252 						: (((AllocInfo) info).getSizeInt() <= threshold))) {
       
   253 			return true;
       
   254 		}
       
   255 
       
   256 		if (info instanceof FreeInfo
       
   257 				&& ((aboveThreshold && ((FreeInfo) info).getSizeInt() >= threshold) || (!aboveThreshold && ((FreeInfo) info)
       
   258 						.getSizeInt() <= threshold))) {
       
   259 			// check at least one of its alloc qualifies
       
   260 			for (AllocInfo allocInfo : ((FreeInfo) info).getFreedAllocs()) {
       
   261 				if ((aboveThreshold && allocInfo.getSizeInt() >= threshold)
       
   262 						|| (!aboveThreshold && allocInfo.getSizeInt() <= threshold)) {
       
   263 					return true;
       
   264 				}
       
   265 			}
       
   266 		}
       
   267 		return false;
       
   268 	}
       
   269 
       
   270 	/**
       
   271 	 * Draws the background grid on the canvas. Intended to be called on a paint
       
   272 	 * event.
       
   273 	 * 
   214 	 * @param graphics
   274 	 * @param graphics
   215 	 */
   275 	 */
   216 	public void drawBackGroundLines(Graphics graphics) {
   276 	public void drawBackGroundLines(Graphics graphics) {
   217 		Rectangle canvasRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
   277 		Rectangle canvasRect = graphics
       
   278 				.getClip(new org.eclipse.draw2d.geometry.Rectangle());
   218 		graphics.setForegroundColor(ColorUtil.COLOR_100); // middle grey
   279 		graphics.setForegroundColor(ColorUtil.COLOR_100); // middle grey
   219 		graphics.setBackgroundColor(ColorUtil.COLOR_170); // lighter grey
   280 		graphics.setBackgroundColor(ColorUtil.COLOR_170); // lighter grey
   220 
   281 
   221 		int height = getClientArea().height;
   282 		int height = getClientArea().height;
   222 		int width = getClientArea().width;
   283 		int width = getClientArea().width;
   223 
   284 
   224 		graphics.fillRectangle(new Rectangle(canvasRect.x, 0, width, height - X_AXIS_HEIGHT));
   285 		graphics.fillRectangle(new Rectangle(canvasRect.x, 0, width, height
       
   286 				- X_AXIS_HEIGHT));
   225 
   287 
   226 		double visY = height - X_AXIS_HEIGHT;
   288 		double visY = height - X_AXIS_HEIGHT;
   227 
   289 
   228 		int k = 0;
   290 		int k = 0;
   229 		// horizontal lines, height is divided into 10 sections, line is dotted
   291 		// horizontal lines, height is divided into 10 sections, line is dotted
   235 			}
   297 			}
   236 		}
   298 		}
   237 
   299 
   238 		graphics.setForegroundColor(ColorUtil.COLOR_100);
   300 		graphics.setForegroundColor(ColorUtil.COLOR_100);
   239 		graphics.setBackgroundColor(ColorUtil.WHITE);
   301 		graphics.setBackgroundColor(ColorUtil.WHITE);
   240 		
   302 
   241 		int alignedLeftEdge = (canvasRect.x / 50)*50;
   303 		int alignedLeftEdge = (canvasRect.x / 50) * 50;
   242 
   304 
   243 		// vertical lines (one darker, one lighter vertical line in turns every
   305 		// vertical lines (one darker, one lighter vertical line in turns every
   244 		// 50 points in width)
   306 		// 50 points in width)
   245 		if (width > 0) {
   307 		if (width > 0) {
   246 			for (int x = alignedLeftEdge ; x <= canvasRect.x + canvasRect.width; x += 50) {
   308 			for (int x = alignedLeftEdge; x <= canvasRect.x + canvasRect.width; x += 50) {
   247 				if (x % 100 == 0)
   309 				if (x % 100 == 0)
   248 					graphics.setForegroundColor(ColorUtil.COLOR_100);
   310 					graphics.setForegroundColor(ColorUtil.COLOR_100);
   249 				else
   311 				else
   250 					graphics.setForegroundColor(ColorUtil.COLOR_200);
   312 					graphics.setForegroundColor(ColorUtil.COLOR_200);
   251 
   313 
   258 
   320 
   259 		graphics.setForegroundColor(ColorUtil.COLOR_100);
   321 		graphics.setForegroundColor(ColorUtil.COLOR_100);
   260 		graphics.setBackgroundColor(ColorUtil.WHITE);
   322 		graphics.setBackgroundColor(ColorUtil.WHITE);
   261 
   323 
   262 		for (int x = alignedLeftEdge; x <= canvasRect.x + canvasRect.width; x += 50) {
   324 		for (int x = alignedLeftEdge; x <= canvasRect.x + canvasRect.width; x += 50) {
   263 			String timeStringWithUnits = GraphUtils.getTimeStringWithUnits(x * scale);
   325 			String timeStringWithUnits = GraphUtils.getTimeStringWithUnits(x
       
   326 					* scale);
   264 			graphics.drawString(timeStringWithUnits, x + 5, height - 13);
   327 			graphics.drawString(timeStringWithUnits, x + 5, height - 13);
   265 		}
   328 		}
   266 		if (timeImage == null){
   329 		if (timeImage == null) {
   267 			timeImage = GraphUtils.getVerticalLabel("Time");			
   330 			timeImage = GraphUtils.getVerticalLabel("Time");
   268 		}
   331 		}
   269 		graphics.drawImage(timeImage, width / 2, height - 30);
   332 		graphics.drawImage(timeImage, width / 2, height - 30);
   270 	}
   333 	}
   271 
   334 
   272 	/**
   335 	/**
   273 	 * Returns the content of the tooltip appropriate for the given coordinate
   336 	 * Returns the content of the tooltip appropriate for the given coordinate
   274 	 * @param x the X-coordinate
   337 	 * 
   275 	 * @param y the Y-coordinate
   338 	 * @param x
       
   339 	 *            the X-coordinate
       
   340 	 * @param y
       
   341 	 *            the Y-coordinate
   276 	 * @return String containing the content of the tooltip
   342 	 * @return String containing the content of the tooltip
   277 	 */
   343 	 */
   278 	public String getToolTipText(int x, int y) {
   344 	public String getToolTipText(int x, int y) {
   279 		StringBuilder text = new StringBuilder();
   345 		StringBuilder text = new StringBuilder();
   280 		if (model.getSelectedProcess() == null) {
   346 		if (model.getSelectedProcess() == null) {
   285 			return null;
   351 			return null;
   286 		}
   352 		}
   287 
   353 
   288 		double timeInMs = (x * getScale());// x value in milliseconds
   354 		double timeInMs = (x * getScale());// x value in milliseconds
   289 
   355 
   290 		YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
   356 		YConverter yConverter = new YConverter(getClientArea().height, model
       
   357 				.getHighestCumulatedMemoryAlloc());
   291 		double bytes = yConverter.yToBytes(y); // y value in bytes
   358 		double bytes = yConverter.yToBytes(y); // y value in bytes
   292 
   359 
   293 		text.append(GraphUtils.renderTime(timeInMs)); 
   360 		text.append(GraphUtils.renderTime(timeInMs));
   294 
   361 
   295 		BaseInfo allocInfo = findClosestAlloc((int) timeInMs, (int) ((x - BOUNDARY_OFFSET) * getScale()), (int) ((x + BOUNDARY_OFFSET) * getScale()),
   362 		BaseInfo allocInfo = findClosestAlloc((int) timeInMs,
   296 				(int) bytes, (int) yConverter.yToBytes(y + BOUNDARY_OFFSET), (int) yConverter.yToBytes(y - BOUNDARY_OFFSET));
   363 				(int) ((x - BOUNDARY_OFFSET) * getScale()),
       
   364 				(int) ((x + BOUNDARY_OFFSET) * getScale()), (int) bytes,
       
   365 				(int) yConverter.yToBytes(y + BOUNDARY_OFFSET),
       
   366 				(int) yConverter.yToBytes(y - BOUNDARY_OFFSET));
   297 		if (allocInfo != null) {
   367 		if (allocInfo != null) {
   298 			text.append(String.format("%n%s: %,d B%nTotal: %,d B",
   368 			text.append(String.format("%n%s: %,d B%nTotal: %,d B",
   299 					getMemOpString(allocInfo), 
   369 					getMemOpString(allocInfo),
   300 					Math.abs(allocInfo.getSizeInt()), 
   370 					Math.abs(allocInfo.getSizeInt()), allocInfo.getTotalMem()));
   301 					allocInfo.getTotalMem()));
       
   302 		} else {
   371 		} else {
   303 			text.append(", " + GraphUtils.formatBytes(bytes));
   372 			text.append(", " + GraphUtils.formatBytes(bytes));
   304 		}
   373 		}
   305 
       
   306 		return text.toString();
   374 		return text.toString();
   307 	}
   375 	}
   308 	
   376 
   309 	/**
   377 	/**
   310 	 * Returns a string representation of the type of the given memory operation
   378 	 * Returns a string representation of the type of the given memory operation
   311 	 * @param allocInfo the memory operation to use
   379 	 * 
   312 	 * @return 
   380 	 * @param allocInfo
   313 	 */
   381 	 *            the memory operation to use
   314 	private String getMemOpString(BaseInfo allocInfo){
   382 	 * @return
   315 		return allocInfo instanceof AllocInfo ? (((AllocInfo) allocInfo).isFreed() ? "Alloc" : "Leak"  ): "Free";
   383 	 */
       
   384 	private String getMemOpString(BaseInfo allocInfo) {
       
   385 		return allocInfo instanceof AllocInfo ? (((AllocInfo) allocInfo)
       
   386 				.isFreed() ? "Alloc" : "Leak") : "Free";
   316 	}
   387 	}
   317 
   388 
   318 	/**
   389 	/**
   319 	 * Convenience method for
   390 	 * Convenience method for
   320 	 * {@link #findClosestAlloc(int, int, int, int, int, int)} wrapping
   391 	 * {@link #findClosestAlloc(int, int, int, int, int, int)} wrapping
   329 	private BaseInfo findClosest(int x, int y) {
   400 	private BaseInfo findClosest(int x, int y) {
   330 		if (y > getClientArea().height - X_AXIS_HEIGHT) {
   401 		if (y > getClientArea().height - X_AXIS_HEIGHT) {
   331 			return null;
   402 			return null;
   332 		}
   403 		}
   333 
   404 
   334 		YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
   405 		YConverter yConverter = new YConverter(getClientArea().height, model
   335 		return findClosestAlloc((int) (x * getScale()), (int) ((x - BOUNDARY_OFFSET) * getScale()), (int) ((x + BOUNDARY_OFFSET) * getScale()),
   406 				.getHighestCumulatedMemoryAlloc());
   336 				(int) (yConverter.yToBytes(y)), (int) yConverter.yToBytes(y + BOUNDARY_OFFSET), (int) yConverter.yToBytes(y - BOUNDARY_OFFSET));
   407 		return findClosestAlloc((int) (x * getScale()),
       
   408 				(int) ((x - BOUNDARY_OFFSET) * getScale()),
       
   409 				(int) ((x + BOUNDARY_OFFSET) * getScale()), (int) (yConverter
       
   410 						.yToBytes(y)), (int) yConverter.yToBytes(y
       
   411 						+ BOUNDARY_OFFSET), (int) yConverter.yToBytes(y
       
   412 						- BOUNDARY_OFFSET));
   337 	}
   413 	}
   338 
   414 
   339 	/**
   415 	/**
   340 	 * Finds the closest matching BaseInfo in the model. BaseInfo has to fit
   416 	 * Finds the closest matching BaseInfo in the model. BaseInfo has to fit
   341 	 * into the given bounds and be a better match than other BaseInfo in the
   417 	 * into the given bounds and be a better match than other BaseInfo in the
   353 	 *            Left boundary for cumulative memory in bytes
   429 	 *            Left boundary for cumulative memory in bytes
   354 	 * @param bytesBoundRight
   430 	 * @param bytesBoundRight
   355 	 *            Right boundary for cumulative memory in bytes
   431 	 *            Right boundary for cumulative memory in bytes
   356 	 * @return
   432 	 * @return
   357 	 */
   433 	 */
   358 	private BaseInfo findClosestAlloc(int timeInMsMidPoint, int timeInMsBoundLeft, int timeInMsBoundRight, int bytesMidPoint, int bytesBoundLeft,
   434 	private BaseInfo findClosestAlloc(int timeInMsMidPoint,
   359 			int bytesBoundRight) {
   435 			int timeInMsBoundLeft, int timeInMsBoundRight, int bytesMidPoint,
       
   436 			int bytesBoundLeft, int bytesBoundRight) {
   360 		BaseInfo ret = null;
   437 		BaseInfo ret = null;
   361 		if (model.getSelectedProcess() == null){
   438 		if (model.getSelectedProcess() == null) {
   362 			return ret;
   439 			return ret;
   363 		}
   440 		}
   364 		
   441 
   365 		int marginEnd = timeInMsBoundRight;
   442 		int marginEnd = timeInMsBoundRight;
   366 		ProcessInfo process = model.getSelectedProcess();
   443 		ProcessInfo process = model.getSelectedProcess();
   367 		AbstractList<BaseInfo> allocsFrees = process.getAllocsFrees();
   444 		AbstractList<BaseInfo> allocsFrees = process.getAllocsFrees();
   368 		Long firstTime = model.getFirstProcessTime();
   445 		Long firstTime = model.getFirstProcessTime();
   369 
   446 
   370 		for (BaseInfo info : allocsFrees) {
   447 		for (BaseInfo info : allocsFrees) {
   371 			Long infoRelativeTime = info.getTime() - firstTime;
   448 			Long infoRelativeTime = info.getTime() - firstTime;
   372 			// check current alloc info is within given bounds
   449 			// check current alloc info is within given bounds
   373 			if (infoRelativeTime >= timeInMsBoundLeft && infoRelativeTime <= marginEnd && info.getTotalMem() >= bytesBoundLeft
   450 			if (infoRelativeTime >= timeInMsBoundLeft
       
   451 					&& infoRelativeTime <= marginEnd
       
   452 					&& info.getTotalMem() >= bytesBoundLeft
   374 					&& info.getTotalMem() <= bytesBoundRight) {
   453 					&& info.getTotalMem() <= bytesBoundRight) {
   375 				// check whether current alloc info is a better match than
   454 				// check whether current alloc info is a better match than
   376 				// previously found
   455 				// previously found
   377 				if (ret == null
   456 				if (ret == null
   378 						|| (Math.abs(infoRelativeTime - timeInMsMidPoint) < Math.abs((ret.getTime() - firstTime) - timeInMsMidPoint))
   457 						|| (Math.abs(infoRelativeTime - timeInMsMidPoint) < Math
   379 						|| ((ret.getTime() - firstTime) == infoRelativeTime && Math.abs(info.getTotalMem() - bytesMidPoint) < Math.abs(ret
   458 								.abs((ret.getTime() - firstTime)
   380 								.getTotalMem()
   459 										- timeInMsMidPoint))
   381 								- bytesMidPoint))) {
   460 						|| ((ret.getTime() - firstTime) == infoRelativeTime && Math
       
   461 								.abs(info.getTotalMem() - bytesMidPoint) < Math
       
   462 								.abs(ret.getTotalMem() - bytesMidPoint))) {
   382 					ret = info;
   463 					ret = info;
   383 				}
   464 				}
   384 			} else if ((info.getTime() - firstTime) > timeInMsBoundRight) {
   465 			} else if ((info.getTime() - firstTime) > timeInMsBoundRight) {
   385 				break;
   466 				break;
   386 			}
   467 			}
   397 	 *         passed object was the last in the model.
   478 	 *         passed object was the last in the model.
   398 	 */
   479 	 */
   399 	private BaseInfo findNextAlloc(BaseInfo allocInfo, boolean forward) {
   480 	private BaseInfo findNextAlloc(BaseInfo allocInfo, boolean forward) {
   400 		BaseInfo ret = null;
   481 		BaseInfo ret = null;
   401 		ProcessInfo processInfo = model.getSelectedProcess();
   482 		ProcessInfo processInfo = model.getSelectedProcess();
   402 		if (processInfo == null){
   483 		if (processInfo == null) {
   403 			return ret;
   484 			return ret;
   404 		}
   485 		}
   405 		
   486 
   406 		AbstractList<BaseInfo> allocsFrees = processInfo.getAllocsFrees(); 
   487 		AbstractList<BaseInfo> allocsFrees = processInfo.getAllocsFrees();
   407 		int i = allocsFrees.indexOf(allocInfo);
   488 		int i = allocsFrees.indexOf(allocInfo);
   408 		if (forward) {
   489 		if (forward) {
   409 			if (i < allocsFrees.size() - 1) {
   490 			if (i < allocsFrees.size() - 1) {
   410 				ret = allocsFrees.get(i + 1);
   491 				ret = allocsFrees.get(i + 1);
   411 			}
   492 			}
   432 		setZoomedSize(0);
   513 		setZoomedSize(0);
   433 	}
   514 	}
   434 
   515 
   435 	/**
   516 	/**
   436 	 * Returns the current scaling factor for the graph's width
   517 	 * Returns the current scaling factor for the graph's width
       
   518 	 * 
   437 	 * @return Scale
   519 	 * @return Scale
   438 	 */
   520 	 */
   439 	public double getScale() {
   521 	public double getScale() {
   440 		return scale;
   522 		return scale;
   441 	}
   523 	}
   442 
   524 
   443 	/**
   525 	/**
   444 	 * Sets the scaling factor for the graph's width
   526 	 * Sets the scaling factor for the graph's width
   445 	 * @param newScale 
   527 	 * 
       
   528 	 * @param newScale
   446 	 */
   529 	 */
   447 	public void setScale(double newScale) {
   530 	public void setScale(double newScale) {
   448 		this.scale = newScale;
   531 		this.scale = newScale;
   449 	}
   532 	}
   450 
   533 
   451 	/**
   534 	/**
   452 	 * Returns the highest time value of the current graph in milliseconds
   535 	 * Returns the highest time value of the current graph in milliseconds
   453 	 * @return Last time 
   536 	 * 
       
   537 	 * @return Last time
   454 	 */
   538 	 */
   455 	public long getLastTimeValueInMilliSeconds() {
   539 	public long getLastTimeValueInMilliSeconds() {
   456 		return model.getLastProcessTime() - model.getFirstProcessTime();
   540 		return model.getLastProcessTime() - model.getFirstProcessTime();
   457 	}
   541 	}
   458 
   542 
   460 	 * Returns the last time value in the model plus 1 per cent.
   544 	 * Returns the last time value in the model plus 1 per cent.
   461 	 * 
   545 	 * 
   462 	 * @return
   546 	 * @return
   463 	 */
   547 	 */
   464 	private long getMaxTimeValueInMilliSeconds() {
   548 	private long getMaxTimeValueInMilliSeconds() {
   465 		return getLastTimeValueInMilliSeconds() + (int) (getLastTimeValueInMilliSeconds() * 0.01);
   549 		return getLastTimeValueInMilliSeconds()
   466 	}
   550 				+ (int) (getLastTimeValueInMilliSeconds() * 0.01);
   467 
   551 	}
   468 	/**
   552 
   469 	 * Adds a new model to this class 
   553 	/**
   470 	 * @param newModel the IMemoryActivityModel to use
   554 	 * Adds a new model to this class
       
   555 	 * 
       
   556 	 * @param newModel
       
   557 	 *            the IMemoryActivityModel to use
   471 	 */
   558 	 */
   472 	public void setInput(IMemoryActivityModel newModel) {
   559 	public void setInput(IMemoryActivityModel newModel) {
   473 		if (this.model != null){
   560 		if (this.model != null) {
   474 			this.model.removeListener(this);
   561 			this.model.removeListener(this);
   475 		}
   562 		}
       
   563 		threshold = 0; // reset threshold
   476 		this.model = newModel;
   564 		this.model = newModel;
   477 		this.model.addListener(this);
   565 		this.model.addListener(this);
   478 	}
   566 	}
   479 
   567 
   480 	/**
   568 	/**
   481 	 * Creates the content of the FigureCanvas. Intended to be called
   569 	 * Creates the content of the FigureCanvas. Intended to be called once in
   482 	 * once in creating the ViewPart content. 
   570 	 * creating the ViewPart content.
   483 	 */
   571 	 */
   484 	public void createContent() {
   572 	public void createContent() {
   485 		mc = new MouseAndKeyController();
   573 		mc = new MouseAndKeyController();
   486 		Panel panel = new Panel() {
   574 		Panel panel = new Panel() {
   487 			@Override
   575 			@Override
   506 		final org.eclipse.swt.widgets.ScrollBar horizontalBar = getHorizontalBar();
   594 		final org.eclipse.swt.widgets.ScrollBar horizontalBar = getHorizontalBar();
   507 
   595 
   508 		horizontalBar.addSelectionListener(new SelectionListener() {
   596 		horizontalBar.addSelectionListener(new SelectionListener() {
   509 
   597 
   510 			public void widgetDefaultSelected(SelectionEvent arg0) {
   598 			public void widgetDefaultSelected(SelectionEvent arg0) {
   511 				//do nothing by design
   599 				// do nothing by design
   512 			}
   600 			}
   513 
   601 
   514 			public void widgetSelected(SelectionEvent event) {
   602 			public void widgetSelected(SelectionEvent event) {
   515 				AnalyzeToolGraph.this.redraw();
   603 				AnalyzeToolGraph.this.redraw();
   516 			}
   604 			}
   522 			public void controlResized(ControlEvent e) {
   610 			public void controlResized(ControlEvent e) {
   523 				horizontalBar.setPageIncrement(getBounds().width);
   611 				horizontalBar.setPageIncrement(getBounds().width);
   524 				redraw();
   612 				redraw();
   525 			}
   613 			}
   526 		});
   614 		});
   527 		
       
   528 	}
   615 	}
   529 
   616 
   530 	/**
   617 	/**
   531 	 * Class containing code to deal with mouse and key events
   618 	 * Class containing code to deal with mouse and key events
   532 	 *
   619 	 * 
   533 	 */
   620 	 */
   534 	private class MouseAndKeyController implements MouseMotionListener, MouseListener, KeyListener {
   621 	private class MouseAndKeyController implements MouseMotionListener,
       
   622 			MouseListener, KeyListener {
   535 
   623 
   536 		protected int mouseButton;
   624 		protected int mouseButton;
   537 		protected Point start;
   625 		protected Point start;
   538 		protected boolean beingDragged;
   626 		protected boolean beingDragged;
   539 		private BaseInfo lastShownAlloc;
   627 		private BaseInfo lastShownAlloc;
   557 			}
   645 			}
   558 		}
   646 		}
   559 
   647 
   560 		public void render(Graphics graphics) {
   648 		public void render(Graphics graphics) {
   561 			graphics.pushState();
   649 			graphics.pushState();
   562 			if (beingDragged){
   650 			if (beingDragged) {
   563 				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
   651 				graphics.setForegroundColor(Display.getDefault()
       
   652 						.getSystemColor(SWT.COLOR_BLACK));
   564 				graphics.setLineWidth(1);
   653 				graphics.setLineWidth(1);
   565 				
   654 
   566 				int dragEnd = lastMouse.x;
   655 				int dragEnd = lastMouse.x;
   567 				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag area left edge
   656 				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag
   568 				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag area right edge
   657 				// area
   569 				graphics.drawRectangle(new Rectangle(dragLeftX, 0, (dragRightX-dragLeftX), getClientArea().height));
   658 				// left
   570 			}
   659 				// edge
   571 			
   660 				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag
   572 			if (lastShownAlloc != null){
   661 				// area
   573 				
   662 				// right
   574 				//for the selected dot, try to mark related allocs and free
   663 				// edge
       
   664 				graphics.drawRectangle(new Rectangle(dragLeftX, 0,
       
   665 						(dragRightX - dragLeftX), getClientArea().height));
       
   666 			}
       
   667 
       
   668 			if (lastShownAlloc != null) {
       
   669 
       
   670 				// for the selected dot, try to mark related allocs and free
   575 				FreeInfo freeInfo = null;
   671 				FreeInfo freeInfo = null;
   576 				if (lastShownAlloc instanceof FreeInfo){
   672 				if (lastShownAlloc instanceof FreeInfo) {
   577 					freeInfo = (FreeInfo)lastShownAlloc;
   673 					freeInfo = (FreeInfo) lastShownAlloc;
   578 				} else{
   674 				} else {
   579 					freeInfo = ((AllocInfo)lastShownAlloc).getFreedBy();
   675 					freeInfo = ((AllocInfo) lastShownAlloc).getFreedBy();
   580 				}
   676 				}
   581 				if (freeInfo != null){
   677 				if (freeInfo != null) {
   582 					YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
   678 					YConverter yConverter = new YConverter(
   583 					Rectangle visibleRect = graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
   679 							getClientArea().height, model
       
   680 									.getHighestCumulatedMemoryAlloc());
       
   681 					Rectangle visibleRect = graphics
       
   682 							.getClip(new org.eclipse.draw2d.geometry.Rectangle());
   584 					Point pfree = getLocationOnGraph(yConverter, freeInfo);
   683 					Point pfree = getLocationOnGraph(yConverter, freeInfo);
   585 					if (lastShownAlloc != freeInfo && visibleRect.contains(pfree)){
   684 					if (lastShownAlloc != freeInfo
   586 						graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
   685 							&& visibleRect.contains(pfree)) {
   587 						graphics.drawLine(pfree.x+1, pfree.y+3, pfree.x+1, yConverter.bytesToY(0));
   686 						graphics.setForegroundColor(Display.getDefault()
   588 						if (optimisedDrawing){ //draw circle as well since we don't have dots
   687 								.getSystemColor(SWT.COLOR_DARK_GREEN));
   589 							graphics.drawOval(pfree.x - 2, pfree.y - 2, 5, 5);							
   688 						graphics.drawLine(pfree.x + 1, pfree.y + 3,
       
   689 								pfree.x + 1, yConverter.bytesToY(0));
       
   690 						if (optimisedDrawing) { // draw circle as well since we
       
   691 							// don't have dots
       
   692 							graphics.drawOval(pfree.x - 2, pfree.y - 2, 5, 5);
   590 						}
   693 						}
   591 					}
   694 					}
   592 					for (AllocInfo freedAlloc : freeInfo.getFreedAllocs()) {
   695 					for (AllocInfo freedAlloc : freeInfo.getFreedAllocs()) {
   593 						Point pAlloc = getLocationOnGraph(yConverter, freedAlloc);
   696 						Point pAlloc = getLocationOnGraph(yConverter,
   594 						if (lastShownAlloc != freedAlloc && visibleRect.contains(pAlloc)){
   697 								freedAlloc);
   595 							graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE));
   698 						if (lastShownAlloc != freedAlloc
   596 							graphics.drawLine(pAlloc.x+1, pAlloc.y+3, pAlloc.x+1, yConverter.bytesToY(0));
   699 								&& visibleRect.contains(pAlloc)) {
   597 							if (optimisedDrawing){ //draw circle as well since we don't have dots
   700 							graphics.setForegroundColor(Display.getDefault()
   598 								graphics.drawOval(pAlloc.x - 2, pAlloc.y - 2, 5, 5);							
   701 									.getSystemColor(SWT.COLOR_DARK_BLUE));
       
   702 							graphics.drawLine(pAlloc.x + 1, pAlloc.y + 3,
       
   703 									pAlloc.x + 1, yConverter.bytesToY(0));
       
   704 							if (optimisedDrawing) { // draw circle as well since
       
   705 								// we don't have dots
       
   706 								graphics.drawOval(pAlloc.x - 2, pAlloc.y - 2,
       
   707 										5, 5);
   599 							}
   708 							}
   600 						}
   709 						}
   601 						
   710 
   602 					}
   711 					}
   603 				}
   712 				}
   604 				//this should be the alloc that has its details displayed
   713 				// this should be the alloc that has its details displayed
   605 				//mark it in the graph
   714 				// mark it in the graph
   606 				//draw a small circle around the alloc / dealloc, and a vertical line towards the X-axis
   715 				// draw a small circle around the alloc / dealloc, and a
       
   716 				// vertical line towards the X-axis
   607 				Point p = getLocationOnGraph(lastShownAlloc);
   717 				Point p = getLocationOnGraph(lastShownAlloc);
   608 				graphics.setForegroundColor(Display.getDefault().getSystemColor(SWT.COLOR_CYAN));
   718 				graphics.setForegroundColor(Display.getDefault()
       
   719 						.getSystemColor(SWT.COLOR_CYAN));
   609 				graphics.setLineWidth(1);
   720 				graphics.setLineWidth(1);
   610 				graphics.drawOval(p.x - 2, p.y - 2, 5, 5);
   721 				graphics.drawOval(p.x - 2, p.y - 2, 5, 5);
   611 				if (optimisedDrawing || !isLeak(lastShownAlloc)){
   722 				if (optimisedDrawing || !isLeak(lastShownAlloc)) {
   612 					graphics.drawLine(p.x+1, p.y+3, p.x+1, getClientArea().height - X_AXIS_HEIGHT);					
   723 					graphics.drawLine(p.x + 1, p.y + 3, p.x + 1,
       
   724 							getClientArea().height - X_AXIS_HEIGHT);
   613 				}
   725 				}
   614 			}
   726 			}
   615 			graphics.popState();
   727 			graphics.popState();
   616 		}
   728 		}
   617 
   729 
   618 		private Point getLocationOnGraph(BaseInfo alloc) {
   730 		private Point getLocationOnGraph(BaseInfo alloc) {
   619 			YConverter yConverter = new YConverter(getClientArea().height, model.getHighestCumulatedMemoryAlloc());
   731 			YConverter yConverter = new YConverter(getClientArea().height,
       
   732 					model.getHighestCumulatedMemoryAlloc());
   620 			return getLocationOnGraph(yConverter, alloc);
   733 			return getLocationOnGraph(yConverter, alloc);
   621 		}
   734 		}
       
   735 
   622 		private Point getLocationOnGraph(YConverter yConverter, BaseInfo alloc) {
   736 		private Point getLocationOnGraph(YConverter yConverter, BaseInfo alloc) {
   623 			int x = (int) ((alloc.getTime() - model.getFirstProcessTime()) / getScale());
   737 			int x = (int) ((alloc.getTime() - model.getFirstProcessTime()) / getScale());
   624 			int y = yConverter.bytesToY(alloc.getTotalMem());
   738 			int y = yConverter.bytesToY(alloc.getTotalMem());
   625 
   739 
   626 			if (y < 0) {
   740 			if (y < 0) {
   635 		 * @see
   749 		 * @see
   636 		 * org.eclipse.draw2d.MouseMotionListener#mouseEntered(org.eclipse.draw2d
   750 		 * org.eclipse.draw2d.MouseMotionListener#mouseEntered(org.eclipse.draw2d
   637 		 * .MouseEvent)
   751 		 * .MouseEvent)
   638 		 */
   752 		 */
   639 		public void mouseEntered(MouseEvent e) {
   753 		public void mouseEntered(MouseEvent e) {
   640 			//do nothing by design
   754 			// do nothing by design
   641 		}
   755 		}
   642 
   756 
   643 		/*
   757 		/*
   644 		 * (non-Javadoc)
   758 		 * (non-Javadoc)
   645 		 * 
   759 		 * 
   646 		 * @see
   760 		 * @see
   647 		 * org.eclipse.draw2d.MouseMotionListener#mouseExited(org.eclipse.draw2d
   761 		 * org.eclipse.draw2d.MouseMotionListener#mouseExited(org.eclipse.draw2d
   648 		 * .MouseEvent)
   762 		 * .MouseEvent)
   649 		 */
   763 		 */
   650 		public void mouseExited(MouseEvent e) {
   764 		public void mouseExited(MouseEvent e) {
   651 			//do nothing by design
   765 			// do nothing by design
   652 		}
   766 		}
   653 
   767 
   654 		/*
   768 		/*
   655 		 * (non-Javadoc)
   769 		 * (non-Javadoc)
   656 		 * 
   770 		 * 
   671 		 * @see
   785 		 * @see
   672 		 * org.eclipse.draw2d.MouseMotionListener#mouseMoved(org.eclipse.draw2d
   786 		 * org.eclipse.draw2d.MouseMotionListener#mouseMoved(org.eclipse.draw2d
   673 		 * .MouseEvent)
   787 		 * .MouseEvent)
   674 		 */
   788 		 */
   675 		public void mouseMoved(MouseEvent e) {
   789 		public void mouseMoved(MouseEvent e) {
   676 			//do nothing by design
   790 			// do nothing by design
   677 		}
   791 		}
   678 
   792 
   679 		/*
   793 		/*
   680 		 * (non-Javadoc)
   794 		 * (non-Javadoc)
   681 		 * 
   795 		 * 
   714 				beingDragged = false;
   828 				beingDragged = false;
   715 				// finished drag - perform zoom in now
   829 				// finished drag - perform zoom in now
   716 
   830 
   717 				// set new scale
   831 				// set new scale
   718 				int dragEnd = me.getLocation().x;
   832 				int dragEnd = me.getLocation().x;
   719 				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag area left edge
   833 				int dragLeftX = start.x <= dragEnd ? start.x : dragEnd;// drag
   720 				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag area right edge
   834 				// area
       
   835 				// left
       
   836 				// edge
       
   837 				int dragRightX = start.x <= dragEnd ? dragEnd : start.x;// drag
       
   838 				// area
       
   839 				// right
       
   840 				// edge
   721 				int dragWindowStartTime = (int) (dragLeftX * getScale());
   841 				int dragWindowStartTime = (int) (dragLeftX * getScale());
   722 
   842 
   723 
       
   724 				int dragWidth = dragRightX - dragLeftX;// drag area width
   843 				int dragWidth = dragRightX - dragLeftX;// drag area width
   725 				int oldVisibleWidth = getViewport().getSize().width;// visible window width
   844 				int oldVisibleWidth = getViewport().getSize().width;// visible
       
   845 				// window
       
   846 				// width
   726 				double newScale = getScale() * dragWidth / oldVisibleWidth;
   847 				double newScale = getScale() * dragWidth / oldVisibleWidth;
   727 				if (newScale < 1.0) {
   848 				if (newScale < 1.0) {
   728 					// don't allow a scale smaller than 1 millisecond per pixel
   849 					// don't allow a scale smaller than 1 millisecond per pixel
   729 					// TODO: indicate a failed zoom
   850 					// TODO: indicate a failed zoom
   730 					return;
   851 					return;
   734 
   855 
   735 				// set new window location
   856 				// set new window location
   736 				setScale(newScale);
   857 				setScale(newScale);
   737 				setZoomedSize(dragLeftXScaled);
   858 				setZoomedSize(dragLeftXScaled);
   738 
   859 
   739 				//make sure the drag window disappears
   860 				// make sure the drag window disappears
   740 				AnalyzeToolGraph.this.redraw();				
   861 				AnalyzeToolGraph.this.redraw();
   741 			} else if (me.button == 3) {
   862 			} else if (me.button == 3) {
   742 				// mouse right click - zoom out
   863 				// mouse right click - zoom out
   743 
   864 
   744 				double maxScale = getMaxTimeValueInMilliSeconds() / getClientArea().width;
   865 				double maxScale = getMaxTimeValueInMilliSeconds()
       
   866 						/ getClientArea().width;
   745 				if (getScale() < maxScale) {
   867 				if (getScale() < maxScale) {
   746 					double newScale = GraphUtils.nextScale(getScale(), true);
   868 					double newScale = GraphUtils.nextScale(getScale(), true);
   747 					if (getScale() != newScale) {
   869 					if (getScale() != newScale) {
   748 						if (newScale > maxScale) {
   870 						if (newScale > maxScale) {
   749 							newScale = maxScale;
   871 							newScale = maxScale;
   750 						}
   872 						}
   751 
   873 
   752 						// get left window edge is ms to be set to after zooming
   874 						// get left window edge is ms to be set to after zooming
   753 						double leftEdgeInMs = getViewport().getViewLocation().x * getScale();
   875 						double leftEdgeInMs = getViewport().getViewLocation().x
       
   876 								* getScale();
   754 						setScale(newScale);
   877 						setScale(newScale);
   755 						setZoomedSize((int) (leftEdgeInMs / newScale));
   878 						setZoomedSize((int) (leftEdgeInMs / newScale));
   756 					}
   879 					}
   757 				}
   880 				}
   758 			} else if (me.button == 1) {
   881 			} else if (me.button == 1) {
   759 				BaseInfo info = findClosest(me.x, me.y);
   882 				BaseInfo info = findClosest(me.x, me.y);
   760 				if (info != null) {
   883 				if (info != null) {
   761 					iDotsSelecProv.setSelection(new StructuredSelection(new MemOpDescriptor(model.getFirstProcessTime(), info, iCurrentProject, iSymReader, cppFileNames, model.getCallstackManager())));
   884 					iDotsSelecProv
       
   885 							.setSelection(new StructuredSelection(
       
   886 									new MemOpDescriptor(model
       
   887 											.getFirstProcessTime(), info,
       
   888 											iCurrentProject, iSymReader,
       
   889 											cppFileNames, model
       
   890 													.getCallstackManager())));
   762 					lastShownAlloc = info;
   891 					lastShownAlloc = info;
   763 				}
   892 				}
   764 				}
   893 			}
   765 
   894 		}
   766 			}
       
   767 
       
   768 
   895 
   769 		public void keyPressed(KeyEvent ke) {
   896 		public void keyPressed(KeyEvent ke) {
   770 			//do nothing by design
   897 			// do nothing by design
   771 		}
   898 		}
   772 
   899 
   773 		public void keyReleased(KeyEvent ke) {
   900 		public void keyReleased(KeyEvent ke) {
   774 			if (ke.keycode == SWT.ARROW_RIGHT || ke.keycode == SWT.ARROW_LEFT) {
   901 			if (ke.keycode == SWT.ARROW_RIGHT || ke.keycode == SWT.ARROW_LEFT) {
   775 				if (lastShownAlloc != null) {
   902 				if (lastShownAlloc != null) {
   776 					BaseInfo info = findNextAlloc(lastShownAlloc, ke.keycode == SWT.ARROW_RIGHT);
   903 					BaseInfo info = findNextAlloc(lastShownAlloc,
       
   904 							ke.keycode == SWT.ARROW_RIGHT);
   777 					if (info != null) {
   905 					if (info != null) {
   778 						iDotsSelecProv.setSelection(new StructuredSelection(new MemOpDescriptor(model.getFirstProcessTime(), info, iCurrentProject, iSymReader, cppFileNames, model.getCallstackManager())));
   906 						iDotsSelecProv.setSelection(new StructuredSelection(
       
   907 								new MemOpDescriptor(
       
   908 										model.getFirstProcessTime(), info,
       
   909 										iCurrentProject, iSymReader,
       
   910 										cppFileNames, model
       
   911 												.getCallstackManager())));
   779 						lastShownAlloc = info;
   912 						lastShownAlloc = info;
   780 						
   913 
   781 						//if info is hidden from the visible graph area, scroll to reveal
   914 						// if info is hidden from the visible graph area, scroll
       
   915 						// to reveal
   782 						int x = getLocationOnGraph(info).x;
   916 						int x = getLocationOnGraph(info).x;
   783 						int leftEdge = getViewport().getHorizontalRangeModel().getValue();
   917 						int leftEdge = getViewport().getHorizontalRangeModel()
   784 						int width = getViewport().getHorizontalRangeModel().getExtent();
   918 								.getValue();
   785 						if (x < leftEdge){
   919 						int width = getViewport().getHorizontalRangeModel()
   786 							if (x > 10){
   920 								.getExtent();
   787 								x -=10;
   921 						if (x < leftEdge) {
       
   922 							if (x > 10) {
       
   923 								x -= 10;
   788 							}
   924 							}
   789 							getViewport().getHorizontalRangeModel().setValue(x);
   925 							getViewport().getHorizontalRangeModel().setValue(x);
   790 						} else if (x > (leftEdge + width)){
   926 						} else if (x > (leftEdge + width)) {
   791 							x -= (width - 10);
   927 							x -= (width - 10);
   792 							getViewport().getHorizontalRangeModel().setValue(x);							
   928 							getViewport().getHorizontalRangeModel().setValue(x);
   793 						}
   929 						}
   794 						AnalyzeToolGraph.this.redraw();
   930 						AnalyzeToolGraph.this.redraw();
   795 					}
   931 					}
   796 				}
   932 				}
   797 			}
   933 			}
   798 
       
   799 		}
   934 		}
   800 
   935 
   801 		/**
   936 		/**
   802 		 * resets any state
   937 		 * Resets any state.
   803 		 */
   938 		 */
   804 		public void clearState() {
   939 		public void clearState() {
   805 			mouseButton = 0;
   940 			mouseButton = 0;
   806 			start = null;
   941 			start = null;
   807 			beingDragged = false;
   942 			beingDragged = false;
   808 			lastShownAlloc = null;
   943 			lastShownAlloc = null;
   809 			lastMouse = null;
   944 			lastMouse = null;
   810 			if (iDotsSelecProv != null){
   945 			if (iDotsSelecProv != null) {
   811 				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);				
   946 				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);
   812 			}
   947 			}
   813 		}
   948 		}
   814 		
   949 	}
   815 	}
   950 
   816 	
   951 	/**
   817 	/**
   952 	 * Returns an SWT system color code depending on the type of the paramter
   818 	 * Returns an SWT system color code depending on the type of the paramter passed.
   953 	 * passed. </br> SWT.COLOR_DARK_BLUE for a alloc (that is not a leak) </br>
   819 	 * </br> SWT.COLOR_DARK_BLUE for a alloc (that is not a leak)
   954 	 * SWT.COLOR_RED for a leak </br> SWT.COLOR_DARK_GREEN for a free
   820 	 * </br> SWT.COLOR_RED for a leak
   955 	 * 
   821 	 * </br> SWT.COLOR_DARK_GREEN for a free
   956 	 * @param info
   822 	 * @param info the allocation to evaluate
   957 	 *            the allocation to evaluate
   823 	 * @return the appropriate SWT system color code
   958 	 * @return the appropriate SWT system color code
   824 	 */
   959 	 */
   825 	private int getColorForAllocType(BaseInfo info){
   960 	private int getColorForAllocType(BaseInfo info) {
   826 		int color;
   961 		int color;
   827 		if (info instanceof AllocInfo) {
   962 		if (info instanceof AllocInfo) {
   828 			if (((AllocInfo) info).isFreed()) {
   963 			if (((AllocInfo) info).isFreed()) {
   829 				color = SWT.COLOR_DARK_BLUE;
   964 				color = SWT.COLOR_DARK_BLUE;
   830 			} else {
   965 			} else {
   833 		} else {
   968 		} else {
   834 			color = SWT.COLOR_DARK_GREEN;
   969 			color = SWT.COLOR_DARK_GREEN;
   835 		}
   970 		}
   836 		return color;
   971 		return color;
   837 	}
   972 	}
   838 	
   973 
   839 	/**
   974 	/**
   840 	 * Returns true if the passed info is a leak, false otherwise.
   975 	 * Returns true if the passed info is a leak, false otherwise. AllocInfo
   841 	 * AllocInfo that haven't been freed are considered leaks.
   976 	 * that haven't been freed are considered leaks.
   842 	 * 
   977 	 * 
   843 	 * @param info the BaseInfo to test
   978 	 * @param info
       
   979 	 *            the BaseInfo to test
   844 	 * @return true if leak, false otherwise
   980 	 * @return true if leak, false otherwise
   845 	 */
   981 	 */
   846 	private static boolean isLeak(BaseInfo info){
   982 	private static boolean isLeak(BaseInfo info) {
   847 		return info instanceof AllocInfo && !(((AllocInfo) info).isFreed()) ? true : false;
   983 		return info instanceof AllocInfo && !(((AllocInfo) info).isFreed()) ? true
       
   984 				: false;
   848 	}
   985 	}
   849 
   986 
   850 	/**
   987 	/**
   851 	 * 
   988 	 * 
   852 	 * Converts bytes from/to Y values
   989 	 * Converts bytes from/to Y values
   868 		public double yToBytes(int y) {
  1005 		public double yToBytes(int y) {
   869 			return (visY - y) * multiplier;
  1006 			return (visY - y) * multiplier;
   870 		}
  1007 		}
   871 	}
  1008 	}
   872 
  1009 
   873 	/* (non-Javadoc)
  1010 	/*
   874 	 * @see com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener#onProcessesAdded()
  1011 	 * (non-Javadoc)
       
  1012 	 * 
       
  1013 	 * @see
       
  1014 	 * com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener
       
  1015 	 * #onProcessesAdded()
   875 	 */
  1016 	 */
   876 	public void onProcessesAdded() {
  1017 	public void onProcessesAdded() {
   877 		//the model is now ready to use - call a redraw on the graph
  1018 		// the model is now ready to use - call a redraw on the graph
   878 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
  1019 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
   879 			public void run() {
  1020 			public void run() {
   880 				mc.clearState();
  1021 				mc.clearState();
   881 				zoomGraph();
  1022 				zoomGraph();
   882 				redraw();
  1023 				redraw();
   883 			}
  1024 			}
   884 		});
  1025 		});
   885 	}
  1026 	}
   886 
  1027 
   887 	/* (non-Javadoc)
  1028 	/*
   888 	 * @see com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener#onProcessSelected(com.nokia.s60tools.analyzetool.engine.statistic.ProcessInfo)
  1029 	 * (non-Javadoc)
       
  1030 	 * 
       
  1031 	 * @see
       
  1032 	 * com.nokia.s60tools.analyzetool.engine.IMemoryActivityModelChangeListener
       
  1033 	 * #onProcessSelected
       
  1034 	 * (com.nokia.s60tools.analyzetool.engine.statistic.ProcessInfo)
   889 	 */
  1035 	 */
   890 	public void onProcessSelected(ProcessInfo p) {
  1036 	public void onProcessSelected(ProcessInfo p) {
   891 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
  1037 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
   892 			public void run() {
  1038 			public void run() {
   893 				mc.clearState();
  1039 				mc.clearState();
   894 				optimisedDrawing = model.getSelectedProcess().getAllocsFrees().size() > 25000 ? true : false;
  1040 				optimisedDrawing = model.getSelectedProcess().getAllocsFrees()
       
  1041 						.size() > ChartContainer.OPT_DRAWING_LIMIT ? true
       
  1042 						: false;
   895 				userInformed = false;
  1043 				userInformed = false;
   896 				zoomGraph();
  1044 				zoomGraph();
   897 				redraw();
  1045 				redraw();
   898 			}
  1046 			}
   899 		});
  1047 		});
   900 	}
  1048 	}
   901 	
  1049 
   902 	@Override
  1050 	@Override
   903 	public void dispose() {
  1051 	public void dispose() {
   904 		//there is no dispose() entry point in this class; we may have to call this via MainView.dispose()
  1052 		// there is no dispose() entry point in this class; we may have to call
       
  1053 		// this via MainView.dispose()
   905 		site.setSelectionProvider(null);
  1054 		site.setSelectionProvider(null);
   906 		iDotsSelecProv = null;
  1055 		iDotsSelecProv = null;
   907 		if (timeImage != null){
  1056 		if (timeImage != null) {
   908 			timeImage.dispose();
  1057 			timeImage.dispose();
   909 		}
  1058 		}
   910 		IPartService partService = PlatformUI.getWorkbench()
  1059 		IPartService partService = PlatformUI.getWorkbench()
   911 		.getActiveWorkbenchWindow().getPartService();
  1060 				.getActiveWorkbenchWindow().getPartService();
   912 		partService.removePartListener(iGraphPartServiceListener);
  1061 		partService.removePartListener(iGraphPartServiceListener);
   913 		iGraphPartServiceListener = null;
  1062 		iGraphPartServiceListener = null;
   914 		if (iSymReader != null) {
  1063 		if (iSymReader != null) {
   915 			iSymReader.dispose();
  1064 			iSymReader.dispose();
   916 			iSymReader = null;
  1065 			iSymReader = null;
   917 		}
  1066 		}
   918 	}
  1067 	}
   919 	
  1068 
   920 	private void setZoomedSize(final int newXLocation) {
  1069 	private void setZoomedSize(final int newXLocation) {
   921 		int prefSize = (int) (getMaxTimeValueInMilliSeconds() / getScale());
  1070 		int prefSize = (int) (getMaxTimeValueInMilliSeconds() / getScale());
   922 
  1071 
   923 		// new width has to propagate to viewport first before we can set
  1072 		// new width has to propagate to viewport first before we can set
   924 		// the new viewport selection
  1073 		// the new viewport selection
   925 		// set newXLocation in listener
  1074 		// set newXLocation in listener
   926 		Panel panel = (Panel) (getContents());
  1075 		Panel panel = (Panel) (getContents());
   927 		panel.setPreferredSize(prefSize, 0);
  1076 		panel.setPreferredSize(prefSize, 0);
   928 
  1077 
   929 		if (prefSize > getClientArea().width) {
  1078 		if (prefSize > getClientArea().width) {
   930 			getViewport().getHorizontalRangeModel().addPropertyChangeListener(new PropertyChangeListener() {
  1079 			getViewport().getHorizontalRangeModel().addPropertyChangeListener(
   931 				public void propertyChange(PropertyChangeEvent e) {
  1080 					new PropertyChangeListener() {
   932 					if (e.getPropertyName().equals(PROP_MAXIMUM)) {
  1081 						public void propertyChange(PropertyChangeEvent e) {
   933 						getViewport().getHorizontalRangeModel().removePropertyChangeListener(this);
  1082 							if (e.getPropertyName().equals(PROP_MAXIMUM)) {
   934 						getViewport().getHorizontalRangeModel().setValue(newXLocation);
  1083 								getViewport().getHorizontalRangeModel()
   935 					}
  1084 										.removePropertyChangeListener(this);
   936 				}
  1085 								getViewport().getHorizontalRangeModel()
   937 
  1086 										.setValue(newXLocation);
   938 			});
  1087 							}
       
  1088 						}
       
  1089 
       
  1090 					});
   939 			panel.setSize(prefSize, 0);
  1091 			panel.setSize(prefSize, 0);
   940 
  1092 
   941 		} else {
  1093 		} else {
   942 			// this only works if the canvas is large enough, otherwise use property listener
  1094 			// this only works if the canvas is large enough, otherwise use
   943 			getViewport().getHorizontalRangeModel().setValue(newXLocation); 
  1095 			// property listener
   944 		}
  1096 			getViewport().getHorizontalRangeModel().setValue(newXLocation);
   945 	}
  1097 		}
   946 	
  1098 	}
   947 	/**
  1099 
   948 	 * DotSelectionProvider :  when a user selects a Dot on the graph, this class delivers the associated
  1100 	/**
   949 	 * descriptor MemOpDescriptor to the views interested in it mainly the Properties View. 
  1101 	 * DotSelectionProvider : when a user selects a Dot on the graph, this class
   950 	 *
  1102 	 * delivers the associated descriptor MemOpDescriptor to the views
   951 	 */
  1103 	 * interested in it mainly the Properties View.
   952 	private class DotSelectionProvider implements ISelectionProvider, SelectionListener {
  1104 	 * 
       
  1105 	 */
       
  1106 	private class DotSelectionProvider implements ISelectionProvider,
       
  1107 			SelectionListener {
   953 		private ListenerList iSelectionChangedListeners = new ListenerList();
  1108 		private ListenerList iSelectionChangedListeners = new ListenerList();
   954 
  1109 
   955 		/* (non-Javadoc)
  1110 		/*
   956 		 * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
  1111 		 * (non-Javadoc)
   957 		 */
  1112 		 * 
   958 		public void addSelectionChangedListener(ISelectionChangedListener listener) {
  1113 		 * @see
   959 			//TODO is there a way to allow only properties view to register.
  1114 		 * org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener
       
  1115 		 * (org.eclipse.jface.viewers.ISelectionChangedListener)
       
  1116 		 */
       
  1117 		public void addSelectionChangedListener(
       
  1118 				ISelectionChangedListener listener) {
       
  1119 			// TODO is there a way to allow only properties view to register.
   960 			iSelectionChangedListeners.add(listener);
  1120 			iSelectionChangedListeners.add(listener);
   961 
  1121 		}
   962 		}
  1122 
   963 
  1123 		/*
   964 		/* (non-Javadoc)
  1124 		 * (non-Javadoc)
       
  1125 		 * 
   965 		 * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
  1126 		 * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
   966 		 */
  1127 		 */
   967 		public ISelection getSelection() {
  1128 		public ISelection getSelection() {
   968 			return iCurrentSelectedDot;
  1129 			return iCurrentSelectedDot;
   969 		}
  1130 		}
   970 
  1131 
   971 		/* (non-Javadoc)
  1132 		/*
   972 		 * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
  1133 		 * (non-Javadoc)
   973 		 */
  1134 		 * 
   974 		public void removeSelectionChangedListener(ISelectionChangedListener listener) {
  1135 		 * @seeorg.eclipse.jface.viewers.ISelectionProvider#
       
  1136 		 * removeSelectionChangedListener
       
  1137 		 * (org.eclipse.jface.viewers.ISelectionChangedListener)
       
  1138 		 */
       
  1139 		public void removeSelectionChangedListener(
       
  1140 				ISelectionChangedListener listener) {
   975 			iSelectionChangedListeners.remove(listener);
  1141 			iSelectionChangedListeners.remove(listener);
   976 
  1142 		}
   977 		}
  1143 
   978 
  1144 		/*
   979 		/* (non-Javadoc)
  1145 		 * (non-Javadoc)
   980 		 * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
  1146 		 * 
       
  1147 		 * @see
       
  1148 		 * org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse
       
  1149 		 * .jface.viewers.ISelection)
   981 		 */
  1150 		 */
   982 		public void setSelection(ISelection selection) {
  1151 		public void setSelection(ISelection selection) {
   983 			iCurrentSelectedDot = selection;
  1152 			iCurrentSelectedDot = selection;
   984 			//notify the listeners mainly the property view
  1153 			// notify the listeners mainly the property view
   985 			for (final Object listenerObj : iSelectionChangedListeners
  1154 			for (final Object listenerObj : iSelectionChangedListeners
   986 					.getListeners())
  1155 					.getListeners()) {
   987 			{
       
   988 				((ISelectionChangedListener) listenerObj)
  1156 				((ISelectionChangedListener) listenerObj)
   989 					.selectionChanged(new SelectionChangedEvent(this, getSelection()));
  1157 						.selectionChanged(new SelectionChangedEvent(this,
   990 			}
  1158 								getSelection()));
   991 		}
  1159 			}
   992 
  1160 		}
   993 		/* (non-Javadoc)
  1161 
   994 		 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
  1162 		/*
       
  1163 		 * (non-Javadoc)
       
  1164 		 * 
       
  1165 		 * @see
       
  1166 		 * org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org
       
  1167 		 * .eclipse.swt.events.SelectionEvent)
   995 		 */
  1168 		 */
   996 		public void widgetDefaultSelected(SelectionEvent event) {
  1169 		public void widgetDefaultSelected(SelectionEvent event) {
   997 			widgetSelected(event);
  1170 			widgetSelected(event);
   998 			
  1171 		}
   999 		}
  1172 
  1000 
  1173 		/*
  1001 		/* (non-Javadoc)
  1174 		 * (non-Javadoc)
  1002 		 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
  1175 		 * 
       
  1176 		 * @see
       
  1177 		 * org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse
       
  1178 		 * .swt.events.SelectionEvent)
  1003 		 */
  1179 		 */
  1004 		public void widgetSelected(SelectionEvent arg0) {
  1180 		public void widgetSelected(SelectionEvent arg0) {
  1005 			for (final Object listenerObj : iSelectionChangedListeners
  1181 			for (final Object listenerObj : iSelectionChangedListeners
  1006 					.getListeners())
  1182 					.getListeners()) {
  1007 			{
       
  1008 				((ISelectionChangedListener) listenerObj)
  1183 				((ISelectionChangedListener) listenerObj)
  1009 					.selectionChanged(new SelectionChangedEvent(this, getSelection()));
  1184 						.selectionChanged(new SelectionChangedEvent(this,
  1010 			}
  1185 								getSelection()));
  1011 			
  1186 			}
  1012 		}
  1187 		}
  1013 
  1188 	}
  1014 	}
  1189 
  1015 	
  1190 	/**
  1016 	
  1191 	 * GraphPartServiceListener is for convenience only. It serves to find an
  1017 	/**
  1192 	 * appropriate time to add DotSelectionProvider to the part site. It also
  1018 	 * GraphPartServiceListener is for convenience only. It serves to find an appropriate time to
  1193 	 * covers that case where the properties View is already open before opening
  1019 	 * add DotSelectionProvider to the part site. It also covers that case where the properties View is already
  1194 	 * AnalyzeTool View.
  1020 	 * open before opening AnalyzeTool View.
  1195 	 * 
  1021 	 *
  1196 	 */
  1022 	 */
  1197 	private class GraphPartServiceListener implements IPartListener,
  1023 	private class GraphPartServiceListener implements IPartListener, IWindowListener {
  1198 			IWindowListener {
  1024 
  1199 
  1025 		public void partActivated(IWorkbenchPart part) {
  1200 		public void partActivated(IWorkbenchPart part) {
  1026 			if (part instanceof MainView || part instanceof PropertySheet) {
  1201 			if (part instanceof MainView || part instanceof PropertySheet) {
  1027 				
  1202 
  1028 				site = part.getSite();
  1203 				site = part.getSite();
  1029 				//set property sheet selection provider.
  1204 				// set property sheet selection provider.
  1030 				site.setSelectionProvider(iDotsSelecProv);
  1205 				site.setSelectionProvider(iDotsSelecProv);
  1031 				if (part instanceof MainView && iSymReader != null) {
  1206 				if (part instanceof MainView && iSymReader != null) {
  1032 					iSymReader.reOpenCachedSymbolFiles();
  1207 					iSymReader.reOpenCachedSymbolFiles();
  1033 				}
  1208 				}
  1034 			}
  1209 			}
  1035 		}
  1210 		}
  1036 
  1211 
  1037 		public void partBroughtToTop(IWorkbenchPart part) {
  1212 		public void partBroughtToTop(IWorkbenchPart part) {
  1038 			//do nothing
  1213 			// do nothing
  1039 		}
  1214 		}
  1040 
  1215 
  1041 		public void partClosed(IWorkbenchPart part) {
  1216 		public void partClosed(IWorkbenchPart part) {
  1042 			//TODO this is not working. why?
  1217 			// TODO this is not working. why?
  1043 			if (part instanceof MainView || part instanceof PropertySheet) {			
  1218 			if (part instanceof MainView || part instanceof PropertySheet) {
  1044 				site = part.getSite();
  1219 				site = part.getSite();
  1045 				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);	
  1220 				iDotsSelecProv.setSelection(StructuredSelection.EMPTY);
  1046 				//set property sheet selection provider.
  1221 				// set property sheet selection provider.
  1047 				site.setSelectionProvider(null);
  1222 				site.setSelectionProvider(null);
  1048 			}
  1223 			}
  1049 		}
  1224 		}
  1050 
  1225 
  1051 		public void partDeactivated(IWorkbenchPart part) {
  1226 		public void partDeactivated(IWorkbenchPart part) {
  1052 			//the user might want to rebuild the project, so close the sumbol files
  1227 			// the user might want to rebuild the project, so close the sumbol
       
  1228 			// files
  1053 			if (part instanceof MainView && iSymReader != null) {
  1229 			if (part instanceof MainView && iSymReader != null) {
  1054 				iSymReader.closeCachedSymbolFiles();
  1230 				iSymReader.closeCachedSymbolFiles();
  1055 			}
  1231 			}
  1056 		}
  1232 		}
  1057 
  1233 
  1058 		public void partOpened(IWorkbenchPart part) {
  1234 		public void partOpened(IWorkbenchPart part) {
  1059 			if (part instanceof MainView) {
  1235 			if (part instanceof MainView) {
  1060 				try {
  1236 				try {
  1061 					part.getSite().getPage().showView("org.eclipse.ui.views.PropertySheet");//$NON-NLS-1$
  1237 					part.getSite().getPage().showView(
       
  1238 							"org.eclipse.ui.views.PropertySheet");//$NON-NLS-1$
  1062 				} catch (PartInitException e) {
  1239 				} catch (PartInitException e) {
  1063 					//just log the exception
  1240 					// just log the exception
  1064 					Activator.getDefault().log(IStatus.ERROR, e.getMessage(), e);
  1241 					Activator.getDefault()
       
  1242 							.log(IStatus.ERROR, e.getMessage(), e);
  1065 				}
  1243 				}
  1066 			}
  1244 			}
  1067 		}
  1245 		}
  1068 
  1246 
  1069 		public void windowActivated(IWorkbenchWindow window) {
  1247 		public void windowActivated(IWorkbenchWindow window) {
  1070 			if (iSymReader != null && window.getActivePage().getActivePart() instanceof MainView) {
  1248 			if (iSymReader != null
       
  1249 					&& window.getActivePage().getActivePart() instanceof MainView) {
  1071 				iSymReader.reOpenCachedSymbolFiles();
  1250 				iSymReader.reOpenCachedSymbolFiles();
  1072 			}			
  1251 			}
  1073 		}
  1252 		}
  1074 
  1253 
  1075 		public void windowClosed(IWorkbenchWindow window) {
  1254 		public void windowClosed(IWorkbenchWindow window) {
  1076 			//do nothing
  1255 			// do nothing
  1077 			
  1256 
  1078 		}
  1257 		}
  1079 
  1258 
  1080 		public void windowDeactivated(IWorkbenchWindow window) {
  1259 		public void windowDeactivated(IWorkbenchWindow window) {
  1081 			// the user might do a re-build from the command line
  1260 			// the user might do a re-build from the command line
  1082 			if (iSymReader != null) {
  1261 			if (iSymReader != null) {
  1083 				iSymReader.closeCachedSymbolFiles();
  1262 				iSymReader.closeCachedSymbolFiles();
  1084 			}		
  1263 			}
  1085 		}
  1264 		}
  1086 
  1265 
  1087 		public void windowOpened(IWorkbenchWindow window) {
  1266 		public void windowOpened(IWorkbenchWindow window) {
  1088 			//do nothing	
  1267 			// do nothing
  1089 		}
  1268 		}
  1090 	}
  1269 	}
  1091 	
  1270 
  1092 	/**
  1271 	/**
  1093 	 * set a new project
  1272 	 * set a new project
       
  1273 	 * 
  1094 	 * @param aProject
  1274 	 * @param aProject
  1095 	 */
  1275 	 */
  1096 	public void setProject(IProject aProject) {
  1276 	public void setProject(IProject aProject) {
  1097 		if(iCurrentProject != aProject) {
  1277 		if (iCurrentProject != aProject) {
  1098 			iCurrentProject = aProject;
  1278 			iCurrentProject = aProject;
  1099 			iSymReader = new SymReader(aProject);
  1279 			iSymReader = new SymReader(aProject);
  1100 			iSymReader.loadProjectTargetsInfo();
  1280 			iSymReader.loadProjectTargetsInfo();
  1101 			ResourceVisitor visitor = new ResourceVisitor(this);
  1281 			ResourceVisitor visitor = new ResourceVisitor(this);
  1102 			try {
  1282 			try {
  1103 				iCurrentProject.accept(visitor);
  1283 				iCurrentProject.accept(visitor);
  1104 			} catch (CoreException ce) {
  1284 			} catch (CoreException ce) {
  1105 				//just log the exception
  1285 				// just log the exception
  1106 				Activator.getDefault().log(IStatus.ERROR, ce.getMessage(), ce);
  1286 				Activator.getDefault().log(IStatus.ERROR, ce.getMessage(), ce);
  1107 			}
  1287 			}
  1108 		}
  1288 		}
  1109 	}
  1289 	}
  1110 	
  1290 
  1111 	/**
  1291 	/**
  1112 	 * Load all cpp files from the project
  1292 	 * Load all cpp files from the project. This is callback to
  1113 	 * This is callback to ResourcceVisitor.
  1293 	 * ResourcceVisitor.
  1114 	 *
  1294 	 * 
  1115 	 * @param resource
  1295 	 * @param resource
  1116 	 */
  1296 	 */
  1117 	public final void loadFileInfo(IResource resource) {
  1297 	public final void loadFileInfo(IResource resource) {
  1118 		// get all the cpp file info which are belongs to current project
  1298 		// get all the cpp file info which are belongs to current project
  1119 		String cppFileName = Util.getCPPFileNameAndPath(resource);
  1299 		String cppFileName = Util.getCPPFileNameAndPath(resource);
  1122 		if (cppFileName != null && !cppFileNames.contains(cppFileName)) {
  1302 		if (cppFileName != null && !cppFileNames.contains(cppFileName)) {
  1123 			this.cppFileNames.add(cppFileName);
  1303 			this.cppFileNames.add(cppFileName);
  1124 		}
  1304 		}
  1125 	}
  1305 	}
  1126 
  1306 
       
  1307 	/**
       
  1308 	 * Sets the threshold. Only memory operations of a size greater or equals /
       
  1309 	 * lower or equals the threshold will be drawn on the graph.
       
  1310 	 * 
       
  1311 	 * @param value
       
  1312 	 *            the threshold value in bytes
       
  1313 	 * @param above
       
  1314 	 *            true if filtering "above", false if "below" the threshold
       
  1315 	 */
       
  1316 	public void setThreshold(long value, boolean above) {
       
  1317 		if (value < 0) {
       
  1318 			throw new IllegalArgumentException(
       
  1319 					"The threshold cannot be less than 0");
       
  1320 		}
       
  1321 		threshold = value;
       
  1322 		aboveThreshold = above;
       
  1323 	}
  1127 }
  1324 }