sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTraceGraph.java
changeset 2 b9ab3b238396
child 5 844b047e260d
equal deleted inserted replaced
1:1050670c6980 2:b9ab3b238396
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of the License "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description: 
       
    15  *
       
    16  */
       
    17 
       
    18 package com.nokia.carbide.cpp.pi.memory;
       
    19 
       
    20 import java.awt.Dimension;
       
    21 import java.awt.event.FocusEvent;
       
    22 import java.awt.event.FocusListener;
       
    23 import java.text.DecimalFormat;
       
    24 import java.util.ArrayList;
       
    25 import java.util.Enumeration;
       
    26 import java.util.Hashtable;
       
    27 import java.util.Iterator;
       
    28 import java.util.TreeMap;
       
    29 import java.util.Map.Entry;
       
    30 
       
    31 import org.eclipse.draw2d.ColorConstants;
       
    32 import org.eclipse.draw2d.FigureCanvas;
       
    33 import org.eclipse.draw2d.Graphics;
       
    34 import org.eclipse.draw2d.MouseEvent;
       
    35 import org.eclipse.draw2d.MouseMotionListener;
       
    36 import org.eclipse.draw2d.Panel;
       
    37 import org.eclipse.jface.viewers.CheckboxTableViewer;
       
    38 import org.eclipse.swt.SWT;
       
    39 import org.eclipse.swt.events.SelectionAdapter;
       
    40 import org.eclipse.swt.events.SelectionEvent;
       
    41 import org.eclipse.swt.graphics.Color;
       
    42 import org.eclipse.swt.graphics.GC;
       
    43 import org.eclipse.swt.graphics.Point;
       
    44 import org.eclipse.swt.graphics.RGB;
       
    45 import org.eclipse.swt.graphics.Rectangle;
       
    46 import org.eclipse.swt.layout.GridData;
       
    47 import org.eclipse.swt.layout.GridLayout;
       
    48 import org.eclipse.swt.widgets.Composite;
       
    49 import org.eclipse.swt.widgets.Display;
       
    50 import org.eclipse.swt.widgets.Event;
       
    51 import org.eclipse.swt.widgets.Label;
       
    52 import org.eclipse.swt.widgets.Menu;
       
    53 import org.eclipse.swt.widgets.MenuItem;
       
    54 
       
    55 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
       
    56 import com.nokia.carbide.cpp.internal.pi.memory.actions.MemoryStatisticsDialog;
       
    57 import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
       
    58 import com.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu;
       
    59 import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
       
    60 import com.nokia.carbide.cpp.internal.pi.visual.GraphComposite;
       
    61 import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
       
    62 import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
       
    63 import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
       
    64 import com.nokia.carbide.cpp.pi.util.ColorPalette;
       
    65 
       
    66 public class MemTraceGraph extends GenericTraceGraph implements FocusListener,
       
    67 		PIEventListener, MouseMotionListener, IContextMenu {
       
    68 	private enum UsageType {
       
    69 		CHUNKS, HEAPSTACK, CHUNKS_HEAPSTACK
       
    70 	};
       
    71 
       
    72 	private boolean dynamicMemoryVisualisation = false;
       
    73 
       
    74 	private MemThreadTable memThreadTable;
       
    75 	private CheckboxTableViewer memoryTableViewer;
       
    76 
       
    77 	Hashtable<Integer, Integer> threadList;
       
    78 
       
    79 	// 3 tabs can share the same trace, but they need different graphs
       
    80 	private MemTrace memTrace;
       
    81 
       
    82 	private FigureCanvas leftFigureCanvas;
       
    83 
       
    84 	// whether any table items are enabled
       
    85 	private boolean haveEnabled = false;
       
    86 
       
    87 	private boolean readyToDraw = false;
       
    88 	private int width = 600;
       
    89 	private int height = 400;
       
    90 
       
    91 	private final int defaultSamplingTime = 3000;
       
    92 	private int samplingTime;
       
    93 	private UsageType paintMode;
       
    94 	private int[] chunkListY;
       
    95 	private int[] stackListY;
       
    96 	private int[] chunkStackListY;
       
    97 	private int[] polyListX;
       
    98 
       
    99 	int[] stackAndHeapPoints;
       
   100 	int[] chunkPoints;
       
   101 
       
   102 	private TreeMap<Long, Integer> eventChunkListY;
       
   103 	private TreeMap<Long, Integer> eventStackListY;
       
   104 	private TreeMap<Long, Integer> eventChunkStackListY;
       
   105 
       
   106 	private int minStack = Integer.MAX_VALUE;
       
   107 	private int maxStack = 0;
       
   108 	private int minHeap = Integer.MAX_VALUE;
       
   109 	private int maxChunks = 0;
       
   110 	private int minStackHeap = Integer.MAX_VALUE;
       
   111 	private int maxStackHeap = 0;
       
   112 
       
   113 	private DecimalFormat memKBFormat = new DecimalFormat(Messages
       
   114 			.getString("MemTraceGraph.KBformat")); //$NON-NLS-1$
       
   115 	private DecimalFormat memMBFloatFormat = new DecimalFormat(Messages
       
   116 			.getString("MemTraceGraph.MBformat")); //$NON-NLS-1$
       
   117 
       
   118 	private static int xLegendHeight = 20;
       
   119 
       
   120 	private boolean firstTimeDrawThreadList = true;
       
   121 	
       
   122 	public MemTraceGraph(int graphIndex, MemTrace memTrace, int uid) {
       
   123 		super((GenericSampledTrace) memTrace);
       
   124 
       
   125 		// 
       
   126 
       
   127 		if (memTrace != null) {
       
   128 
       
   129 			// if no version number is found from trace, we can assume
       
   130 			// that sampling based memory model is in use
       
   131 			this.memTrace = memTrace;
       
   132 			if (memTrace.getVersion() == 0) {
       
   133 				memTrace.setVersion(156);
       
   134 			}
       
   135 		}
       
   136 
       
   137 		this.graphIndex = graphIndex;
       
   138 		this.memTrace = memTrace;
       
   139 		this.paintMode = UsageType.CHUNKS_HEAPSTACK;
       
   140 		this.setScale(10);
       
   141 
       
   142 		if (memTrace == null) {
       
   143 			System.out.print(Messages
       
   144 					.getString("MemTraceGraph.traceDataNotFound")); //$NON-NLS-1$
       
   145 			return;
       
   146 		}
       
   147 
       
   148 		samplingTime = calcSamplingTime();
       
   149 		memTrace.gatherDrawData();
       
   150 
       
   151 		// create the label and a tableviewer
       
   152 		Composite holder = new Composite(NpiInstanceRepository.getInstance()
       
   153 				.getProfilePage(uid, graphIndex).getBottomComposite(), SWT.NONE);
       
   154 
       
   155 		GridLayout gl = new GridLayout();
       
   156 		gl.marginHeight = 0;
       
   157 		gl.marginWidth = 0;
       
   158 		gl.marginLeft = 0;
       
   159 		gl.marginRight = 0;
       
   160 		holder.setLayout(gl);
       
   161 
       
   162 		Label label = new Label(holder, SWT.CENTER);
       
   163 		label
       
   164 				.setBackground(holder.getDisplay().getSystemColor(
       
   165 						SWT.COLOR_WHITE));
       
   166 		label.setFont(PIPageEditor.helvetica_8);
       
   167 		label.setText(Messages.getString("MemTraceGraph.graphTitle")); //$NON-NLS-1$
       
   168 		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
       
   169 
       
   170 		this.memThreadTable = new MemThreadTable(this, holder);
       
   171 		this.memoryTableViewer = this.memThreadTable.getTableViewer();
       
   172 
       
   173 		this.readyToDraw = true;
       
   174 	}
       
   175 
       
   176 	public void action(String actionString) {
       
   177 		if (actionString.equals("chunk_on")) //$NON-NLS-1$
       
   178 		{
       
   179 			paintMode = UsageType.CHUNKS;
       
   180 		} else if (actionString.equals("heapstack_on")) //$NON-NLS-1$
       
   181 		{
       
   182 			paintMode = UsageType.HEAPSTACK;
       
   183 		} else if (actionString.equals("chunk_heapstack_on")) //$NON-NLS-1$
       
   184 		{
       
   185 			paintMode = UsageType.CHUNKS_HEAPSTACK;
       
   186 		} else if (actionString.equals("rescale_on")) //$NON-NLS-1$
       
   187 		{
       
   188 			dynamicMemoryVisualisation = true;
       
   189 			makeThreadDrawLists();
       
   190 		} else if (actionString.equals("rescale_off")) //$NON-NLS-1$
       
   191 		{
       
   192 			dynamicMemoryVisualisation = false;
       
   193 			makeThreadDrawLists();
       
   194 		} else {
       
   195 			return;
       
   196 		}
       
   197 
       
   198 		this.repaint();
       
   199 		if (this.leftFigureCanvas != null)
       
   200 			this.leftFigureCanvas.redraw();
       
   201 	}
       
   202 
       
   203 	public void piEventReceived(PIEvent be) {
       
   204 		switch (be.getType()) {
       
   205 		// when the selection area changes, the maximum values shown for each
       
   206 		// thread/process
       
   207 		// may change; if dynamicMemoryVisualisation is on, we'll also have a
       
   208 		// new y-scaling factor
       
   209 		case PIEvent.SELECTION_AREA_CHANGED:
       
   210 
       
   211 			// before updating the tables, make sure that the memory trace has
       
   212 			// computing the
       
   213 			// maximum usage by each thread/process within the new time interval
       
   214 			double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
   215 			double endTime = PIPageEditor.currentPageEditor().getEndTime();
       
   216 
       
   217 			memTrace.setMaxMemDataByInterval((int) (startTime * 1000),
       
   218 					(int) (endTime * 1000));
       
   219 
       
   220 			// send this message to the 2 other graphs
       
   221 			PIEvent be2 = new PIEvent(be.getValueObject(),
       
   222 					PIEvent.SELECTION_AREA_CHANGED2);
       
   223 
       
   224 			for (int i = 0; i < 3; i++) {
       
   225 				MemTraceGraph graph = (MemTraceGraph) memTrace.getTraceGraph(i);
       
   226 
       
   227 				if (graph != this) {
       
   228 					graph.piEventReceived(be2);
       
   229 				}
       
   230 			}
       
   231 
       
   232 			be = be2;
       
   233 
       
   234 			// FALL THROUGH
       
   235 		case PIEvent.SELECTION_AREA_CHANGED2:
       
   236 			double[] values = (double[]) be.getValueObject();
       
   237 			this.setSelectionStart(values[0]);
       
   238 			this.setSelectionEnd(values[1]);
       
   239 			this.memThreadTable.piEventReceived(be);
       
   240 			this.repaint();
       
   241 			break;
       
   242 
       
   243 		case PIEvent.CHANGED_MEMORY_TABLE:
       
   244 			this.makeThreadDrawLists();
       
   245 			this.repaint();
       
   246 			if (this.leftFigureCanvas != null)
       
   247 				this.leftFigureCanvas.redraw();
       
   248 			break;
       
   249 
       
   250 		case PIEvent.SCALE_CHANGED:
       
   251 			double scale = ((Double) be.getValueObject()).doubleValue();
       
   252 			this.setScale(scale);
       
   253 			this.repaint();
       
   254 			break;
       
   255 
       
   256 		case PIEvent.SCROLLED:
       
   257 			Event event = ((Event) be.getValueObject());
       
   258 			this.parentComponent.setScrolledOrigin(event.x, event.y);
       
   259 			this.repaint();
       
   260 			break;
       
   261 
       
   262 		default:
       
   263 			break;
       
   264 		}
       
   265 	}
       
   266 
       
   267 	public void focusGained(FocusEvent fe) {
       
   268 	}
       
   269 
       
   270 	public void focusLost(FocusEvent fe) {
       
   271 	}
       
   272 
       
   273 	public void paint(Panel panel, Graphics graphics) {
       
   274 		if (!readyToDraw)
       
   275 			return;
       
   276 
       
   277 		this.setSize(this.getSize().width, getVisualSize().height);
       
   278 		this.makeThreadDrawLists();
       
   279 		this.paintThreads(graphics);
       
   280 		this.drawDottedLineBackground(graphics, MemTraceGraph.xLegendHeight);
       
   281 
       
   282 		// draw the same selection as the Address/Thread trace
       
   283 		this.drawSelectionSection(graphics, MemTraceGraph.xLegendHeight);
       
   284 	}
       
   285 
       
   286 	private void paintSampledChunks(Graphics graphics) {
       
   287 		if (chunkListY == null)
       
   288 			return;
       
   289 
       
   290 		int[] points = new int[chunkListY.length * 2];
       
   291 
       
   292 		for (int i = 0, j = 0; i < chunkListY.length; i++) {
       
   293 			points[j++] = polyListX[i];
       
   294 			points[j++] = chunkListY[i];
       
   295 		}
       
   296 
       
   297 		graphics.setBackgroundColor(ColorConstants.orange);
       
   298 		graphics.fillPolygon(points);
       
   299 		graphics.setBackgroundColor(ColorConstants.gray);
       
   300 	}
       
   301 
       
   302 	private void paintEventBasedChunks(Graphics graphics) {
       
   303 		/*
       
   304 		 * if (chunkListY == null) return;
       
   305 		 */
       
   306 
       
   307 		/*
       
   308 		 * int[] points = new int[chunkListY.length * 2];
       
   309 		 * 
       
   310 		 * for (int i = 0, j =0; i < chunkListY.length; i++) { points[j++] =
       
   311 		 * polyListX[i]; points[j++] = chunkListY[i]; }
       
   312 		 */
       
   313 
       
   314 		graphics.setBackgroundColor(ColorConstants.orange);
       
   315 		graphics.fillPolygon(chunkPoints);
       
   316 		graphics.setBackgroundColor(ColorConstants.gray);
       
   317 	}
       
   318 
       
   319 	private void paintSampledStack(Graphics graphics, UsageType paintMode) {
       
   320 		if (stackListY == null)
       
   321 			return;
       
   322 
       
   323 		// if needed, move every y-value that is 0 down a little so that the
       
   324 		// line is more visible
       
   325 		boolean increase0 = paintMode != UsageType.HEAPSTACK;
       
   326 
       
   327 		int[] points = new int[stackListY.length * 2];
       
   328 
       
   329 		for (int i = 0, j = 0; i < stackListY.length; i++) {
       
   330 			points[j++] = polyListX[i];
       
   331 			points[j] = stackListY[i];
       
   332 
       
   333 			if (increase0 && (points[j] == 0))
       
   334 				points[j] = 1;
       
   335 
       
   336 			j++;
       
   337 		}
       
   338 
       
   339 		if (paintMode == UsageType.HEAPSTACK) {
       
   340 			graphics.setBackgroundColor(ColorConstants.blue);
       
   341 			graphics.fillPolygon(points);
       
   342 			graphics.setBackgroundColor(ColorConstants.gray);
       
   343 		} else {
       
   344 			int lineWidth = graphics.getLineWidth();
       
   345 			Color color = graphics.getForegroundColor();
       
   346 
       
   347 			graphics.setForegroundColor(ColorConstants.blue);
       
   348 			graphics.setLineWidth(2);
       
   349 			graphics.drawPolyline(points);
       
   350 			graphics.setForegroundColor(color);
       
   351 			graphics.setLineWidth(lineWidth);
       
   352 		}
       
   353 	}
       
   354 
       
   355 	private void paintEventBasedStack(Graphics graphics, UsageType paintMode) {
       
   356 		if (eventStackListY == null)
       
   357 			return;
       
   358 
       
   359 		// if needed, move every y-value that is 0 down a little so that the
       
   360 		// line is more visible
       
   361 		boolean increase0 = paintMode != UsageType.HEAPSTACK;
       
   362 
       
   363 		/*
       
   364 		 * int[] points = new int[stackListY.length * 2];
       
   365 		 * 
       
   366 		 * for (int i = 0, j =0; i < stackListY.length; i++) { points[j++] =
       
   367 		 * polyListX[i]; points[j] = stackListY[i];
       
   368 		 * 
       
   369 		 * if (increase0 && (points[j] == 0)) points[j] = 1;
       
   370 		 * 
       
   371 		 * j++; }
       
   372 		 */
       
   373 
       
   374 		if (paintMode == UsageType.HEAPSTACK) {
       
   375 			graphics.setBackgroundColor(ColorConstants.blue);
       
   376 			graphics.fillPolygon(stackAndHeapPoints);
       
   377 			graphics.setBackgroundColor(ColorConstants.gray);
       
   378 		} else {
       
   379 			int lineWidth = graphics.getLineWidth();
       
   380 			Color color = graphics.getForegroundColor();
       
   381 
       
   382 			graphics.setForegroundColor(ColorConstants.blue);
       
   383 			graphics.setLineWidth(2);
       
   384 			graphics.drawPolyline(stackAndHeapPoints);
       
   385 			graphics.setForegroundColor(color);
       
   386 			graphics.setLineWidth(lineWidth);
       
   387 		}
       
   388 	}
       
   389 
       
   390 	private void paintThreads(Graphics graphics) {
       
   391 		if (memTrace.getVersion() >= 202) {
       
   392 			paintEventBasedThreads(graphics);
       
   393 		} else {
       
   394 			paintSampledThreads(graphics);
       
   395 		}
       
   396 	}
       
   397 
       
   398 	private void paintSampledThreads(Graphics graphics) {
       
   399 		// if there are no threads to draw
       
   400 		if (!haveEnabled)
       
   401 			return;
       
   402 
       
   403 		int maxBytes = 0;
       
   404 
       
   405 		double multiplier;
       
   406 
       
   407 		if (paintMode == UsageType.CHUNKS && chunkListY != null) {
       
   408 			if (dynamicMemoryVisualisation)
       
   409 				maxBytes = maxChunks;
       
   410 			else
       
   411 				maxBytes = memTrace.getTraceMaxChunks();
       
   412 
       
   413 			// multiplier is bytes / pixel in the graph
       
   414 			if (true)// !dynamicMemoryVisualisation)
       
   415 				multiplier = prettyMaxBytes(maxBytes) / height;
       
   416 			else
       
   417 				multiplier = maxBytes / height;
       
   418 			// System.out.println("maxBytes " + maxBytes + " multiplier " +
       
   419 			// multiplier + " height " + height);
       
   420 
       
   421 			for (int j = 1; j < chunkListY.length - 1; j++) {
       
   422 				chunkListY[j] = (int) (height - chunkListY[j] / multiplier);
       
   423 
       
   424 				if (chunkListY[j] < 0)
       
   425 					chunkListY[j] = 0;
       
   426 			}
       
   427 
       
   428 			this.paintSampledChunks(graphics);
       
   429 		} else if (paintMode == UsageType.HEAPSTACK && stackListY != null) {
       
   430 			if (dynamicMemoryVisualisation)
       
   431 				maxBytes = maxStack;
       
   432 			else
       
   433 				maxBytes = memTrace.getTraceMaxStackHeap();
       
   434 
       
   435 			// multiplier is bytes / pixel in the final graph
       
   436 			if (true)// !dynamicMemoryVisualisation)
       
   437 				multiplier = prettyMaxBytes(maxBytes) / height;
       
   438 			else
       
   439 				multiplier = maxBytes / height;
       
   440 			// System.out.println("maxBytes " + maxBytes + " multiplier " +
       
   441 			// multiplier + " height " + height);
       
   442 
       
   443 			for (int j = 1; j < stackListY.length - 1; j++) {
       
   444 				stackListY[j] = (int) (height - stackListY[j] / multiplier);
       
   445 
       
   446 				if (stackListY[j] < 0)
       
   447 					stackListY[j] = 0;
       
   448 			}
       
   449 
       
   450 			this.paintSampledStack(graphics, paintMode);
       
   451 		} else if (chunkStackListY != null) // heap and stack
       
   452 		{
       
   453 			if (dynamicMemoryVisualisation)
       
   454 				maxBytes = maxChunks > maxStack ? maxChunks : maxStack;
       
   455 			else
       
   456 				maxBytes = memTrace.getTraceMaxChunks() > memTrace
       
   457 						.getTraceMaxStackHeap() ? memTrace.getTraceMaxChunks()
       
   458 						: memTrace.getTraceMaxStackHeap();
       
   459 
       
   460 			// multiplier is bytes / pixel in the final graph
       
   461 			if (true)// !dynamicMemoryVisualisation)
       
   462 				multiplier = prettyMaxBytes(maxBytes) / height;
       
   463 			else
       
   464 				multiplier = maxBytes / height;
       
   465 			// System.out.println("maxBytes " + maxBytes + " multiplier " +
       
   466 			// multiplier + " height " + height);
       
   467 
       
   468 			int totalStackUsed = 0;
       
   469 
       
   470 			for (int j = 1; j < chunkListY.length - 1; j++) {
       
   471 				totalStackUsed += stackListY[j];
       
   472 
       
   473 				chunkListY[j] = (int) (height - chunkListY[j] / multiplier);
       
   474 				stackListY[j] = (int) (height - stackListY[j] / multiplier);
       
   475 
       
   476 				if (stackListY[j] < 0)
       
   477 					stackListY[j] = 0;
       
   478 
       
   479 				if (chunkListY[j] < 0)
       
   480 					chunkListY[j] = 0;
       
   481 			}
       
   482 
       
   483 			this.paintSampledChunks(graphics);
       
   484 			if (totalStackUsed > 0)
       
   485 				this.paintSampledStack(graphics, paintMode);
       
   486 		}
       
   487 	}
       
   488 
       
   489 	private void paintEventBasedThreads(Graphics graphics) {
       
   490 		// paints treads when using event based memory model
       
   491 
       
   492 		// if there are no threads to draw
       
   493 		if (!haveEnabled)
       
   494 			return;
       
   495 
       
   496 		int maxBytes = 0;
       
   497 
       
   498 		double yMultiplier;
       
   499 		double xMultiplier;
       
   500 		xMultiplier = this.getScale();
       
   501 
       
   502 		// get las x coordinate of trace
       
   503 		long lastEvent = ((MemSample) memTrace.samples.get(memTrace.samples
       
   504 				.size() - 1)).sampleSynchTime;
       
   505 		int lastXCoord = (int) (lastEvent / xMultiplier);
       
   506 
       
   507 		if (paintMode == UsageType.CHUNKS && eventChunkListY != null) {
       
   508 			chunkPoints = new int[eventChunkListY.size() * 4 + 6];
       
   509 
       
   510 			if (dynamicMemoryVisualisation)
       
   511 				maxBytes = maxChunks;
       
   512 			else
       
   513 				maxBytes = memTrace.getTraceMaxChunks();
       
   514 
       
   515 			// multiplier is bytes / pixel in the graph
       
   516 			if (true)// !dynamicMemoryVisualisation)
       
   517 				yMultiplier = prettyMaxBytes(maxBytes) / height;
       
   518 			else
       
   519 				yMultiplier = maxBytes / height;
       
   520 			// System.out.println("maxBytes " + maxBytes + " multiplier " +
       
   521 			// multiplier + " height " + height);
       
   522 
       
   523 			createGraphPolygon(this.eventChunkListY, chunkPoints, xMultiplier,
       
   524 					yMultiplier, lastXCoord);
       
   525 
       
   526 			this.paintEventBasedChunks(graphics);
       
   527 		} else if (paintMode == UsageType.HEAPSTACK && eventStackListY != null) {
       
   528 			stackAndHeapPoints = new int[eventStackListY.size() * 4 + 6];
       
   529 
       
   530 			if (dynamicMemoryVisualisation)
       
   531 				maxBytes = maxStack;
       
   532 			else
       
   533 				maxBytes = memTrace.getTraceMaxStackHeap();
       
   534 
       
   535 			// multiplier is bytes / pixel in the final graph
       
   536 			if (true)// !dynamicMemoryVisualisation)
       
   537 				yMultiplier = prettyMaxBytes(maxBytes) / height;
       
   538 			else
       
   539 				yMultiplier = (double) maxBytes / height;
       
   540 
       
   541 			createGraphPolygon(this.eventStackListY, stackAndHeapPoints,
       
   542 					xMultiplier, yMultiplier, lastXCoord);
       
   543 			this.paintEventBasedStack(graphics, paintMode);
       
   544 		} else if (eventChunkStackListY != null) // heap and stack
       
   545 		{
       
   546 			stackAndHeapPoints = new int[eventStackListY.size() * 4 + 6];
       
   547 			chunkPoints = new int[eventChunkListY.size() * 4 + 6];
       
   548 
       
   549 			if (dynamicMemoryVisualisation)
       
   550 				maxBytes = maxChunks > maxStack ? maxChunks : maxStack;
       
   551 			else
       
   552 				maxBytes = memTrace.getTraceMaxChunks() > memTrace
       
   553 						.getTraceMaxStackHeap() ? memTrace.getTraceMaxChunks()
       
   554 						: memTrace.getTraceMaxStackHeap();
       
   555 
       
   556 			// multiplier is bytes / pixel in the final graph
       
   557 			if (true)// !dynamicMemoryVisualisation)
       
   558 				yMultiplier = prettyMaxBytes(maxBytes) / height;
       
   559 			else
       
   560 				yMultiplier = maxBytes / height;
       
   561 			// System.out.println("maxBytes " + maxBytes + " multiplier " +
       
   562 			// multiplier + " height " + height);
       
   563 
       
   564 			int totalStackUsed = 1;
       
   565 
       
   566 			createGraphPolygon(this.eventStackListY, stackAndHeapPoints,
       
   567 					xMultiplier, yMultiplier, lastXCoord);
       
   568 			createGraphPolygon(this.eventChunkListY, chunkPoints, xMultiplier,
       
   569 					yMultiplier, lastXCoord);
       
   570 
       
   571 			this.paintEventBasedChunks(graphics);
       
   572 			if (totalStackUsed > 0)
       
   573 				this.paintEventBasedStack(graphics, paintMode);
       
   574 		}
       
   575 	}
       
   576 
       
   577 	public void createGraphPolygon(TreeMap<Long, Integer> map, int[] points,
       
   578 			double xMultiplier, double yMultiplier, int endXCoord) {
       
   579 		// Creates graph polygon from TreeMap that contains all x and y values
       
   580 		// of one graph.
       
   581 
       
   582 		int index = 2;
       
   583 		int xCoord = 0;
       
   584 		int yCoord = 0;
       
   585 		int previousYCoord = 0;
       
   586 
       
   587 		// get first event and key from map.
       
   588 		Iterator<Long> keys = map.keySet().iterator();
       
   589 		Iterator<Integer> values = map.values().iterator();
       
   590 		
       
   591 	
       
   592 		int previousXCoord = 0;
       
   593 		int countOfSameXCoords = 1;
       
   594 
       
   595 		// set first into zero so that polygon is drawn correctly
       
   596 		points[0] = 0;
       
   597 		points[1] = height;
       
   598 
       
   599 		while (keys.hasNext()) {
       
   600 			// create polygon's points so that each memory allocation is drawn
       
   601 			// as one leap in graph
       
   602 
       
   603 			// calculate new x coord's value and round it to integer
       
   604 			xCoord = (int) (((double) keys.next() / xMultiplier) + 0.5);
       
   605 
       
   606 			// calculate new y-coord's value and round it to integer
       
   607 			yCoord = (int) (((double) height - (double) values.next() / yMultiplier) + 0.5);
       
   608 
       
   609 			if (xCoord == previousXCoord && index > 3) {
       
   610 				// if more than one sample at one point in the screen, count
       
   611 				// average value
       
   612 				// for y coordinate
       
   613 
       
   614 				// count average value
       
   615 				double sum = ((double) yCoord + (double) previousYCoord
       
   616 						* (double) countOfSameXCoords);
       
   617 				countOfSameXCoords++;
       
   618 				yCoord = (int) (sum / (double) (countOfSameXCoords));
       
   619 
       
   620 				// add average coordinate to array
       
   621 				index = index - 4;
       
   622 				index = addCoordsToGraphArray(xCoord, yCoord, index, points);
       
   623 
       
   624 			} else {
       
   625 				countOfSameXCoords = 1;
       
   626 			}
       
   627 
       
   628 			index = addCoordsToGraphArray(xCoord, yCoord, index, points);
       
   629 
       
   630 			// save coordinates to previousValues
       
   631 			previousYCoord = yCoord;
       
   632 			previousXCoord = xCoord;
       
   633 		}
       
   634 
       
   635 		// Set last coordinates to zero so that polygon is drawn correctly
       
   636 		points[points.length - 4] = endXCoord;
       
   637 		points[points.length - 3] = points[points.length - 5];
       
   638 
       
   639 		points[points.length - 2] = endXCoord;
       
   640 		points[points.length - 1] = height;
       
   641 	}
       
   642 
       
   643 	private int addCoordsToGraphArray(int xCoord, int yCoord, int arrayIndex,
       
   644 			int[] array) {
       
   645 
       
   646 		// adds coordinates to array so that polygon can be drawn from that
       
   647 		// array
       
   648 
       
   649 		// instead of straight lines between points, we draw graph more
       
   650 		// realistically
       
   651 		// so that single memory events are shown as a leap in graph.
       
   652 
       
   653 		// first x coordinate
       
   654 		array[arrayIndex] = xCoord;
       
   655 		arrayIndex++;
       
   656 
       
   657 		// first y coordinate, if possible use same y-coord than previous value
       
   658 		if ((arrayIndex - 2) < 0) {
       
   659 			array[arrayIndex] = 0;
       
   660 		} else {
       
   661 			array[arrayIndex] = array[arrayIndex - 2];
       
   662 		}
       
   663 		arrayIndex++;
       
   664 
       
   665 		// second x coordinate
       
   666 		array[arrayIndex] = xCoord;
       
   667 		arrayIndex++;
       
   668 
       
   669 		// second y coordinate
       
   670 		array[arrayIndex] = yCoord;
       
   671 		arrayIndex++;
       
   672 
       
   673 		return arrayIndex;
       
   674 	}
       
   675 
       
   676 	private void makeThreadDrawLists() {
       
   677 		if (memTrace.getVersion() >= 202) {
       
   678 			makeEventBasedThreadDrawLists();
       
   679 		} else {
       
   680 			makeSamplingBasedThreadDrawLists();
       
   681 		}
       
   682 	}
       
   683 
       
   684 	private void makeEventBasedThreadDrawLists() {
       
   685 
       
   686 		// Get checked table items
       
   687 		Object[] checked = this.memoryTableViewer.getCheckedElements();
       
   688 
       
   689 		// if no items is checked do nothing
       
   690 		haveEnabled = (checked != null) && (checked.length > 0);
       
   691 		if (!haveEnabled) {
       
   692 			this.eventChunkListY = null;
       
   693 			this.eventStackListY = null;
       
   694 			this.eventChunkStackListY = null;
       
   695 			return;
       
   696 		}
       
   697 
       
   698 		// create maps for events for chunks, stacks and chunksandstacks
       
   699 		this.eventChunkListY = new TreeMap<Long, Integer>();
       
   700 		this.eventStackListY = new TreeMap<Long, Integer>();
       
   701 		this.eventChunkStackListY = new TreeMap<Long, Integer>();
       
   702 
       
   703 		// go thru checked items
       
   704 		for (int j = 0; j < checked.length; j++) {
       
   705 			// check that item is instance of memory thread
       
   706 			if (!(checked[j] instanceof MemThread))
       
   707 				continue;
       
   708 
       
   709 			MemThread memThread = (MemThread) checked[j];
       
   710 
       
   711 			// get all samples of the thread
       
   712 			TreeMap<Long, MemSample> memSamples = memTrace
       
   713 					.getDrawDataByMemThread(memThread);
       
   714 
       
   715 			// ensure that thread has samples
       
   716 			if ((memSamples == null) || (memSamples.size() == 0)) {
       
   717 				System.out
       
   718 						.println(Messages
       
   719 								.getString("MemTraceGraph.threadProcessNoSamples1") + memThread.fullName + Messages.getString("MemTraceGraph.threadProcessNoSamples")); //$NON-NLS-1$ //$NON-NLS-2$
       
   720 				continue;
       
   721 			}
       
   722 
       
   723 			// create empty sample
       
   724 			MemSample previousSample = new MemSample(new MemThread(0, "", ""),
       
   725 					0, 0, 0);
       
   726 
       
   727 			Iterator<MemSample> values = memSamples.values().iterator();
       
   728 
       
   729 			while (values.hasNext()) {
       
   730 				MemSample memSample = values.next(); 
       
   731 				// go thru samples from single threas
       
   732 				// save changes after last received sample into TreeMaps
       
   733 				addEventToTreeMap(this.eventStackListY,
       
   734 						memSample.sampleSynchTime, memSample.stackSize
       
   735 								- previousSample.stackSize);
       
   736 				addEventToTreeMap(this.eventChunkListY,
       
   737 						memSample.sampleSynchTime, memSample.heapSize
       
   738 								- previousSample.heapSize);
       
   739 				addEventToTreeMap(
       
   740 						this.eventChunkStackListY,
       
   741 						memSample.sampleSynchTime,
       
   742 						memSample.heapSize
       
   743 								+ memSample.stackSize
       
   744 								- (previousSample.stackSize + previousSample.heapSize));
       
   745 
       
   746 				previousSample = memSample;
       
   747 
       
   748 			}
       
   749 		}
       
   750 
       
   751 		// calculate max values and values in each event
       
   752 		this.maxStack = calculateValuesInEachEvent(eventStackListY);
       
   753 		this.maxStackHeap = calculateValuesInEachEvent(eventChunkStackListY);
       
   754 		this.maxChunks = calculateValuesInEachEvent(eventChunkListY);
       
   755 
       
   756 		if (this.memTrace.getTraceMaxChunks() == 0) {
       
   757 			this.memTrace.setTraceMaxChunks(maxChunks);
       
   758 			this.memTrace.setTraceMaxStackHeap(maxStack);
       
   759 			this.memTrace.setTraceMaxTotal(maxStackHeap);
       
   760 			
       
   761 			//repaint left legend if this is first time that tread lists are made
       
   762 			if(firstTimeDrawThreadList){
       
   763 				this.parentComponent.paintLeftLegend();
       
   764 				firstTimeDrawThreadList = false;
       
   765 			}
       
   766 
       
   767 		}
       
   768 
       
   769 	}
       
   770 
       
   771 	private int calculateValuesInEachEvent(TreeMap<Long, Integer> map) {
       
   772 		// this function calculates total sum memory in each event based
       
   773 		// on the change map it receives as a parameter
       
   774 
       
   775 		// function also returns maximum value in whole map
       
   776 
       
   777 		int maxValue = 0;
       
   778 		int previousValue = 0;
       
   779 
       
   780 		Iterator<Integer> values = map.values().iterator();
       
   781 		Iterator<Long> keys = map.keySet().iterator();
       
   782 
       
   783 		while (values.hasNext()) {
       
   784 			
       
   785 			int memValue = values.next();
       
   786 			long memKey = keys.next();
       
   787 			
       
   788 			// go thru array and count actual state of
       
   789 			// memory in each event
       
   790 			int value = previousValue + memValue;
       
   791 
       
   792 			// is value is greater that max value save
       
   793 			// it as max value
       
   794 			if (value > maxValue) {
       
   795 				maxValue = value;
       
   796 			}
       
   797 
       
   798 			map.put(memKey, value);
       
   799 			previousValue = value;
       
   800 		}
       
   801 		return maxValue;
       
   802 	}
       
   803 
       
   804 	private void addEventToTreeMap(TreeMap<Long, Integer> map, long key,
       
   805 			int item) {
       
   806 		// Adds event into tree map.
       
   807 		// If event with that same key(time code) already exists values are
       
   808 		// added.
       
   809 
       
   810 		int previousValue = 0;
       
   811 		if (map.containsKey(key)) {
       
   812 			previousValue = map.get(key);
       
   813 		}
       
   814 
       
   815 		map.put(key, previousValue + item);
       
   816 	}
       
   817 
       
   818 	private void makeSamplingBasedThreadDrawLists() {
       
   819 
       
   820 		// Get checked table items
       
   821 		Object[] checked = this.memoryTableViewer.getCheckedElements();
       
   822 
       
   823 		haveEnabled = (checked != null) && (checked.length > 0);
       
   824 
       
   825 		// is no items are checked do nothing
       
   826 		if (!haveEnabled) {
       
   827 			this.chunkListY = null;
       
   828 			this.stackListY = null;
       
   829 			this.chunkStackListY = null;
       
   830 			calculateMinAndMaxValues();
       
   831 			return;
       
   832 		}
       
   833 
       
   834 		// Get first and last sample from trace
       
   835 		int firstSample = memTrace.getFirstSampleNumber();
       
   836 		int lastSample = memTrace.getLastSampleNumber();
       
   837 
       
   838 		// Get number of sampling points
       
   839 		int samplesTotal = (int) 1 + (lastSample - firstSample) / samplingTime;
       
   840 
       
   841 		// create arrays for y axis values of chunks, stacks chunksandstacks +
       
   842 		// polylistx
       
   843 		this.chunkListY = new int[samplesTotal * 2 + 1];
       
   844 		this.stackListY = new int[samplesTotal * 2 + 1];
       
   845 		this.chunkStackListY = new int[samplesTotal * 2 + 1];
       
   846 		this.polyListX = new int[samplesTotal * 2 + 1];
       
   847 
       
   848 		// go thru checked items
       
   849 		for (int j = 0; j < checked.length; j++) {
       
   850 			// check that item is instance of memory thread
       
   851 			if (!(checked[j] instanceof MemThread))
       
   852 				continue;
       
   853 
       
   854 			MemThread memThread = (MemThread) checked[j];
       
   855 
       
   856 			// get all samples of the thread
       
   857 			TreeMap<Long, MemSample> memSamples = memTrace
       
   858 					.getDrawDataByMemThread(memThread);
       
   859 
       
   860 			// ensure that thread has samples
       
   861 			if ((memSamples == null) || (memSamples.size() == 0)) {
       
   862 				System.out
       
   863 						.println(Messages
       
   864 								.getString("MemTraceGraph.threadProcessNoSamples1") + memThread.fullName + Messages.getString("MemTraceGraph.threadProcessNoSamples")); //$NON-NLS-1$ //$NON-NLS-2$
       
   865 				continue;
       
   866 			}
       
   867 
       
   868 			int sampleCount = memSamples.size();
       
   869 			int[] tempListX = new int[sampleCount * 2 + 1];
       
   870 
       
   871 			int counter = 0;
       
   872 
       
   873 			Iterator<MemSample> values = memSamples.values().iterator();
       
   874 			while (values.hasNext()) {
       
   875 				MemSample memSample = values.next();
       
   876 				// get index where sample is located at x-axis
       
   877 				int index = (int) ((memSample.sampleSynchTime - firstSample) / samplingTime) * 2 + 1;
       
   878 
       
   879 				tempListX[counter + 1] = (int) (memSample.sampleSynchTime / getScale());
       
   880 
       
   881 				// add samples value to chunks, stacks chunksandstacks arrays
       
   882 				this.stackListY[index] += memSample.stackSize;
       
   883 				this.chunkListY[index] += memSample.heapSize;
       
   884 				this.chunkStackListY[index] += memSample.heapSize
       
   885 						+ memSample.stackSize;
       
   886 
       
   887 				counter++;
       
   888 				tempListX[counter + 1] = (int) ((memSample.sampleSynchTime + samplingTime) / getScale());
       
   889 
       
   890 				index++;
       
   891 				if (this.paintMode == UsageType.CHUNKS) {
       
   892 					this.chunkListY[index] += memSample.heapSize;
       
   893 					counter++;
       
   894 				} else if (this.paintMode == UsageType.HEAPSTACK) {
       
   895 					this.stackListY[index] += memSample.stackSize;
       
   896 					counter++;
       
   897 				} else // paint mode chunk and stack
       
   898 				{
       
   899 					this.stackListY[index] += memSample.stackSize;
       
   900 					this.chunkListY[index] += memSample.heapSize;
       
   901 					this.chunkStackListY[index] += memSample.heapSize
       
   902 							+ memSample.stackSize;
       
   903 					counter++;
       
   904 				}
       
   905 				
       
   906 			}
       
   907 
       
   908 			// tempListX[0] = (int)
       
   909 			// (((MemSample)memSamples.firstEntry().getValue()).sampleSynchTime
       
   910 			// / getScale());
       
   911 			MemSample firstMemSample = (MemSample)memSamples.get(memSamples.firstKey());
       
   912 			tempListX[0] = (int) ((firstMemSample.sampleSynchTime / getScale()));
       
   913 			tempListX[tempListX.length - 1] = tempListX[tempListX.length - 2];
       
   914 
       
   915 			// defaults the originating and ending points into window corners
       
   916 			this.stackListY[0] = height;
       
   917 			this.stackListY[stackListY.length - 1] = height;
       
   918 			this.chunkListY[0] = height;
       
   919 			this.chunkListY[chunkListY.length - 1] = height;
       
   920 			this.chunkStackListY[0] = height;
       
   921 			this.chunkStackListY[chunkStackListY.length - 1] = height;
       
   922 		}
       
   923 
       
   924 		calculatePolylistX();
       
   925 		calculateMinAndMaxValues();
       
   926 	}
       
   927 
       
   928 	private void calculateMinAndMaxValues() {
       
   929 		// find heapValue;
       
   930 		minHeap = Integer.MAX_VALUE;
       
   931 		maxChunks = 0;
       
   932 
       
   933 		if (chunkListY != null) {
       
   934 			for (int i = 1; i < chunkListY.length - 1; i++) {
       
   935 				if (chunkListY[i] < minHeap)
       
   936 					minHeap = chunkListY[i];
       
   937 				if (chunkListY[i] > maxChunks)
       
   938 					maxChunks = chunkListY[i];
       
   939 			}
       
   940 		}
       
   941 
       
   942 		// find stackValue;
       
   943 		minStack = Integer.MAX_VALUE;
       
   944 		maxStack = 0;
       
   945 
       
   946 		if (stackListY != null) {
       
   947 			for (int i = 1; i < stackListY.length - 1; i++) {
       
   948 				if (stackListY[i] < minStack)
       
   949 					minStack = stackListY[i];
       
   950 				if (stackListY[i] > maxStack)
       
   951 					maxStack = stackListY[i];
       
   952 			}
       
   953 		}
       
   954 
       
   955 		// find stackValue+HeapValue;
       
   956 		minStackHeap = Integer.MAX_VALUE;
       
   957 		maxStackHeap = 0;
       
   958 
       
   959 		if (stackListY != null && chunkListY != null) {
       
   960 			for (int i = 1; i < stackListY.length - 1; i++) {
       
   961 				if ((stackListY[i] + chunkListY[i]) < minStackHeap)
       
   962 					minStackHeap = stackListY[i] + chunkListY[i];
       
   963 
       
   964 				if ((stackListY[i] + chunkListY[i]) > maxStackHeap)
       
   965 					maxStackHeap = stackListY[i] + chunkListY[i];
       
   966 			}
       
   967 		}
       
   968 	}
       
   969 
       
   970 	private void calculatePolylistX() {
       
   971 		int currentSample = memTrace.getFirstSampleNumber();
       
   972 		int lastSample = memTrace.getLastSampleNumber();
       
   973 		int sampleCount = (int) 1 + (lastSample - currentSample) / samplingTime;
       
   974 
       
   975 		polyListX = new int[sampleCount * 2 + 1];
       
   976 
       
   977 		int i = 0;
       
   978 
       
   979 		for (Enumeration e = memTrace.getSamples(); e.hasMoreElements();) {
       
   980 			MemSample ms = (MemSample) e.nextElement();
       
   981 			if ((int) ms.sampleSynchTime != currentSample) {
       
   982 				i++;
       
   983 				currentSample = (int) ms.sampleSynchTime;
       
   984 				polyListX[i + 1] = (int) (ms.sampleSynchTime / getScale());
       
   985 				i++;
       
   986 				polyListX[i + 1] = polyListX[i];
       
   987 			}
       
   988 		}
       
   989 
       
   990 		polyListX[0] = (int) (memTrace.getFirstSampleNumber() / getScale());
       
   991 		polyListX[1] = (int) (memTrace.getFirstSampleNumber() / getScale());
       
   992 		polyListX[polyListX.length - 1] = polyListX[polyListX.length - 2];
       
   993 	}
       
   994 
       
   995 	public void setSize(int x, int y) {
       
   996 		this.width = x;
       
   997 		this.height = y - MemTraceGraph.xLegendHeight;
       
   998 
       
   999 		if (this.height <= 0)
       
  1000 			this.height = 1;
       
  1001 	}
       
  1002 
       
  1003 	public Dimension getSize() {
       
  1004 		return new Dimension(width, height);
       
  1005 	}
       
  1006 
       
  1007 	private int calcSamplingTime() {
       
  1008 		long time = memTrace.getFirstSampleNumber();
       
  1009 		for (Enumeration e = memTrace.getSamples(); e.hasMoreElements();) {
       
  1010 			MemSample tmp = (MemSample) e.nextElement();
       
  1011 			if (tmp.sampleSynchTime != time) {
       
  1012 				time = tmp.sampleSynchTime - time;
       
  1013 				return (int) time;
       
  1014 			}
       
  1015 		}
       
  1016 		return defaultSamplingTime;
       
  1017 	}
       
  1018 
       
  1019 	public void refreshDataFromTrace() {
       
  1020 	}
       
  1021 
       
  1022 	public void repaint() {
       
  1023 		this.parentComponent.repaintComponent();
       
  1024 	}
       
  1025 
       
  1026 	public int getSamplingTime() {
       
  1027 		return samplingTime;
       
  1028 	}
       
  1029 
       
  1030 	/*
       
  1031 	 * (non-Javadoc)
       
  1032 	 * 
       
  1033 	 * @seecom.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu#
       
  1034 	 * addContextMenuItems(org.eclipse.swt.widgets.Menu,
       
  1035 	 * org.eclipse.swt.events.MouseEvent)
       
  1036 	 */
       
  1037 	public void addContextMenuItems(Menu menu,
       
  1038 			org.eclipse.swt.events.MouseEvent me) {
       
  1039 		new MenuItem(menu, SWT.SEPARATOR);
       
  1040 
       
  1041 		MenuItem memoryStatsItem = new MenuItem(menu, SWT.PUSH);
       
  1042 		memoryStatsItem.setText(Messages.getString("MemoryPlugin.memoryStats")); //$NON-NLS-1$
       
  1043 		memoryStatsItem.addSelectionListener(new SelectionAdapter() {
       
  1044 			public void widgetSelected(SelectionEvent e) {
       
  1045 				new MemoryStatisticsDialog(Display.getCurrent());
       
  1046 			}
       
  1047 		});
       
  1048 
       
  1049 		new MenuItem(menu, SWT.SEPARATOR);
       
  1050 
       
  1051 		boolean showChunk = true;
       
  1052 		boolean showHeapStack = true;
       
  1053 
       
  1054 		Object obj;
       
  1055 		// if there is a showChunk value associated with the current Analyser
       
  1056 		// tab, then use it
       
  1057 		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState(
       
  1058 				"com.nokia.carbide.cpp.pi.memory.showChunk"); //$NON-NLS-1$
       
  1059 		if ((obj != null) && (obj instanceof Boolean))
       
  1060 			// retrieve the current value
       
  1061 			showChunk = (Boolean) obj;
       
  1062 		else
       
  1063 			// set the initial value
       
  1064 			NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1065 					"com.nokia.carbide.cpp.pi.memory.showChunk", showChunk); //$NON-NLS-1$
       
  1066 
       
  1067 		// if there is a showHeapStack value associated with the current
       
  1068 		// Analyser tab, then use it
       
  1069 		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState(
       
  1070 				"com.nokia.carbide.cpp.pi.memory.showHeapStack"); //$NON-NLS-1$
       
  1071 		if ((obj != null) && (obj instanceof Boolean))
       
  1072 			// retrieve the current value
       
  1073 			showHeapStack = (Boolean) obj;
       
  1074 		else
       
  1075 			// set the initial value
       
  1076 			NpiInstanceRepository
       
  1077 					.getInstance()
       
  1078 					.activeUidSetPersistState(
       
  1079 							"com.nokia.carbide.cpp.pi.memory.showHeapStack", showHeapStack); //$NON-NLS-1$
       
  1080 
       
  1081 		MenuItem showChunkItem = new MenuItem(menu, SWT.RADIO);
       
  1082 		showChunkItem.setText(Messages.getString("MemoryPlugin.showChunks")); //$NON-NLS-1$
       
  1083 		showChunkItem.setSelection(showChunk && !showHeapStack);
       
  1084 		showChunkItem.addSelectionListener(new SelectionAdapter() {
       
  1085 			public void widgetSelected(SelectionEvent e) {
       
  1086 				NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1087 						"com.nokia.carbide.cpp.pi.memory.showChunk", true); //$NON-NLS-1$
       
  1088 				NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1089 						"com.nokia.carbide.cpp.pi.memory.showHeapStack", false); //$NON-NLS-1$
       
  1090 
       
  1091 				for (int i = 0; i < 3; i++) {
       
  1092 					MemTraceGraph graph = (MemTraceGraph) memTrace
       
  1093 							.getTraceGraph(i);
       
  1094 					graph.action("chunk_on"); //$NON-NLS-1$
       
  1095 				}
       
  1096 			}
       
  1097 		});
       
  1098 
       
  1099 		MenuItem showHeapItem = new MenuItem(menu, SWT.RADIO);
       
  1100 		showHeapItem.setText(Messages.getString("MemoryPlugin.showHeapStack")); //$NON-NLS-1$
       
  1101 		showHeapItem.setSelection(showHeapStack && !showChunk);
       
  1102 		showHeapItem.addSelectionListener(new SelectionAdapter() {
       
  1103 			public void widgetSelected(SelectionEvent e) {
       
  1104 				NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1105 						"com.nokia.carbide.cpp.pi.memory.showChunk", false); //$NON-NLS-1$
       
  1106 				NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1107 						"com.nokia.carbide.cpp.pi.memory.showHeapStack", true); //$NON-NLS-1$
       
  1108 
       
  1109 				for (int i = 0; i < 3; i++) {
       
  1110 					MemTraceGraph graph = (MemTraceGraph) memTrace
       
  1111 							.getTraceGraph(i);
       
  1112 					graph.action("heapstack_on"); //$NON-NLS-1$
       
  1113 				}
       
  1114 			}
       
  1115 		});
       
  1116 
       
  1117 		MenuItem showBothItem = new MenuItem(menu, SWT.RADIO);
       
  1118 		showBothItem.setText(Messages.getString("MemoryPlugin.showAll")); //$NON-NLS-1$
       
  1119 		showBothItem.setSelection(showChunk && showHeapStack);
       
  1120 		showBothItem.addSelectionListener(new SelectionAdapter() {
       
  1121 			public void widgetSelected(SelectionEvent e) {
       
  1122 				NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1123 						"com.nokia.carbide.cpp.pi.memory.showChunk", true); //$NON-NLS-1$
       
  1124 				NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1125 						"com.nokia.carbide.cpp.pi.memory.showHeapStack", true); //$NON-NLS-1$
       
  1126 
       
  1127 				for (int i = 0; i < 3; i++) {
       
  1128 					MemTraceGraph graph = (MemTraceGraph) memTrace
       
  1129 							.getTraceGraph(i);
       
  1130 					graph.action("chunk_heapstack_on"); //$NON-NLS-1$
       
  1131 				}
       
  1132 			}
       
  1133 		});
       
  1134 
       
  1135 		new MenuItem(menu, SWT.SEPARATOR);
       
  1136 
       
  1137 		boolean rescale = false;
       
  1138 
       
  1139 		// if there is a rescale value associated with the current Analyser tab,
       
  1140 		// then use it
       
  1141 		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState(
       
  1142 				"com.nokia.carbide.cpp.pi.memory.rescale"); //$NON-NLS-1$
       
  1143 		if ((obj != null) && (obj instanceof Boolean))
       
  1144 			// retrieve the current value
       
  1145 			rescale = (Boolean) obj;
       
  1146 		else
       
  1147 			// set the initial value
       
  1148 			NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
  1149 					"com.nokia.carbide.cpp.pi.memory.rescale", rescale); //$NON-NLS-1$
       
  1150 
       
  1151 		final boolean rescaleFinal = rescale;
       
  1152 
       
  1153 		MenuItem rescaleItem = new MenuItem(menu, SWT.CHECK);
       
  1154 		rescaleItem.setText(Messages.getString("MemoryPlugin.dynamicRescale")); //$NON-NLS-1$
       
  1155 		rescaleItem.setSelection(rescale);
       
  1156 		rescaleItem.addSelectionListener(new SelectionAdapter() {
       
  1157 			public void widgetSelected(SelectionEvent e) {
       
  1158 				String action;
       
  1159 				NpiInstanceRepository
       
  1160 						.getInstance()
       
  1161 						.activeUidSetPersistState(
       
  1162 								"com.nokia.carbide.cpp.pi.memory.rescale", !rescaleFinal); //$NON-NLS-1$
       
  1163 				if (!rescaleFinal) {
       
  1164 					action = "rescale_on"; //$NON-NLS-1$
       
  1165 				} else {
       
  1166 					action = "rescale_off"; //$NON-NLS-1$
       
  1167 				}
       
  1168 
       
  1169 				for (int i = 0; i < 3; i++) {
       
  1170 					MemTraceGraph graph = (MemTraceGraph) memTrace
       
  1171 							.getTraceGraph(i);
       
  1172 					graph.action(action);
       
  1173 				}
       
  1174 			}
       
  1175 		});
       
  1176 	}
       
  1177 
       
  1178 	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
       
  1179 		// System.out.println("MEM"); if (true)return;
       
  1180 		// if there are no threads to draw
       
  1181 		GC localGC = gc;
       
  1182 
       
  1183 		if (gc == null)
       
  1184 			gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
       
  1185 
       
  1186 		if (this.leftFigureCanvas == null)
       
  1187 			this.leftFigureCanvas = figureCanvas;
       
  1188 
       
  1189 		Rectangle rect = ((GraphComposite) figureCanvas.getParent()).figureCanvas
       
  1190 				.getClientArea();
       
  1191 
       
  1192 		double visY = rect.height - MemTraceGraph.xLegendHeight;
       
  1193 
       
  1194 		gc.setForeground(ColorPalette.getColor(new RGB(100, 100, 100)));
       
  1195 		gc.setBackground(ColorPalette.getColor(new RGB(255, 255, 255)));
       
  1196 
       
  1197 		int maxBytes = 0;
       
  1198 
       
  1199 		if (paintMode == UsageType.CHUNKS) {
       
  1200 			if (dynamicMemoryVisualisation)
       
  1201 				maxBytes = maxChunks;
       
  1202 			else
       
  1203 				maxBytes = memTrace.getTraceMaxChunks();
       
  1204 		} else if (paintMode == UsageType.HEAPSTACK) {
       
  1205 			if (dynamicMemoryVisualisation)
       
  1206 				maxBytes = maxStack;
       
  1207 			else
       
  1208 				maxBytes = memTrace.getTraceMaxStackHeap();
       
  1209 		} else {
       
  1210 			if (dynamicMemoryVisualisation)
       
  1211 				maxBytes = maxChunks > maxStack ? maxChunks : maxStack;
       
  1212 			else
       
  1213 				maxBytes = memTrace.getTraceMaxChunks() > memTrace
       
  1214 						.getTraceMaxStackHeap() ? memTrace.getTraceMaxChunks()
       
  1215 						: memTrace.getTraceMaxStackHeap();
       
  1216 		}
       
  1217 
       
  1218 		double multiplier = 0;
       
  1219 
       
  1220 		if (true)// !dynamicMemoryVisualisation)
       
  1221 			multiplier = prettyMaxBytes(maxBytes) / visY;
       
  1222 		else
       
  1223 			multiplier = maxBytes / visY;
       
  1224 
       
  1225 		int previousBottom = 0; // bottom of the previous legend drawn
       
  1226 		String legend;
       
  1227 		double yIncrement = visY / 10;
       
  1228 
       
  1229 		// draw 11 value indicators (0..10) to the scale
       
  1230 		for (int k = 10; k >= 0; k--) {
       
  1231 			// location for the value indicator is k * 1/10 the height of the
       
  1232 			// display
       
  1233 			int y = (int) (visY - (yIncrement * k));
       
  1234 
       
  1235 			// calculate the exact byte value at the height by multiplying
       
  1236 			// the height with the [bytes / pixel] value
       
  1237 			int bytes = (int) ((visY * multiplier) / 10.0) * k;
       
  1238 
       
  1239 			// construct the text for each scale
       
  1240 			legend = ""; //$NON-NLS-1$
       
  1241 
       
  1242 			// if the amount of data is less than 512KB, draw it as bytes
       
  1243 			if (maxBytes < 10000) {
       
  1244 				legend += bytes + Messages.getString("MemTraceGraph.byByte"); //$NON-NLS-1$
       
  1245 			}
       
  1246 			// if the amount is more than 512KB, draw it as KB
       
  1247 			else if (maxBytes <= 500 * 1024) {
       
  1248 				legend += (bytes / 1024)
       
  1249 						+ Messages.getString("MemTraceGraph.byKB"); //$NON-NLS-1$
       
  1250 			} else {
       
  1251 				legend += memMBFloatFormat
       
  1252 						.format(((float) bytes / (1024 * 1024)))
       
  1253 						+ Messages.getString("MemTraceGraph.byMB"); //$NON-NLS-1$
       
  1254 			}
       
  1255 
       
  1256 			Point extent = gc.stringExtent(legend);
       
  1257 
       
  1258 			gc.drawLine(GenericTraceGraph.yLegendWidth - 3, (int) y + 1,
       
  1259 					GenericTraceGraph.yLegendWidth, (int) y + 1);
       
  1260 
       
  1261 			if (y >= previousBottom) {
       
  1262 				gc.drawString(legend, GenericTraceGraph.yLegendWidth - extent.x
       
  1263 						- 4, (int) y);
       
  1264 				previousBottom = (int) y + extent.y;
       
  1265 			}
       
  1266 		}
       
  1267 
       
  1268 		if (localGC == null) {
       
  1269 			gc.dispose();
       
  1270 			figureCanvas.redraw();
       
  1271 		}
       
  1272 	}
       
  1273 
       
  1274 	/*
       
  1275 	 * (non-Javadoc)
       
  1276 	 * 
       
  1277 	 * @see
       
  1278 	 * org.eclipse.draw2d.MouseMotionListener#mouseDragged(org.eclipse.draw2d
       
  1279 	 * .MouseEvent)
       
  1280 	 */
       
  1281 	public void mouseDragged(MouseEvent me) {
       
  1282 	}
       
  1283 
       
  1284 	/*
       
  1285 	 * (non-Javadoc)
       
  1286 	 * 
       
  1287 	 * @see
       
  1288 	 * org.eclipse.draw2d.MouseMotionListener#mouseEntered(org.eclipse.draw2d
       
  1289 	 * .MouseEvent)
       
  1290 	 */
       
  1291 	public void mouseEntered(MouseEvent me) {
       
  1292 	}
       
  1293 
       
  1294 	/*
       
  1295 	 * (non-Javadoc)
       
  1296 	 * 
       
  1297 	 * @see
       
  1298 	 * org.eclipse.draw2d.MouseMotionListener#mouseExited(org.eclipse.draw2d
       
  1299 	 * .MouseEvent)
       
  1300 	 */
       
  1301 	public void mouseExited(MouseEvent me) {
       
  1302 	}
       
  1303 
       
  1304 	/*
       
  1305 	 * (non-Javadoc)
       
  1306 	 * 
       
  1307 	 * @see
       
  1308 	 * org.eclipse.draw2d.MouseMotionListener#mouseHover(org.eclipse.draw2d.
       
  1309 	 * MouseEvent)
       
  1310 	 */
       
  1311 	public void mouseHover(MouseEvent me) {
       
  1312 	}
       
  1313 
       
  1314 	/*
       
  1315 	 * (non-Javadoc)
       
  1316 	 * 
       
  1317 	 * @see
       
  1318 	 * org.eclipse.draw2d.MouseMotionListener#mouseMoved(org.eclipse.draw2d.
       
  1319 	 * MouseEvent)
       
  1320 	 */
       
  1321 	public void mouseMoved(MouseEvent me) {
       
  1322 		double x = me.x * this.getScale();
       
  1323 		double y = me.y;
       
  1324 
       
  1325 		if (y > this.getVisualSizeY() - MemTraceGraph.xLegendHeight) {
       
  1326 			this.setToolTipText(null);
       
  1327 			return;
       
  1328 		}
       
  1329 
       
  1330 		// mouse event may return out of range X, that may
       
  1331 		// crash when we use it to index data array
       
  1332 		x = x >= 0 ? x : 0;
       
  1333 		if (me.x >= this.getVisualSize().width
       
  1334 				+ this.parentComponent.getScrolledOrigin().x) {
       
  1335 			x = (this.getVisualSize().width - 1) * this.getScale();
       
  1336 		}
       
  1337 
       
  1338 		if (x > PIPageEditor.currentPageEditor().getMaxEndTime() * 1000) {
       
  1339 			this.setToolTipText(null);
       
  1340 			return;
       
  1341 		}
       
  1342 
       
  1343 		long chunkSize = 0;
       
  1344 		long stackHeapSize = 0;
       
  1345 		// long totalSize = 0;
       
  1346 		Entry<Long, Integer> entry;
       
  1347 		if (memTrace.getVersion() >= 202) {
       
  1348 			if (eventStackListY != null) {
       
  1349 				/*
       
  1350 				 * TODO entry = eventStackListY.floorEntry((long)x); if(entry !=
       
  1351 				 * null){ stackHeapSize = entry.getValue(); }
       
  1352 				 */
       
  1353 				Integer value = (Integer) MemTrace.getFloorEntryFromMap(
       
  1354 						(long) x, eventStackListY);
       
  1355 				if (value != null) {
       
  1356 					stackHeapSize = value;
       
  1357 				}
       
  1358 			}
       
  1359 			if (eventChunkListY != null) {
       
  1360 				/*
       
  1361 				 * TODO entry = eventChunkListY.floorEntry((long)x); if(entry !=
       
  1362 				 * null){ chunkSize = entry.getValue(); }
       
  1363 				 */
       
  1364 				Integer value = (Integer) MemTrace.getFloorEntryFromMap(
       
  1365 						(long) x, eventChunkListY);
       
  1366 				if (value != null) {
       
  1367 					chunkSize = value;
       
  1368 				}
       
  1369 
       
  1370 			}/*
       
  1371 			 * if(stackHeapSize == null){ this.setToolTipText(null); return; }
       
  1372 			 */
       
  1373 		} else {
       
  1374 			ArrayList<MemSample> samples = memTrace
       
  1375 					.getMemSampleDataByTime((long) x);
       
  1376 
       
  1377 			if (samples != null) {
       
  1378 				// tooltip always shows totals for the threads/processes that
       
  1379 				// are selected
       
  1380 				for (int i = 0; i < samples.size(); i++) {
       
  1381 					MemSample sample = samples.get(i);
       
  1382 					MemThread memThread = sample.thread;
       
  1383 					if (memThread.isEnabled(this.graphIndex)) {
       
  1384 						chunkSize += sample.heapSize;
       
  1385 						stackHeapSize += sample.stackSize;
       
  1386 						// totalSize += sample.heapSize + sample.stackSize;
       
  1387 					}
       
  1388 				}
       
  1389 			}
       
  1390 		}
       
  1391 
       
  1392 		int time = (int) x;
       
  1393 
       
  1394 		if (this.paintMode == UsageType.CHUNKS_HEAPSTACK) {
       
  1395 			this.setToolTipText((time / 1000.0)
       
  1396 					+ Messages.getString("MemTraceGraph.totalTooltip1") //$NON-NLS-1$
       
  1397 					+ memKBFormat.format((chunkSize + 512) / 1024)
       
  1398 					+ Messages.getString("MemTraceGraph.totalTooltip2") //$NON-NLS-1$
       
  1399 					+ memKBFormat.format((stackHeapSize + 512) / 1024));
       
  1400 		} else if (this.paintMode == UsageType.CHUNKS) {
       
  1401 			this.setToolTipText((time / 1000.0)
       
  1402 					+ Messages.getString("MemTraceGraph.chunkTooltip1") //$NON-NLS-1$
       
  1403 					+ (chunkSize + 512) / 1024
       
  1404 					+ Messages.getString("MemTraceGraph.chunkTooltip2")); //$NON-NLS-1$
       
  1405 		} else if (this.paintMode == UsageType.HEAPSTACK) {
       
  1406 			this.setToolTipText((time / 1000.0)
       
  1407 					+ Messages.getString("MemTraceGraph.stackHeapTooltip1") //$NON-NLS-1$
       
  1408 					+ (stackHeapSize + 512) / 1024
       
  1409 					+ Messages.getString("MemTraceGraph.stackHeapTooltip2")); //$NON-NLS-1$
       
  1410 		} else
       
  1411 			return;
       
  1412 
       
  1413 	}
       
  1414 
       
  1415 	public void setCurrentThreads(Hashtable<Integer, Integer> threadList) {
       
  1416 		this.threadList = threadList;
       
  1417 	}
       
  1418 
       
  1419 	public int getGraphIndex() {
       
  1420 		return this.graphIndex;
       
  1421 	}
       
  1422 
       
  1423 	public MemTrace getMemTrace() {
       
  1424 		return this.memTrace;
       
  1425 	}
       
  1426 
       
  1427 	public MemThreadTable getMemThreadTable() {
       
  1428 		return this.memThreadTable;
       
  1429 	}
       
  1430 
       
  1431 	public boolean haveEnabled() {
       
  1432 		return this.haveEnabled;
       
  1433 	}
       
  1434 
       
  1435 	private int prettyMaxBytes(int bytes) {
       
  1436 		if (bytes < 1000)
       
  1437 			bytes = 1000;
       
  1438 		else if (bytes < 10000)
       
  1439 			bytes = 10000;
       
  1440 		else if (bytes <= 10 * 1024)
       
  1441 			bytes = 10 * 1024;
       
  1442 		else if (bytes <= 20 * 1024)
       
  1443 			bytes = 20 * 1024;
       
  1444 		else if (bytes <= 30 * 1024)
       
  1445 			bytes = 30 * 1024;
       
  1446 		else if (bytes <= 50 * 1024)
       
  1447 			bytes = 50 * 1024;
       
  1448 		else if (bytes <= 100 * 1024)
       
  1449 			bytes = 100 * 1024;
       
  1450 		else if (bytes <= 200 * 1024)
       
  1451 			bytes = 200 * 1024;
       
  1452 		else if (bytes <= 300 * 1024)
       
  1453 			bytes = 300 * 1024;
       
  1454 		else if (bytes <= 500 * 1024)
       
  1455 			bytes = 500 * 1024;
       
  1456 		else if (bytes <= 1000 * 1024)
       
  1457 			bytes = 1000 * 1024;
       
  1458 		else if (bytes <= 1 * 1024 * 1024)
       
  1459 			bytes = 1 * 1024 * 1024;
       
  1460 		else if (bytes <= 2 * 1024 * 1024)
       
  1461 			bytes = 2 * 1024 * 1024;
       
  1462 		else if (bytes <= 3 * 1024 * 1024)
       
  1463 			bytes = 3 * 1024 * 1024;
       
  1464 		else if (bytes <= 5 * 1024 * 1024)
       
  1465 			bytes = 5 * 1024 * 1024;
       
  1466 		else if (bytes <= 10 * 1024 * 1024)
       
  1467 			bytes = 10 * 1024 * 1024;
       
  1468 		else if (bytes <= 20 * 1024 * 1024)
       
  1469 			bytes = 20 * 1024 * 1024;
       
  1470 		else if (bytes <= 30 * 1024 * 1024)
       
  1471 			bytes = 30 * 1024 * 1024;
       
  1472 		else if (bytes <= 50 * 1024 * 1024)
       
  1473 			bytes = 50 * 1024 * 1024;
       
  1474 		else if (bytes <= 100 * 1024 * 1024)
       
  1475 			bytes = 100 * 1024 * 1024;
       
  1476 		else if (bytes <= 200 * 1024 * 1024)
       
  1477 			bytes = 200 * 1024 * 1024;
       
  1478 		else if (bytes <= 300 * 1024 * 1024)
       
  1479 			bytes = 300 * 1024 * 1024;
       
  1480 		else if (bytes <= 500 * 1024 * 1024)
       
  1481 			bytes = 500 * 1024 * 1024;
       
  1482 		else
       
  1483 			bytes = ((bytes + 1024 * 1024 * 1024 - 1) / (1024 * 1024 * 1024))
       
  1484 					* (1024 * 1024 * 1024);
       
  1485 
       
  1486 		return bytes;
       
  1487 	}
       
  1488 
       
  1489 }