sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.peccommon/src/com/nokia/carbide/cpp/pi/peccommon/PecCommonLegend.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.peccommon;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.SubMenuManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.ide.IIDEActionConstants;
import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveTable;
import com.nokia.carbide.cpp.internal.pi.save.SaveTableWizard;
import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
/**
* Manages the legend for Performance Counter traces.
*/
public class PecCommonLegend extends Composite{
private static final char QUOTE = '"';
private static final String PI_SAVE_TABLE = "PISaveTable";//$NON-NLS-1$
private static final String PI_COPY_TABLE = "PICopyTable";//$NON-NLS-1$
private static final String SAVE_ALL = "saveAll";//$NON-NLS-1$
private final static String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$
private static final String TAB = "\t"; //$NON-NLS-1$
private static final String COMMA = ",";//$NON-NLS-1$
/** short description column, such as 'A' */
public static final int COLUMN_SHORT_TITLE = 0;
/** performance counter name column */
public static final int COLUMN_NAME = 1;
/** average value column */
public static final int COLUMN_AVERAGE = 2;
/** sum of values column */
public static final int COLUMN_SUM = 3;
/** minimum of values column */
public static final int COLUMN_MIN = 4;
/** maximum of values column */
public static final int COLUMN_MAX = 5;
protected CheckboxTableViewer viewer;
protected PecCommonTraceGraph graph;
protected PecCommonTrace trace;
// menu items
protected Action copyTableAction;
protected Action copyAction;
protected Action saveTableAction;
private IAction checkAllAction;
private IAction uncheckAllAction;
/**
* Constructor
* @param graph the graph that this legend belongs to
* @param parent the parent composite
* @param title Title for the legend
* @param trace The model containing the samples
*/
public PecCommonLegend(final PecCommonTraceGraph graph, Composite parent, String title, PecCommonTrace trace){
super(parent, SWT.NONE);
this.graph = graph;
this.trace = trace;
setLayout(GridLayoutFactory.fillDefaults().numColumns(1).spacing(0, 0).create());
Label label = new Label(this, SWT.CENTER);
label.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
//label.setFont(PIPageEditor.helvetica_8);
label.setText(title);
label.setLayoutData(GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).create());
//create table viewer
final Table table = new Table(this, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
this.viewer = new CheckboxTableViewer(table);
PecCommonLegendLabelProvider labelProvider = createLabelProvider();
viewer.setLabelProvider(labelProvider);
viewer.setContentProvider(new PecCommonLegendContentProvider(trace));
PecCommonLegendViewerSorter columnSorter = createLegendSorter();
createColumns(this.viewer, columnSorter);
table.setHeaderVisible(true);
table.setLinesVisible(true);
columnSorter.setSortColumn(COLUMN_SHORT_TITLE);
viewer.setComparator(columnSorter);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent arg0) {
if (copyAction == null)
return;
// when selection changes, the ability to copy may change
copyAction.setEnabled(table.getSelectionCount() > 0);
PIPageEditor.getActionBars().updateActionBars();
}
});
viewer.addCheckStateListener(new ICheckStateListener() {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
*/
public void checkStateChanged(CheckStateChangedEvent event) {
PecCommonLegendElement el = (PecCommonLegendElement)event.getElement();
graph.addOrRemoveSeries(el.getId(), event.getChecked());
}
});
viewer.setInput(trace);
viewer.getTable().setLayoutData(GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).create());
addActions(viewer);
viewer.getTable().addFocusListener(new PecCommonLegendFocusListener(viewer));
addContextMenu(viewer);
viewer.setAllChecked(true); //default
PlatformUI.getWorkbench().getHelpSystem().setHelp(this, graph.getContextHelpId());
}
/**
* Creates the LabelProvider for the legend table
* @return
*/
protected PecCommonLegendLabelProvider createLabelProvider() {
return new PecCommonLegendLabelProvider();
}
/**
* Refreshes content of the legend
*/
public void refreshLegend(){
viewer.refresh();
}
protected void createColumns(final TableViewer aViewer, final PecCommonLegendViewerSorter columnSorter)
{
final Table table = aViewer.getTable();
TableColumn column = new TableColumn(table, SWT.LEFT);
column.setText(Messages.PecCommonLegend_0);
column.setWidth(50);
column.setMoveable(true);
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
columnSorter.setSortColumn(COLUMN_SHORT_TITLE);
aViewer.refresh();
}
});
column = new TableColumn(table, SWT.LEFT);
column.setText(Messages.PecCommonLegend_1);
column.setWidth(150);
column.setMoveable(true);
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
columnSorter.setSortColumn(COLUMN_NAME);
aViewer.refresh();
}
});
column = new TableColumn(table, SWT.RIGHT);
column.setText(String.format(Messages.PecCommonLegend_2, trace.getSamplingInterval()));
column.setWidth(100);
column.setMoveable(true);
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
columnSorter.setSortColumn(COLUMN_AVERAGE);
aViewer.refresh();
}
});
column = new TableColumn(table, SWT.RIGHT);
column.setText(Messages.PecCommonLegend_3);
column.setWidth(100);
column.setMoveable(true);
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
columnSorter.setSortColumn(COLUMN_SUM);
aViewer.refresh();
}
});
column = new TableColumn(table, SWT.RIGHT);
column.setText(String.format(Messages.PecCommonLegend_4, trace.getSamplingInterval()));
column.setWidth(100);
column.setMoveable(true);
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
columnSorter.setSortColumn(COLUMN_MIN);
aViewer.refresh();
}
});
column = new TableColumn(table, SWT.RIGHT);
column.setText(String.format(Messages.PecCommonLegend_5, trace.getSamplingInterval()));
column.setWidth(100);
column.setMoveable(true);
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
columnSorter.setSortColumn(COLUMN_MAX);
aViewer.refresh();
}
});
}
/**
* Maximises or restores the legend table viewer
* @param maximise true for maximise, false for restore
*/
public void setLegendMaximised(boolean maximise) {
((SashForm)this.getParent()).setMaximizedControl(maximise ? this : null);
}
/**
* Minimises or restores legend view
* @param visible true for setting visible, false for hiding
*/
public void setLegendVisible(boolean visible) {
this.setVisible(visible);
}
private void addActions(final TableViewer legendViewer) {
checkAllAction = new Action(Messages.PecCommonLegend_6){
@Override
public void run() {
viewer.setAllChecked(true);
graph.showAllSeries();
}
};
checkAllAction.setEnabled(true);
checkAllAction.setText(Messages.PecCommonLegend_7);
uncheckAllAction = new Action(Messages.PecCommonLegend_8){
@Override
public void run() {
viewer.setAllChecked(false);
graph.removeAllSeries();
}
};
uncheckAllAction.setEnabled(true);
uncheckAllAction.setText(Messages.PecCommonLegend_9);
copyAction = new Action(Messages.PecCommonLegend_10) {
@Override
public void run() {
copyToClipboard(legendContentToString(((IStructuredSelection)legendViewer.getSelection()).toArray(), false, TAB));
}
};
copyAction.setEnabled(false);
copyAction.setText(Messages.PecCommonLegend_11);
copyTableAction = new Action(Messages.PecCommonLegend_12) {
@Override
public void run() {
Object[] elements = ((IStructuredContentProvider)legendViewer.getContentProvider()).getElements(null);
legendViewer.getComparator().sort(legendViewer, elements);
copyToClipboard(legendContentToString(elements, true, TAB));
}
};
copyTableAction.setEnabled(true);
copyTableAction.setId(PI_COPY_TABLE);
copyTableAction.setText(Messages.PecCommonLegend_13);
saveTableAction = new Action(Messages.PecCommonLegend_14) {
@Override
public void run() {
WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), new SaveTableWizard(new ISaveTable(){
public String getData() {
Object[] elements = ((PecCommonLegendContentProvider)legendViewer.getContentProvider()).getElements(null);
legendViewer.getComparator().sort(legendViewer, elements);
return legendContentToString(elements, true, COMMA).toString();
}
}));
dialog.open();
}
};
saveTableAction.setEnabled(true);
saveTableAction.setId(PI_SAVE_TABLE);
saveTableAction.setText(Messages.PecCommonLegend_15);
}
/**
* Copies the content of the given StringBuilder to the clipboard.
*/
protected void copyToClipboard(StringBuilder sb) {
if (sb.length() > 0) {
TextTransfer textTransfer = TextTransfer.getInstance();
Clipboard cb = new Clipboard(this.getDisplay());
try {
cb.setContents(new Object[] { sb.toString() },
new Transfer[] { textTransfer });
} finally {
cb.dispose();
}
}
}
/**
* Returns the content of the given objects in human-readable format.
* Optionally includes column headers. Columns are separated by tabs. Elements are separated
* by newlines.
* @param objects Array of objects. Elements of the array are assumed to be of type PecCommonLegendElement
* @param includeHeader true if column headers are to be included
* @return
*/
protected StringBuilder legendContentToString(Object[] objects, boolean includeHeader, String separator) {
StringBuilder sb = new StringBuilder();
if (includeHeader){
for (int i = 0; i < viewer.getTable().getColumnCount(); i++) {
if (i != 0){
sb.append(separator);
}
sb.append(viewer.getTable().getColumn(i).getText());
}
sb.append(NEWLINE);
}
PecCommonLegendLabelProvider labelProvider = (PecCommonLegendLabelProvider)viewer.getLabelProvider();
for (Object o : objects) {
PecCommonLegendElement pecLegendElement = (PecCommonLegendElement) o;
for (int i = 0; i < viewer.getTable().getColumnCount(); i++) {
if (i != 0){
sb.append(separator);
}
String s = labelProvider.getColumnText(pecLegendElement, i);
if (s.indexOf(separator) >= 0){
sb.append(QUOTE).append(s).append(QUOTE); //quote if the separator occurs in the value string
} else {
sb.append(s);
}
}
sb.append(NEWLINE);
}
return sb;
}
/**
* Updates enabled-state of actions
* @param table the table that the actions apply to
*/
protected void updateActionStatus(Table table) {
copyAction.setEnabled(table.getSelectionCount() > 0);
copyTableAction.setEnabled(table.getItemCount() > 0);
saveTableAction.setEnabled(table.getItemCount() > 0);
}
private void addContextMenu(final TableViewer aViewer) {
final MenuManager mgr = new MenuManager();
mgr.add(new Separator());
mgr.add(checkAllAction);
mgr.add(uncheckAllAction);
mgr.add(new Separator());
mgr.add(copyAction);
mgr.add(copyTableAction);
mgr.add(new Separator());
mgr.add(saveTableAction);
aViewer.getControl().setMenu(mgr.createContextMenu(aViewer.getControl()));
}
/**
* On gaining focus, we add copy / save actions to the top file and edit menu,
* on losing it, we remove those actions again.
*
*/
private class PecCommonLegendFocusListener implements FocusListener {
private TableViewer legendViewer;
private IAction oldCopyAction;
public PecCommonLegendFocusListener(TableViewer legendViewer) {
this.legendViewer = legendViewer;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.
* swt.events.FocusEvent)
*/
public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
IActionBars bars = PIPageEditor.getActionBars();
oldCopyAction = PIPageEditor.getActionBars().getGlobalActionHandler(ActionFactory.COPY.getId());
bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
bars.updateActionBars();
// add copyTableAction to the Edit menu
IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
if (editMenuManager instanceof SubMenuManager) {
IContributionManager editManager = ((SubMenuManager) editMenuManager).getParent();
editMenuManager.remove(PI_COPY_TABLE);
ActionContributionItem item = new ActionContributionItem(copyTableAction);
item.setVisible(true);
editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
}
// add saveTableAction to the File menu
IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
if (fileMenuManager instanceof SubMenuManager) {
IContributionManager fileManager = ((SubMenuManager) fileMenuManager).getParent();
fileMenuManager.remove(PI_SAVE_TABLE);
ActionContributionItem item = new ActionContributionItem(saveTableAction);
item.setVisible(true);
fileManager.insertAfter(SAVE_ALL, item);
}
updateActionStatus(legendViewer.getTable());
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt
* .events.FocusEvent)
*/
public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
IActionBars bars = PIPageEditor.getActionBars();
bars.setGlobalActionHandler(ActionFactory.COPY.getId(),
oldCopyAction);
bars.updateActionBars();
SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor
.getMenuManager().find(IIDEActionConstants.M_EDIT);
editMenuManager.remove(PI_COPY_TABLE);
editMenuManager.update();
SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor
.getMenuManager().find(IIDEActionConstants.M_FILE);
fileMenuManager.remove(PI_SAVE_TABLE);
fileMenuManager.update();
}
}
/**
* Creates the sorter used for the legend view. Sub classes may override this
* @return PecCommonLegendViewerSorter
*/
protected PecCommonLegendViewerSorter createLegendSorter(){
return new PecCommonLegendViewerSorter();
}
}