sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.irq/src/com/nokia/carbide/cpp/pi/irq/IrqLineTable.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.Enumeration;
import java.util.Hashtable;
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.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
/**
* Table for irq lines
*/
public class IrqLineTable extends GenericTable implements ICheckStateListener {
/* sort direction */
private boolean sortAscending = true;
/* Graph */
private IrqTraceGraph myGraph;
/* Parent component where ui components are placed */
private Composite parent;
/* item data for table */
protected Vector<IrqSampleTypeWrapper> tableItemData;
/**
* Constructor
*
* @param myGraph
* graph
* @param parent
* Parent component where ui components are placed
*/
public IrqLineTable(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 IrqLineLabelProvider(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 and color column
column = new TableColumn(this.table, SWT.CENTER);
column.setText(Messages.IrqLineTable_0);
column.setWidth(COLUMN_WIDTH_CHECK_COLUMN);
column.setData(COLOR_COLUMN_INDEX);
column.setMoveable(true);
column.setResizable(true);
column.addSelectionListener(new ColumnSelectionHandler());
// Thread line column
column = new TableColumn(this.table, SWT.LEFT);
column.setText(Messages.IrqLineTable_1);
column.setWidth(COLUMN_WIDTH_THREAD_IRQ_LINE);
column.setData(COLUMN_ID_IRQ_LINE);
column.setMoveable(true);
column.setResizable(true);
column.addSelectionListener(new ColumnSelectionHandler());
// Return address
column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
column.setText(Messages.IrqLineTable_2);
column.setWidth(COLUMN_WIDTH_ADDRESS_COUNT);
column.setData(COLUMN_ID_IRQ_COUNT);
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_IRQ_COUNT);
// 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();
this.addColor();
}
/**
* 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<IrqSampleTypeWrapper>) 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(Messages.IrqLineTable_3)) {
actionRecolor();
} 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 irq lines from table
*
* @param value
* true if items are checked
*/
private void checkOrUncheckSelectedItems(boolean value) {
// go thru selected items from thread table and notify graph that
// threads are checked or unchecked
TableItem[] selectedItems = this.table.getSelection();
for (int i = 0; i < selectedItems.length; i++) {
if (selectedItems[i].getData().getClass() == IrqSampleTypeWrapper.class) {
selectedItems[i].setChecked(value);
IrqSampleTypeWrapper wrapper = (IrqSampleTypeWrapper) selectedItems[i]
.getData();
if (value) {
myGraph.irqLineChecked(wrapper);
} else {
myGraph.irqLineUnchecked(wrapper);
}
}
}
myGraph.updateIrqCountsInLegendsAsynch(IrqTraceGraph.TYPE_IRQ);
myGraph.repaint();
}
/**
* Checks or unchecks all table items
*
* @param value
* true if all items are checked
*/
private void checkOrUncheckAllItems(boolean value) {
// go thru all items from thread table and notify graph that threads are
// checked or unchecked
TableItem[] allItems = this.table.getItems();
for (int i = 0; i < allItems.length; i++) {
if (allItems[i].getData().getClass() == IrqSampleTypeWrapper.class) {
allItems[i].setChecked(value);
IrqSampleTypeWrapper wrapper = (IrqSampleTypeWrapper) allItems[i]
.getData();
if (value) {
myGraph.irqLineChecked(wrapper);
} else {
myGraph.irqLineUnchecked(wrapper);
}
}
}
myGraph.updateIrqCountsInLegendsAsynch(IrqTraceGraph.TYPE_IRQ);
myGraph.repaint();
}
/**
* Updates item data to table
*
* @param setInput
* true if table needs to be refreshed
*/
public void updateItemData(boolean setInput) {
// get sample type wrappers from irq trace
tableItemData = new Vector<IrqSampleTypeWrapper>();
Hashtable<Long, IrqSampleTypeWrapper> irqLines = this.myGraph
.getIrqTrace().getIrqTable();
// create table item for each sample type wrapper
Enumeration<Long> k = irqLines.keys();
while (k.hasMoreElements()) {
IrqSampleTypeWrapper threadValue = (IrqSampleTypeWrapper) irqLines
.get(k.nextElement());
tableItemData.add(threadValue);
}
// refresh the table, if needed
if (setInput)
refreshTableViewer();
}
/**
* Refreshes table viewer
*/
public void refreshTableViewer() {
this.tableViewer.setInput(tableItemData);
this.addColor();
}
/**
* @return table viewer
*/
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() == IrqSampleTypeWrapper.class) {
IrqSampleTypeWrapper irqLine = (IrqSampleTypeWrapper) event
.getElement();
if (event.getChecked()) {
myGraph.irqLineChecked(irqLine);
} else {
myGraph.irqLineUnchecked(irqLine);
}
myGraph.repaint();
myGraph.updateIrqCountsInLegendsAsynch(IrqTraceGraph.TYPE_IRQ);
}
}
/**
* Adds colors into irq line table
*/
public void addColor() {
if (this.tableViewer == null)
return;
IrqSampleTypeWrapper pGeneric;
TableItem[] items = this.table.getItems();
for (int i = 0; i < items.length; i++) {
if (items[i].getData().getClass() == IrqSampleTypeWrapper.class) {
pGeneric = (IrqSampleTypeWrapper) items[i].getData();
items[i].setBackground(COLOR_COLUMN_INDEX, new Color(parent
.getDisplay(), pGeneric.rgb));
}
}
table.redraw();
}
/**
* MouseListener for 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.IrqLineTable_4, table
.getSelectionCount() > 0);
contextMenu.setLocation(parent.toDisplay(e.x
+ table.getLocation().x, e.y + table.getLocation().y));
contextMenu.setVisible(true);
table.setMenu(contextMenu);
}
}
}
/**
* ColumnselectionHandler for irq columns
*/
private class ColumnSelectionHandler extends SelectionAdapter {
/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
* .swt.events.SelectionEvent)
*/
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 irq 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 COLOR_COLUMN_INDEX: {
// sort in ascending order
sortAscending = true;
break;
}
case COLUMN_ID_IRQ_LINE:
case COLUMN_ID_IRQ_COUNT: {
// 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;
IrqSampleTypeWrapper elem1 = (IrqSampleTypeWrapper) e1;
IrqSampleTypeWrapper elem2 = (IrqSampleTypeWrapper) e2;
// find the information for the two irq lines
// compare based on the memory information
switch (column) {
case COLOR_COLUMN_INDEX:
if (tableViewer.getChecked(e1) == true
&& tableViewer.getChecked(e2) == false) {
returnCode = -1;
} else {
returnCode = 1;
}
break;
case COLUMN_ID_IRQ_LINE:
returnCode = elem1.getPrototypeSample().getIrqL1Value() > elem2
.getPrototypeSample().getIrqL1Value() ? 1 : -1;
break;
case COLUMN_ID_IRQ_COUNT:
returnCode = elem1.count > elem2.count ? 1 : -1;
break;
default:
break;
}
// for descending order, reverse the sense of the compare
if (!sortAscending)
returnCode = -returnCode;
return returnCode;
}
}
/**
* Action for opening color dialog for all selected irq lines.
*/
private void actionRecolor() {
// go thru selected items and open color dialog for each.
TableItem[] selection = table.getSelection();
for (TableItem item : selection) {
if (item.getData().getClass() == IrqSampleTypeWrapper.class) {
IrqSampleTypeWrapper wrapper = (IrqSampleTypeWrapper) item
.getData();
ColorDialog colorDialog = new ColorDialog(
this.table.getShell(), SWT.PRIMARY_MODAL);
// set name of the irq line as topic of the dialog
colorDialog.setText(IrqSampleTypeWrapper.getLineText(wrapper
.getPrototypeSample().getIrqL1Value()));
RGB color = colorDialog.open();
// if OK pressed, save new color into trace and set editor as
// dirty
if (color != null && color != wrapper.rgb) {
// ensure that color is not yet assigned for another
// thread/irq line
if (!myGraph.getIrqTrace().getColorSet().contains(color)) {
myGraph.getIrqTrace().changeColorOfThreadOrIRQLine(
wrapper, color);
} else {
// if same color was alreadyassigned for another
// thread/irq line, show error message
MessageBox errorDialog = new MessageBox(this.table
.getShell(), SWT.ICON_ERROR | SWT.OK);
errorDialog.setText(Messages.IrqLineTable_5);
errorDialog
.setMessage(Messages.IrqLineTable_6);
errorDialog.open();
}
}
}
}
this.myGraph.repaint();
myGraph.getIrqTrace().updateAllTableViewers();
}
/**
* sets sort direction
*
* @param sortAscending
* new sort direction
*/
public void setSortAscending(boolean sortAscending) {
this.sortAscending = sortAscending;
}
}