sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrThreadTable.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.address;
       
    19 
       
    20 import java.awt.Toolkit;
       
    21 import java.awt.datatransfer.Clipboard;
       
    22 import java.awt.datatransfer.StringSelection;
       
    23 import java.awt.event.FocusEvent;
       
    24 import java.text.DecimalFormat;
       
    25 import java.util.ArrayList;
       
    26 import java.util.Arrays;
       
    27 import java.util.Collections;
       
    28 import java.util.Comparator;
       
    29 import java.util.Enumeration;
       
    30 import java.util.Hashtable;
       
    31 import java.util.Vector;
       
    32 
       
    33 import org.eclipse.jface.viewers.CheckStateChangedEvent;
       
    34 import org.eclipse.jface.viewers.CheckboxTableViewer;
       
    35 import org.eclipse.jface.viewers.ICheckStateListener;
       
    36 import org.eclipse.jface.viewers.ISelectionChangedListener;
       
    37 import org.eclipse.jface.viewers.IStructuredContentProvider;
       
    38 import org.eclipse.jface.viewers.ITableLabelProvider;
       
    39 import org.eclipse.jface.viewers.LabelProvider;
       
    40 import org.eclipse.jface.viewers.SelectionChangedEvent;
       
    41 import org.eclipse.jface.viewers.Viewer;
       
    42 import org.eclipse.swt.SWT;
       
    43 import org.eclipse.swt.events.SelectionAdapter;
       
    44 import org.eclipse.swt.events.SelectionEvent;
       
    45 import org.eclipse.swt.graphics.Color;
       
    46 import org.eclipse.swt.graphics.Image;
       
    47 import org.eclipse.swt.layout.FormAttachment;
       
    48 import org.eclipse.swt.layout.FormData;
       
    49 import org.eclipse.swt.layout.FormLayout;
       
    50 import org.eclipse.swt.widgets.Composite;
       
    51 import org.eclipse.swt.widgets.Decorations;
       
    52 import org.eclipse.swt.widgets.Display;
       
    53 import org.eclipse.swt.widgets.Event;
       
    54 import org.eclipse.swt.widgets.Listener;
       
    55 import org.eclipse.swt.widgets.Menu;
       
    56 import org.eclipse.swt.widgets.MenuItem;
       
    57 import org.eclipse.swt.widgets.Sash;
       
    58 import org.eclipse.swt.widgets.Table;
       
    59 import org.eclipse.swt.widgets.TableColumn;
       
    60 import org.eclipse.swt.widgets.TableItem;
       
    61 
       
    62 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
       
    63 import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
       
    64 import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
       
    65 import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
       
    66 import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
       
    67 import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
       
    68 import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
       
    69 import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
       
    70 import com.nokia.carbide.cpp.internal.pi.visual.Defines;
       
    71 import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
       
    72 import com.nokia.carbide.cpp.internal.pi.visual.PIVisualSharedData;
       
    73 import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
       
    74 import com.nokia.carbide.cpp.pi.util.TableColorPalette;
       
    75 
       
    76 
       
    77 public class AddrThreadTable extends GenericAddrTable
       
    78 {
       
    79 	// local copy of profiled threads, which we can sort
       
    80 	// without affecting the original
       
    81 	Vector<ProfiledGeneric> profiledThreads = new Vector<ProfiledGeneric>();
       
    82 
       
    83 	// changes made to support priority plugin
       
    84 	private boolean priorityAdded = false;
       
    85 	private Hashtable<Integer,String> priorityTable;
       
    86 	private Hashtable<Integer,Integer> priorityValues;
       
    87 
       
    88 	public AddrThreadTable(GppTraceGraph myGraph, Composite parent)
       
    89 	{
       
    90 		this.myGraph = myGraph;
       
    91 		this.parent  = parent;
       
    92 	}
       
    93 
       
    94 	public void createTableViewer(int drawMode)
       
    95 	{
       
    96 		if (this.parent == null)
       
    97 			return;
       
    98 
       
    99 		// Thread table:
       
   100 		//		checkbox + colored or white background
       
   101 		//  	percent load
       
   102 		//  	thread name
       
   103 		//		sample count
       
   104 		//		priority (optional)
       
   105 
       
   106 		// Check the drawMode, and use it to decide whether or not to show a color column
       
   107 		// or the number of samples
       
   108 		switch (drawMode)
       
   109 		{
       
   110 			case Defines.THREADS:
       
   111 			case Defines.BINARIES_THREADS:
       
   112 			case Defines.BINARIES_FUNCTIONS_THREADS:
       
   113 			case Defines.FUNCTIONS_THREADS:
       
   114 			case Defines.FUNCTIONS_BINARIES_THREADS:
       
   115 			case Defines.THREADS_FUNCTIONS:
       
   116 			case Defines.THREADS_FUNCTIONS_BINARIES:
       
   117 			case Defines.THREADS_BINARIES:
       
   118 			case Defines.THREADS_BINARIES_FUNCTIONS:
       
   119 			case Defines.BINARIES_THREADS_FUNCTIONS:
       
   120 			case Defines.FUNCTIONS_THREADS_BINARIES:
       
   121 			{
       
   122 				break;
       
   123 			}
       
   124 			default:
       
   125 				// no thread table in this draw mode
       
   126 				return;
       
   127 		}
       
   128 
       
   129 		// create the table viewer
       
   130 		this.tableViewer = CheckboxTableViewer.newCheckList(this.parent,
       
   131   				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
       
   132 
       
   133 		// add the check state handler, label provider and content provider
       
   134 		tableViewer.addCheckStateListener(new SharedCheckHandler());
       
   135 		tableViewer.setLabelProvider(new shownThreadsLabelProvider());
       
   136 		tableViewer.setContentProvider(new shownThreadsContentProvider());
       
   137 		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
       
   138 			public void selectionChanged(SelectionChangedEvent arg0) {
       
   139 				if (copyAction == null)
       
   140 					return;
       
   141 
       
   142 				// when selection changes, the ability to copy may change
       
   143 				copyAction.setEnabled(table.getSelectionCount() > 0);
       
   144 				PIPageEditor.getActionBars().updateActionBars();
       
   145 			}
       
   146 		});
       
   147 
       
   148 		createDefaultActions();
       
   149 		
       
   150 		// make sure the table viewer has a sorter
       
   151 		if (this.sorter == null)
       
   152 			this.sorter = new GppTableSorter();
       
   153 
       
   154 		this.table = tableViewer.getTable();
       
   155 		this.table.setRedraw(false);
       
   156 
       
   157 		// give the table a heading for use in copying and exported
       
   158 		this.table.setData(Messages.getString("AddrThreadTable.threads")); //$NON-NLS-1$
       
   159 		
       
   160 		// create the columns
       
   161 		TableColumn column;
       
   162 
       
   163 		// data associated with the TableViewer will note which columns contain hex values
       
   164 		// Keep this in the order in which columns have been created
       
   165 		// Includes the priority column
       
   166 		boolean[] isHex = {false, false, false, false, false};
       
   167 		this.table.setData("isHex", isHex); //$NON-NLS-1$
       
   168 
       
   169 		// select/deselect column
       
   170 		column = new TableColumn(table, SWT.CENTER);
       
   171 		column.setText(COLUMN_HEAD_SHOW);
       
   172 		column.setWidth(COLUMN_WIDTH_SHOW);
       
   173 		column.setData(new Integer(COLUMN_ID_SHOW));
       
   174 		column.setMoveable(true);
       
   175 		column.setResizable(true);
       
   176 		column.addSelectionListener(new ColumnSelectionHandler());
       
   177 
       
   178 		// percent load column
       
   179 		column = new TableColumn(table, SWT.RIGHT);
       
   180 		column.setText(COLUMN_HEAD_PERCENT_LOAD);
       
   181 		column.setWidth(COLUMN_WIDTH_PERCENT_LOAD);
       
   182 		column.setData(new Integer(COLUMN_ID_PERCENT_LOAD));
       
   183 		column.setMoveable(true);
       
   184 		column.setResizable(true);
       
   185 		column.addSelectionListener(new ColumnSelectionHandler());
       
   186 
       
   187 		// thread name column
       
   188 		column = new TableColumn(table, SWT.LEFT);
       
   189 		column.setText(COLUMN_HEAD_THREAD);
       
   190 		column.setWidth(COLUMN_WIDTH_THREAD_NAME);
       
   191 		column.setData(new Integer(COLUMN_ID_THREAD));
       
   192 		column.setMoveable(true);
       
   193 		column.setResizable(true);
       
   194 		column.addSelectionListener(new ColumnSelectionHandler());
       
   195 
       
   196 		// sample count column
       
   197 		column = new TableColumn(table, SWT.CENTER);
       
   198 		column.setText(COLUMN_HEAD_SAMPLE_COUNT);
       
   199 		column.setWidth(COLUMN_WIDTH_SAMPLE_COUNT);
       
   200 		column.setData(new Integer(COLUMN_ID_SAMPLE_COUNT));
       
   201 		column.setMoveable(true);
       
   202 		column.setResizable(true);
       
   203 		column.addSelectionListener(new ColumnSelectionHandler());
       
   204 
       
   205 		// priority column
       
   206 		if (priorityAdded)
       
   207 			this.addPriorityColumn();
       
   208 
       
   209 		// listen for mouse clicks: to select a row, pop up a menu, etc.
       
   210 		table.addMouseListener(new TableMouseListener());
       
   211 
       
   212 		// listen for key sequences such as Ctrl-A and Ctrl-C
       
   213 		table.addKeyListener(new TableKeyListener());
       
   214 		
       
   215 		table.addFocusListener(new AddrTableFocusListener());
       
   216 		
       
   217 		// add form data in case later we add a sash to the right
       
   218 		FormData viewerData = new FormData();
       
   219 		viewerData.top    = new FormAttachment(0);
       
   220 		viewerData.bottom = new FormAttachment(100);
       
   221 		viewerData.left   = new FormAttachment(0);
       
   222 		viewerData.right  = new FormAttachment(100);
       
   223 		table.setLayoutData(viewerData);
       
   224 		table.setLayout(new FormLayout());
       
   225 
       
   226 		table.setHeaderVisible(true);
       
   227 		table.setLinesVisible(true);
       
   228 		table.setRedraw(true);
       
   229 	}
       
   230 
       
   231 	public void setTableViewer(CheckboxTableViewer tableViewer)
       
   232 	{
       
   233 		this.tableViewer = tableViewer;
       
   234 
       
   235 		if (tableViewer == null)
       
   236 			this.table = null;
       
   237 	}
       
   238 
       
   239 	public void setTableViewer(int drawMode)
       
   240 	{
       
   241 		if (this.parent == null)
       
   242 			return;
       
   243 
       
   244 		createTableViewer(drawMode);
       
   245 
       
   246 		// sort by percent load
       
   247 		this.sortColumn = COLUMN_ID_SAMPLE_COUNT;
       
   248 		this.sortAscending = false;
       
   249 
       
   250 		// profiledThreads and tableItemData contain one entry per table row
       
   251 		updateProfiledAndItemData(false);
       
   252 		quickSort(sortColumn, profiledThreads);
       
   253 
       
   254 		// initially, all rows are checked
       
   255 		this.tableViewer.setAllChecked(true);
       
   256 	}
       
   257 
       
   258 	public void refreshTableViewer()
       
   259 	{
       
   260 		if (this.tableViewer == null)
       
   261 			return;
       
   262 
       
   263 		this.tableViewer.setInput(tableItemData);
       
   264 		
       
   265 		addColor(this.myGraph.getDrawMode());
       
   266 	}
       
   267 	
       
   268 	public void addColor(int drawMode)
       
   269 	{
       
   270 		if (this.tableViewer == null)
       
   271 			return;
       
   272 
       
   273 		// make sure that this table's colors are being shown
       
   274 		if (   (drawMode != Defines.THREADS)
       
   275 			&& (drawMode != Defines.BINARIES_THREADS)
       
   276 			&& (drawMode != Defines.BINARIES_FUNCTIONS_THREADS)
       
   277 			&& (drawMode != Defines.FUNCTIONS_THREADS)
       
   278 			&& (drawMode != Defines.FUNCTIONS_BINARIES_THREADS))
       
   279 			return;
       
   280 
       
   281 		ProfiledGeneric pGeneric;
       
   282 
       
   283 		TableItem[] items = this.table.getItems();
       
   284 
       
   285 		for (int i = 0; i < items.length; i++) {
       
   286 			pGeneric = (ProfiledGeneric) items[i].getData();
       
   287 //			Color color = ((GppTrace)this.myGraph.getTrace()).getThreadColorPalette().getColor(pGeneric.getNameString());
       
   288 			items[i].setBackground(COLOR_COLUMN_INDEX, pGeneric.getColor());
       
   289 		}
       
   290 
       
   291 		table.redraw();
       
   292 	}
       
   293 	
       
   294 	public void removeColor(int drawMode)
       
   295 	{
       
   296 		if (this.tableViewer == null)
       
   297 			return;
       
   298 
       
   299 		// make sure that this table's colors should not be shown
       
   300 		if (   (drawMode == Defines.THREADS)
       
   301 			|| (drawMode == Defines.BINARIES_THREADS)
       
   302 			|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
       
   303 			|| (drawMode == Defines.FUNCTIONS_THREADS)
       
   304 			|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS))
       
   305 			return;
       
   306 
       
   307 		TableItem[] items = this.table.getItems();
       
   308 
       
   309 		for (int i = 0; i < items.length; i++) {
       
   310 			items[i].setBackground(COLOR_COLUMN_INDEX, this.parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
       
   311 		}
       
   312 
       
   313 		table.redraw();
       
   314 	}
       
   315 
       
   316 	private static class shownThreadsContentProvider implements IStructuredContentProvider {
       
   317 
       
   318 		public shownThreadsContentProvider() {
       
   319 			super();
       
   320 		}
       
   321 
       
   322 		public Object[] getElements(Object inputElement) {
       
   323 			return ((Vector) inputElement).toArray();
       
   324 		}
       
   325 
       
   326 		public void dispose() {
       
   327 		}
       
   328 
       
   329 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
       
   330 		}
       
   331 	}
       
   332 
       
   333 	private class shownThreadsLabelProvider extends LabelProvider implements ITableLabelProvider {
       
   334 
       
   335         public shownThreadsLabelProvider() {
       
   336 			super();
       
   337 		}
       
   338 
       
   339 		public String getColumnText(Object element, int columnIndex) {
       
   340 
       
   341 			int graphIndex = myGraph.getGraphIndex();
       
   342 	        int columnId = ((Integer) table.getColumn(columnIndex).getData()).intValue();
       
   343 
       
   344 			if (element instanceof ProfiledThreshold) {
       
   345 				ProfiledThreshold pThreshold = (ProfiledThreshold) element;
       
   346 
       
   347 				switch (columnId)
       
   348 				{
       
   349 					case COLUMN_ID_SHOW:
       
   350 					{
       
   351 						return SHOW_ITEM_VALUE;
       
   352 					}
       
   353 					case COLUMN_ID_PERCENT_LOAD:
       
   354 					{
       
   355 						// Percent load string
       
   356 						double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
   357 						double endTime   = PIPageEditor.currentPageEditor().getEndTime();
       
   358 						if (   (startTime == -1)
       
   359 							|| (endTime   == -1)
       
   360 							|| (startTime == endTime)) {
       
   361 							pThreshold.setAverageLoadValueString(graphIndex, ""); //$NON-NLS-1$
       
   362 						} else {
       
   363 							float load = (float) (pThreshold.getSampleCount(graphIndex)/(endTime - startTime)/10.0);
       
   364 							
       
   365 							if (load < 0.005)
       
   366 								pThreshold.setAverageLoadValueString(graphIndex, Messages.getString("AddrThreadTable.zeroFormat")); //$NON-NLS-1$
       
   367 							else
       
   368 								pThreshold.setAverageLoadValueString(graphIndex, load);
       
   369 						}
       
   370 						return pThreshold.getAverageLoadValueString(graphIndex);
       
   371 					}
       
   372 					case COLUMN_ID_THREAD:
       
   373 					{
       
   374 						DecimalFormat timeFormat = new DecimalFormat(Messages.getString("AddrThreadTable.decimalFormat")); //$NON-NLS-1$
       
   375 
       
   376 						int count = pThreshold.getItemCount(graphIndex);
       
   377 
       
   378 						return count + (count > 1 ? Messages.getString("AddrThreadTable.thresholdMsg1") : Messages.getString("AddrThreadTable.thresholdMsg2"))   //$NON-NLS-1$ //$NON-NLS-2$
       
   379 								+ timeFormat.format((Double)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadThread") * 100.0) + Messages.getString("AddrThreadTable.thresholdMsg3") //$NON-NLS-1$ //$NON-NLS-2$ 
       
   380 								+ (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread") + Messages.getString("AddrThreadTable.thresholdMsg4"); //$NON-NLS-1$ //$NON-NLS-2$ 
       
   381 					}
       
   382 					case COLUMN_ID_SAMPLE_COUNT:
       
   383 					{
       
   384 						// Sample count
       
   385 						return String.valueOf(pThreshold.getSampleCount(graphIndex));
       
   386 					}
       
   387 					default:
       
   388 					{
       
   389 						return ""; //$NON-NLS-1$
       
   390 					}
       
   391 				}
       
   392 			}
       
   393 
       
   394 			if (!(element instanceof ProfiledThread))
       
   395 				return ""; //$NON-NLS-1$
       
   396 
       
   397 			ProfiledThread profiledItem = (ProfiledThread) element;
       
   398 
       
   399 			switch (columnId)
       
   400 			{
       
   401 				case COLUMN_ID_SHOW:
       
   402 				{
       
   403 					return SHOW_ITEM_VALUE;
       
   404 				}
       
   405 				case COLUMN_ID_PERCENT_LOAD:
       
   406 				{
       
   407 					// Percent load string
       
   408 					return profiledItem.getAverageLoadValueString(graphIndex);
       
   409 				}
       
   410 				case COLUMN_ID_THREAD:
       
   411 				{
       
   412 					// Thread
       
   413 					if (profiledItem.getNameString().startsWith("*Native*")) //$NON-NLS-1$
       
   414 						return Messages.getString("AddrThreadTable.NOSthreads"); //$NON-NLS-1$
       
   415 					else
       
   416 						return profiledItem.getNameString();
       
   417 				}
       
   418 				case COLUMN_ID_SAMPLE_COUNT:
       
   419 				{
       
   420 					// Sample count
       
   421 					return String.valueOf(profiledItem.getSampleCount(graphIndex));
       
   422 				}
       
   423 				case COLUMN_ID_PRIORITY:
       
   424 			    {
       
   425 					if (priorityAdded) {
       
   426 				        String priority = priorityTable.get(new Integer(profiledItem.getThreadId()));
       
   427 				        if (priority == null)
       
   428 				        	return Messages.getString("AddrThreadTable.unknownPriority"); //$NON-NLS-1$
       
   429 				        else
       
   430 				        	return priority;
       
   431 					}
       
   432 					return ""; //$NON-NLS-1$
       
   433 			    }
       
   434 				default:
       
   435 				{
       
   436 					break;
       
   437 				}
       
   438 			}
       
   439 			// should never get here
       
   440 			return ""; //$NON-NLS-1$
       
   441 		}
       
   442 
       
   443 		public Image getColumnImage(Object element, int columnIndex) {
       
   444 			return null;
       
   445 		}
       
   446 	}
       
   447 
       
   448     public void action(String actionString)
       
   449 	{
       
   450 		int graphIndex = this.myGraph.getGraphIndex();
       
   451 
       
   452 		if (   actionString.equals("add") //$NON-NLS-1$
       
   453 			|| actionString.equals("remove")) //$NON-NLS-1$
       
   454 	    {
       
   455 			actionAddRemove(actionString, graphIndex);
       
   456 			return;
       
   457 	    }
       
   458 		else if (   actionString.equals("addall") //$NON-NLS-1$
       
   459 				 || actionString.equals("removeall")) //$NON-NLS-1$
       
   460 	    {
       
   461 			actionAddRemoveAll(actionString, graphIndex);
       
   462 			return;
       
   463 	    }
       
   464 		else if (actionString.equals("recolor")) //$NON-NLS-1$
       
   465 		{
       
   466 			actionRecolor();
       
   467 			return;
       
   468 		}
       
   469 	    else if (actionString.equals("copy")) //$NON-NLS-1$
       
   470 	    {
       
   471 	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   472 	        return;
       
   473 	    }
       
   474 	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
       
   475 	    {
       
   476 	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   477 	        return;
       
   478 	    }
       
   479 	    else if (actionString.equals("copyDrilldown")) //$NON-NLS-1$
       
   480 	    {
       
   481 	    	actionCopyOrSaveDrilldown(true, "\t"); //$NON-NLS-1$
       
   482 	        return;
       
   483 	    }
       
   484 	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
       
   485 	    {
       
   486 	    	actionCopyOrSave(false, this.table, CHECKBOX_NO_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   487 	        return;
       
   488 	    }
       
   489 	    else if (actionString.equals("saveDrilldown")) //$NON-NLS-1$
       
   490 	    {
       
   491 	    	actionCopyOrSaveDrilldown(false, ","); //$NON-NLS-1$
       
   492 	        return;
       
   493 	    }
       
   494 	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
       
   495 	    {
       
   496 	    	SaveSampleString saveSampleString = new SaveSampleString(graphIndex, myGraph.getDrawMode());
       
   497 	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
       
   498 	        return;
       
   499 	    }
       
   500 	    else if (actionString.equals("savePrioritySamples")) //$NON-NLS-1$
       
   501 	    {
       
   502 	    	SavePrioritySampleString saveSampleString = new SavePrioritySampleString(graphIndex, myGraph.getDrawMode());
       
   503 	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
       
   504 	        return;
       
   505 	    }
       
   506 		else if (actionString.equals("selectAll")) //$NON-NLS-1$
       
   507 	    {
       
   508 	    	actionSelectAll();
       
   509 	        return;
       
   510 	    }
       
   511 		else if (actionString.equals("doubleClick")) //$NON-NLS-1$
       
   512 	    {
       
   513 	    	copyAction.setEnabled(false);
       
   514 			PIPageEditor.getActionBars().updateActionBars();
       
   515 	        return;
       
   516 	    }
       
   517 		else if (actionString.equals("thread-only")) //$NON-NLS-1$
       
   518 		{
       
   519 			actionThread();
       
   520 			return;
       
   521 		}
       
   522 		else if (actionString.equals("thread-binary")) //$NON-NLS-1$
       
   523 		{
       
   524 			actionThreadBinary();
       
   525 			return;
       
   526 		}
       
   527 		else if (actionString.equals("thread-binary-function")) //$NON-NLS-1$
       
   528 		{
       
   529 			actionThreadBinaryFunction();
       
   530 			return;
       
   531 		}
       
   532 		else if (actionString.equals("thread-function")) //$NON-NLS-1$
       
   533 		{
       
   534 			actionThreadFunction();
       
   535 			return;
       
   536 		}
       
   537 		else if (actionString.equals("thread-function-binary")) //$NON-NLS-1$
       
   538 		{
       
   539 			actionThreadFunctionBinary();
       
   540 			return;
       
   541 		}
       
   542 		else if (   (actionString.equals("binary-only")) //$NON-NLS-1$
       
   543 				 || (actionString.equals("binary-thread")) //$NON-NLS-1$
       
   544 				 || (actionString.equals("binary-thread-function")) //$NON-NLS-1$
       
   545 				 || (actionString.equals("binary-function")) //$NON-NLS-1$
       
   546 				 || (actionString.equals("binary-function-thread"))) //$NON-NLS-1$
       
   547 		{
       
   548 			// let the binary page action handler handle it
       
   549 			this.myGraph.getBinaryTable().action(actionString);
       
   550 			return;
       
   551 		}
       
   552 		else if (   (actionString.equals("function-only")) //$NON-NLS-1$
       
   553 				 || (actionString.equals("function-thread")) //$NON-NLS-1$
       
   554 				 || (actionString.equals("function-thread-binary")) //$NON-NLS-1$
       
   555 				 || (actionString.equals("function-binary")) //$NON-NLS-1$
       
   556 				 || (actionString.equals("function-binary-thread"))) //$NON-NLS-1$
       
   557 		{
       
   558 			// let the function page action handler handle it
       
   559 			this.myGraph.getFunctionTable().action(actionString);
       
   560 			return;
       
   561 		}
       
   562 		else if (actionString.equals("changeThresholdThread")) //$NON-NLS-1$
       
   563 		{
       
   564 			ProfiledThreshold threshold = this.myGraph.getThresholdThread();
       
   565 			boolean enabled = threshold.isEnabled(graphIndex);
       
   566 
       
   567 			this.tableItemData.clear();
       
   568 			this.profiledThreads.clear();
       
   569 			this.myGraph.getSortedThreads().clear();
       
   570 			if (threshold.getItems(graphIndex) != null)
       
   571 				threshold.getItems(graphIndex).clear();
       
   572 			threshold.initAll();
       
   573 
       
   574 			// if this appears, it needs to be the first item, so that it is drawn at the bottom
       
   575 			myGraph.getSortedThreads().add(threshold);
       
   576 
       
   577 			int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
       
   578 			for (int i = 0; i < this.myGraph.getGppTrace().getSortedThreads().size(); i++) {
       
   579 				ProfiledGeneric nextElement = (ProfiledGeneric)this.myGraph.getGppTrace().getSortedThreads().get(i);
       
   580 				if (nextElement.getTotalSampleCount() < threadThreshold) {
       
   581 					nextElement.setEnabled(graphIndex, enabled);
       
   582 					threshold.addItem(graphIndex, nextElement, 0);
       
   583 				} else {
       
   584 					tableItemData.add(nextElement);
       
   585 					profiledThreads.add(nextElement);
       
   586 					myGraph.getSortedThreads().add(nextElement);
       
   587 				}
       
   588 			}
       
   589 
       
   590 			if (threshold.getItemCount(graphIndex) != 0) {
       
   591 				tableItemData.add(threshold);
       
   592 				profiledThreads.add(threshold);
       
   593 			} else {
       
   594 				// remove the threshold item
       
   595 				myGraph.getSortedThreads().remove(0);
       
   596 			}
       
   597 			
       
   598 			refreshTableViewer();
       
   599 			threshold.setEnabled(graphIndex, enabled);
       
   600 			
       
   601 			// make sure that checkboxes shown reflect the actual enabled values
       
   602 			TableItem[] tableItems = this.table.getItems();
       
   603 			for (int i = 0; i < tableItems.length; i++) {
       
   604 				if (tableItems[i].getData() instanceof ProfiledGeneric) {
       
   605 					ProfiledGeneric pGeneric = (ProfiledGeneric) tableItems[i].getData();
       
   606 					if (tableItems[i].getChecked() != pGeneric.isEnabled(graphIndex))
       
   607 						tableItems[i].setChecked(pGeneric.isEnabled(graphIndex));
       
   608 				}
       
   609 			}
       
   610 
       
   611 			this.myGraph.genericRefreshCumulativeThreadTable();
       
   612 		}
       
   613 	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
       
   614 	    {
       
   615 			// copy save file contents to the clipboard for easy viewing
       
   616 	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
       
   617 			SaveTableString getString = new SaveTableString(this.table, CHECKBOX_NO_TEXT, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   618 	        String copyString = getString.getData();
       
   619 			StringSelection contents = new StringSelection(copyString);
       
   620 	        cb.setContents(contents, contents);
       
   621 	        return;
       
   622 	    }
       
   623 	    else if (actionString.equals("saveDrilldownTest")) //$NON-NLS-1$
       
   624 	    {
       
   625 			// copy save file contents to the clipboard for easy viewing
       
   626 	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
       
   627 	        Table[] tables = getDrillDownTables();
       
   628 	        
       
   629 	        int tableCount = 0;
       
   630 	        while (tableCount < tables.length && tables[tableCount] != null)
       
   631 	        	tableCount++;
       
   632 
       
   633 	        SaveDrillDownString getString = new SaveDrillDownString(tableCount, tables, ","); //$NON-NLS-1$
       
   634 	        String copyString = getString.getData();
       
   635 			StringSelection contents = new StringSelection(copyString);
       
   636 	        cb.setContents(contents, contents);
       
   637 	        return;
       
   638 	    }
       
   639 	}
       
   640 
       
   641 	private void actionAddRemove(String actionString, int graphIndex)
       
   642 	{
       
   643 		ProfiledGeneric pGeneric;
       
   644 		int totalSamples = 0;
       
   645 		
       
   646 		// true for "add", false for "remove"
       
   647 		boolean addIt = actionString.equals("add"); //$NON-NLS-1$
       
   648 
       
   649 		TableItem[] selectedItems = this.table.getSelection();
       
   650 		for (int i = 0; i < selectedItems.length; i++)
       
   651 		{
       
   652 			selectedItems[i].setChecked(addIt);
       
   653 			Object item = ((TableItem)selectedItems[i]).getData();
       
   654 			if (item instanceof ProfiledGeneric)
       
   655 			{
       
   656 				pGeneric = (ProfiledGeneric)item;
       
   657 				pGeneric.setEnabled(graphIndex, addIt);
       
   658 				totalSamples += pGeneric.getSampleCount(graphIndex);
       
   659    				
       
   660    				if (item instanceof ProfiledThreshold)
       
   661    				{
       
   662    					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
       
   663    					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
       
   664    					for (int j = 0; j < items.size(); j++)
       
   665    						items.get(j).setEnabled(graphIndex, addIt);
       
   666    				}
       
   667 			}
       
   668 		}
       
   669 
       
   670         // this table's set of checkbox-selected rows has changed,
       
   671 		// so propagate that information
       
   672 		Object[] selectedValues = this.tableViewer.getCheckedElements();
       
   673 		String[] nameList = new String[selectedValues.length];
       
   674 
       
   675 		for (int i = 0; i < selectedValues.length; i++)
       
   676 		{
       
   677    			if (selectedValues[i] instanceof ProfiledGeneric)
       
   678    			{
       
   679    				pGeneric = (ProfiledGeneric)selectedValues[i];
       
   680    				nameList[i] = pGeneric.getNameString();
       
   681    			}
       
   682 		}
       
   683 
       
   684 		PIVisualSharedData shared = myGraph.getSharedDataInstance();
       
   685 		shared.GPP_SelectedThreadNames = nameList;
       
   686 
       
   687   		if (   (totalSamples != 0)
       
   688       		|| (myGraph.getDrawMode() == Defines.THREADS))
       
   689       			selectionChangeNotify();
       
   690 
       
   691   		this.table.deselectAll();
       
   692 	}
       
   693 	
       
   694 	private void actionAddRemoveAll(String actionString, int graphIndex)
       
   695 	{
       
   696 		ProfiledGeneric pGeneric;
       
   697 
       
   698 		// true for "add", false for "remove"
       
   699 		boolean addIt = actionString.equals("addall"); //$NON-NLS-1$
       
   700 
       
   701 		TableItem[] selectedItems = this.table.getItems();
       
   702 		String[] nameList = new String[selectedItems.length];
       
   703 		for (int i = 0; i < selectedItems.length; i++)
       
   704 		{
       
   705 			selectedItems[i].setChecked(addIt);
       
   706 			Object item = ((TableItem)selectedItems[i]).getData();
       
   707 			if (item instanceof ProfiledGeneric)
       
   708 			{
       
   709 				pGeneric = (ProfiledGeneric)item;
       
   710 				pGeneric.setEnabled(graphIndex, addIt);
       
   711    				nameList[i] = pGeneric.getNameString();
       
   712    				
       
   713    				if (item instanceof ProfiledThreshold)
       
   714    				{
       
   715    					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
       
   716    					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
       
   717    					for (int j = 0; j < items.size(); j++)
       
   718    						items.get(j).setEnabled(graphIndex, addIt);
       
   719    				}
       
   720 			}
       
   721 		}
       
   722 
       
   723         // this table's set of checkbox-selected rows has changed,
       
   724 		// so propagate that information
       
   725 		PIVisualSharedData shared = myGraph.getSharedDataInstance();
       
   726 		shared.GPP_SelectedThreadNames = nameList;
       
   727 
       
   728 			selectionChangeNotify();
       
   729   		this.table.deselectAll();
       
   730 	}
       
   731 	
       
   732 	private void actionRecolor()
       
   733 	{
       
   734 		int uid 			= this.myGraph.getUid();
       
   735 		GppTrace gppTrace = this.myGraph.getGppTrace();
       
   736 
       
   737 		// recolor selected items
       
   738 		boolean didRecolor = false;
       
   739 
       
   740 		TableItem[] selectedItems = table.getSelection();
       
   741 		for (int i = 0; i < selectedItems.length;i++)
       
   742 		{
       
   743 			if (selectedItems[i].getData() instanceof ProfiledGeneric)
       
   744 			{
       
   745 				ProfiledGeneric pGeneric = (ProfiledGeneric)selectedItems[i].getData();
       
   746 				TableColorPalette palette = ((GppTrace)this.myGraph.getTrace()).getThreadColorPalette();
       
   747 				String nameKey = pGeneric.getNameString();
       
   748 				if (palette.recolorEntryDialog(table.getShell(), nameKey))
       
   749 				{
       
   750 					Color color = palette.getColor(nameKey);
       
   751 					Color oldColor = pGeneric.getColor();
       
   752 					
       
   753 					if (color.equals(oldColor))
       
   754 						continue;
       
   755 					
       
   756 					didRecolor = true;
       
   757 					
       
   758 					if (!(pGeneric instanceof ProfiledThreshold)) {
       
   759 						PIPageEditor.currentPageEditor().setDirty();
       
   760 						pGeneric.setColor(color);
       
   761 					} else {
       
   762 						// for the threshold item, we must change every graph's thread threshold item
       
   763 						gppTrace.getGppGraph(PIPageEditor.THREADS_PAGE,   uid).getThresholdThread().setColor(color);
       
   764 						gppTrace.getGppGraph(PIPageEditor.BINARIES_PAGE,  uid).getThresholdThread().setColor(color);
       
   765 						gppTrace.getGppGraph(PIPageEditor.FUNCTIONS_PAGE, uid).getThresholdThread().setColor(color);
       
   766 					}
       
   767 				}
       
   768 
       
   769 				// recoloring should only be done in a draw mode that displays this table's colors
       
   770 				selectedItems[i].setBackground(COLOR_COLUMN_INDEX, palette.getColor(nameKey));
       
   771 			}
       
   772 		}
       
   773 		
       
   774 		if (!didRecolor)
       
   775 			return;
       
   776 
       
   777 		table.redraw();
       
   778 		this.myGraph.repaint();
       
   779 		this.myGraph.setGraphImageChanged(true);	// any selection change to drill down will change graph
       
   780 		
       
   781 		// if any other tabs are displaying this type of graph, they need to be scheduled for redrawing
       
   782 		for (int i = 0; i < 3; i++) {
       
   783 			GppTraceGraph graph = gppTrace.getGppGraph(i, uid);
       
   784 
       
   785 			if (graph == this.myGraph)
       
   786 				continue;
       
   787 
       
   788 			int drawMode = graph.getDrawMode();
       
   789 			
       
   790 			if (   (drawMode == Defines.THREADS)
       
   791 				|| (drawMode == Defines.BINARIES_THREADS)
       
   792 				|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
       
   793 				|| (drawMode == Defines.FUNCTIONS_THREADS)
       
   794 				|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS)) {
       
   795 				graph.getThreadTable().addColor(drawMode);
       
   796 				graph.setGraphImageChanged(true);	// any selection change to drill down will change graph
       
   797 				graph.repaint();
       
   798 			}
       
   799 		}
       
   800 	}
       
   801 
       
   802 	private void actionThread()
       
   803 	{
       
   804 		// current drawMode should be THREADS, THREADS_BINARIES, THREADS_BINARIES_FUNCTIONS,
       
   805 		// THREADS_FUNCTIONS, or THREADS_FUNCTIONS_BINARIES
       
   806 		int drawMode = this.myGraph.getDrawMode();
       
   807 
       
   808 		if (   (drawMode != Defines.THREADS_BINARIES)
       
   809 			&& (drawMode != Defines.THREADS_BINARIES_FUNCTIONS)
       
   810 			&& (drawMode != Defines.THREADS_FUNCTIONS)
       
   811 			&& (drawMode != Defines.THREADS_FUNCTIONS_BINARIES))
       
   812 		{
       
   813 			// this case should be drawMode == Defines.THREADS
       
   814 			return;
       
   815 		}
       
   816 		
       
   817 		setIsDrilldown(false);
       
   818 
       
   819 		// set the page's graph title
       
   820 		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
   821 		pV.getTitle().setText(Messages.getString("AddrThreadTable.threadLoad")); //$NON-NLS-1$
       
   822 		pV.getTitle2().setText(""); //$NON-NLS-1$
       
   823 
       
   824 		// get rid of any existing tables and sashes
       
   825 		if (this.myGraph.getLeftSash() != null) {
       
   826 			this.myGraph.getLeftSash().dispose();
       
   827 			this.myGraph.setLeftSash(null);
       
   828 
       
   829 			// detach the table from the sash
       
   830 			try {
       
   831 				FormData formData = (FormData) this.table.getLayoutData();
       
   832 				formData.right = new FormAttachment(100);
       
   833 			} catch (ClassCastException e1) {
       
   834 			}
       
   835 		}
       
   836 		if (this.myGraph.getRightSash() != null) {
       
   837 			this.myGraph.getRightSash().dispose();
       
   838 			this.myGraph.setRightSash(null);
       
   839 		}
       
   840 		if (   (this.myGraph.getBinaryTable() != null)
       
   841 			&& (this.myGraph.getBinaryTable().getTable() != null)) {
       
   842 			this.myGraph.getBinaryTable().getTableViewer().getTable().dispose();
       
   843 			this.myGraph.getBinaryTable().setTableViewer(null);
       
   844 		}
       
   845 		if (   (this.myGraph.getFunctionTable() != null)
       
   846 			&& (this.myGraph.getFunctionTable().getTable() != null)) {
       
   847 			this.myGraph.getFunctionTable().getTableViewer().getTable().dispose();
       
   848 			this.myGraph.getFunctionTable().setTableViewer(null);
       
   849 		}
       
   850 
       
   851 		// set the draw mode
       
   852 		this.myGraph.setDrawMode(Defines.THREADS);
       
   853 
       
   854 		// add colors to the rightmost table
       
   855 		addColor(Defines.THREADS);
       
   856 
       
   857 		this.parent.layout();
       
   858 
       
   859 		this.myGraph.repaint();
       
   860 	}
       
   861 
       
   862 	private void actionThreadBinary()
       
   863 	{
       
   864 		// current drawMode should be THREADS, THREADS_BINARIES, or THREADS_BINARIES_FUNCTIONS
       
   865 		int drawMode = this.myGraph.getDrawMode();
       
   866 		int graphIndex = this.myGraph.getGraphIndex();
       
   867 
       
   868 		if (   drawMode != Defines.THREADS
       
   869 			&& drawMode != Defines.THREADS_BINARIES_FUNCTIONS) {
       
   870 			return;
       
   871 		}
       
   872 		
       
   873 		setIsDrilldown(true);
       
   874 
       
   875 		if (drawMode == Defines.THREADS) {
       
   876 			// set the page's graph title
       
   877 			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
   878 			pV.getTitle().setText(Messages.getString("AddrThreadTable.binaryLoad")); //$NON-NLS-1$
       
   879 			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
       
   880 
       
   881 			// set the draw mode before populating table viewers, since the
       
   882 			// color column depends on the draw mode
       
   883 			this.myGraph.setDrawMode(Defines.THREADS_BINARIES);
       
   884 
       
   885 			// create the binary graph table viewer
       
   886 			AddrBinaryTable binaryTable = this.myGraph.getBinaryTable();
       
   887 			binaryTable.createTableViewer(Defines.THREADS_BINARIES);
       
   888 			binaryTable.setIsDrilldown(true);
       
   889 
       
   890 			// create a reduced set of binary entries based on enabled thread entries
       
   891 			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
       
   892 			Vector<ProfiledGeneric> binaries = gppTrace.setThreadBinary(graphIndex);
       
   893 			this.myGraph.setProfiledBinaries(binaries);
       
   894 
       
   895 			// put check marks on all rows, and sort by sample count
       
   896 			binaryTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledBinaries());
       
   897 			binaryTable.updateProfiledAndItemData(true);
       
   898 			binaryTable.getTableViewer().setAllChecked(true);
       
   899 			binaryTable.getTableViewer().refresh();
       
   900 
       
   901 			// put check marks on all enabled thread rows
       
   902 			for (int i = 0; i < this.table.getItemCount(); i++) {
       
   903 				ProfiledGeneric pThread = (ProfiledGeneric) this.table.getItem(i).getData();
       
   904 				if (pThread.isEnabled(graphIndex))
       
   905 					this.table.getItem(i).setChecked(true);
       
   906 			}
       
   907 			
       
   908 			// remove colors where appropriate
       
   909 			removeColor(Defines.THREADS_BINARIES);
       
   910 
       
   911 			// connect the tables with a sash
       
   912 			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
       
   913 
       
   914 			final FormData leftSashData = new FormData();
       
   915 			leftSashData.top    = new FormAttachment(0);
       
   916 			leftSashData.bottom = new FormAttachment(100);
       
   917 			leftSashData.left   = new FormAttachment(50); // middle
       
   918 			leftSash.setLayoutData(leftSashData);
       
   919 
       
   920 			final Composite sashParent = this.parent;
       
   921 			leftSash.addListener(SWT.Selection, new Listener() {
       
   922 				public void handleEvent(Event event) {
       
   923 					if (event.detail != SWT.DRAG) {
       
   924 						leftSashData.left = new FormAttachment(0, event.x);
       
   925 						sashParent.layout();
       
   926 					}
       
   927 				}
       
   928 			});
       
   929 
       
   930 			myGraph.setLeftSash(leftSash);
       
   931 
       
   932 			// attach the binary table to the sash
       
   933 			final FormData viewerData = new FormData();
       
   934 			viewerData.top    = new FormAttachment(0);
       
   935 			viewerData.bottom = new FormAttachment(100);
       
   936 			viewerData.left   = new FormAttachment(leftSash);
       
   937 			viewerData.right  = new FormAttachment(100);
       
   938 			binaryTable.getTable().setLayoutData(viewerData);
       
   939 
       
   940 			// attach the thread table to the sash
       
   941 			try {
       
   942 				FormData formData = (FormData) this.table.getLayoutData();
       
   943 				formData.right = new FormAttachment(leftSash);
       
   944 			} catch (ClassCastException e1) {
       
   945 			}
       
   946 
       
   947 			this.parent.layout();
       
   948 
       
   949 			this.myGraph.repaint();
       
   950 
       
   951 		} else if (drawMode == Defines.THREADS_BINARIES_FUNCTIONS) {
       
   952 			// set the page's graph title
       
   953 			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
   954 			pV.getTitle().setText(Messages.getString("AddrThreadTable.binaryLoad")); //$NON-NLS-1$
       
   955 			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
       
   956 
       
   957 			// get rid of the function table and its sash
       
   958 			if (this.myGraph.getRightSash() != null) {
       
   959 				this.myGraph.getRightSash().dispose();
       
   960 				this.myGraph.setRightSash(null);
       
   961 			}
       
   962 			if (   (this.myGraph.getFunctionTable() != null)
       
   963 				&& (this.myGraph.getFunctionTable().getTable() != null)) {
       
   964 				this.myGraph.getFunctionTable().getTableViewer().getTable().dispose();
       
   965 				this.myGraph.getFunctionTable().setTableViewer(null);
       
   966 			}
       
   967 
       
   968 			// get rid of the middle table's connection to the sash
       
   969 			try {
       
   970 				FormData formData = (FormData) this.myGraph.getBinaryTable().getTable().getLayoutData();
       
   971 				formData.right = new FormAttachment(100);
       
   972 			} catch (ClassCastException e1) {
       
   973 			}
       
   974 
       
   975 			// move the left sash to the middle
       
   976 			try {
       
   977 				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
       
   978 				formData.left = new FormAttachment(50); // middle
       
   979 			} catch (ClassCastException e1) {
       
   980 			}
       
   981 
       
   982 			// set the draw mode
       
   983 			this.myGraph.setDrawMode(Defines.THREADS_BINARIES);
       
   984 
       
   985 			// show colors in the rightmost table
       
   986 			this.myGraph.getBinaryTable().addColor(Defines.THREADS_BINARIES);
       
   987 
       
   988 			this.parent.layout();
       
   989 
       
   990 			this.myGraph.repaint();
       
   991 		}
       
   992 
       
   993 		// this case should be drawMode == Defines.THREADS_BINARIES
       
   994 		return;
       
   995 	}
       
   996 
       
   997 	private void actionThreadBinaryFunction()
       
   998 	{
       
   999 		// current drawMode should be THREADS_BINARIES or THREADS_BINARIES_FUNCTIONS
       
  1000 		int drawMode = this.myGraph.getDrawMode();
       
  1001 		int graphIndex = this.myGraph.getGraphIndex();
       
  1002 
       
  1003 		if (drawMode != Defines.THREADS_BINARIES) {
       
  1004 			// this case should be drawMode == Defines.THREADS_BINARIES_FUNCTIONS
       
  1005 			return;
       
  1006 		}
       
  1007 
       
  1008 		setIsDrilldown(true);
       
  1009 
       
  1010 		// set the page's graph title
       
  1011 		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
  1012 		pV.getTitle().setText(Messages.getString("AddrThreadTable.functionLoad")); //$NON-NLS-1$
       
  1013 		pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadToBinaryTo")); //$NON-NLS-1$
       
  1014 
       
  1015 		// set the draw mode before populating table viewers, since the
       
  1016 		// color column depends on the draw mode
       
  1017 		this.myGraph.setDrawMode(Defines.THREADS_BINARIES_FUNCTIONS);
       
  1018 
       
  1019 		// create the function graph table viewer
       
  1020 		AddrFunctionTable functionTable = this.myGraph.getFunctionTable();
       
  1021 		functionTable.createTableViewer(Defines.THREADS_BINARIES_FUNCTIONS);
       
  1022 		functionTable.setIsDrilldown(true);
       
  1023 
       
  1024 		// create a reduced set of function entries based on enabled thread and binary entries
       
  1025 		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
       
  1026 		Vector<ProfiledGeneric> functions = gppTrace.setThreadBinaryFunction(graphIndex);
       
  1027 		this.myGraph.setProfiledFunctions(functions);
       
  1028 
       
  1029 		// put check marks on all rows, and sort by sample count
       
  1030 		functionTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledFunctions());
       
  1031 		functionTable.updateProfiledAndItemData(true);
       
  1032 		functionTable.getTableViewer().setAllChecked(true);
       
  1033 		functionTable.getTableViewer().refresh();
       
  1034 
       
  1035 		// remove colors where appropriate
       
  1036 		this.myGraph.getBinaryTable().removeColor(Defines.THREADS_BINARIES_FUNCTIONS);
       
  1037 
       
  1038 		// connect the 2nd and 3rd tables with a sash
       
  1039 		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
       
  1040 
       
  1041 		final FormData rightSashData = new FormData();
       
  1042 		rightSashData.top    = new FormAttachment(0);
       
  1043 		rightSashData.bottom = new FormAttachment(100);
       
  1044 		rightSashData.left   = new FormAttachment(67); // two thirds
       
  1045 		rightSash.setLayoutData(rightSashData);
       
  1046 
       
  1047 		final Composite sashParent = this.parent;
       
  1048 		rightSash.addListener(SWT.Selection, new Listener() {
       
  1049 			public void handleEvent(Event event) {
       
  1050 				if (event.detail != SWT.DRAG) {
       
  1051 					rightSashData.left = new FormAttachment(0, event.x);
       
  1052 					sashParent.layout();
       
  1053 				}
       
  1054 			}
       
  1055 		});
       
  1056 
       
  1057 		myGraph.setRightSash(rightSash);
       
  1058 
       
  1059 		// attach the function table to the sash
       
  1060 		final FormData viewerData = new FormData();
       
  1061 		viewerData.top    = new FormAttachment(0);
       
  1062 		viewerData.bottom = new FormAttachment(100);
       
  1063 		viewerData.left   = new FormAttachment(rightSash);
       
  1064 		viewerData.right  = new FormAttachment(100);
       
  1065 		functionTable.getTable().setLayoutData(viewerData);
       
  1066 
       
  1067 		// attach the binary table to the sash
       
  1068 		try {
       
  1069 			FormData formData = (FormData) this.myGraph.getBinaryTable().getTable().getLayoutData();
       
  1070 			formData.right = new FormAttachment(rightSash);
       
  1071 		} catch (ClassCastException e1) {
       
  1072 		}
       
  1073 
       
  1074 		// move the left sash to 1/3 from the left
       
  1075 		try {
       
  1076 			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
       
  1077 			formData.left = new FormAttachment(33); // one third
       
  1078 		} catch (ClassCastException e1) {
       
  1079 		}
       
  1080 
       
  1081 		this.parent.layout();
       
  1082 
       
  1083 		this.myGraph.repaint();
       
  1084 	}
       
  1085 
       
  1086 	private void actionThreadFunction()
       
  1087 	{
       
  1088 		// current drawMode should be THREADS, THREADS_FUNCTIONS, or THREADS_FUNCTIONS_BINARIES
       
  1089 		int drawMode = this.myGraph.getDrawMode();
       
  1090 		int graphIndex = this.myGraph.getGraphIndex();
       
  1091 
       
  1092 		if (   drawMode != Defines.THREADS
       
  1093 			&& drawMode != Defines.THREADS_FUNCTIONS_BINARIES) {
       
  1094 			return;
       
  1095 		}
       
  1096 
       
  1097 		setIsDrilldown(true);
       
  1098 
       
  1099 		if (drawMode == Defines.THREADS) {
       
  1100 			// set the page's graph title
       
  1101 			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
  1102 			pV.getTitle().setText(Messages.getString("AddrThreadTable.functionLoad")); //$NON-NLS-1$
       
  1103 			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
       
  1104 
       
  1105 			// set the draw mode
       
  1106 			this.myGraph.setDrawMode(Defines.THREADS_FUNCTIONS);
       
  1107 
       
  1108 			// create the function graph table viewer
       
  1109 			AddrFunctionTable functionTable = this.myGraph.getFunctionTable();
       
  1110 			functionTable.createTableViewer(Defines.THREADS_FUNCTIONS);
       
  1111 			functionTable.setIsDrilldown(true);
       
  1112 
       
  1113 			// create a reduced set of function entries based on enabled thread and binary entries
       
  1114 			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
       
  1115 			Vector<ProfiledGeneric> functions = gppTrace.setThreadFunction(graphIndex);
       
  1116 			this.myGraph.setProfiledFunctions(functions);
       
  1117 
       
  1118 			// put check marks on all rows, and sort by sample count
       
  1119 			functionTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledFunctions());
       
  1120 			functionTable.updateProfiledAndItemData(true);
       
  1121 			functionTable.getTableViewer().setAllChecked(true);
       
  1122 			functionTable.getTableViewer().refresh();
       
  1123 
       
  1124 			// remove colors where appropriate
       
  1125 			removeColor(Defines.THREADS_FUNCTIONS);
       
  1126 
       
  1127 			// connect the tables with a sash
       
  1128 			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
       
  1129 
       
  1130 			final FormData leftSashData = new FormData();
       
  1131 			leftSashData.top    = new FormAttachment(0);
       
  1132 			leftSashData.bottom = new FormAttachment(100);
       
  1133 			leftSashData.left   = new FormAttachment(50); // middle
       
  1134 			leftSash.setLayoutData(leftSashData);
       
  1135 
       
  1136 			final Composite sashParent = this.parent;
       
  1137 			leftSash.addListener(SWT.Selection, new Listener() {
       
  1138 				public void handleEvent(Event event) {
       
  1139 					if (event.detail != SWT.DRAG) {
       
  1140 						leftSashData.left = new FormAttachment(0, event.x);
       
  1141 						sashParent.layout();
       
  1142 					}
       
  1143 				}
       
  1144 			});
       
  1145 
       
  1146 			myGraph.setLeftSash(leftSash);
       
  1147 
       
  1148 			// attach the function table to the sash
       
  1149 			final FormData viewerData = new FormData();
       
  1150 			viewerData.top    = new FormAttachment(0);
       
  1151 			viewerData.bottom = new FormAttachment(100);
       
  1152 			viewerData.left   = new FormAttachment(leftSash);
       
  1153 			viewerData.right  = new FormAttachment(100);
       
  1154 			functionTable.getTable().setLayoutData(viewerData);
       
  1155 
       
  1156 			// attach the thread table to the sash
       
  1157 			try {
       
  1158 				FormData formData = (FormData) this.table.getLayoutData();
       
  1159 				formData.right = new FormAttachment(leftSash);
       
  1160 			} catch (ClassCastException e1) {
       
  1161 			}
       
  1162 
       
  1163 			this.parent.layout();
       
  1164 
       
  1165 			this.myGraph.repaint();
       
  1166 
       
  1167 		} else if (drawMode == Defines.THREADS_FUNCTIONS_BINARIES) {
       
  1168 			// set the page's graph title
       
  1169 			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
  1170 			pV.getTitle().setText(Messages.getString("AddrThreadTable.functionLoad")); //$NON-NLS-1$
       
  1171 			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
       
  1172 
       
  1173 			// get rid of the binary table and its sash
       
  1174 			if (this.myGraph.getRightSash() != null) {
       
  1175 				this.myGraph.getRightSash().dispose();
       
  1176 				this.myGraph.setRightSash(null);
       
  1177 			}
       
  1178 			if (   (this.myGraph.getBinaryTable() != null)
       
  1179 				&& (this.myGraph.getBinaryTable().getTable() != null)) {
       
  1180 				this.myGraph.getBinaryTable().getTableViewer().getTable().dispose();
       
  1181 				this.myGraph.getBinaryTable().setTableViewer(null);
       
  1182 			}
       
  1183 
       
  1184 			// get rid of the middle table's connection to the sash
       
  1185 			try {
       
  1186 				FormData formData = (FormData) this.myGraph.getFunctionTable().getTable().getLayoutData();
       
  1187 				formData.right = new FormAttachment(100);
       
  1188 			} catch (ClassCastException e1) {
       
  1189 			}
       
  1190 
       
  1191 			// move the left sash to the middle
       
  1192 			try {
       
  1193 				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
       
  1194 				formData.left = new FormAttachment(50); // middle
       
  1195 			} catch (ClassCastException e1) {
       
  1196 			}
       
  1197 
       
  1198 			// set the draw mode
       
  1199 			this.myGraph.setDrawMode(Defines.THREADS_FUNCTIONS);
       
  1200 
       
  1201 			// show colors in the rightmost table
       
  1202 			this.myGraph.getFunctionTable().addColor(Defines.THREADS_FUNCTIONS);
       
  1203 
       
  1204 			this.parent.layout();
       
  1205 
       
  1206 			this.myGraph.repaint();
       
  1207 		}
       
  1208 
       
  1209 		// this case should be drawMode == Defines.THREADS_BINARIES
       
  1210 		return;
       
  1211 	}
       
  1212 
       
  1213 	private void actionThreadFunctionBinary()
       
  1214 	{
       
  1215 		// current drawMode is THREADS_FUNCTIONS, or THREADS_FUNCTIONS_BINARIES
       
  1216 		int drawMode   = this.myGraph.getDrawMode();
       
  1217 		int graphIndex = this.myGraph.getGraphIndex();
       
  1218 
       
  1219 		if (drawMode != Defines.THREADS_FUNCTIONS) {
       
  1220 			// this case should be drawMode == Defines.THREADS_FUNCTIONS_BINARIES
       
  1221 			return;
       
  1222 		}
       
  1223 
       
  1224 		setIsDrilldown(true);
       
  1225 
       
  1226 		// set the page's graph title
       
  1227 		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
       
  1228 		pV.getTitle().setText(Messages.getString("AddrThreadTable.binaryLoad")); //$NON-NLS-1$
       
  1229 		pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadToFunctionTo")); //$NON-NLS-1$
       
  1230 
       
  1231 		// set the draw mode
       
  1232 		this.myGraph.setDrawMode(Defines.THREADS_FUNCTIONS_BINARIES);
       
  1233 
       
  1234 		// create the binary graph table viewer
       
  1235 		AddrBinaryTable binaryTable = this.myGraph.getBinaryTable();
       
  1236 		binaryTable.createTableViewer(Defines.THREADS_FUNCTIONS_BINARIES);
       
  1237 		binaryTable.setIsDrilldown(true);
       
  1238 
       
  1239 		// create a reduced set of binary entries based on enabled thread and function entries
       
  1240 		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
       
  1241 		Vector<ProfiledGeneric> binaries = gppTrace.setThreadFunctionBinary(graphIndex);
       
  1242 		this.myGraph.setProfiledBinaries(binaries);
       
  1243 
       
  1244 		// put check marks on all rows, and sort by sample count
       
  1245 		binaryTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledBinaries());
       
  1246 		binaryTable.updateProfiledAndItemData(true);
       
  1247 		binaryTable.getTableViewer().setAllChecked(true);
       
  1248 		binaryTable.getTableViewer().refresh();
       
  1249 
       
  1250 		// remove colors where appropriate
       
  1251 		this.myGraph.getFunctionTable().removeColor(Defines.THREADS_FUNCTIONS_BINARIES);
       
  1252 
       
  1253 		// connect the 2nd and 3rd tables with a sash
       
  1254 		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
       
  1255 
       
  1256 		final FormData rightSashData = new FormData();
       
  1257 		rightSashData.top    = new FormAttachment(0);
       
  1258 		rightSashData.bottom = new FormAttachment(100);
       
  1259 		rightSashData.left   = new FormAttachment(67); // two thirds
       
  1260 		rightSash.setLayoutData(rightSashData);
       
  1261 
       
  1262 		final Composite sashParent = this.parent;
       
  1263 		rightSash.addListener(SWT.Selection, new Listener() {
       
  1264 			public void handleEvent(Event event) {
       
  1265 				if (event.detail != SWT.DRAG) {
       
  1266 					rightSashData.left = new FormAttachment(0, event.x);
       
  1267 					sashParent.layout();
       
  1268 				}
       
  1269 			}
       
  1270 		});
       
  1271 
       
  1272 		myGraph.setRightSash(rightSash);
       
  1273 
       
  1274 		// attach the binary table to the sash
       
  1275 		final FormData viewerData = new FormData();
       
  1276 		viewerData.top    = new FormAttachment(0);
       
  1277 		viewerData.bottom = new FormAttachment(100);
       
  1278 		viewerData.left   = new FormAttachment(rightSash);
       
  1279 		viewerData.right  = new FormAttachment(100);
       
  1280 		binaryTable.getTable().setLayoutData(viewerData);
       
  1281 
       
  1282 		// attach the function table to the sash
       
  1283 		try {
       
  1284 			FormData formData = (FormData) this.myGraph.getFunctionTable().getTable().getLayoutData();
       
  1285 			formData.right = new FormAttachment(rightSash);
       
  1286 		} catch (ClassCastException e1) {
       
  1287 		}
       
  1288 
       
  1289 		// move the left sash to 1/3 from the left
       
  1290 		try {
       
  1291 			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
       
  1292 			formData.left = new FormAttachment(33); // one third
       
  1293 		} catch (ClassCastException e1) {
       
  1294 		}
       
  1295 
       
  1296 		this.parent.layout();
       
  1297 
       
  1298 		this.myGraph.repaint();
       
  1299 	}
       
  1300 
       
  1301 	public void focusGained(FocusEvent e) {}
       
  1302 
       
  1303 	public void focusLost(FocusEvent e) {}
       
  1304 
       
  1305 	public void piEventReceived(PIEvent be)
       
  1306 	{
       
  1307 		if (be.getType() == PIEvent.SELECTION_AREA_CHANGED3)
       
  1308 		{
       
  1309 			// % loads, % load strings, and/or sample counts have been updated
       
  1310 			// due to a change in the graph area selected, and all table items
       
  1311 			// need to be checked
       
  1312 			updateProfiledAndItemData(true);
       
  1313 
       
  1314 			Display.getDefault().syncExec(new Runnable() {
       
  1315 				public void run() {
       
  1316 					quickSort(sortColumn, profiledThreads);
       
  1317 
       
  1318 					// initially, all rows are selected
       
  1319 					tableViewer.setAllChecked(true);
       
  1320 
       
  1321 					table.redraw();
       
  1322 				}
       
  1323 			});
       
  1324 		}
       
  1325 		else if (   (be.getType() == PIEvent.SELECTION_AREA_CHANGED2)
       
  1326 				 || (be.getType() == PIEvent.CHANGED_THREAD_TABLE))
       
  1327 		{
       
  1328 			int graphIndex = this.myGraph.getGraphIndex();
       
  1329 
       
  1330 			// This routine does not change which threads are enabled, but it enables
       
  1331 			// all entries in the 2nd and 3rd tables.
       
  1332 			// It assumes that GppTrace.setSelectedArea(), action("add") or action("remove") has set
       
  1333 			// the % load and sample counts for threads, except for the threshold list.
       
  1334 			if (be.getType() == PIEvent.SELECTION_AREA_CHANGED2) {
       
  1335 				int thresholdCount = (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
       
  1336 				if (thresholdCount > 0) {
       
  1337 					Vector<ProfiledGeneric> pGeneric = this.myGraph.getProfiledThreads();
       
  1338 					int sampleCount = 0;
       
  1339 					for (int i = 0; i < pGeneric.size(); i++)
       
  1340 						if (pGeneric.elementAt(i).getTotalSampleCount() < thresholdCount)
       
  1341 							sampleCount += pGeneric.elementAt(i).getSampleCount(graphIndex);
       
  1342 					this.myGraph.getThresholdThread().setSampleCount(graphIndex, sampleCount);
       
  1343 				}
       
  1344 			}
       
  1345 
       
  1346 			// redraw this table
       
  1347 			Display.getDefault().syncExec(new Runnable() {
       
  1348 				public void run() {
       
  1349 					if (   (sortColumn == COLUMN_ID_PERCENT_LOAD)
       
  1350 						|| (sortColumn == COLUMN_ID_SAMPLE_COUNT))
       
  1351 					{
       
  1352 						quickSort(sortColumn, profiledThreads);
       
  1353 					}
       
  1354 					else
       
  1355 						refreshTableViewer();
       
  1356 
       
  1357 					table.redraw();
       
  1358 				}
       
  1359 			});
       
  1360 
       
  1361 			int drawMode = this.myGraph.getDrawMode();
       
  1362 			if (drawMode == Defines.THREADS)
       
  1363 				return;
       
  1364 
       
  1365 			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
       
  1366 			Vector<ProfiledGeneric> traceThreads = trace.getIndexedThreads();
       
  1367 
       
  1368 			int startSampleIndex = trace.getStartSampleIndex();
       
  1369 			int endSampleIndex   = trace.getEndSampleIndex();
       
  1370 			double percentPerSample;
       
  1371 			if (startSampleIndex == endSampleIndex)
       
  1372 				percentPerSample = 0.0;
       
  1373 			else
       
  1374 				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
       
  1375 
       
  1376 			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
       
  1377 
       
  1378 			switch (drawMode) {
       
  1379 				case Defines.THREADS_BINARIES:
       
  1380 				{
       
  1381 					// get new binary counts and loads
       
  1382 					Vector<ProfiledGeneric> traceBinaries = trace.getIndexedBinaries();
       
  1383 					Vector<ProfiledGeneric> graphBinaries  = this.myGraph.getProfiledBinaries();
       
  1384 					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
       
  1385 
       
  1386 					// previous binaries are not necessarily graphed this time
       
  1387 					Enumeration<ProfiledGeneric> enu = graphBinaries.elements();
       
  1388 					while (enu.hasMoreElements()) {
       
  1389 						ProfiledBinary pBinary = (ProfiledBinary) enu.nextElement();
       
  1390 						pBinary.setEnabled(graphIndex, false);
       
  1391 					}
       
  1392 					graphBinaries.clear();
       
  1393 
       
  1394 					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
       
  1395 
       
  1396 					if (thresholdBinary.isEnabled(graphIndex)) {
       
  1397 						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
       
  1398 						// disable all items below the threshold
       
  1399 						for (int i = 0; i < items.size(); i++) {
       
  1400 							items.get(i).setEnabled(graphIndex, false);
       
  1401 						}
       
  1402 					}
       
  1403 
       
  1404 					GppSample[] sortedSamples = trace.getSortedGppSamples();
       
  1405 
       
  1406 					// set up in case we find binaries below the threshold
       
  1407 					boolean lowBinary;
       
  1408 					thresholdBinary.init(graphIndex);
       
  1409 					
       
  1410 					int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
  1411 					for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
  1412 						GppSample sample = sortedSamples[i];
       
  1413 
       
  1414 						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
       
  1415 						if (pThread.isEnabled(graphIndex)) {
       
  1416 							// binary list is based on threads
       
  1417 							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
       
  1418 							String binaryName = pBinary.getNameString();
       
  1419 
       
  1420 							lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
       
  1421 
       
  1422 							if (!foundBinaries.containsKey(binaryName)) {
       
  1423 								foundBinaries.put(binaryName, binaryName);
       
  1424 								if (lowBinary) {
       
  1425 									thresholdBinary.addItem(graphIndex, pBinary, 1);
       
  1426 								} else {
       
  1427 									pBinary.setEnabled(graphIndex, true);
       
  1428 									pBinary.setSampleCount(graphIndex, 1);
       
  1429 									graphBinaries.add(pBinary);
       
  1430 								}
       
  1431 							} else {
       
  1432 								if (lowBinary)
       
  1433 									thresholdBinary.incSampleCount(graphIndex);
       
  1434 								else
       
  1435 									pBinary.incSampleCount(graphIndex);
       
  1436 							}
       
  1437 						}
       
  1438 					}
       
  1439 
       
  1440 					// set the % load
       
  1441 					for (int i = 0; i < graphBinaries.size(); i++) {
       
  1442 						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
  1443 						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1444 					}
       
  1445 					thresholdBinary.setLoadAndString(graphIndex,
       
  1446 							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1447 
       
  1448 					// update the table items and redraw the table
       
  1449 					this.myGraph.getBinaryTable().piEventReceived(be3);
       
  1450 					break;
       
  1451 				}
       
  1452 				case Defines.THREADS_BINARIES_FUNCTIONS:
       
  1453 				{
       
  1454 					// get new binary and function counts and loads
       
  1455 					Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
       
  1456 					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
       
  1457 					Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
       
  1458 					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
       
  1459 					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
       
  1460 					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
  1461 
       
  1462 					// previous functions are not necessarily graphed this time
       
  1463 					Enumeration<ProfiledGeneric> enuFunctions = graphFunctions.elements();
       
  1464 					while (enuFunctions.hasMoreElements()) {
       
  1465 						ProfiledFunction pFunction = (ProfiledFunction) enuFunctions.nextElement();
       
  1466 						pFunction.setEnabled(graphIndex, false);
       
  1467 					}
       
  1468 					graphFunctions.clear();
       
  1469 
       
  1470 					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
       
  1471 
       
  1472 					if (thresholdFunction.isEnabled(graphIndex)) {
       
  1473 						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
       
  1474 						// disable all items below the threshold
       
  1475 						for (int i = 0; i < items.size(); i++) {
       
  1476 							items.get(i).setEnabled(graphIndex, false);
       
  1477 						}
       
  1478 					}
       
  1479 
       
  1480 					// previous binaries are not necessarily graphed this time
       
  1481 					Enumeration<ProfiledGeneric> enuBinary = graphBinaries.elements();
       
  1482 					while (enuBinary.hasMoreElements()) {
       
  1483 						ProfiledBinary pBinary = (ProfiledBinary) enuBinary.nextElement();
       
  1484 						pBinary.setEnabled(graphIndex, false);
       
  1485 					}
       
  1486 					graphBinaries.clear();
       
  1487 
       
  1488 					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
       
  1489 
       
  1490 					if (thresholdBinary.isEnabled(graphIndex)) {
       
  1491 						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
       
  1492 						// disable all items below the threshold
       
  1493 						for (int i = 0; i < items.size(); i++) {
       
  1494 							items.get(i).setEnabled(graphIndex, false);
       
  1495 						}
       
  1496 					}
       
  1497 
       
  1498 					GppSample[] sortedSamples = trace.getSortedGppSamples();
       
  1499 
       
  1500 					// set up in case we find functions below the threshold
       
  1501 					boolean lowFunction;
       
  1502 					thresholdFunction.init(graphIndex);
       
  1503 
       
  1504 					// set up in case we find binaries below the threshold
       
  1505 					boolean lowBinary;
       
  1506 					thresholdBinary.init(graphIndex);
       
  1507 
       
  1508 					int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
  1509 					for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
  1510 						GppSample sample = sortedSamples[i];
       
  1511 
       
  1512 						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
       
  1513 						if (pThread.isEnabled(graphIndex)) {
       
  1514 							// binary list is based on threads
       
  1515 							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
       
  1516 							String binaryName = pBinary.getNameString();
       
  1517 
       
  1518 							lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
       
  1519 
       
  1520 							if (!foundBinaries.containsKey(binaryName)) {
       
  1521 								foundBinaries.put(binaryName, binaryName);
       
  1522 								if (lowBinary) {
       
  1523 									thresholdBinary.addItem(graphIndex, pBinary, 1);
       
  1524 								} else {
       
  1525 									pBinary.setEnabled(graphIndex, true);
       
  1526 									pBinary.setSampleCount(graphIndex, 1);
       
  1527 									graphBinaries.add(pBinary);
       
  1528 								}
       
  1529 							} else {
       
  1530 								if (lowBinary)
       
  1531 									thresholdBinary.incSampleCount(graphIndex);
       
  1532 								else
       
  1533 									pBinary.incSampleCount(graphIndex);
       
  1534 							}
       
  1535 
       
  1536 							// function list is based on threads and binaries
       
  1537 							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
       
  1538 							String functionName = pFunction.getNameString();
       
  1539 
       
  1540 							lowFunction = pFunction.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
  1541 
       
  1542 							if (!foundFunctions.containsKey(functionName)) {
       
  1543 								foundFunctions.put(functionName, functionName);
       
  1544 								if (lowFunction) {
       
  1545 									thresholdFunction.addItem(graphIndex, pFunction, 1);
       
  1546 								} else {
       
  1547 									pFunction.setEnabled(graphIndex, true);
       
  1548 									pFunction.setSampleCount(graphIndex, 1);
       
  1549 									graphFunctions.add(pFunction);
       
  1550 								}
       
  1551 							} else {
       
  1552 								if (lowFunction)
       
  1553 									thresholdFunction.incSampleCount(graphIndex);
       
  1554 								else
       
  1555 									pFunction.incSampleCount(graphIndex);
       
  1556 							}
       
  1557 						}
       
  1558 					}
       
  1559 
       
  1560 					// set the % load
       
  1561 					for (int i = 0; i < graphBinaries.size(); i++) {
       
  1562 						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
  1563 						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1564 					}
       
  1565 					thresholdBinary.setLoadAndString(graphIndex,
       
  1566 							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1567 
       
  1568 					for (int i = 0; i < graphFunctions.size(); i++) {
       
  1569 						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
  1570 						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1571 					}
       
  1572 					thresholdFunction.setLoadAndString(graphIndex,
       
  1573 							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1574 
       
  1575 					// update the table items and redraw the table
       
  1576 					this.myGraph.getBinaryTable().piEventReceived(be3);
       
  1577 					this.myGraph.getFunctionTable().piEventReceived(be3);
       
  1578 					break;
       
  1579 				}
       
  1580 				case Defines.THREADS_FUNCTIONS:
       
  1581 				{
       
  1582 					// get new function counts and loads
       
  1583 					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
       
  1584 					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
       
  1585 					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
  1586 
       
  1587 					// previous functions are not necessarily graphed this time
       
  1588 					Enumeration<ProfiledGeneric> enu = graphFunctions.elements();
       
  1589 					while (enu.hasMoreElements()) {
       
  1590 						ProfiledFunction pFunction = (ProfiledFunction) enu.nextElement();
       
  1591 						pFunction.setEnabled(graphIndex, false);
       
  1592 					}
       
  1593 					graphFunctions.clear();
       
  1594 
       
  1595 					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
       
  1596 
       
  1597 					if (thresholdFunction.isEnabled(graphIndex)) {
       
  1598 						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
       
  1599 						// disable all items below the threshold
       
  1600 						for (int i = 0; i < items.size(); i++) {
       
  1601 							items.get(i).setEnabled(graphIndex, false);
       
  1602 						}
       
  1603 					}
       
  1604 
       
  1605 					GppSample[] sortedSamples = trace.getSortedGppSamples();
       
  1606 
       
  1607 					// set up in case we find functions below the threshold
       
  1608 					boolean lowFunction;
       
  1609 					thresholdFunction.init(graphIndex);
       
  1610 
       
  1611 					int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
  1612 					for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
  1613 						GppSample sample = sortedSamples[i];
       
  1614 
       
  1615 						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
       
  1616 						if (pThread.isEnabled(graphIndex)) {
       
  1617 							// function list is based on threads
       
  1618 							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
       
  1619 							String functionName = pFunction.getNameString();
       
  1620 
       
  1621 							lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
       
  1622 
       
  1623 							if (!foundFunctions.containsKey(functionName)) {
       
  1624 								foundFunctions.put(functionName, functionName);
       
  1625 								if (lowFunction) {
       
  1626 									thresholdFunction.addItem(graphIndex, pFunction, 1);
       
  1627 								} else {
       
  1628 									pFunction.setEnabled(graphIndex, true);
       
  1629 									pFunction.setSampleCount(graphIndex, 1);
       
  1630 									graphFunctions.add(pFunction);
       
  1631 								}
       
  1632 							} else {
       
  1633 								if (lowFunction)
       
  1634 									thresholdFunction.incSampleCount(graphIndex);
       
  1635 								else
       
  1636 									pFunction.incSampleCount(graphIndex);
       
  1637 							}
       
  1638 						}
       
  1639 					}
       
  1640 
       
  1641 					// set the % load
       
  1642 					for (int i = 0; i < graphFunctions.size(); i++) {
       
  1643 						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
  1644 						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1645 					}
       
  1646 					thresholdFunction.setLoadAndString(graphIndex,
       
  1647 							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1648 
       
  1649 					// update the table items and redraw the table
       
  1650 					this.myGraph.getFunctionTable().piEventReceived(be3);
       
  1651 					break;
       
  1652 				}
       
  1653 				case Defines.THREADS_FUNCTIONS_BINARIES:
       
  1654 				{
       
  1655 					// get new function and binary counts and loads
       
  1656 					Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
       
  1657 					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
       
  1658 					Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
       
  1659 					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
       
  1660 					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
       
  1661 					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
  1662 
       
  1663 					// previous binaries are not necessarily graphed this time
       
  1664 					Enumeration<ProfiledGeneric> enuBinaries = graphBinaries.elements();
       
  1665 					while (enuBinaries.hasMoreElements()) {
       
  1666 						ProfiledBinary pBinary = (ProfiledBinary) enuBinaries.nextElement();
       
  1667 						pBinary.setEnabled(graphIndex, false);
       
  1668 					}
       
  1669 					graphBinaries.clear();
       
  1670 
       
  1671 					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
       
  1672 
       
  1673 					if (thresholdBinary.isEnabled(graphIndex)) {
       
  1674 						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
       
  1675 						// disable all items below the threshold
       
  1676 						for (int i = 0; i < items.size(); i++) {
       
  1677 							items.get(i).setEnabled(graphIndex, false);
       
  1678 						}
       
  1679 					}
       
  1680 
       
  1681 					// previous functions are not necessarily graphed this time
       
  1682 					Enumeration<ProfiledGeneric> enuFunctions = graphFunctions.elements();
       
  1683 					while (enuFunctions.hasMoreElements()) {
       
  1684 						ProfiledFunction pFunction = (ProfiledFunction) enuFunctions.nextElement();
       
  1685 						pFunction.setEnabled(graphIndex, false);
       
  1686 					}
       
  1687 					graphFunctions.clear();
       
  1688 
       
  1689 					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
       
  1690 
       
  1691 					if (thresholdFunction.isEnabled(graphIndex)) {
       
  1692 						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
       
  1693 						// disable all items below the threshold
       
  1694 						for (int i = 0; i < items.size(); i++) {
       
  1695 							items.get(i).setEnabled(graphIndex, false);
       
  1696 						}
       
  1697 					}
       
  1698 
       
  1699 					GppSample[] sortedSamples = trace.getSortedGppSamples();
       
  1700 
       
  1701 					// set up in case we find binaries below the threshold
       
  1702 					boolean lowBinary;
       
  1703 					thresholdBinary.init(graphIndex);
       
  1704 
       
  1705 					// set up in case we find functions below the threshold
       
  1706 					boolean lowFunction;
       
  1707 					thresholdFunction.init(graphIndex);
       
  1708 
       
  1709 					int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
  1710 					for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
  1711 						GppSample sample = sortedSamples[i];
       
  1712 
       
  1713 						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
       
  1714 						if (pThread.isEnabled(graphIndex)) {
       
  1715 							// function list is based on threads
       
  1716 							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
       
  1717 							String functionName = pFunction.getNameString();
       
  1718 
       
  1719 							lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
       
  1720 
       
  1721 							if (!foundFunctions.containsKey(functionName)) {
       
  1722 								foundFunctions.put(functionName, functionName);
       
  1723 								if (lowFunction) {
       
  1724 									thresholdFunction.addItem(graphIndex, pFunction, 1);
       
  1725 								} else {
       
  1726 									pFunction.setEnabled(graphIndex, true);
       
  1727 									pFunction.setSampleCount(graphIndex, 1);
       
  1728 									graphFunctions.add(pFunction);
       
  1729 								}
       
  1730 							} else {
       
  1731 								if (lowFunction)
       
  1732 									thresholdFunction.incSampleCount(graphIndex);
       
  1733 								else
       
  1734 									pFunction.incSampleCount(graphIndex);
       
  1735 							}
       
  1736 
       
  1737 							// binary list is based on threads and functions
       
  1738 							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
       
  1739 							String binaryName = pBinary.getNameString();
       
  1740 
       
  1741 							lowBinary = pBinary.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
  1742 
       
  1743 							if (!foundBinaries.containsKey(binaryName)) {
       
  1744 								foundBinaries.put(binaryName, binaryName);
       
  1745 								if (lowBinary) {
       
  1746 									thresholdBinary.addItem(graphIndex, pBinary, 1);
       
  1747 								} else {
       
  1748 									pBinary.setEnabled(graphIndex, true);
       
  1749 									pBinary.setSampleCount(graphIndex, 1);
       
  1750 									graphBinaries.add(pBinary);
       
  1751 								}
       
  1752 							} else {
       
  1753 								if (lowBinary)
       
  1754 									thresholdBinary.incSampleCount(graphIndex);
       
  1755 								else
       
  1756 									pBinary.incSampleCount(graphIndex);
       
  1757 							}
       
  1758 						}
       
  1759 					}
       
  1760 
       
  1761 					// set the % load
       
  1762 					for (int i = 0; i < graphBinaries.size(); i++) {
       
  1763 						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
  1764 						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1765 					}
       
  1766 					thresholdBinary.setLoadAndString(graphIndex,
       
  1767 							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1768 
       
  1769 					for (int i = 0; i < graphFunctions.size(); i++) {
       
  1770 						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
  1771 						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1772 					}
       
  1773 					thresholdFunction.setLoadAndString(graphIndex,
       
  1774 							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1775 
       
  1776 					// update the table items and redraw the table
       
  1777 					this.myGraph.getBinaryTable().piEventReceived(be3);
       
  1778 					this.myGraph.getFunctionTable().piEventReceived(be3);
       
  1779 					break;
       
  1780 				}
       
  1781 				default:
       
  1782 				{
       
  1783 					break;
       
  1784 				}
       
  1785 			}
       
  1786 		}
       
  1787 		else if (be.getType() == PIEvent.CHANGED_BINARY_TABLE)
       
  1788 		{
       
  1789 			// This routine enables all entries in the next table
       
  1790 
       
  1791 			int drawMode = this.myGraph.getDrawMode();
       
  1792 			if (drawMode != Defines.THREADS_BINARIES_FUNCTIONS)
       
  1793 				return;
       
  1794 
       
  1795 			// we don't need to redraw the thread table, since it has not changed
       
  1796 
       
  1797 			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
       
  1798 			Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
       
  1799 
       
  1800 			int graphIndex = this.myGraph.getGraphIndex();
       
  1801 			int startSampleIndex = trace.getStartSampleIndex();
       
  1802 			int endSampleIndex   = trace.getEndSampleIndex();
       
  1803 			double percentPerSample;
       
  1804 			if (startSampleIndex == endSampleIndex)
       
  1805 				percentPerSample = 0.0;
       
  1806 			else
       
  1807 				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
       
  1808 
       
  1809 			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
       
  1810 
       
  1811 			// get new function counts and loads
       
  1812 			Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
       
  1813 			Vector<ProfiledGeneric> graphFunctions = this.myGraph.getProfiledFunctions();
       
  1814 			Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
  1815 
       
  1816 			// previous functions are not necessarily graphed this time
       
  1817 			Enumeration<ProfiledGeneric> enu = graphFunctions.elements();
       
  1818 			while (enu.hasMoreElements()) {
       
  1819 				ProfiledFunction pFunction = (ProfiledFunction) enu.nextElement();
       
  1820 				pFunction.setEnabled(graphIndex, false);
       
  1821 			}
       
  1822 			graphFunctions.clear();
       
  1823 
       
  1824 			ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
       
  1825 
       
  1826 			if (thresholdFunction.isEnabled(graphIndex)) {
       
  1827 				ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
       
  1828 				// disable all items below the threshold
       
  1829 				for (int i = 0; i < items.size(); i++) {
       
  1830 					items.get(i).setEnabled(graphIndex, false);
       
  1831 				}
       
  1832 			}
       
  1833 
       
  1834 			GppSample[] sortedSamples = trace.getSortedGppSamples();
       
  1835 
       
  1836 			// set up in case we find functions below the threshold
       
  1837 			boolean lowFunction;
       
  1838 			thresholdFunction.init(graphIndex);
       
  1839 
       
  1840 			for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
  1841 				GppSample sample = sortedSamples[i];
       
  1842 
       
  1843 				ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
       
  1844 				if (pBinary.isEnabled(graphIndex)) {
       
  1845 					// function list is based on binaries
       
  1846 					ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
       
  1847 					String functionName = pFunction.getNameString();
       
  1848 
       
  1849 					lowFunction = pFunction.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
  1850 
       
  1851 					if (!foundFunctions.containsKey(functionName)) {
       
  1852 						foundFunctions.put(functionName, functionName);
       
  1853 						if (lowFunction) {
       
  1854 							thresholdFunction.addItem(graphIndex, pFunction, 1);
       
  1855 						} else {
       
  1856 							pFunction.setEnabled(graphIndex, true);
       
  1857 							pFunction.setSampleCount(graphIndex, 1);
       
  1858 							graphFunctions.add(pFunction);
       
  1859 						}
       
  1860 					} else {
       
  1861 						if (lowFunction)
       
  1862 							thresholdFunction.incSampleCount(graphIndex);
       
  1863 						else
       
  1864 							pFunction.incSampleCount(graphIndex);
       
  1865 					}
       
  1866 				}
       
  1867 			}
       
  1868 
       
  1869 			// set the % load
       
  1870 			for (int i = 0; i < graphFunctions.size(); i++) {
       
  1871 				ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
  1872 				pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1873 			}
       
  1874 			thresholdFunction.setLoadAndString(graphIndex,
       
  1875 					(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
       
  1876 
       
  1877 			// update the table items and redraw the table
       
  1878 			this.myGraph.getFunctionTable().piEventReceived(be3);
       
  1879 		}
       
  1880 		else if (be.getType() == PIEvent.CHANGED_FUNCTION_TABLE)
       
  1881 		{
       
  1882 			// This routine enables all entries in the next table
       
  1883 
       
  1884 			int drawMode = this.myGraph.getDrawMode();
       
  1885 			if (drawMode != Defines.THREADS_FUNCTIONS_BINARIES)
       
  1886 				return;
       
  1887 
       
  1888 			// we don't need to redraw the thread table, since it has not changed
       
  1889 
       
  1890 			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
       
  1891 			Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
       
  1892 
       
  1893 			int graphIndex = this.myGraph.getGraphIndex();
       
  1894 			int startSampleIndex = trace.getStartSampleIndex();
       
  1895 			int endSampleIndex   = trace.getEndSampleIndex();
       
  1896 			double percentPerSample;
       
  1897 			if (startSampleIndex == endSampleIndex)
       
  1898 				percentPerSample = 0.0;
       
  1899 			else
       
  1900 				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
       
  1901 
       
  1902 			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
       
  1903 
       
  1904 			// get new counts and loads
       
  1905 			Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
       
  1906 			Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
       
  1907 			Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
       
  1908 
       
  1909 			// previous binaries are not necessarily graphed this time
       
  1910 			Enumeration<ProfiledGeneric> enu = graphBinaries.elements();
       
  1911 			while (enu.hasMoreElements()) {
       
  1912 				ProfiledBinary pBinary = (ProfiledBinary) enu.nextElement();
       
  1913 				pBinary.setEnabled(graphIndex, false);
       
  1914 			}
       
  1915 			graphBinaries.clear();
       
  1916 
       
  1917 			ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
       
  1918 
       
  1919 			if (thresholdBinary.isEnabled(graphIndex)) {
       
  1920 				ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
       
  1921 				// disable all items below the threshold
       
  1922 				for (int i = 0; i < items.size(); i++) {
       
  1923 					items.get(i).setEnabled(graphIndex, false);
       
  1924 				}
       
  1925 			}
       
  1926 
       
  1927 			GppSample[] sortedSamples = trace.getSortedGppSamples();
       
  1928 
       
  1929 			// set up in case we find binaries below the threshold
       
  1930 			boolean lowBinary;
       
  1931 			thresholdBinary.init(graphIndex);
       
  1932 
       
  1933 			int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
  1934 			for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
  1935 				GppSample sample = sortedSamples[i];
       
  1936 
       
  1937 				ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
       
  1938 				if (pFunction.isEnabled(graphIndex)) {
       
  1939 					// binary list is based on functions
       
  1940 					ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
       
  1941 					String binaryName = pBinary.getNameString();
       
  1942 
       
  1943 					lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
       
  1944 
       
  1945 					if (!foundBinaries.containsKey(binaryName)) {
       
  1946 						foundBinaries.put(binaryName, binaryName);
       
  1947 						if (lowBinary) {
       
  1948 							thresholdBinary.addItem(graphIndex, pBinary, 1);
       
  1949 						} else {
       
  1950 							pBinary.setEnabled(graphIndex, true);
       
  1951 							pBinary.setSampleCount(graphIndex, 1);
       
  1952 							graphBinaries.add(pBinary);
       
  1953 						}
       
  1954 					} else {
       
  1955 						if (lowBinary)
       
  1956 							thresholdBinary.incSampleCount(graphIndex);
       
  1957 						else
       
  1958 							pBinary.incSampleCount(graphIndex);
       
  1959 					}
       
  1960 				}
       
  1961 			}
       
  1962 
       
  1963 			// set the % load
       
  1964 			for (int i = 0; i < graphBinaries.size(); i++) {
       
  1965 				ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
  1966 				pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1967 			}
       
  1968 			thresholdBinary.setLoadAndString(graphIndex,
       
  1969 					(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
       
  1970 
       
  1971 			// update the table items and redraw the table
       
  1972 			this.myGraph.getBinaryTable().piEventReceived(be3);
       
  1973 		}
       
  1974 	}
       
  1975 
       
  1976 	public void setSelectedNames()
       
  1977 	{
       
  1978 		Object[] selectedValues = this.tableViewer.getCheckedElements();
       
  1979         String[] threadNames = new String[selectedValues.length];
       
  1980 
       
  1981         for (int i = 0; i < selectedValues.length; i++)
       
  1982 		{
       
  1983 			if (selectedValues[i] instanceof ProfiledThread)
       
  1984 			{
       
  1985 				ProfiledThread pt = (ProfiledThread)selectedValues[i];
       
  1986 				threadNames[i] = pt.getNameString();
       
  1987 			}
       
  1988 		}
       
  1989 
       
  1990         PIVisualSharedData shared = myGraph.getSharedDataInstance();
       
  1991 		shared.GPP_SelectedThreadNames = threadNames;
       
  1992 	}
       
  1993 
       
  1994 	private class SharedCheckHandler implements ICheckStateListener
       
  1995 	{
       
  1996 		public void checkStateChanged(CheckStateChangedEvent event) {
       
  1997 
       
  1998        		if (!(event.getElement() instanceof ProfiledGeneric))
       
  1999        			return;
       
  2000        		
       
  2001        		// set the stored value to the checkbox value
       
  2002        		ProfiledGeneric pg = (ProfiledGeneric)event.getElement();
       
  2003 	        pg.setEnabled(myGraph.getGraphIndex(), event.getChecked());
       
  2004  
       
  2005 	        // this table's set of checkbox-selected rows has changed, so propagate that information
       
  2006        		setSelectedNames();
       
  2007 
       
  2008        		if (   (pg.getSampleCount(myGraph.getGraphIndex()) != 0)
       
  2009        			|| (myGraph.getDrawMode() == Defines.THREADS))
       
  2010        			selectionChangeNotify();
       
  2011 
       
  2012        		table.deselectAll();
       
  2013 		}
       
  2014 	}
       
  2015 
       
  2016 	protected void selectionChangeNotify() {
       
  2017 		PIEvent be = new PIEvent(null, PIEvent.CHANGED_THREAD_TABLE);
       
  2018 		myGraph.piEventReceived(be);
       
  2019     }
       
  2020 	
       
  2021 	public void sortOnColumnSelection(TableColumn tableColumn) {
       
  2022 			int columnId = ((Integer) tableColumn.getData()).intValue();
       
  2023             if (sortColumn == columnId) {
       
  2024             	// sort in other order
       
  2025             	sortAscending = !sortAscending;
       
  2026             } else {
       
  2027             	// sort in the default order
       
  2028 				switch (columnId)
       
  2029 				{
       
  2030 					case COLUMN_ID_SHOW:
       
  2031 					case COLUMN_ID_PERCENT_LOAD:
       
  2032 					case COLUMN_ID_SAMPLE_COUNT:
       
  2033 					case COLUMN_ID_PRIORITY:
       
  2034 					{
       
  2035 		            	// sort in descending order (for checked boxes column, this means selected boxes first)
       
  2036 		            	sortAscending = false;
       
  2037 		                break;
       
  2038 					}
       
  2039 					case COLUMN_ID_THREAD:
       
  2040 					{
       
  2041 		            	// sort in ascending order
       
  2042 		            	sortAscending = true;
       
  2043 		                break;
       
  2044 					}
       
  2045 					default:
       
  2046 					{
       
  2047 						return;
       
  2048 					}
       
  2049 				}
       
  2050             }
       
  2051 
       
  2052 			sortColumn = columnId;
       
  2053 			quickSort(sortColumn, profiledThreads);
       
  2054 	}
       
  2055 
       
  2056 	private class ColumnSelectionHandler extends SelectionAdapter
       
  2057 	{
       
  2058 		public void widgetSelected(SelectionEvent e)
       
  2059         {
       
  2060         	// wait for the previous sort to finish
       
  2061         	if (sorting || !(e.widget instanceof TableColumn))
       
  2062         		return;
       
  2063 
       
  2064         	sortOnColumnSelection((TableColumn) e.widget);
       
  2065         }
       
  2066 	}
       
  2067 
       
  2068 	public void updateProfiledAndItemData(boolean setInput)
       
  2069 	{
       
  2070 		tableItemData.clear();
       
  2071 		profiledThreads.clear();
       
  2072 
       
  2073 		// profiledThreads and tableItemData contain one entry per table row
       
  2074 		Enumeration<ProfiledGeneric> enu = myGraph.getProfiledThreads().elements();
       
  2075 		while (enu.hasMoreElements())
       
  2076 		{
       
  2077 			ProfiledThread nextElement = (ProfiledThread)enu.nextElement();
       
  2078 			tableItemData.add(nextElement);
       
  2079 			profiledThreads.add(nextElement);
       
  2080 		}
       
  2081 
       
  2082 		if (myGraph.getThresholdThread().getItemCount(myGraph.getGraphIndex()) != 0) {
       
  2083 			tableItemData.add(myGraph.getThresholdThread());
       
  2084 			profiledThreads.add(myGraph.getThresholdThread());
       
  2085 		}
       
  2086 		
       
  2087 		// now sort the items in increasing total sample count, so that they graph correctly
       
  2088 		Object[] sorted = myGraph.getProfiledThreads().toArray();
       
  2089 		Arrays.sort(sorted, new Comparator<Object>() {
       
  2090 			
       
  2091 			public int compare(Object arg0, Object arg1)
       
  2092 			{
       
  2093 				if (arg0 instanceof ProfiledGeneric && arg1 instanceof ProfiledGeneric)
       
  2094 					return ((ProfiledGeneric)arg0).getTotalSampleCount() -
       
  2095 							((ProfiledGeneric)arg1).getTotalSampleCount();
       
  2096 				else
       
  2097 					return 0;
       
  2098 			}
       
  2099 		});
       
  2100 
       
  2101 		// now create the sorted list used to draw the graph
       
  2102 		myGraph.getSortedThreads().clear();
       
  2103 
       
  2104 		if (myGraph.getThresholdThread().getItemCount(myGraph.getGraphIndex()) != 0)
       
  2105 			myGraph.getSortedThreads().add(myGraph.getThresholdThread());
       
  2106 
       
  2107 		for (int i = 0; i < sorted.length; i++)
       
  2108 			myGraph.getSortedThreads().add((ProfiledGeneric) sorted[i]);
       
  2109 
       
  2110 		// refresh the table, if needed
       
  2111 		if (setInput)
       
  2112 			refreshTableViewer();
       
  2113 	}
       
  2114 
       
  2115 	public void quickSort(int sortBy, Vector<ProfiledGeneric> profiled)
       
  2116 	{
       
  2117 		if (profiled.size() == 0)
       
  2118 			return;
       
  2119 
       
  2120 		this.sorting = true;
       
  2121 
       
  2122 		ProfiledGeneric pGeneric = profiled.elementAt(profiled.size() - 1);
       
  2123 
       
  2124 		if (pGeneric instanceof ProfiledThreshold) {
       
  2125 			profiled.removeElementAt(profiled.size() - 1);
       
  2126 		}
       
  2127 
       
  2128 		this.sorter.setupSort(sortBy, this.myGraph.getGraphIndex(), sortAscending);
       
  2129 
       
  2130 		switch (sortBy) {
       
  2131 			case COLUMN_ID_SHOW:
       
  2132 			{
       
  2133 			    this.sorter.quickSortByShow(profiled);
       
  2134 	            break;
       
  2135 			}
       
  2136 			case COLUMN_ID_PERCENT_LOAD:
       
  2137 			{
       
  2138 			    this.sorter.quickSortByAverageLoad(profiled);
       
  2139 	            break;
       
  2140 			}
       
  2141 			case COLUMN_ID_THREAD:
       
  2142 			{
       
  2143 			    this.sorter.quickSortByThread(profiled);
       
  2144 	            break;
       
  2145 			}
       
  2146 			case COLUMN_ID_BINARY:
       
  2147 			{
       
  2148 			    this.sorter.quickSortByBinary(profiled);
       
  2149 	            break;
       
  2150 			}
       
  2151 			case COLUMN_ID_FUNCTION:
       
  2152 			{
       
  2153 			    this.sorter.quickSortByFunction(profiled);
       
  2154 	            break;
       
  2155 			}
       
  2156 			case COLUMN_ID_SAMPLE_COUNT:
       
  2157 			{
       
  2158 			    this.sorter.quickSortBySampleCount(profiled);
       
  2159 	            break;
       
  2160 			}
       
  2161 			case COLUMN_ID_PRIORITY:
       
  2162 			{
       
  2163 			    this.sorter.quickSortByPriority(profiled, priorityValues);
       
  2164 	            break;
       
  2165 			}
       
  2166 			default:
       
  2167 			{
       
  2168 				break;
       
  2169 			}
       
  2170 		}
       
  2171  		
       
  2172 		Enumeration<ProfiledGeneric> e = this.sorter.getSortedList().elements();
       
  2173 		tableItemData = setTableItemData(e);
       
  2174 		if (pGeneric instanceof ProfiledThreshold) {
       
  2175 			tableItemData.add(pGeneric);
       
  2176 			profiled.add(pGeneric);
       
  2177 		}
       
  2178 		
       
  2179 		// find the column corresponding to sortBy, and give it a column direction
       
  2180 		// NOTE: treat sort by binary path then by binary name as sort by path
       
  2181 		if (sortBy == COLUMN_ID_FULL_PATH)
       
  2182 			sortBy = COLUMN_ID_PATH;
       
  2183 		else if (sortBy == COLUMN_ID_FULL_IN_PATH)
       
  2184 			sortBy = COLUMN_ID_IN_BINARY_PATH;
       
  2185 
       
  2186 		TableColumn sortByColumn = null;
       
  2187 		for (int i = 0; i < this.table.getColumnCount(); i++) {
       
  2188 			if (this.table.getColumn(i).getData() instanceof Integer) {
       
  2189 				if (((Integer)this.table.getColumn(i).getData()) == sortBy) {
       
  2190 					sortByColumn = this.table.getColumn(i);
       
  2191 					break;
       
  2192 				}
       
  2193 			}
       
  2194 		}
       
  2195 
       
  2196 		if (sortByColumn != null) {
       
  2197 			this.table.setSortColumn(sortByColumn);
       
  2198 			this.table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
       
  2199 		}
       
  2200 
       
  2201 		refreshTableViewer();
       
  2202 		this.sorting = false;
       
  2203 	}
       
  2204 
       
  2205 	protected MenuItem getSavePrioritySamplesItem(Menu menu, boolean enabled) {
       
  2206 	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
       
  2207 
       
  2208 		saveSamplesItem.setText(Messages.getString("AddrThreadTable.savePrioritySamples")); //$NON-NLS-1$
       
  2209 		saveSamplesItem.setEnabled(enabled);
       
  2210 		
       
  2211 		if (enabled) {
       
  2212 			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
       
  2213 				public void widgetSelected(SelectionEvent e) {
       
  2214 					action("savePrioritySamples"); //$NON-NLS-1$
       
  2215 				}
       
  2216 			});
       
  2217 		}
       
  2218 
       
  2219 		return saveSamplesItem;
       
  2220 	}
       
  2221 
       
  2222 	protected Menu getTableMenu(Decorations parent, int graphIndex, int drawMode) {
       
  2223 
       
  2224 		// get rid of last Menu created so we don't have double menu
       
  2225 		// in on click
       
  2226 		if (contextMenu != null) {
       
  2227 			contextMenu.dispose();
       
  2228 		}
       
  2229 		
       
  2230 		// recreate each time, in case the drawMode has changed since creation
       
  2231 		contextMenu = new Menu(parent, SWT.POP_UP);
       
  2232 
       
  2233 		// Use drawMode to determine the drill down items and
       
  2234 		// whether to show a color column
       
  2235 		addDrillDownItems(contextMenu, drawMode);
       
  2236 		
       
  2237 		// check and uncheck boxes
       
  2238 		new MenuItem(contextMenu, SWT.SEPARATOR);
       
  2239 		getCheckRows(contextMenu, this.table.getSelectionCount() > 0);
       
  2240 		
       
  2241 		// select all, copy, and copy all
       
  2242 		new MenuItem(contextMenu, SWT.SEPARATOR);
       
  2243 		getSelectAllItem(contextMenu, this.table.getItemCount() > 0);
       
  2244 		getCopyItem(contextMenu, this.table.getSelectionCount() > 0);
       
  2245 		getCopyTableItem(contextMenu, this.table.getItemCount() > 0);
       
  2246 		
       
  2247 		// copy drilldown tables, if in drilldown mode
       
  2248 		switch (drawMode)
       
  2249 		{
       
  2250 			case Defines.THREADS:
       
  2251 			case Defines.BINARIES:
       
  2252 			case Defines.FUNCTIONS:
       
  2253 				getCopyDrilldownItem(contextMenu, false);
       
  2254 				break;
       
  2255 			default:
       
  2256 				getCopyDrilldownItem(contextMenu, true);
       
  2257 				break;
       
  2258 		}
       
  2259 		
       
  2260 		// save all and save drilldown tables, if in drilldown mode
       
  2261 		new MenuItem(contextMenu, SWT.SEPARATOR);
       
  2262 		getSaveTableItem(contextMenu, this.table.getItemCount() > 0);
       
  2263 		
       
  2264 		switch (drawMode)
       
  2265 		{
       
  2266 			case Defines.THREADS:
       
  2267 			case Defines.BINARIES:
       
  2268 			case Defines.FUNCTIONS:
       
  2269 				getSaveDrilldownItem(contextMenu, false);
       
  2270 				break;
       
  2271 			default:
       
  2272 				getSaveDrilldownItem(contextMenu, true);
       
  2273 				break;
       
  2274 		}
       
  2275 		
       
  2276 		double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
  2277 		double endTime   = PIPageEditor.currentPageEditor().getEndTime();
       
  2278 
       
  2279 		// save raw samples
       
  2280 		boolean haveSamples = false;
       
  2281 		for (int i = 0; !haveSamples && i < profiledThreads.size(); i++) {
       
  2282 			ProfiledGeneric pg = profiledThreads.get(i);
       
  2283 			haveSamples = pg.isEnabled(graphIndex) && pg.getSampleCount(graphIndex) > 0;
       
  2284 		}
       
  2285 		
       
  2286 		if (!haveSamples || (startTime == -1) || (endTime   == -1) || (startTime == endTime))
       
  2287 			getSaveSamplesItem(contextMenu, Messages.getString("AddrThreadTable.threads"), false); //$NON-NLS-1$
       
  2288 		else
       
  2289 			getSaveSamplesItem(contextMenu, Messages.getString("AddrThreadTable.threads"), true); //$NON-NLS-1$
       
  2290 		
       
  2291 		// save priority samples
       
  2292 		if (priorityAdded) {
       
  2293 			if (!haveSamples || (startTime == -1) || (endTime   == -1) || (startTime == endTime))
       
  2294 				getSavePrioritySamplesItem(contextMenu, false);
       
  2295 			else
       
  2296 				getSavePrioritySamplesItem(contextMenu, true);
       
  2297 		}
       
  2298 
       
  2299 		// recolor selected threads
       
  2300 		switch (drawMode)
       
  2301 		{
       
  2302 			case Defines.THREADS:
       
  2303 			case Defines.BINARIES_THREADS:
       
  2304 			case Defines.BINARIES_FUNCTIONS_THREADS:
       
  2305 			case Defines.FUNCTIONS_THREADS:
       
  2306 			case Defines.FUNCTIONS_BINARIES_THREADS:
       
  2307 			{
       
  2308 				// recolor selected items
       
  2309 				new MenuItem(contextMenu, SWT.SEPARATOR);
       
  2310 				getRecolorItem(contextMenu, Messages.getString("AddressPlugin.threads"),  //$NON-NLS-1$
       
  2311 								this.table.getSelectionCount() > 0);
       
  2312 				break;
       
  2313 			}
       
  2314 			case Defines.THREADS_FUNCTIONS:
       
  2315 			case Defines.THREADS_FUNCTIONS_BINARIES:
       
  2316 			case Defines.THREADS_BINARIES:
       
  2317 			case Defines.THREADS_BINARIES_FUNCTIONS:
       
  2318 			case Defines.BINARIES_THREADS_FUNCTIONS:
       
  2319 			case Defines.FUNCTIONS_THREADS_BINARIES:
       
  2320 			{
       
  2321 				break;
       
  2322 			}
       
  2323 			default:
       
  2324 				break;
       
  2325 		}
       
  2326 
       
  2327 		new MenuItem(contextMenu, SWT.SEPARATOR);
       
  2328 		getChangeThresholds(contextMenu);
       
  2329 
       
  2330 		contextMenu.setVisible(true);
       
  2331 		
       
  2332 		return contextMenu;
       
  2333 	}
       
  2334 
       
  2335 	protected void addPriorityColumn(Hashtable<Integer,String> priorities)
       
  2336 	{
       
  2337 		if (priorityAdded)
       
  2338 			return;
       
  2339 		
       
  2340 		// store the priority information
       
  2341 		this.priorityTable = priorities;
       
  2342 	    priorityValues = new Hashtable<Integer,Integer>();
       
  2343 		for (Enumeration<Integer> e = priorityTable.keys(); e.hasMoreElements();)
       
  2344 		{
       
  2345 			Integer key = e.nextElement();
       
  2346 			priorityValues.put(key, parsePriorityValue(this.priorityTable.get(key)));
       
  2347 		}
       
  2348 
       
  2349 		// if the tableViewer already exists, add a column
       
  2350 		if (   (tableViewer != null)
       
  2351 			&& (tableViewer.getTable() != null))
       
  2352 	    {
       
  2353 			Display.getDefault().syncExec( new Runnable() {
       
  2354 				public void run() {
       
  2355 					addPriorityColumn();
       
  2356 				}
       
  2357 			});	
       
  2358 	    }
       
  2359 
       
  2360 		priorityAdded = true;
       
  2361 	}
       
  2362 	
       
  2363 	private void addPriorityColumn()
       
  2364 	{
       
  2365 		TableColumn column;
       
  2366 		column = new TableColumn(tableViewer.getTable(), SWT.LEFT);
       
  2367 		column.setText(COLUMN_HEAD_PRIORITY);
       
  2368 		column.setWidth(COLUMN_WIDTH_PRIORITY);
       
  2369 		column.setData(new Integer(COLUMN_ID_PRIORITY));
       
  2370 		column.setMoveable(true);
       
  2371 		column.setResizable(true);
       
  2372 		column.addSelectionListener(new ColumnSelectionHandler());
       
  2373 	}
       
  2374 
       
  2375 	private Integer parsePriorityValue(String priorityString)
       
  2376 	{
       
  2377 		if (priorityString == null || priorityString.equals(Messages.getString("AddrThreadTable.unsolvedPriority"))) //$NON-NLS-1$
       
  2378 			return new Integer(Integer.MIN_VALUE);
       
  2379 		else
       
  2380 		{
       
  2381 			int endIndex = priorityString.indexOf(Messages.getString("AddrThreadTable.priorityStringEnding")); //$NON-NLS-1$
       
  2382 			int beginIndex = priorityString.indexOf(Messages.getString("AddrThreadTable.priorityStringStart")); //$NON-NLS-1$
       
  2383 			String value = priorityString.substring(beginIndex+2, endIndex);
       
  2384 			return new Integer(Integer.parseInt(value));
       
  2385 		}
       
  2386 	}
       
  2387 
       
  2388     // class to pass sample data to the save wizard
       
  2389     public class SavePrioritySampleString implements ISaveSamples {
       
  2390     	int graphIndex;
       
  2391     	int drawMode;
       
  2392     	boolean done = false;
       
  2393     	
       
  2394     	public SavePrioritySampleString(int graphIndex, int drawMode) {
       
  2395     		this.graphIndex = graphIndex;
       
  2396     		this.drawMode   = drawMode;
       
  2397 		}
       
  2398 
       
  2399     	public String getData() {
       
  2400     		if (done)
       
  2401     			return null;
       
  2402     		
       
  2403 			String returnString = getPrioritySampleString(graphIndex, drawMode);
       
  2404 			done = true;
       
  2405 			return returnString;
       
  2406 		}
       
  2407 
       
  2408 		public String getData(int size) {
       
  2409  			return getData();
       
  2410 		}
       
  2411 
       
  2412 		public int getIndex() {
       
  2413 			return done ? 1 : 0;
       
  2414 		}
       
  2415 
       
  2416 		public void clear() {
       
  2417 			done = false;
       
  2418 		}
       
  2419     }
       
  2420     
       
  2421     protected class PrioritySample {
       
  2422     	int time;
       
  2423     	ProfiledThread pt;
       
  2424     	String priorityString;
       
  2425     	
       
  2426     	PrioritySample(int time, ProfiledThread pt, String priorityString) {
       
  2427     		this.time = time;
       
  2428     		this.pt   = pt;
       
  2429     		this.priorityString = priorityString;
       
  2430     	}
       
  2431     }
       
  2432 
       
  2433     protected void createPrioritySample(ArrayList<PrioritySample> prioritySamples, int graphIndex, ProfiledThread pt, int startTime, int endTime) {
       
  2434     	PrioritySample localSample = null;
       
  2435     	boolean addedLocalSample = false;
       
  2436     	String priority = priorityTable.get(new Integer(pt.getThreadId()));
       
  2437 		
       
  2438 		if (priority == null) {
       
  2439 			prioritySamples.add(new PrioritySample(0, pt, Messages.getString("AddrThreadTable.unknownPriority"))); //$NON-NLS-1$
       
  2440 			return;
       
  2441 		}
       
  2442 		
       
  2443 		localSample = new PrioritySample(0, pt, Messages.getString("AddrThreadTable.unrecordedPriority")); //$NON-NLS-1$
       
  2444 		addedLocalSample = false;
       
  2445 		
       
  2446 		while (priority.indexOf('(') != -1) {
       
  2447 			while (priority.charAt(0) == ' ')		// remove leading spaces
       
  2448 				priority = priority.substring(1);
       
  2449 			
       
  2450 			int nextMatch = priority.indexOf('(');
       
  2451 			String priorityStr = priority.substring(0, nextMatch);	// priority is before the open paren
       
  2452 			priority = priority.substring(nextMatch + 1);			// consume the paren, too 
       
  2453 			
       
  2454 			nextMatch = priority.indexOf(')');
       
  2455 			String timeStr = priority.substring(0, nextMatch - 1);
       
  2456 			
       
  2457 			double d = Double.parseDouble(timeStr) * 1000.0; 
       
  2458 			int time = (int) d;
       
  2459 			
       
  2460 			if (time > endTime) {
       
  2461 				// we're past the end
       
  2462 				if (!addedLocalSample) {
       
  2463 					// previous priority was before the start time, but include it anyway
       
  2464 					prioritySamples.add(localSample);
       
  2465 					return;
       
  2466 				}
       
  2467 			} else if (time < startTime) {
       
  2468 				// we're before the start
       
  2469 				// only keep the priority closest to the start time
       
  2470 				localSample = new PrioritySample(time, pt, priorityStr);
       
  2471 			} else {
       
  2472 				// we're in the interval, so add the previous sample, if needed
       
  2473 				if (!addedLocalSample && time != startTime)
       
  2474 					prioritySamples.add(localSample);
       
  2475 
       
  2476 				localSample = new PrioritySample(time, pt, priorityStr);
       
  2477 				prioritySamples.add(localSample);
       
  2478 				addedLocalSample = true;
       
  2479 			}
       
  2480 			priority = priority.substring(nextMatch + 1);
       
  2481 		}
       
  2482 		
       
  2483 		if (localSample != null && !addedLocalSample)
       
  2484 			prioritySamples.add(localSample);
       
  2485     }
       
  2486     
       
  2487     protected class PrioritySampleCompare implements Comparator<PrioritySample> {
       
  2488     	public int compare(PrioritySample ps1, PrioritySample ps2) {
       
  2489     		try {
       
  2490     			if (ps1.time == ps2.time)
       
  2491     				return ps1.pt.getNameString().compareToIgnoreCase(ps2.pt.getNameString());
       
  2492     			else
       
  2493     				return ps1.time - ps2.time;
       
  2494     		} catch (Exception e) {
       
  2495     			return 0;
       
  2496     		}
       
  2497     	}
       
  2498     }
       
  2499     
       
  2500 	protected String getPrioritySampleString(int graphIndex, int drawMode)
       
  2501 	{
       
  2502 		GppTraceGraph graph = (GppTraceGraph)(this.myGraph);
       
  2503 		GppTrace trace = (GppTrace)(graph.getTrace());
       
  2504 		
       
  2505 		int startIndex = trace.getStartSampleIndex();
       
  2506 		int endIndex   = trace.getEndSampleIndex();
       
  2507 
       
  2508 		ArrayList<PrioritySample> prioritySamples = new ArrayList<PrioritySample>();
       
  2509 		ProfiledThread pt;
       
  2510 		
       
  2511 		for (int i = 0; i < profiledThreads.size(); i++) {
       
  2512 			if (!profiledThreads.get(i).isEnabled(graphIndex) || profiledThreads.get(i).getSampleCount(graphIndex) <= 0)
       
  2513 				continue;
       
  2514 
       
  2515 			if (profiledThreads.get(i) instanceof ProfiledThread) {
       
  2516 				pt = (ProfiledThread) profiledThreads.get(i);
       
  2517 
       
  2518 				createPrioritySample(prioritySamples, graphIndex, pt, startIndex, endIndex); 
       
  2519 			} else if (profiledThreads.get(i) instanceof ProfiledThreshold) {
       
  2520 				ProfiledThreshold pth = (ProfiledThreshold) profiledThreads.get(i);
       
  2521 				for (int j = 0; j < pth.getItems(graphIndex).size(); j++) {
       
  2522 					pt = (ProfiledThread) pth.getItems(graphIndex).get(j);
       
  2523 					
       
  2524 					if (pt.isEnabled(graphIndex) && pt.getSampleCount(graphIndex) > 0)
       
  2525 						createPrioritySample(prioritySamples, graphIndex, pt, startIndex, endIndex); 
       
  2526 				}
       
  2527 			}
       
  2528 		}
       
  2529 		
       
  2530 		Collections.sort(prioritySamples, new PrioritySampleCompare());
       
  2531 		
       
  2532 		String returnString = "Time (ms),Thread,Priority\n";  //$NON-NLS-1$
       
  2533 			
       
  2534 			for (PrioritySample sample : prioritySamples) {
       
  2535 				returnString +=   sample.time + "," + sample.pt.getNameString() + "," //$NON-NLS-1$ //$NON-NLS-2$
       
  2536 								+ sample.priorityString + "\n";  //$NON-NLS-1$ //$NON-NLS-2$
       
  2537 			}
       
  2538 		
       
  2539 		return returnString;
       
  2540 	}
       
  2541 }