sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.irq/src/com/nokia/carbide/cpp/pi/irq/SwiThreadTable.java
changeset 5 844b047e260d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.irq/src/com/nokia/carbide/cpp/pi/irq/SwiThreadTable.java	Wed Apr 21 15:14:16 2010 +0300
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description: 
+ *
+ */
+
+package com.nokia.carbide.cpp.pi.irq;
+
+import java.awt.event.MouseEvent;
+import java.util.Vector;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
+
+/**
+ *	Software thread interrupt table 
+ */
+public class SwiThreadTable extends GenericTable implements ICheckStateListener {
+	
+	private IrqTraceGraph myGraph;
+	private Composite parent;
+	
+    protected Vector<SwiThreadWrapper> tableItemData;
+
+	// sort direction
+	private boolean sortAscending = true;
+	
+	/**
+	 * Constructor
+	 * @param myGraph irq graph
+	 * @param parent parent where table is placed
+	 */
+	public SwiThreadTable(IrqTraceGraph myGraph, Composite parent){
+		this.myGraph = myGraph;
+		this.parent  = parent;
+
+		this.tableViewer = CheckboxTableViewer.newCheckList(parent,
+  				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+		this.table = this.tableViewer.getTable();
+		
+		// add the check state handler, label provider and content provider
+		this.tableViewer.addCheckStateListener(this);
+		this.tableViewer.setLabelProvider(new SwiThreadLabelProvider(this.table));
+		this.tableViewer.setContentProvider(new TableContentProvider());
+		this.tableViewer.setSorter(new SharedSorter());
+
+		// create the columns
+		TableColumn column;
+
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, false};
+		this.table.setData("isHex", isHex); //$NON-NLS-1$
+
+		// Check column
+		column = new TableColumn(this.table, SWT.CENTER);
+		column.setText(Messages.SwiThreadTable_0);
+		column.setWidth(20);
+		column.setData(COLUMN_ID_SWI_CHECK);
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+		
+		// Thread Name column
+		column = new TableColumn(this.table, SWT.LEFT);
+		column.setText(Messages.SwiThreadTable_1);
+		column.setWidth(COLUMN_WIDTH_THREAD_IRQ_LINE);
+		column.setData(COLUMN_ID_SWI_THREAD);
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// Thread address
+		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
+		column.setText(Messages.SwiThreadTable_2);
+		column.setWidth(COLUMN_WIDTH_ADDRESS_COUNT);
+		column.setData(COLUMN_ID_ADDRESS);
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// add mouse listener and set other table settings
+		this.table.addMouseListener(new TableMouseListener());
+		this.table.setHeaderVisible(true);
+		this.table.setLinesVisible(true);
+		this.table.setRedraw(true);
+		
+		// format data into table
+		this.updateItemData(true);
+		((SharedSorter) tableViewer.getSorter()).doSort(COLUMN_ID_SWI_THREAD);
+
+		// Select initially no lines
+		this.tableViewer.setAllChecked(false);
+		
+		// listen for key sequences such as Ctrl-A and Ctrl-C
+		table.addKeyListener(new TableKeyListener());
+		
+		tableViewer.refresh();
+		table.redraw();
+	}
+	
+	
+	/**
+	 * Content provider for table
+	 */
+	private static class TableContentProvider implements IStructuredContentProvider {
+		
+		/**
+		 * Constructor
+		 */
+		public TableContentProvider() {
+			super();
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+		 */
+		@SuppressWarnings("unchecked")
+		public Object[] getElements(Object inputElement) {
+			return ((Vector<SwiThreadWrapper>) inputElement).toArray();
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+		 */
+		public void dispose() {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+		 */
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.visual.GenericTable#action(java.lang.String)
+	 */
+	public void action(String actionString)
+	{
+		if (actionString.equals("add")){ //$NON-NLS-1$
+			checkOrUncheckSelectedItems(true);
+		}
+		else if (actionString.equals("remove")){ //$NON-NLS-1$
+			checkOrUncheckSelectedItems(false);
+		}
+		else if (actionString.equals("addall")){ //$NON-NLS-1$
+			checkOrUncheckAllItems(true);
+		}
+		else if (actionString.equals("removeall")){ //$NON-NLS-1$
+			checkOrUncheckAllItems(false);
+		}
+	    else if (actionString.equals("copy")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return; // no redraw needed
+	    }
+	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return; // no redraw needed
+	    }
+		else if (actionString.equals("selectAll")) //$NON-NLS-1$
+	    {
+	    	actionSelectAll();
+	        return;
+	    }
+		
+	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(false, this.table, CHECKBOX_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return; // no redraw needed
+	    }
+	}
+	
+	/**
+	 * Checks or unchecks all selected threads from table
+	 * @param value true if items are checked 
+	 */
+	private void checkOrUncheckSelectedItems(boolean value)
+	{
+		
+		TableItem[] selectedItems = this.table.getSelection();
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			if(selectedItems[i].getData().getClass() == SwiThreadWrapper.class){
+				selectedItems[i].setChecked(value);
+				SwiThreadWrapper wrapper = (SwiThreadWrapper)selectedItems[i].getData();
+				if(value){
+					myGraph.threadChecked(wrapper.threadName);
+				}
+				else{
+					myGraph.threadUnchecked(wrapper.threadName);
+
+				}
+			}
+		}
+		myGraph.updateIrqCountsInLegendsAsynch(IrqTraceGraph.TYPE_SWI);
+		myGraph.repaint();
+
+	}
+	
+	/**
+	 * Checks or unchecks all table items
+	 * @param value true if all items are checked
+	 */
+	private void checkOrUncheckAllItems(boolean value)
+	{
+		
+		TableItem[] allItems = this.table.getItems();
+		for (int i = 0; i < allItems.length; i++)
+		{
+			if(allItems[i].getData().getClass() == SwiThreadWrapper.class){
+				allItems[i].setChecked(value);
+				SwiThreadWrapper wrapper = (SwiThreadWrapper)allItems[i].getData();
+				if(value){
+					myGraph.threadChecked(wrapper.threadName);
+				}
+				else{
+					myGraph.threadUnchecked(wrapper.threadName);
+
+				}
+			}
+
+			
+		}
+		myGraph.repaint();
+		myGraph.updateIrqCountsInLegendsAsynch(IrqTraceGraph.TYPE_SWI);
+
+	}
+	
+	/**
+	 * Formats item data into table
+	 * @param setInput true if table needs to be refreshed
+	 */
+	public void updateItemData(boolean setInput)
+	{
+		tableItemData = ((IrqTrace)this.myGraph.getTrace()).getAllThreadWrappers();
+
+		// refresh the table, if needed
+		if (setInput)
+			refreshTableViewer();
+	}
+	
+	/**
+	 * Refreshes table viewer
+	 */
+	public void refreshTableViewer()
+	{
+		this.tableViewer.setInput(tableItemData);
+	}
+
+	/**
+	 * @return tableviewer of the thread table
+	 */
+	public CheckboxTableViewer getTableViewer(){
+		return this.tableViewer;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
+	 */
+	public void checkStateChanged(CheckStateChangedEvent event) {
+		if(event.getElement().getClass() == SwiThreadWrapper.class){
+			SwiThreadWrapper wrapper = (SwiThreadWrapper) event.getElement();
+			if(event.getChecked()){
+				myGraph.threadChecked(wrapper.threadName);
+			}
+			else{
+				myGraph.threadUnchecked(wrapper.threadName);
+			}
+			myGraph.repaint();
+			myGraph.updateIrqCountsInLegendsAsynch(IrqTraceGraph.TYPE_SWI);
+			
+		}
+		
+	}
+	
+	/**
+	 * Mouse listener of the table
+	 */
+	private class TableMouseListener implements MouseListener
+	{
+		/*
+		 * (non-Javadoc)
+		 * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+		 */
+		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
+			
+		}
+		
+		/*
+		 * (non-Javadoc)
+		 * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+		 */
+		public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
+		}
+		
+		/*
+		 * (non-Javadoc)
+		 * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+		 */
+		public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
+
+			if (e.button == MouseEvent.BUTTON3) {
+				// get rid of last Menu created so we don't have double menu
+				// on click
+				if (contextMenu != null) {
+					contextMenu.dispose();
+				}
+
+				contextMenu = new Menu(table.getShell(), SWT.POP_UP);
+				getCheckRows(contextMenu, table.getSelectionCount() > 0);
+				
+				
+				// select all, copy, and copy all
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getSelectAllItem(contextMenu, table.getItemCount() > 0);
+				getCopyItem(contextMenu, table.getSelectionCount() > 0);
+				getCopyTableItem(contextMenu, table.getItemCount() > 0);
+
+				// save all
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getSaveTableItem(contextMenu, table.getItemCount() > 0);
+				
+				// Recolor highlighted items
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getRecolorItem(contextMenu, Messages.SwiThreadTable_3, table.getSelectionCount() > 0);
+
+				contextMenu.setLocation(parent.toDisplay(e.x + table.getLocation().x, e.y + table.getLocation().y));
+			    contextMenu.setVisible(true);
+
+			    table.setMenu(contextMenu);
+			}
+		}
+	}
+	
+	/**
+	 * Column selection handler for the table
+	 */
+	private class ColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	if (!(e.widget instanceof TableColumn))
+        		return;
+        	
+        	sortOnColumnSelection((TableColumn) e.widget);
+        }
+	}
+	
+	/**
+	 * @param tableColumn which column is sorted
+	 */
+	public void sortOnColumnSelection(TableColumn tableColumn) {
+    	int columnID = ((Integer) tableColumn.getData()).intValue();
+    	((SharedSorter) tableViewer.getSorter()).doSort(columnID);
+
+		this.refreshTableViewer();
+		this.table.redraw();
+	}
+	
+	/**
+	 * Sorter for the table
+	 */
+	private class SharedSorter extends ViewerSorter {
+		// last column sorted
+		private int column = -1;
+		
+		/* 
+		 * decide on which column to sort by, and the sort ordering
+		 */
+		public void doSort(int column) {
+			// ignore the column passed in and use the id set by the column selection handler
+			if (column == this.column) {
+				// sort in other order
+				sortAscending = !sortAscending;
+			} else {
+				// changed columns, so sort in the default order
+				switch (column) {
+					case COLUMN_ID_SWI_CHECK:
+					{
+		            	// sort in ascending order
+		            	sortAscending = true;
+		                break;
+					}
+					case COLUMN_ID_SWI_THREAD:
+					case COLUMN_ID_ADDRESS:
+					{
+		            	// sort in descending order
+		            	sortAscending = false;
+		                break;
+					}
+					default:
+					{
+						// ignore the column
+						return;
+					}
+				}
+				this.column = column;
+			}
+
+			// find the TableColumn corresponding to column, and give it a column direction
+			TableColumn sortByColumn = null;
+			for (int i = 0; i < table.getColumnCount(); i++) {
+				if (table.getColumn(i).getData() instanceof Integer) {
+					if (((Integer)table.getColumn(i).getData()) == column) {
+						sortByColumn = table.getColumn(i);
+						break;
+					}
+				}
+			}
+
+			if (sortByColumn != null) {
+				table.setSortColumn(sortByColumn);
+				table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
+			}
+		}
+		
+		/*
+		 * compare two items from a table column
+		 */
+		public int compare(Viewer viewer, Object e1, Object e2) {
+			int returnCode = 0;
+			
+			SwiThreadWrapper elem1 = (SwiThreadWrapper)e1;
+			SwiThreadWrapper elem2 = (SwiThreadWrapper)e2;
+
+			// find the memory information for the two threads
+			
+			// compare based on the memory information
+			switch (column) {
+			case COLUMN_ID_SWI_CHECK:
+				if(tableViewer.getChecked(e1) == true && tableViewer.getChecked(e2) == false){
+					returnCode = -1;
+				}
+				else{
+					returnCode = 1;
+				}
+				break;
+			case COLUMN_ID_SWI_THREAD:
+				returnCode = elem1.threadName.compareToIgnoreCase(elem2.threadName);
+				break;
+			case COLUMN_ID_ADDRESS:
+				returnCode = elem1.threadAddress > elem2.threadAddress ? 1 : -1;
+				break;
+			default:
+				break;
+			}
+
+			// for descending order, reverse the sense of the compare
+			if (!sortAscending)
+				returnCode = -returnCode;
+
+			return returnCode;
+		}
+	}
+	
+	
+	/**
+	 * sets sort direction
+	 * @param sortAscending new sort direction
+	 */
+	public void setSortAscending(boolean sortAscending) {
+		this.sortAscending = sortAscending;
+	}
+	
+}