sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemThreadTable.java
changeset 2 b9ab3b238396
child 5 844b047e260d
equal deleted inserted replaced
1:1050670c6980 2:b9ab3b238396
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of the License "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description: 
       
    15  *
       
    16  */
       
    17 
       
    18 package com.nokia.carbide.cpp.pi.memory;
       
    19 
       
    20 import java.awt.Toolkit;
       
    21 import java.awt.datatransfer.Clipboard;
       
    22 import java.awt.datatransfer.StringSelection;
       
    23 import java.awt.event.ActionEvent;
       
    24 import java.awt.event.FocusEvent;
       
    25 import java.awt.event.MouseEvent;
       
    26 import java.text.DecimalFormat;
       
    27 import java.util.ArrayList;
       
    28 import java.util.HashSet;
       
    29 import java.util.Iterator;
       
    30 import java.util.Vector;
       
    31 
       
    32 import org.eclipse.jface.action.Action;
       
    33 import org.eclipse.jface.action.ActionContributionItem;
       
    34 import org.eclipse.jface.action.IAction;
       
    35 import org.eclipse.jface.action.IContributionManager;
       
    36 import org.eclipse.jface.action.IMenuManager;
       
    37 import org.eclipse.jface.action.SubMenuManager;
       
    38 import org.eclipse.jface.viewers.CheckStateChangedEvent;
       
    39 import org.eclipse.jface.viewers.CheckboxTableViewer;
       
    40 import org.eclipse.jface.viewers.ICheckStateListener;
       
    41 import org.eclipse.jface.viewers.IStructuredContentProvider;
       
    42 import org.eclipse.jface.viewers.ITableLabelProvider;
       
    43 import org.eclipse.jface.viewers.LabelProvider;
       
    44 import org.eclipse.jface.viewers.Viewer;
       
    45 import org.eclipse.jface.viewers.ViewerSorter;
       
    46 import org.eclipse.swt.SWT;
       
    47 import org.eclipse.swt.events.FocusListener;
       
    48 import org.eclipse.swt.events.MouseListener;
       
    49 import org.eclipse.swt.events.SelectionAdapter;
       
    50 import org.eclipse.swt.events.SelectionEvent;
       
    51 import org.eclipse.swt.graphics.Image;
       
    52 import org.eclipse.swt.layout.GridData;
       
    53 import org.eclipse.swt.widgets.Composite;
       
    54 import org.eclipse.swt.widgets.Display;
       
    55 import org.eclipse.swt.widgets.Menu;
       
    56 import org.eclipse.swt.widgets.MenuItem;
       
    57 import org.eclipse.swt.widgets.Table;
       
    58 import org.eclipse.swt.widgets.TableColumn;
       
    59 import org.eclipse.swt.widgets.TableItem;
       
    60 import org.eclipse.ui.IActionBars;
       
    61 import org.eclipse.ui.actions.ActionFactory;
       
    62 import org.eclipse.ui.ide.IIDEActionConstants;
       
    63 
       
    64 import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
       
    65 import com.nokia.carbide.cpp.internal.pi.memory.actions.MemoryStatisticsDialog;
       
    66 import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
       
    67 import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
       
    68 import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
       
    69 
       
    70 
       
    71 public class MemThreadTable extends GenericTable
       
    72 {
       
    73 	private static final int COLUMN_ID_MEMORY_CHUNKS  = 14;
       
    74 	private static final int COLUMN_ID_MEMORY_STACK   = 15;
       
    75 	private static final int COLUMN_ID_MEMORY_TOTAL   = 16;
       
    76 	private static final int COLUMN_ID_MEMORY_NAME    = 17;
       
    77 
       
    78 	// sort direction
       
    79 	private boolean sortAscending = true;
       
    80 	
       
    81 	// trace associated with this display
       
    82 //	private MemTrace myTrace;
       
    83 	private MemTraceGraph myGraph;
       
    84 	private Composite parent;
       
    85 
       
    86 	// override
       
    87     protected Vector<MemThread> tableItemData;
       
    88 
       
    89     // menu items
       
    90 	private Action selectAllAction;
       
    91 	private Action copyTableAction;
       
    92 	private Action copyAction;
       
    93 	private Action saveTableAction;
       
    94 	
       
    95 	// class to pass sample data to the save wizard
       
    96     public class SaveSampleString implements ISaveSamples {
       
    97     	boolean done = false;
       
    98     	
       
    99     	public SaveSampleString() {
       
   100 		}
       
   101 
       
   102     	public String getData() {
       
   103     		if (done)
       
   104     			return null;
       
   105     		
       
   106 			String returnString = getSampleString();
       
   107 			done = true;
       
   108 			return returnString;
       
   109 		}
       
   110 
       
   111 		public String getData(int size) {
       
   112 			return getData();
       
   113 		}
       
   114 
       
   115 		public int getIndex() {
       
   116 			return done ? 1 : 0;
       
   117 		}
       
   118 
       
   119 		public void clear() {
       
   120 			done = false;
       
   121 		}
       
   122     }
       
   123 
       
   124 	/*
       
   125 	 * return the memory samples selected in the interval 
       
   126 	 */
       
   127 	protected String getSampleString()
       
   128 	{
       
   129 		int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0 + 0.0005);
       
   130 		int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0 + 0.0005);
       
   131 		
       
   132 		MemTrace trace = this.myGraph.getMemTrace();
       
   133 		ArrayList<MemSampleByTime> drawDataByTime = trace.getDrawDataByTime();
       
   134 		
       
   135 		if (drawDataByTime == null || drawDataByTime.size() == 0)
       
   136 			return "";	// should have been checked so this never happens //$NON-NLS-1$
       
   137 		
       
   138 		String returnString = Messages.getString("MemThreadTable.saveSamplesHeading"); //$NON-NLS-1$
       
   139 
       
   140 		if (drawDataByTime.get(0).getTime() > startTime) {
       
   141 			int graphIndex = this.myGraph.getGraphIndex();
       
   142 			TableItem[] items = this.table.getItems();
       
   143 			
       
   144 			for (int i = 0; i < items.length; i++) {
       
   145 				Object data = items[i].getData();
       
   146 				
       
   147 				if (!(data instanceof MemThread))
       
   148 					continue;
       
   149 				
       
   150 				MemThread pmt = (MemThread) data;
       
   151 				
       
   152 				if (!pmt.enabled[graphIndex])
       
   153 					continue;
       
   154 				
       
   155 				returnString +=   Messages.getString("MemThreadTable.notRecorded1") + items[i].getText() + Messages.getString("MemThreadTable.notRecorded2"); //$NON-NLS-1$ //$NON-NLS-2$
       
   156 			}
       
   157 		}
       
   158 		
       
   159 		// find least sampling time greater than or equal to the start time
       
   160 		int i = 0;
       
   161 		long sampleTime = 0;
       
   162 		for ( ; i < drawDataByTime.size(); i++)	{
       
   163 			sampleTime = drawDataByTime.get(i).getTime(); 
       
   164 			if (sampleTime > startTime)
       
   165 				break;
       
   166 		}
       
   167 		
       
   168 		if (i != 0)
       
   169 			i--;
       
   170 
       
   171 		int graphIndex = myGraph.getGraphIndex();
       
   172 		for ( ; i < drawDataByTime.size() && drawDataByTime.get(i).getTime() <= endTime; i++) {
       
   173 			ArrayList<MemSample> samples = drawDataByTime.get(i).getSamples();
       
   174 			for (MemSample sample : samples) {
       
   175 				if (!sample.thread.enabled[graphIndex])
       
   176 					continue;
       
   177 					
       
   178 				returnString +=   sample.sampleSynchTime + Messages.getString("MemThreadTable.comma") + sample.thread.fullName //$NON-NLS-1$
       
   179 								+ Messages.getString("MemThreadTable.comma") + (sample.heapSize / 1024) + Messages.getString("MemThreadTable.comma") + (sample.stackSize / 1024) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   180 			}
       
   181 		}
       
   182 
       
   183 		return returnString;
       
   184 	}
       
   185 
       
   186 	protected MenuItem getSaveSamplesItem(Menu menu, boolean enabled) {
       
   187 	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
       
   188 
       
   189 		saveSamplesItem.setText(Messages.getString("MemThreadTable.saveCheckedSamples")); //$NON-NLS-1$
       
   190 		saveSamplesItem.setEnabled(enabled);
       
   191 		
       
   192 		if (enabled) {
       
   193 			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
       
   194 				public void widgetSelected(SelectionEvent e) {
       
   195 					action("saveSamples"); //$NON-NLS-1$
       
   196 				}
       
   197 			});
       
   198 		}
       
   199 	
       
   200 		return saveSamplesItem;
       
   201 	}
       
   202 
       
   203 	public MemThreadTable(MemTraceGraph myGraph, Composite parent)
       
   204 	{
       
   205 		this.myGraph = myGraph;
       
   206 		this.parent  = parent;
       
   207 
       
   208 		this.tableViewer = CheckboxTableViewer.newCheckList(parent,
       
   209   				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
       
   210 		this.table = this.tableViewer.getTable();
       
   211 		this.table.setLayoutData(new GridData(GridData.FILL_BOTH));
       
   212 		
       
   213 		// add the check state handler, label provider and content provider
       
   214 		this.tableViewer.addCheckStateListener(new CheckHandler());
       
   215 		this.tableViewer.setLabelProvider(new SharedLabelProvider(this.table));
       
   216 		this.tableViewer.setContentProvider(new MemoryTableContentProvider());
       
   217 		this.tableViewer.setSorter(new SharedSorter());
       
   218 
       
   219 		// give the table a heading for possible use in copying and exported
       
   220 		this.table.setData(Messages.getString("MemThreadTable.memory")); //$NON-NLS-1$
       
   221 		
       
   222 		// create the columns
       
   223 		TableColumn column;
       
   224 
       
   225 		// data associated with the TableViewer will note which columns contain hex values
       
   226 		// Keep this in the order in which columns have been created
       
   227 		boolean[] isHex = {false, false, false, false};
       
   228 		this.table.setData("isHex", isHex); //$NON-NLS-1$
       
   229 
       
   230 		// select/deselect column
       
   231 		column = new TableColumn(this.table, SWT.CENTER);
       
   232 		column.setText(COLUMN_HEAD_MEMORY_NAME);
       
   233 		column.setWidth(COLUMN_WIDTH_MEMORY_NAME + 15); // extra space for the checkbox
       
   234 		column.setData(new Integer(COLUMN_ID_MEMORY_NAME));
       
   235 		column.setMoveable(true);
       
   236 		column.setResizable(true);
       
   237 		column.addSelectionListener(new ColumnSelectionHandler());
       
   238 
       
   239 		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
       
   240 		column.setText(COLUMN_HEAD_MEMORY_CHUNKS);
       
   241 		column.setWidth(COLUMN_WIDTH_MEMORY_CHUNKS);
       
   242 		column.setData(new Integer(COLUMN_ID_MEMORY_CHUNKS));
       
   243 		column.setMoveable(true);
       
   244 		column.setResizable(true);
       
   245 		column.addSelectionListener(new ColumnSelectionHandler());
       
   246 
       
   247 		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
       
   248 		column.setText(COLUMN_HEAD_MEMORY_STACK);
       
   249 		column.setWidth(COLUMN_WIDTH_MEMORY_STACK);
       
   250 		column.setData(new Integer(COLUMN_ID_MEMORY_STACK));
       
   251 		column.setMoveable(true);
       
   252 		column.setResizable(true);
       
   253 		column.addSelectionListener(new ColumnSelectionHandler());
       
   254 
       
   255 		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
       
   256 		column.setText(COLUMN_HEAD_MEMORY_TOTAL);
       
   257 		column.setWidth(COLUMN_WIDTH_MEMORY_TOTAL);
       
   258 		column.setData(new Integer(COLUMN_ID_MEMORY_TOTAL));
       
   259 		column.setMoveable(true);
       
   260 		column.setResizable(true);
       
   261 		column.addSelectionListener(new ColumnSelectionHandler());
       
   262 		
       
   263 		// initially, all rows are checked
       
   264 		this.tableViewer.setAllChecked(true);
       
   265 
       
   266 		this.table.addMouseListener(new TableMouseListener());
       
   267 		this.table.setHeaderVisible(true);
       
   268 		this.table.setLinesVisible(true);
       
   269 		this.table.setRedraw(true);
       
   270 		
       
   271 		updateItemData(true);
       
   272 		((SharedSorter) tableViewer.getSorter()).doSort(COLUMN_ID_MEMORY_NAME);
       
   273 
       
   274 		// initially, all rows are checked
       
   275 		this.tableViewer.setAllChecked(true);
       
   276 		
       
   277 		createDefaultActions();
       
   278 
       
   279 		// listen for key sequences such as Ctrl-A and Ctrl-C
       
   280 		table.addKeyListener(new TableKeyListener());
       
   281 		
       
   282 		table.addFocusListener(new FocusListener() {
       
   283 			IAction oldSelectAllAction = null;
       
   284 			IAction oldCopyAction = null;
       
   285 
       
   286 			public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
       
   287 				IActionBars bars = PIPageEditor.getActionBars();
       
   288 				
       
   289 				oldSelectAllAction = PIPageEditor.getActionBars().getGlobalActionHandler(ActionFactory.SELECT_ALL.getId());
       
   290 				oldCopyAction = PIPageEditor.getActionBars().getGlobalActionHandler(ActionFactory.COPY.getId());
       
   291 
       
   292 				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
       
   293 				bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction);
       
   294 
       
   295 				copyAction.setEnabled(table.getSelectionCount() > 0);
       
   296 				selectAllAction.setEnabled(table.getItemCount() > 0);
       
   297 				bars.updateActionBars();
       
   298 				
       
   299 				// add to the Edit menu
       
   300 		        IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
       
   301 
       
   302 		        if (editMenuManager instanceof SubMenuManager)
       
   303 		        {
       
   304 		        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
       
   305 		        	ActionContributionItem item;
       
   306 
       
   307 					editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
       
   308 		        	copyTableAction.setEnabled(table.getItemCount() > 0);
       
   309 		        	item = new ActionContributionItem(copyTableAction);
       
   310 		        	item.setVisible(true);
       
   311 		        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
       
   312 		        }
       
   313 				
       
   314 				// add to the File menu
       
   315 		        IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
       
   316 
       
   317 		        if (fileMenuManager instanceof SubMenuManager)
       
   318 		        {
       
   319 		        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
       
   320 		        	ActionContributionItem item;
       
   321 
       
   322 		        	fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
       
   323 		        	saveTableAction.setEnabled(table.getItemCount() > 0);
       
   324 		        	item = new ActionContributionItem(saveTableAction);
       
   325 		        	item.setVisible(true);
       
   326 		        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
       
   327 		        }
       
   328 			}
       
   329 
       
   330 			public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
       
   331 				IActionBars bars = PIPageEditor.getActionBars();
       
   332 				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
       
   333 				bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), oldSelectAllAction);
       
   334 				bars.updateActionBars();
       
   335 
       
   336 				SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
       
   337 				editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
       
   338 				editMenuManager.update();
       
   339 
       
   340 				SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
       
   341 				fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
       
   342 				fileMenuManager.update();
       
   343 			}
       
   344 		});
       
   345 
       
   346 		tableViewer.refresh();
       
   347 		table.redraw();
       
   348 	}
       
   349 
       
   350 	private class TableMouseListener implements MouseListener
       
   351 	{
       
   352 		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
       
   353 			if (e.button == MouseEvent.BUTTON1)
       
   354 			{
       
   355 				TableItem[] selectedItems = table.getSelection();
       
   356 				if (selectedItems.length == 0)
       
   357 					return;
       
   358 
       
   359 				if (selectedItems[0].getData() instanceof MemThread)
       
   360 				{
       
   361 					MemThread pMemThread = (MemThread)(selectedItems[0].getData());
       
   362 				    if (pMemThread.isEnabled(myGraph.getGraphIndex()))
       
   363 				        action("remove"); //$NON-NLS-1$
       
   364 				    else
       
   365 				        action("add"); //$NON-NLS-1$
       
   366 				}
       
   367 			}
       
   368 			selectAllAction.setEnabled(table.getItemCount() > 0);
       
   369 			copyAction.setEnabled(table.getSelectionCount() > 0);
       
   370 			copyTableAction.setEnabled(table.getItemCount() > 0);
       
   371 		}
       
   372 
       
   373 		public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
       
   374 		}
       
   375 
       
   376 		public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
       
   377 
       
   378 			selectAllAction.setEnabled(table.getItemCount() > 0);
       
   379 			copyAction.setEnabled(table.getSelectionCount() > 0);
       
   380 			copyTableAction.setEnabled(table.getItemCount() > 0);
       
   381 
       
   382 			if (e.button == MouseEvent.BUTTON3) {
       
   383 				// get rid of last Menu created so we don't have double menu
       
   384 				// on click
       
   385 				if (contextMenu != null) {
       
   386 					contextMenu.dispose();
       
   387 				}
       
   388 
       
   389 				contextMenu = new Menu(table.getShell(), SWT.POP_UP);
       
   390 				getCheckRows(contextMenu, table.getSelectionCount() > 0);
       
   391 
       
   392 				// select all, copy, and copy all
       
   393 				new MenuItem(contextMenu, SWT.SEPARATOR);
       
   394 				getSelectAllItem(contextMenu, table.getItemCount() > 0);
       
   395 				getCopyItem(contextMenu, table.getSelectionCount() > 0);
       
   396 				getCopyTableItem(contextMenu, table.getItemCount() > 0);
       
   397 				selectAllAction.setEnabled(table.getItemCount() > 0);
       
   398 				copyAction.setEnabled(table.getSelectionCount() > 0);
       
   399 				copyTableAction.setEnabled(table.getItemCount() > 0);
       
   400 				
       
   401 				// save all
       
   402 				new MenuItem(contextMenu, SWT.SEPARATOR);
       
   403 				getSaveTableItem(contextMenu, table.getItemCount() > 0);
       
   404 				saveTableAction.setEnabled(table.getItemCount() > 0);
       
   405 
       
   406 				// save samples
       
   407 				int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0f);
       
   408 				int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0f);
       
   409 
       
   410 				getSaveSamplesItem(contextMenu,
       
   411 					myGraph.haveEnabled() && (startTime != -1) && (endTime != -1) && (startTime != endTime));
       
   412 
       
   413 				contextMenu.setLocation(parent.toDisplay(e.x + table.getLocation().x, e.y + table.getLocation().y));
       
   414 			    contextMenu.setVisible(true);
       
   415 
       
   416 				new MenuItem(contextMenu, SWT.SEPARATOR);
       
   417 
       
   418 				MenuItem memoryStatsItem = new MenuItem(contextMenu, SWT.PUSH);
       
   419 				memoryStatsItem.setText(Messages.getString("MemoryPlugin.memoryStats")); //$NON-NLS-1$
       
   420 				memoryStatsItem.addSelectionListener(new SelectionAdapter() {
       
   421 					public void widgetSelected(SelectionEvent e) {
       
   422 						new MemoryStatisticsDialog(Display.getCurrent());
       
   423 					}
       
   424 				});
       
   425 
       
   426 				table.setMenu(contextMenu);
       
   427 			}
       
   428 		}
       
   429 	}
       
   430 
       
   431 	private static class MemoryTableContentProvider implements IStructuredContentProvider {
       
   432 
       
   433 		public MemoryTableContentProvider() {
       
   434 			super();
       
   435 		}
       
   436 
       
   437 		public Object[] getElements(Object inputElement) {
       
   438 			return ((Vector<MemThread>) inputElement).toArray();
       
   439 		}
       
   440 
       
   441 		public void dispose() {
       
   442 		}
       
   443 
       
   444 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
       
   445 		}
       
   446 	}
       
   447 
       
   448 	private class CheckHandler implements ICheckStateListener
       
   449 	{
       
   450 		public void checkStateChanged(CheckStateChangedEvent event) {
       
   451 
       
   452        		if (!(event.getElement() instanceof MemThread))
       
   453        			return;
       
   454        		
       
   455        		// set the stored value to the checkbox value
       
   456        		MemThread pMemThread = (MemThread)event.getElement();
       
   457        		pMemThread.setEnabled(myGraph.getGraphIndex(), event.getChecked());
       
   458 
       
   459        		selectionChangeNotify();
       
   460 
       
   461        		table.deselectAll();
       
   462 		}
       
   463 	}
       
   464 
       
   465 	void selectionChangeNotify() {
       
   466 		this.tableViewer.refresh();
       
   467 		this.table.redraw();
       
   468 		PIEvent be = new PIEvent(null, PIEvent.CHANGED_MEMORY_TABLE);
       
   469 		myGraph.piEventReceived(be);
       
   470     }
       
   471 
       
   472 	private class SharedLabelProvider extends LabelProvider implements ITableLabelProvider {
       
   473 		
       
   474         private DecimalFormat decimalFormat = new DecimalFormat(Messages.getString("MemThreadTable.kbFormat")); //$NON-NLS-1$
       
   475 
       
   476         Table table;
       
   477 
       
   478 		public SharedLabelProvider(Table table) {
       
   479 			super();
       
   480 			this.table = table;
       
   481 		}
       
   482 
       
   483 		public String getColumnText(Object element, int columnIndex) {
       
   484 	        int columnId = ((Integer) table.getColumn(columnIndex).getData()).intValue();
       
   485 
       
   486 			if (!(element instanceof MemThread))
       
   487 				return ""; //$NON-NLS-1$
       
   488 
       
   489 			MemThread profiledItem = (MemThread) element;
       
   490 			
       
   491 			switch (columnId)
       
   492 			{
       
   493 				case COLUMN_ID_MEMORY_NAME:
       
   494 				{
       
   495 					return profiledItem.fullName;
       
   496 				}
       
   497 				case COLUMN_ID_MEMORY_CHUNKS:
       
   498 			    {
       
   499 					double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
   500 					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
       
   501 
       
   502 					if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
       
   503 						return ""; //$NON-NLS-1$
       
   504 
       
   505 					return decimalFormat.format((profiledItem.maxMemoryItem.maxChunks + 512)/1024);
       
   506 			    }
       
   507 				case COLUMN_ID_MEMORY_STACK:
       
   508 			    {
       
   509 					double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
   510 					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
       
   511 
       
   512 					if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
       
   513 						return ""; //$NON-NLS-1$
       
   514 
       
   515 					return decimalFormat.format((profiledItem.maxMemoryItem.maxStackHeap + 512)/1024);
       
   516 			    }
       
   517 				case COLUMN_ID_MEMORY_TOTAL:
       
   518 			    {
       
   519 					double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
   520 					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
       
   521 
       
   522 					if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
       
   523 						return ""; //$NON-NLS-1$
       
   524 					
       
   525 					return decimalFormat.format((profiledItem.maxMemoryItem.maxTotal + 512)/1024);
       
   526 			    }
       
   527 				default:
       
   528 				{
       
   529 					break;
       
   530 				}
       
   531 			}
       
   532 			// should never get here
       
   533 			return ""; //$NON-NLS-1$
       
   534 		}
       
   535 
       
   536 		public Image getColumnImage(Object element, int columnIndex) {
       
   537 			return null;
       
   538 		}
       
   539 	}
       
   540 
       
   541 	
       
   542 	/*
       
   543 	 * TableViewer sorter for the called-by and called function tableviewers
       
   544 	 */
       
   545 	private class SharedSorter extends ViewerSorter {
       
   546 		// last column sorted
       
   547 		private int column = -1;
       
   548 		
       
   549 		/* 
       
   550 		 * decide on which column to sort by, and the sort ordering
       
   551 		 */
       
   552 		public void doSort(int column) {
       
   553 			// ignore the column passed in and use the id set by the column selection handler
       
   554 			if (column == this.column) {
       
   555 				// sort in other order
       
   556 				sortAscending = !sortAscending;
       
   557 			} else {
       
   558 				// changed columns, so sort in the default order
       
   559 				switch (column) {
       
   560 					case COLUMN_ID_MEMORY_NAME:
       
   561 					{
       
   562 		            	// sort in ascending order
       
   563 		            	sortAscending = true;
       
   564 		                break;
       
   565 					}
       
   566 					case COLUMN_ID_MEMORY_CHUNKS:
       
   567 					case COLUMN_ID_MEMORY_STACK:
       
   568 					case COLUMN_ID_MEMORY_TOTAL:
       
   569 					{
       
   570 		            	// sort in descending order
       
   571 		            	sortAscending = false;
       
   572 		                break;
       
   573 					}
       
   574 					default:
       
   575 					{
       
   576 						// ignore the column
       
   577 						return;
       
   578 					}
       
   579 				}
       
   580 				this.column = column;
       
   581 			}
       
   582 
       
   583 			// find the TableColumn corresponding to column, and give it a column direction
       
   584 			TableColumn sortByColumn = null;
       
   585 			for (int i = 0; i < table.getColumnCount(); i++) {
       
   586 				if (table.getColumn(i).getData() instanceof Integer) {
       
   587 					if (((Integer)table.getColumn(i).getData()) == column) {
       
   588 						sortByColumn = table.getColumn(i);
       
   589 						break;
       
   590 					}
       
   591 				}
       
   592 			}
       
   593 
       
   594 			if (sortByColumn != null) {
       
   595 				table.setSortColumn(sortByColumn);
       
   596 				table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
       
   597 			}
       
   598 		}
       
   599 		
       
   600 		/*
       
   601 		 * compare two items from a table column
       
   602 		 */
       
   603 		public int compare(Viewer viewer, Object e1, Object e2) {
       
   604 			int returnCode = 0;
       
   605 			
       
   606 			MemThread elem1 = (MemThread)e1;
       
   607 			MemThread elem2 = (MemThread)e2;
       
   608 
       
   609 			// find the memory information for the two threads
       
   610 			
       
   611 			// compare based on the memory information
       
   612 			switch (column) {
       
   613 			case COLUMN_ID_MEMORY_CHUNKS:
       
   614 				
       
   615 				returnCode = elem1.maxMemoryItem.maxChunks >
       
   616 									elem2.maxMemoryItem.maxChunks ? 1 : -1;
       
   617 				break;
       
   618 			case COLUMN_ID_MEMORY_STACK:
       
   619 				returnCode = elem1.maxMemoryItem.maxStackHeap >
       
   620 									elem2.maxMemoryItem.maxStackHeap ? 1 : -1;
       
   621 				break;
       
   622 			case COLUMN_ID_MEMORY_TOTAL:
       
   623 				returnCode = elem1.maxMemoryItem.maxTotal >
       
   624 									elem2.maxMemoryItem.maxTotal ? 1 : -1;
       
   625 				break;
       
   626 			case COLUMN_ID_MEMORY_NAME:
       
   627 			{
       
   628 				returnCode = this.getComparator().compare(elem1.fullName, elem2.fullName);
       
   629 				break;
       
   630 			}
       
   631 			default:
       
   632 				break;
       
   633 			}
       
   634 
       
   635 			// for descending order, reverse the sense of the compare
       
   636 			if (!sortAscending)
       
   637 				returnCode = -returnCode;
       
   638 
       
   639 			return returnCode;
       
   640 		}
       
   641 	}
       
   642 
       
   643 	public void actionPerformed(ActionEvent e) {}
       
   644 	
       
   645 	public void action(String actionString)
       
   646 	{
       
   647 		int graphIndex = this.myGraph.getGraphIndex();
       
   648 
       
   649 		if (   actionString.equals("add") //$NON-NLS-1$
       
   650 			|| actionString.equals("remove")) //$NON-NLS-1$
       
   651 	    {
       
   652 			actionAddRemove(actionString, graphIndex);
       
   653 	    }
       
   654 		else if (   actionString.equals("addall") //$NON-NLS-1$
       
   655 				 || actionString.equals("removeall")) //$NON-NLS-1$
       
   656 	    {
       
   657 			actionAddRemoveAll(actionString, graphIndex);
       
   658 	    }
       
   659 	    else if (actionString.equals("copy")) //$NON-NLS-1$
       
   660 	    {
       
   661 	    	actionCopyOrSave(true, this.table, CHECKBOX_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   662 	        return; // no redraw needed
       
   663 	    }
       
   664 	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
       
   665 	    {
       
   666 	    	actionCopyOrSave(true, this.table, CHECKBOX_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   667 	        return; // no redraw needed
       
   668 	    }
       
   669 		else if (actionString.equals("selectAll")) //$NON-NLS-1$
       
   670 	    {
       
   671 	    	actionSelectAll();
       
   672 	        return;
       
   673 	    }
       
   674 	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
       
   675 	    {
       
   676 	    	actionCopyOrSave(false, this.table, CHECKBOX_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   677 	        return; // no redraw needed
       
   678 	    }
       
   679 	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
       
   680 	    {
       
   681 	    	SaveSampleString saveSampleString = new SaveSampleString();
       
   682 	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
       
   683 	        return;
       
   684 	    }
       
   685 	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
       
   686 	    {
       
   687 			// copy save file contents to the clipboard for easy viewing
       
   688 	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
       
   689 			SaveTableString getString = new SaveTableString(this.table, CHECKBOX_TEXT, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
       
   690 	        String copyString = getString.getData();
       
   691 			StringSelection contents = new StringSelection(copyString);
       
   692 	        cb.setContents(contents, contents);
       
   693 	        return;
       
   694 	    }
       
   695 
       
   696 		tableViewer.refresh();
       
   697 	    table.redraw();
       
   698 	    this.myGraph.repaint();
       
   699 	}
       
   700 
       
   701 	private void actionAddRemove(String actionString, int graphIndex)
       
   702 	{
       
   703 		MemThread memThread;
       
   704 		
       
   705 		// true for "add", false for "remove"
       
   706 		boolean addIt = actionString.equals("add"); //$NON-NLS-1$
       
   707 
       
   708 		TableItem[] selectedItems = this.table.getSelection();
       
   709 		for (int i = 0; i < selectedItems.length; i++)
       
   710 		{
       
   711 			selectedItems[i].setChecked(addIt);
       
   712 			memThread = (MemThread)((TableItem)selectedItems[i]).getData();
       
   713 			memThread.setEnabled(graphIndex, addIt);
       
   714 		}
       
   715 
       
   716         // this table's set of checkbox-selected rows has changed,
       
   717 		// so propagate that information
       
   718   		if (selectedItems.length != 0)
       
   719    			selectionChangeNotify();
       
   720 
       
   721   		this.table.deselectAll();
       
   722 	}
       
   723 	
       
   724 	private void actionAddRemoveAll(String actionString, int graphIndex)
       
   725 	{
       
   726 		MemThread memThread;
       
   727 
       
   728 		// true for "add", false for "remove"
       
   729 		boolean addIt = actionString.equals("addall"); //$NON-NLS-1$
       
   730 
       
   731 		TableItem[] selectedItems = this.table.getItems();
       
   732 		for (int i = 0; i < selectedItems.length; i++)
       
   733 		{
       
   734 			selectedItems[i].setChecked(addIt);
       
   735 			memThread = (MemThread)((TableItem)selectedItems[i]).getData();
       
   736 			memThread.setEnabled(graphIndex, addIt);
       
   737 		}
       
   738 
       
   739         // this table's set of checkbox-selected rows has changed,
       
   740 		// so propagate that information
       
   741 		selectionChangeNotify();
       
   742 
       
   743 		this.table.deselectAll();
       
   744 	}
       
   745 
       
   746 	public void focusGained(FocusEvent e) {}
       
   747 
       
   748 	public void focusLost(FocusEvent e)	{}
       
   749 
       
   750 	public void piEventReceived(PIEvent be) 
       
   751 	{
       
   752 	    if (be.getType() == PIEvent.SELECTION_AREA_CHANGED2)
       
   753 		{
       
   754 			this.tableViewer.refresh();
       
   755 			this.table.redraw();
       
   756 		}
       
   757 	    else if (be.getType() == PIEvent.CHANGED_MEMORY_TABLE)
       
   758 		{
       
   759 //			this.tableViewer.refresh();
       
   760 //			this.table.redraw();
       
   761 		}
       
   762 	}
       
   763 
       
   764 	public void updateItemData(boolean setInput)
       
   765 	{
       
   766 		HashSet<MemThread> noDuplicateMemThreads = myGraph.getMemTrace().getNoDuplicateMemThreads();
       
   767 		if (tableItemData == null)
       
   768 			tableItemData = new Vector<MemThread>(noDuplicateMemThreads.size());
       
   769 		else
       
   770 			tableItemData.clear();
       
   771 		
       
   772 		// tableItemData contains one entry per table row
       
   773 		// the first profiled thread is the system-wide total memory information
       
   774 		for (Iterator<MemThread> iter = noDuplicateMemThreads.iterator(); iter.hasNext(); )
       
   775 		{
       
   776 			MemThread memThread = iter.next();
       
   777 			if (   (memThread.threadId != 0xffffffffbabbeaaaL)
       
   778 				&& (memThread.threadId != 0xffffffffbabbea20L))
       
   779 			{
       
   780 				tableItemData.add(memThread);
       
   781 			}
       
   782 		}
       
   783 
       
   784 		// refresh the table, if needed
       
   785 		if (setInput)
       
   786 			refreshTableViewer();
       
   787 	}
       
   788 
       
   789 	public void refreshTableViewer()
       
   790 	{
       
   791 		this.tableViewer.setInput(tableItemData);
       
   792 	}
       
   793 	
       
   794 	public void sortOnColumnSelection(TableColumn tableColumn) {
       
   795     	int columnID = ((Integer) tableColumn.getData()).intValue();
       
   796     	((SharedSorter) tableViewer.getSorter()).doSort(columnID);
       
   797 
       
   798 		tableViewer.refresh();
       
   799     	table.redraw();
       
   800 	}
       
   801 	
       
   802 	private class ColumnSelectionHandler extends SelectionAdapter
       
   803 	{
       
   804 		public void widgetSelected(SelectionEvent e)
       
   805         {
       
   806         	if (!(e.widget instanceof TableColumn))
       
   807         		return;
       
   808         	
       
   809         	sortOnColumnSelection((TableColumn) e.widget);
       
   810         }
       
   811 	}
       
   812 	
       
   813 	public CheckboxTableViewer getTableViewer()
       
   814 	{
       
   815 		return this.tableViewer;
       
   816 	}
       
   817 
       
   818 	protected void createDefaultActions()
       
   819 	{
       
   820 		selectAllAction = new Action("SelectAll") { //$NON-NLS-1$
       
   821 			public void run() {
       
   822 				action("selectAll"); //$NON-NLS-1$
       
   823 			}
       
   824 		};
       
   825 		selectAllAction.setEnabled(true);
       
   826 
       
   827 		copyAction = new Action("Copy") { //$NON-NLS-1$
       
   828 			public void run() {
       
   829 				action("copy"); //$NON-NLS-1$
       
   830 			}
       
   831 		};
       
   832 		copyAction.setEnabled(false);
       
   833 
       
   834 		copyTableAction = new Action("CopyTable") { //$NON-NLS-1$
       
   835 			public void run() {
       
   836 				action("copyTable"); //$NON-NLS-1$
       
   837 			}
       
   838 		};
       
   839 		copyTableAction.setEnabled(true);
       
   840 		copyTableAction.setId("PICopyTable"); //$NON-NLS-1$
       
   841 		copyTableAction.setText(Messages.getString("MemThreadTable.copyTable")); //$NON-NLS-1$
       
   842 
       
   843 		saveTableAction = new Action("SaveTable") { //$NON-NLS-1$
       
   844 			public void run() {
       
   845 				action("saveTable"); //$NON-NLS-1$
       
   846 			}
       
   847 		};
       
   848 		saveTableAction.setEnabled(true);
       
   849 		saveTableAction.setId("PISaveTable"); //$NON-NLS-1$
       
   850 		saveTableAction.setText(Messages.getString("MemThreadTable.SaveTable")); //$NON-NLS-1$
       
   851 	}
       
   852 }