--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GenericAddrTable.java Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1156 @@
+/*
+ * Copyright (c) 2009 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.address;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+
+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.SubMenuManager;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusListener;
+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.Decorations;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+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.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveTable;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.save.SaveTableWizard;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public abstract class GenericAddrTable extends GenericTable
+{
+ protected GppTraceGraph myGraph;
+ protected Composite parent;
+
+ // sorting column and order
+ protected int sortColumn = COLUMN_ID_SAMPLE_COUNT;
+ protected boolean sortAscending;
+
+ protected GppTableSorter sorter;
+ protected boolean sorting = false;
+
+ abstract protected Menu getTableMenu(Decorations parent, int graphIndex, int drawMode);
+
+ protected boolean isDrilldown = false;
+
+ // menu items
+ protected Action selectAllAction;
+ protected Action copyTableAction;
+ protected Action copyAction;
+ protected Action copyDrilldownAction;
+ protected Action saveTableAction;
+ protected Action saveDrilldownAction;
+
+ protected static int SAMPLES_AT_ONE_TIME = 1000;
+
+ // class to pass sample data to the save wizard
+ public class SaveSampleString implements ISaveSamples {
+ int graphIndex;
+ int drawMode;
+ int startIndex = 0;
+
+ public SaveSampleString(int graphIndex, int drawMode) {
+ this.graphIndex = graphIndex;
+ this.drawMode = drawMode;
+ }
+
+ public String getData() {
+ return getData(SAMPLES_AT_ONE_TIME);
+ }
+
+ public String getData(int size) {
+ String returnString = getSampleString(graphIndex, drawMode, this.startIndex, this.startIndex + size);
+ if (returnString == null)
+ this.startIndex = 0;
+ else
+ this.startIndex += size;
+ return returnString;
+ }
+
+ public int getIndex() {
+ return this.startIndex;
+ }
+
+ public void clear() {
+ this.startIndex = 0;
+ }
+ }
+
+ protected MenuItem getSaveSamplesItem(Menu menu, String sampleType, boolean enabled) {
+ MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+ saveSamplesItem.setText(Messages.getString("GenericAddrTable.saveSamples1") + sampleType + Messages.getString("GenericAddrTable.saveSamples2")); //$NON-NLS-1$ //$NON-NLS-2$
+ saveSamplesItem.setEnabled(enabled);
+
+ if (enabled) {
+ saveSamplesItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("saveSamples"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ return saveSamplesItem;
+ }
+
+ public GppTraceGraph getGraph() {
+ return myGraph;
+ }
+
+ protected class TableMouseListener implements MouseListener
+ {
+ public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
+ if (e.button == MouseEvent.BUTTON1)
+ {
+ TableItem[] selectedItems = table.getSelection();
+ if (selectedItems.length == 0)
+ return;
+
+ if (selectedItems[0].getData() instanceof ProfiledGeneric)
+ {
+ ProfiledGeneric pg = (ProfiledGeneric)(selectedItems[0].getData());
+ if (pg.isEnabled(myGraph.getGraphIndex()))
+ action("remove"); //$NON-NLS-1$
+ else
+ action("add"); //$NON-NLS-1$
+ action("doubleClick"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
+ }
+
+ public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
+ if (e.button == MouseEvent.BUTTON3) {
+ Menu menu = getTableMenu(table.getShell(), myGraph.getGraphIndex(), myGraph.getDrawMode());
+ menu.setLocation(parent.toDisplay(e.x + table.getLocation().x, e.y + table.getLocation().y));
+ table.setMenu(menu);
+ }
+ }
+ }
+
+ public void setVisualisationColumnVisible(boolean flag) {}
+
+ public void valueChanged(SelectionEvent e) {}
+
+ protected Vector<ProfiledGeneric> setTableItemData(Enumeration<ProfiledGeneric> enu) {
+ Vector<ProfiledGeneric> tmpItems = new Vector<ProfiledGeneric>();
+
+ while (enu.hasMoreElements())
+ {
+ tmpItems.add(enu.nextElement());
+ }
+ return tmpItems;
+ }
+
+ protected void addDrillDownItems(Menu tableMenu, int drawMode)
+ {
+ switch (drawMode)
+ {
+ case Defines.THREADS:
+ {
+ // thread drill down items
+ threadItem (tableMenu, true);
+ threadBinaryItem (tableMenu, false);
+ threadFunctionItem(tableMenu, false);
+ break;
+ }
+ case Defines.THREADS_BINARIES:
+ {
+ // thread drill down items
+ threadItem (tableMenu, false);
+ threadBinaryItem (tableMenu, true);
+ threadBinaryFunctionItem(tableMenu, false);
+ break;
+ }
+ case Defines.THREADS_BINARIES_FUNCTIONS:
+ {
+ // thread drill down items
+ threadItem (tableMenu, false);
+ threadBinaryItem (tableMenu, false);
+ threadBinaryFunctionItem(tableMenu, true);
+ break;
+ }
+ case Defines.THREADS_FUNCTIONS:
+ {
+ // thread drill down items
+ threadItem (tableMenu, false);
+ threadFunctionItem (tableMenu, true);
+ newThreadFunctionBinary(tableMenu, false);
+ break;
+ }
+ case Defines.THREADS_FUNCTIONS_BINARIES:
+ {
+ // thread drill down items
+ threadItem (tableMenu, false);
+ threadFunctionItem (tableMenu, false);
+ newThreadFunctionBinary(tableMenu, true);
+ break;
+ }
+ case Defines.BINARIES:
+ {
+ // binary drill down items
+ binaryItem (tableMenu, true);
+ binaryThreadItem (tableMenu, false);
+ binaryFunctionItem(tableMenu, false);
+ break;
+ }
+ case Defines.BINARIES_THREADS:
+ {
+ // binary drill down items
+ binaryItem (tableMenu, false);
+ binaryThreadItem (tableMenu, true);
+ binaryThreadFunctionItem(tableMenu, false);
+ break;
+ }
+ case Defines.BINARIES_THREADS_FUNCTIONS:
+ {
+ // binary drill down items
+ binaryItem (tableMenu, false);
+ binaryThreadItem (tableMenu, false);
+ binaryThreadFunctionItem(tableMenu, true);
+ break;
+ }
+ case Defines.BINARIES_FUNCTIONS:
+ {
+ // binary drill down items
+ binaryItem (tableMenu, false);
+ binaryFunctionItem (tableMenu, true);
+ binaryFunctionThreadItem(tableMenu, false);
+ break;
+ }
+ case Defines.BINARIES_FUNCTIONS_THREADS:
+ {
+ // binary drill down items
+ binaryItem (tableMenu, false);
+ binaryFunctionItem (tableMenu, false);
+ binaryFunctionThreadItem(tableMenu, true);
+ break;
+ }
+ case Defines.FUNCTIONS:
+ {
+ // function drill down items
+ functionItem (tableMenu, true);
+ functionThreadItem(tableMenu, false);
+ functionBinaryItem(tableMenu, false);
+ break;
+ }
+ case Defines.FUNCTIONS_THREADS:
+ {
+ // function drill down items
+ functionItem (tableMenu, false);
+ functionThreadItem (tableMenu, true);
+ functionThreadBinaryItem(tableMenu, false);
+ break;
+ }
+ case Defines.FUNCTIONS_THREADS_BINARIES:
+ {
+ // function drill down items
+ functionItem (tableMenu, false);
+ functionThreadItem (tableMenu, false);
+ functionThreadBinaryItem(tableMenu, true);
+ break;
+ }
+ case Defines.FUNCTIONS_BINARIES:
+ {
+ // function drill down items
+ functionItem (tableMenu, false);
+ functionBinaryItem (tableMenu, true);
+ functionBinaryThreadItem(tableMenu, false);
+ break;
+ }
+ case Defines.FUNCTIONS_BINARIES_THREADS:
+ {
+ // function drill down items
+ functionItem (tableMenu, false);
+ functionBinaryItem (tableMenu, false);
+ functionBinaryThreadItem(tableMenu, true);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Find if any threads with checkboxes checked
+ */
+ protected boolean haveCheckedThread(GppTrace trace, int graphIndex)
+ {
+ ProfiledThread pThread;
+ for (ProfiledGeneric pGeneric: trace.getIndexedThreads()) {
+ if (pGeneric instanceof ProfiledThread) {
+ pThread = (ProfiledThread) pGeneric;
+ if (pThread.isEnabled(graphIndex))
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /*
+ * Find if any binaries with checkboxes checked
+ */
+ protected boolean haveCheckedBinary(GppTrace trace, int graphIndex)
+ {
+ ProfiledBinary pBinary;
+ for (ProfiledGeneric pGeneric: trace.getIndexedBinaries()) {
+ if (pGeneric instanceof ProfiledBinary) {
+ pBinary = (ProfiledBinary) pGeneric;
+ if (pBinary.isEnabled(graphIndex))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Find if any functions with checkboxes checked
+ */
+ protected boolean haveCheckedFunction(GppTrace trace, int graphIndex)
+ {
+ ProfiledFunction pFunction;
+ for (ProfiledGeneric pGeneric: trace.getIndexedFunctions()) {
+ if (pGeneric instanceof ProfiledFunction) {
+ pFunction = (ProfiledFunction) pGeneric;
+ if (pFunction.isEnabled(graphIndex))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * get list of matching samples based on draw mode
+ */
+ private ArrayList<GppSample> getMatchingSamples(int drawMode, GppTrace trace, int startIndex, int endIndex, int graphIndex)
+ {
+ ArrayList<GppSample> samplesArray = new ArrayList<GppSample>(endIndex - startIndex > 1000 ? 1000 : endIndex - startIndex);
+ Vector<ProfiledGeneric> traceThreads = trace.getIndexedThreads();
+ Vector<ProfiledGeneric> traceBinaries = trace.getIndexedBinaries();
+ Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
+ GppSample[] samples = trace.getSortedGppSamples();
+ GppSample sample;
+
+ switch (drawMode)
+ {
+ case Defines.THREADS:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+ if (pThread.isEnabled(graphIndex))
+ samplesArray.add(sample);
+ }
+ break;
+ case Defines.BINARIES:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+ if (pBinary.isEnabled(graphIndex))
+ samplesArray.add(sample);
+ }
+ break;
+ case Defines.FUNCTIONS:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+ if (pFunction.isEnabled(graphIndex))
+ samplesArray.add(sample);
+ }
+ break;
+ case Defines.THREADS_BINARIES:
+ case Defines.BINARIES_THREADS:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+ if (pThread.isEnabled(graphIndex)) {
+ ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+ if (pBinary.isEnabled(graphIndex)) {
+ samplesArray.add(sample);
+ }
+ }
+ }
+ break;
+ case Defines.THREADS_FUNCTIONS:
+ case Defines.FUNCTIONS_THREADS:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+ if (pThread.isEnabled(graphIndex)) {
+ ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+ if (pFunction.isEnabled(graphIndex)) {
+ samplesArray.add(sample);
+ }
+ }
+ }
+ break;
+ case Defines.BINARIES_FUNCTIONS:
+ case Defines.FUNCTIONS_BINARIES:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+ if (pBinary.isEnabled(graphIndex)) {
+ ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+ if (pFunction.isEnabled(graphIndex)) {
+ samplesArray.add(sample);
+ }
+ }
+ }
+ break;
+ case Defines.THREADS_FUNCTIONS_BINARIES:
+ case Defines.THREADS_BINARIES_FUNCTIONS:
+ for (int i = startIndex; i < endIndex; i++) {
+ sample = samples[i];
+ ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+ if (pThread.isEnabled(graphIndex)) {
+ ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+ if (pBinary.isEnabled(graphIndex)) {
+ ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+ if (pFunction.isEnabled(graphIndex)) {
+ samplesArray.add(sample);
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ samplesArray.trimToSize();
+ return samplesArray;
+ }
+
+ /*
+ * return the thread, binary, or function samples selected in the interval
+ */
+ protected String getSampleString(int graphIndex, int drawMode, int startIndex, int endIndex)
+ {
+ boolean threads = false;
+ boolean binaries = false;
+ boolean functions = false;
+ GppTraceGraph graph = (GppTraceGraph)(this.myGraph);
+ GppTrace trace = (GppTrace)(graph.getTrace());
+
+ // The current graph shows either threads, binaries, or functions
+ switch (drawMode)
+ {
+ case Defines.THREADS:
+ case Defines.BINARIES_THREADS:
+ case Defines.BINARIES_FUNCTIONS_THREADS:
+ case Defines.FUNCTIONS_THREADS:
+ case Defines.FUNCTIONS_BINARIES_THREADS:
+ threads = true;
+ break;
+ case Defines.BINARIES:
+ case Defines.THREADS_BINARIES:
+ case Defines.THREADS_FUNCTIONS_BINARIES:
+ case Defines.FUNCTIONS_BINARIES:
+ case Defines.FUNCTIONS_THREADS_BINARIES:
+ binaries = true;
+ break;
+ case Defines.FUNCTIONS:
+ case Defines.THREADS_FUNCTIONS:
+ case Defines.THREADS_BINARIES_FUNCTIONS:
+ case Defines.BINARIES_FUNCTIONS:
+ case Defines.BINARIES_THREADS_FUNCTIONS:
+ functions = true;
+ break;
+ default:
+ break;
+ }
+
+ int startTime = trace.getStartSampleIndex();
+ int endTime = trace.getEndSampleIndex();
+
+ // check if we have returned everything
+ if (startIndex > (endTime - startTime))
+ return null;
+
+ ArrayList<GppSample> matchingSamples = getMatchingSamples(drawMode, trace, startTime, endTime, graphIndex);
+
+ String returnString = ""; //$NON-NLS-1$
+
+ if (threads) {
+ Vector<ProfiledGeneric> traceThreads = trace.getIndexedThreads();
+ if (startIndex == 0)
+ returnString = Messages.getString("GenericAddrTable.threadSampleHeading"); //$NON-NLS-1$
+
+ for (int i = startIndex; i < matchingSamples.size() && i < endIndex; i++) {
+ GppSample sample = matchingSamples.get(i);
+ returnString += sample.sampleSynchTime + ",0x" + Long.toHexString(sample.programCounter) + "," //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+ + traceThreads.get(sample.threadIndex).getNameString() + "\n"; //$NON-NLS-1$
+ }
+ } else if (binaries) {
+ if (startIndex == 0)
+ returnString = Messages.getString("GenericAddrTable.binarySampleHeading"); //$NON-NLS-1$
+
+ for (int i = startIndex; i < matchingSamples.size() && i < endIndex; i++) {
+ GppSample sample = matchingSamples.get(i);
+ ProfiledBinary binary = (ProfiledBinary) trace.getIndexedBinaries().get(sample.binaryIndex);
+ returnString += sample.sampleSynchTime + ",0x" + Long.toHexString(sample.programCounter) + "," //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+ + binary.getNameString() + "\n"; // $NON-NLS-1$; //$NON-NLS-1$
+ }
+ } else if (functions) {
+ if (startIndex == 0)
+ returnString = Messages.getString("GenericAddrTable.functionSampleHeading"); //$NON-NLS-1$
+
+ for (int i = startIndex; i < matchingSamples.size() && i < endIndex; i++) {
+ GppSample sample = matchingSamples.get(i);
+ ProfiledFunction function = (ProfiledFunction) trace.getIndexedFunctions().get(sample.functionIndex);
+ returnString += sample.sampleSynchTime + ",0x" + Long.toHexString(sample.programCounter) + ",\"" //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+ + function.getNameString() + "\",0x" + Long.toHexString(function.getFunctionAddress()) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+ }
+ }
+
+ return returnString;
+ }
+
+ private void threadItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.threadOnly")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("thread-only"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void threadBinaryItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.threadBinary")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("thread-binary"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void threadBinaryFunctionItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.threadBinaryFunction")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("thread-binary-function"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void threadFunctionItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.threadFunction")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("thread-function"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void newThreadFunctionBinary(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.threadFunctionBinary")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("thread-function-binary"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void binaryItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.binaryOnly")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("binary-only"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void binaryThreadItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.binaryThread")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("binary-thread"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void binaryThreadFunctionItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.binaryThreadFunction")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("binary-thread-function"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void binaryFunctionItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.binaryFunction")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("binary-function"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void binaryFunctionThreadItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.binaryFunctionThread")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("binary-function-thread"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void functionItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.functionOnly")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("function-only"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void functionThreadItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.functionThread")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("function-thread"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void functionThreadBinaryItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.functionThreadBinary")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("function-thread-binary"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void functionBinaryItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.functionBinary")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("function-binary"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ private void functionBinaryThreadItem(Menu menu, boolean chosen) {
+ MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+ menuItem.setText(Messages.getString("GenericAddrTable.functionBinaryThread")); //$NON-NLS-1$
+ menuItem.setSelection(chosen);
+ menuItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("function-binary-thread"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ protected String copyDrilldown(int tableCount, Table[] tables, String separator)
+ {
+ // make sure it's a valid drilldown
+ if ( (tableCount < 2) || (tableCount > 3)
+ || (tables[0] == null) || (tables[1] == null)
+ || (tableCount == 2 && tables[2] != null)
+ || (tableCount == 3 && tables[2] == null))
+ return ""; //$NON-NLS-1$
+
+ String copyString = ""; //$NON-NLS-1$
+
+ // create the multiple table heading line (e.g., "Threads Binaries")
+ // space them out based on how many columns are in their table
+ for (int i = 0; i < tableCount; i++) {
+ if (tables[i].getData() instanceof String) {
+ copyString += (String) (tables[i].getData());
+ }
+ for (int j = 0; j < tables[i].getColumnCount(); j++) {
+ copyString += separator;
+ }
+ }
+ copyString += "\n"; //$NON-NLS-1$
+
+ // create the multiple table column headings
+ for (int i = 0; i < tableCount; i++) {
+ if (i != tableCount - 1) {
+ copyString += copyHeading(tables[i], CHECKBOX_NO_TEXT, separator, separator); //$NON-NLS-1$
+ } else {
+ copyString += copyHeading(tables[i], CHECKBOX_NO_TEXT, separator, "\n"); //$NON-NLS-1$
+ }
+ }
+
+ // determine the row, column count, and column ordering in each table
+ int rowCount0 = tables[0].getItemCount();
+ int columnCount0 = tables[0].getColumnCount();
+ int[] columnOrder0 = tables[0].getColumnOrder();
+ boolean[] isHex0 = (boolean[]) tables[0].getData("isHex"); //$NON-NLS-1$
+ String emptyRow0 = ""; //$NON-NLS-1$
+
+ int rowCount1 = tables[1].getItemCount();
+ int columnCount1 = tables[1].getColumnCount();
+ int[] columnOrder1 = tables[1].getColumnOrder();
+ boolean[] isHex1 = (boolean[]) tables[1].getData("isHex"); //$NON-NLS-1$
+ String emptyRow1 = ""; //$NON-NLS-1$
+
+ int rowCount2 = tableCount > 2 ? tables[2].getItemCount() : 0;
+ int columnCount2 = tableCount > 2 ? tables[2].getColumnCount() : 0;
+ int[] columnOrder2 = tableCount > 2 ? tables[2].getColumnOrder() : null;
+ boolean[] isHex2 = tableCount > 2 ? ((boolean[]) tables[2].getData("isHex")) : null; //$NON-NLS-1$
+ String emptyRow2 = ""; //$NON-NLS-1$
+
+ // determine the number of multiple table rows (max of any table's rows)
+ int rowCount = rowCount0 >= rowCount1 ? rowCount0 : rowCount1;
+ rowCount = rowCount > rowCount2 ? rowCount : rowCount2;
+
+ // generate empty row strings, to speed things up
+ if (rowCount0 < rowCount) {
+ for (int j = 0; j < columnCount0 - 1; j++) {
+ emptyRow0 += separator;
+ }
+ }
+
+ if (rowCount1 < rowCount) {
+ for (int j = 0; j < columnCount1; j++) {
+ emptyRow1 += separator;
+ }
+ }
+
+ if ((tableCount > 2) && (rowCount2 < rowCount)) {
+ for (int j = 0; j < columnCount2; j++) {
+ emptyRow2 += separator;
+ }
+ }
+
+ // generate the rows
+ for (int i = 0; i < rowCount; i++) {
+ if (i < rowCount0) {
+ copyString += copyRow(isHex0, tables[0].getItem(i), CHECKBOX_NO_TEXT, columnCount0, columnOrder0, separator);
+ } else {
+ copyString += emptyRow0;
+ }
+
+ if (i < rowCount1) {
+ copyString += separator + copyRow(isHex1, tables[1].getItem(i), CHECKBOX_NO_TEXT, columnCount1, columnOrder1, separator);
+ } else {
+ // NOTE: if this is the last table, or the 3rd table has nothing but empty
+ // rows left, we may not need to fill in these fields
+ copyString += emptyRow1;
+ }
+
+ if (tableCount > 2) {
+ if (i < rowCount2) {
+ copyString += separator + copyRow(isHex2, tables[2].getItem(i), CHECKBOX_NO_TEXT, columnCount2, columnOrder2, separator);
+ } else {
+ // NOTE: we may not need to fill in the empty fields of the last table
+ copyString += emptyRow2;
+ }
+ }
+
+ copyString += "\n"; //$NON-NLS-1$
+ }
+
+ return copyString;
+ }
+
+ // class to pass drilldown tables to the save wizard
+ class SaveDrillDownString implements ISaveTable {
+ private int tableCount;
+ private Table[] tables;
+ private String separator;
+
+ public SaveDrillDownString(int tableCount, Table[] tables, String separator) {
+ this.tableCount = tableCount;
+ this.tables = tables;
+ this.separator = separator;
+ }
+
+ public String getData() {
+ return copyDrilldown(tableCount, tables, separator);
+ }
+ }
+
+ public Table[] getDrillDownTables()
+ {
+ // copy all tables in a drilldown to the clipboard or save to a file
+ int drawMode = this.myGraph.getDrawMode();
+
+ int tableCount = 0;
+ Table[] tables = new Table[3];
+
+ // determine which tables are in the drilldown
+ switch (drawMode)
+ {
+ case Defines.THREADS_BINARIES:
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ break;
+ case Defines.THREADS_BINARIES_FUNCTIONS:
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ break;
+ case Defines.THREADS_FUNCTIONS:
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ break;
+ case Defines.THREADS_FUNCTIONS_BINARIES:
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ break;
+ case Defines.BINARIES_THREADS:
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ break;
+ case Defines.BINARIES_THREADS_FUNCTIONS:
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ break;
+ case Defines.BINARIES_FUNCTIONS:
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ break;
+ case Defines.BINARIES_FUNCTIONS_THREADS:
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ break;
+ case Defines.FUNCTIONS_THREADS:
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ break;
+ case Defines.FUNCTIONS_THREADS_BINARIES:
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ break;
+ case Defines.FUNCTIONS_BINARIES:
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ break;
+ case Defines.FUNCTIONS_BINARIES_THREADS:
+ tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+ tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+ tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+ break;
+ default:
+ }
+
+ return tables;
+ }
+
+ protected void actionCopyOrSaveDrilldown(boolean doCopy, String separator)
+ {
+ Table[] tables = getDrillDownTables();
+
+ int tableCount = 0;
+ while ((tableCount < tables.length) && (tables[tableCount] != null))
+ tableCount++;
+
+
+ if (doCopy) {
+ // change the clipboard contents
+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+ String copyString = copyDrilldown(tableCount, tables, separator);
+ StringSelection contents = new StringSelection(copyString);
+ cb.setContents(contents, contents);
+ } else {
+ // save to a file
+ SaveDrillDownString getString = new SaveDrillDownString(tableCount, tables, separator);
+ WizardDialog dialog;
+ Wizard w = new SaveTableWizard(getString);
+ dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), w);
+ dialog.open();
+ }
+ }
+
+ protected void createDefaultActions()
+ {
+ selectAllAction = new Action("SelectAll") { //$NON-NLS-1$
+ public void run() {
+ action("selectAll"); //$NON-NLS-1$
+ }
+ };
+ selectAllAction.setEnabled(true);
+
+ copyAction = new Action("Copy") { //$NON-NLS-1$
+ public void run() {
+ action("copy"); //$NON-NLS-1$
+ }
+ };
+ copyAction.setEnabled(false);
+
+ copyTableAction = new Action("CopyTable") { //$NON-NLS-1$
+ public void run() {
+ action("copyTable"); //$NON-NLS-1$
+ }
+ };
+ copyTableAction.setEnabled(true);
+ copyTableAction.setId("PICopyTable"); //$NON-NLS-1$
+ copyTableAction.setText(Messages.getString("GenericAddrTable.copyTable")); //$NON-NLS-1$
+
+ copyDrilldownAction = new Action("CopyDrilldown") { //$NON-NLS-1$
+ public void run() {
+ action("copyDrilldown"); //$NON-NLS-1$
+ }
+ };
+ copyDrilldownAction.setEnabled(false);
+ copyDrilldownAction.setId("PICopyDrilldown"); //$NON-NLS-1$
+ copyDrilldownAction.setText(Messages.getString("GenericAddrTable.copyDrilldownTables")); //$NON-NLS-1$
+
+ saveTableAction = new Action("SaveTable") { //$NON-NLS-1$
+ public void run() {
+ action("saveTable"); //$NON-NLS-1$
+ }
+ };
+ saveTableAction.setEnabled(true);
+ saveTableAction.setId("PISaveTable"); //$NON-NLS-1$
+ saveTableAction.setText(Messages.getString("GenericAddrTable.saveTable")); //$NON-NLS-1$
+
+ saveDrilldownAction = new Action("SaveDrilldown") { //$NON-NLS-1$
+ public void run() {
+ action("saveDrilldown"); //$NON-NLS-1$
+ }
+ };
+ saveDrilldownAction.setEnabled(false);
+ saveDrilldownAction.setId("PISaveDrilldown"); //$NON-NLS-1$
+ saveDrilldownAction.setText(Messages.getString("GenericAddrTable.saveDrilldownTables")); //$NON-NLS-1$
+
+// saveSamplesAction = new Action("SaveSamples") { //$NON-NLS-1$
+// public void run() {
+// action("saveSamples"); //$NON-NLS-1$
+// }
+// };
+// saveSamplesAction.setEnabled(true);
+// saveSamplesAction.setId("PISaveAddressSamples"); //$NON-NLS-1$
+// saveSamplesAction.setText(Messages.getString("GenericAddrTable.23") + sampleType + Messages.getString("GenericAddrTable.24")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void setIsDrilldown(boolean isDrilldown)
+ {
+ this.isDrilldown = isDrilldown;
+ copyDrilldownAction.setEnabled(isDrilldown);
+ saveDrilldownAction.setEnabled(isDrilldown);
+
+ // may need to clean up stale Edit & File menu entry for PICopyDrilldown and PISaveDrilldown
+ if (!isDrilldown) {
+ IMenuManager editMenuManager = PIPageEditor.getActionBars().getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+ if (editMenuManager instanceof SubMenuManager)
+ {
+ IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+ ActionContributionItem item;
+
+ editMenuManager.remove("PICopyDrilldown"); //$NON-NLS-1$
+ item = new ActionContributionItem(copyDrilldownAction);
+ item.setVisible(true);
+ editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+
+ editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+ copyTableAction.setEnabled(table.getItemCount() > 0);
+ item = new ActionContributionItem(copyTableAction);
+ item.setVisible(true);
+ editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+ }
+
+ IMenuManager fileMenuManager = PIPageEditor.getActionBars().getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+ if (fileMenuManager instanceof SubMenuManager)
+ {
+ IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+ ActionContributionItem item;
+
+ fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+ saveTableAction.setEnabled(table.getItemCount() > 0);
+ item = new ActionContributionItem(saveTableAction);
+ item.setVisible(true);
+ fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+
+ fileMenuManager.remove("PISaveDrilldown"); //$NON-NLS-1$
+ item = new ActionContributionItem(saveDrilldownAction);
+ item.setVisible(true);
+ fileManager.insertAfter("PISaveTable", item); //$NON-NLS-1$
+ fileManager.update(true);
+ }
+ }
+ }
+
+ protected MenuItem getCopyDrilldownItem(Menu menu, boolean enabled) {
+ MenuItem copyDrilldownItem = new MenuItem(menu, SWT.PUSH);
+
+ copyDrilldownItem.setText(Messages.getString("GenericAddrTable.copyDrilldownTables")); //$NON-NLS-1$
+ copyDrilldownItem.setEnabled(enabled);
+
+ if (enabled) {
+ copyDrilldownItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("copyDrilldown"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ return copyDrilldownItem;
+ }
+
+ protected MenuItem getSaveDrilldownItem(Menu menu, boolean enabled) {
+ MenuItem saveDrilldownItem = new MenuItem(menu, SWT.PUSH);
+
+ saveDrilldownItem.setText(Messages.getString("GenericAddrTable.saveDrilldownTables")); //$NON-NLS-1$
+ saveDrilldownItem.setEnabled(enabled);
+
+ if (enabled) {
+ saveDrilldownItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ action("saveDrilldown"); //$NON-NLS-1$
+ }
+ });
+ }
+
+ return saveDrilldownItem;
+ }
+
+ protected class AddrTableFocusListener implements FocusListener
+ {
+ IAction oldSelectAllAction = null;
+ IAction oldCopyAction = null;
+
+ public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
+ IActionBars bars = PIPageEditor.getActionBars();
+
+ // modify what is executed when Select All and Copy are called from the Edit menu
+ oldSelectAllAction = bars.getGlobalActionHandler(ActionFactory.SELECT_ALL.getId());
+ oldCopyAction = bars.getGlobalActionHandler(ActionFactory.COPY.getId());
+
+ bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+ bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction);
+
+ copyAction.setEnabled(table.getSelectionCount() > 0);
+ selectAllAction.setEnabled(table.getItemCount() > 0);
+ bars.updateActionBars();
+
+ // add to the Edit menu
+ IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+ if (editMenuManager instanceof SubMenuManager)
+ {
+ IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+ ActionContributionItem item;
+
+ editMenuManager.remove("PICopyDrilldown"); //$NON-NLS-1$
+ item = new ActionContributionItem(copyDrilldownAction);
+ item.setVisible(true);
+ editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+
+ editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+ copyTableAction.setEnabled(table.getItemCount() > 0);
+ item = new ActionContributionItem(copyTableAction);
+ item.setVisible(true);
+ editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+ }
+
+ // add to the File menu
+ IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+ if (fileMenuManager instanceof SubMenuManager)
+ {
+ IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+ ActionContributionItem item;
+
+ fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+ saveTableAction.setEnabled(table.getItemCount() > 0);
+ item = new ActionContributionItem(saveTableAction);
+ item.setVisible(true);
+ fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+
+ fileMenuManager.remove("PISaveDrilldown"); //$NON-NLS-1$
+ item = new ActionContributionItem(saveDrilldownAction);
+ item.setVisible(true);
+ fileManager.insertAfter("PISaveTable", item); //$NON-NLS-1$
+ }
+ }
+
+ public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
+ IActionBars bars = PIPageEditor.getActionBars();
+ bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
+ bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), oldSelectAllAction);
+ bars.updateActionBars();
+
+ SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
+ editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+ editMenuManager.remove("PICopyDrilldown"); //$NON-NLS-1$
+
+ SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
+ fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+ fileMenuManager.remove("PISaveDrilldown"); //$NON-NLS-1$
+ }
+ }
+}