diff -r bb339882c6e9 -r 0367d2db2c06 sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/internal/ui/graph/AnalyzeToolGraph.java --- 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 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 dotLocations = new ArrayList(); List colorDotLocations = new ArrayList(); 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 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 allocsFrees = processInfo.getAllocsFrees(); + + AbstractList 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. - *
SWT.COLOR_DARK_BLUE for a alloc (that is not a leak) - *
SWT.COLOR_RED for a leak - *
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.
SWT.COLOR_DARK_BLUE for a alloc (that is not a leak)
+ * SWT.COLOR_RED for a leak
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; + } }