sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.irq/src/com/nokia/carbide/cpp/pi/irq/SwiThreadTable.java
/*
* 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;
}
}