crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/ui/editors/SummaryPage.java
changeset 0 5ad7ad99af01
child 4 615035072f7e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/ui/editors/SummaryPage.java	Thu Feb 11 15:06:45 2010 +0200
@@ -0,0 +1,614 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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.s60tools.crashanalyser.ui.editors;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.browser.*;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.s60tools.crashanalyser.files.*;
+import com.nokia.s60tools.crashanalyser.model.HtmlFormatter;
+import com.nokia.s60tools.crashanalyser.containers.Summary;
+import com.nokia.s60tools.crashanalyser.containers.Process;
+import com.nokia.s60tools.crashanalyser.containers.Thread;
+import com.nokia.s60tools.crashanalyser.containers.Stack;
+import com.nokia.s60tools.crashanalyser.containers.StackEntry;
+import com.nokia.s60tools.crashanalyser.containers.RegisterSet;
+import com.nokia.s60tools.crashanalyser.resources.HelpContextIDs;
+import com.nokia.s60tools.crashanalyser.ui.viewers.*;
+import com.nokia.s60tools.crashanalyser.ui.views.*;
+import java.util.List;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.swt.graphics.FontData;
+
+/**
+ * Crash Data page in Crash Visualiser editor. 
+ *
+ */
+public class SummaryPage implements SelectionListener {
+	
+	// summary group UI items
+	Table tableSummary;
+
+	// exit info group UI items
+	Label labelExitType;
+	Label labelPanicSummary;
+	Browser browserPanicDescription;
+	
+	// call stack group UI items
+	Combo comboCallStack;
+	Label labelStackWarning;
+	Button buttonDecodeFile;
+	Table tableCallStack;
+	CallStackTableViewer tableViewerCallStack;
+	Button buttonAllStackEntries;
+	Button buttonSymbolStackEntries;
+	
+	SummaryFile crashFile = null;
+	FontRegistry fontRegistry;
+	Thread selectedThread = null;
+	
+	/**
+	 * Creates the page
+	 * @param parent composite
+	 * @param file summary file
+	 * @return composite
+	 */
+	public Composite createPage(Composite parent, SummaryFile file) {
+		crashFile = file;
+		return doCreate(parent);
+	}
+	
+	/**
+	 * Creates the page
+	 * @param parent composite
+	 * @return composite
+	 */
+	public Composite createPage(Composite parent) {
+		return doCreate(parent);
+	}
+	
+	public void update() {
+		AutoSizeCallStackTableCells();
+	}
+	
+	/**
+	 * Loads data from given file into UI elements.
+	 * @param file crash file
+	 */
+	public void setFile(CrashFile file) {
+		if (file != null) {
+			crashFile = file;
+			loadSummaryTable();
+			loadExitInfo();
+			initialCallStackTableLoad();
+		}
+	}
+	
+	/**
+	 * Creates all UI elements to the page
+	 * @param parent
+	 * @return composite
+	 */
+	Composite doCreate(Composite parent) {
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		parent.setLayout(layout);
+		parent.setLayoutData(new GridData(GridData.FILL_BOTH));
+		fontRegistry = new FontRegistry(Display.getCurrent());
+		fontRegistry.put("monospace", new FontData[]{new FontData("Courier", 8, SWT.NORMAL)});
+		SashForm sashFormMain = new SashForm(parent, SWT.VERTICAL);
+		sashFormMain.setLayoutData(new GridData(GridData.FILL_BOTH));
+		SashForm sashFormTop = new SashForm(sashFormMain, SWT.HORIZONTAL);
+		createSummaryGroup(sashFormTop);
+		createExitInfoGroup(sashFormTop);
+		createCallStackGroup(sashFormMain);
+
+		sashFormMain.setWeights(new int[] {1,2});
+		
+		setHelps();
+		
+		return parent;
+	}
+	
+	/**
+	 * Creates summary group
+	 * @param parent
+	 */
+	void createSummaryGroup(Composite parent) {
+		Group groupSummary = new Group(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		groupSummary.setLayout(layout);
+		groupSummary.setText("Summary");
+		GridData groupGD = new GridData(GridData.FILL_HORIZONTAL);
+		groupGD.heightHint = 200;
+		groupSummary.setLayoutData(groupGD);
+		
+		tableSummary = new Table(groupSummary, SWT.BORDER);
+		tableSummary.setHeaderVisible(true);
+		tableSummary.setLinesVisible(true);
+		TableColumn col1 = new TableColumn(tableSummary, SWT.LEFT);
+		col1.setWidth(130);
+		TableColumn col2 = new TableColumn(tableSummary, SWT.LEFT);
+		col2.setWidth(300);
+		tableSummary.setLayoutData(new GridData(GridData.FILL_BOTH));
+		
+		tableSummary.setFont(fontRegistry.get("monospace"));
+
+		loadSummaryTable();		
+	}
+	
+	/**
+	 * Creates exit info group
+	 * @param parent
+	 */
+	void createExitInfoGroup(Composite parent) {
+		Group groupExitInfo = new Group(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		groupExitInfo.setLayout(layout);
+		groupExitInfo.setText("Exit Info");
+		GridData groupGD = new GridData(GridData.FILL_HORIZONTAL);
+		groupGD.heightHint = 200;
+		groupExitInfo.setLayoutData(groupGD);
+		
+		labelExitType = new Label(groupExitInfo, SWT.NONE);
+		labelExitType.setText("Exit Type:");
+		labelExitType.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		
+		labelPanicSummary = new Label(groupExitInfo, SWT.BORDER);
+		labelPanicSummary.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		
+		browserPanicDescription = new Browser(groupExitInfo, SWT.BORDER);
+		browserPanicDescription.setLayoutData(new GridData(GridData.FILL_BOTH));
+		
+		loadExitInfo();
+	}
+	
+	/**
+	 * Creates call stack group
+	 * @param parent
+	 */
+	void createCallStackGroup(Composite parent) {
+		Group groupCallStack = new Group(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 3;
+		groupCallStack.setLayout(layout);
+		GridData groupGD = new GridData(GridData.FILL_BOTH);
+		groupGD.horizontalSpan = 3;
+		groupCallStack.setText("Call Stack");
+		groupCallStack.setLayoutData(groupGD);
+		
+		comboCallStack = new Combo(groupCallStack, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
+		comboCallStack.addSelectionListener(this);
+		
+		labelStackWarning = new Label(groupCallStack, SWT.NONE);
+		labelStackWarning.setText("(selected stack is build with heuristic algorithm)");
+		labelStackWarning.setVisible(false);
+		
+		buttonDecodeFile = new Button(groupCallStack, SWT.PUSH);
+		buttonDecodeFile.setText("Decode");
+		buttonDecodeFile.setVisible(false);
+		buttonDecodeFile.addSelectionListener(this);
+
+		tableCallStack = new Table(groupCallStack, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | 
+													SWT.V_SCROLL | SWT.H_SCROLL);
+		tableCallStack.setHeaderVisible(true);
+		tableCallStack.setFont(fontRegistry.get("monospace"));
+		
+		GridData tableGD = new GridData(GridData.FILL_BOTH);
+		tableGD.horizontalSpan = 3;
+		tableCallStack.setLayoutData(tableGD);
+
+		GridData buttonGD = new GridData(GridData.FILL_HORIZONTAL);
+		buttonGD.horizontalSpan = 3;
+
+		buttonAllStackEntries = new Button(groupCallStack, SWT.RADIO);
+		buttonAllStackEntries.setText("Show all stack entries");
+		buttonAllStackEntries.addSelectionListener(this);
+		buttonAllStackEntries.setLayoutData(buttonGD);
+		
+		buttonSymbolStackEntries = new Button(groupCallStack, SWT.RADIO);
+		buttonSymbolStackEntries.setText("Show stack entries which have associated symbols");
+		buttonSymbolStackEntries.addSelectionListener(this);
+		buttonSymbolStackEntries.setLayoutData(buttonGD);
+		buttonSymbolStackEntries.setSelection(true);
+		
+		tableViewerCallStack = new CallStackTableViewer(tableCallStack);
+
+		initialCallStackTableLoad();
+		AutoSizeCallStackTableCells();
+	}
+	
+	/**
+	 * Packs all columns for given table
+	 * @param table table which columns are to be packed
+	 */
+	void AutoSizeTableCells(Table table) {
+		for (int i = 0; i < table.getColumnCount(); i++) {
+			table.getColumn(i).pack();
+		}
+	}
+	
+	/**
+	 * Packs columns in call stack table nicely
+	 */
+	void AutoSizeCallStackTableCells() {
+		int tableWidth = tableCallStack.getBounds().width;
+		tableCallStack.getColumn(CallStackTableViewer.COLUMN_ADDRESS).setWidth(80);
+		tableCallStack.getColumn(CallStackTableViewer.COLUMN_VALUE).setWidth(80);
+		tableCallStack.getColumn(CallStackTableViewer.COLUMN_OFFSET).setWidth(65);
+		tableCallStack.getColumn(CallStackTableViewer.COLUMN_TEXT).setWidth(60);
+		int space = tableWidth - 80 - 80 - 65 - 60 - 25;
+		int object = space / 3;
+		if (object < 70)
+			object = 70;
+		tableCallStack.getColumn(CallStackTableViewer.COLUMN_OBJECT).setWidth(object);
+		tableCallStack.getColumn(CallStackTableViewer.COLUMN_SYMBOL).setWidth(object*2);
+	}
+
+	/**
+	 * Loads data into summary table
+	 */
+	void loadSummaryTable() {
+		// if there is no crashFile given, we are waiting for data to be loaded.
+		// Show 'Loading file' text in summary table until we get data.
+		if (crashFile == null) {
+			TableItem item = new TableItem(tableSummary, SWT.NONE);
+			item.setText(new String[] {"Loading file. Please wait.", ""});
+		// we have crash data, load summary table
+		} else {
+			tableSummary.removeAll();
+		
+			// show the data of crashed process
+			Process process = crashFile.getCrashedProcess();
+			if (process != null) {
+				newSummaryTableItem("PROCESS", process.getName(), true);
+				
+				// current UI support only one thread, so show the first thread of first process
+				Thread thread = process.getFirstThread();
+				if (thread != null) {
+					selectedThread = thread;
+					newSummaryTableItem("THREAD", thread.getFullName(), true);
+					newSummaryTableItem("STACK POINTER", thread.getStackPointer(), true);
+					newSummaryTableItem("LINK REGISTER", thread.getLinkRegister(), true);
+					newSummaryTableItem("PROGRAM COUNTER", thread.getProgramCounter(), true);
+				}
+			}
+			
+			Summary crashSummary = crashFile.getSummary();
+			if (crashSummary != null) {
+				newSummaryTableItem("CRASH TIME", crashSummary.getCrashTime(), true);
+				newSummaryTableItem("CRASH DATE", crashSummary.getCrashDate(), true);
+				newSummaryTableItem("UPTIME", crashSummary.getUpTime(), true);
+				newSummaryTableItem("ROM ID", crashSummary.getRomId(), true);
+				// there can be several software version informations, show them all
+				String[] versions = crashSummary.getSwVersion();
+				if (versions != null && versions.length > 0) {
+					for (int i = 0; i < versions.length; i++) {
+						newSummaryTableItem("SW VERSION", versions[i], false);
+					}
+				}
+				// there can be several hardware version informations, show them all
+				versions = crashSummary.getHwVersion();
+				if (versions != null && versions.length > 0) {
+					for (int i = 0; i < versions.length; i++) {
+						newSummaryTableItem("HW VERSION", versions[i], false);
+					}
+				}
+				newSummaryTableItem("PRODUCT TYPE", crashSummary.getProductType(), true);
+				newSummaryTableItem("PRODUCT CODE", crashSummary.getProductCode(), true);
+				newSummaryTableItem("LANGUAGE", crashSummary.getLanguage(), true);
+				newSummaryTableItem("SERIAL NUMBER", crashSummary.getSerialNumber(), true);
+				newSummaryTableItem("IMEI", crashSummary.getImei(), true);
+				newSummaryTableItem("FREE RAM", crashSummary.getFreeRam(), true);
+			}
+			
+			// stand alone stacks don't belong to a thread, check if there are any 
+			// of these, and print SP, LR and PC if needed
+			List<Stack> standAloneStacks = crashFile.getStandAloneStacks();
+			if (standAloneStacks != null && !standAloneStacks.isEmpty()) {
+				for (int i = 0; i < standAloneStacks.size(); i++) {
+					Stack stack = standAloneStacks.get(i);
+					if (stack.stackRegisterContainsCpsr()) {
+						newSummaryTableItem("STACK POINTER", stack.getStackPointer(), true);
+						newSummaryTableItem("LINK REGISTER", stack.getLinkRegister(), true);
+						newSummaryTableItem("PROGRAM COUNTER", stack.getProgramCounter(), true);
+					}
+				}
+			}
+			
+			// stand alone registers don't belong to a thread, check if there are any 
+			// of these, and print SP, LR and PC if needed
+			List<RegisterSet> standAloneRegisterSets = crashFile.getStandAloneRegisterSets();
+			if (standAloneRegisterSets != null && !standAloneRegisterSets.isEmpty()) {
+				for (int i = 0; i < standAloneRegisterSets.size(); i++) {
+					RegisterSet regSet = standAloneRegisterSets.get(i);
+					if (regSet.containsCPSR()) {
+						newSummaryTableItem("STACK POINTER", regSet.getStackPointer(), true);
+						newSummaryTableItem("LINK REGISTER", regSet.getLinkRegister(), true);
+						newSummaryTableItem("PROGRAM COUNTER", regSet.getProgramCounter(), true);
+					}
+				}
+			}
+			
+			AutoSizeTableCells(tableSummary);
+		}
+	}
+	
+	/**
+	 * Load exit information
+	 */
+	void loadExitInfo() {
+		if (crashFile == null)
+			return;
+		
+		String panicSummary = "";
+		String panicDescription = "";
+		if (selectedThread != null && !"".equals(selectedThread.getExitType())) {
+			panicDescription = selectedThread.getPanicDescription();
+			panicSummary = selectedThread.getExitType();
+			if (!"".equals(selectedThread.getExitCategory()) && !"".equals(selectedThread.getExitReason())) {
+				// if crash was an exception
+				if (selectedThread.getExitType().equals("Exception")) {
+					panicSummary += ": " + selectedThread.getExitReason();
+				// crash was a panic
+				} else {
+					panicSummary += ": " + selectedThread.getExitCategory() + " - " + selectedThread.getExitReason();
+				}
+			}
+		}
+		
+		// we could not find panic data
+		if ("".equals(panicSummary.trim())) {
+			panicSummary = "Unknown";
+		}
+		labelPanicSummary.setText(panicSummary);
+		if ("".equals(panicDescription.trim()))
+			panicDescription = HtmlFormatter.formatUnknownPanicMessage(panicSummary); 
+
+		browserPanicDescription.setText(HtmlFormatter.formatHtmlStyle(labelPanicSummary.getFont(), 
+																		panicDescription));
+	}
+	
+	/**
+	 * Loads stacks to combo, selects the correct stack as
+	 * default set and then loads stack's data to table.
+	 */
+	void initialCallStackTableLoad() {
+		int selectedIndex = 0;
+		if (selectedThread != null) {
+			List<Stack> stacks = selectedThread.getStacks();
+			if (stacks != null && !stacks.isEmpty()) {
+				// add all stacks into combo
+				for (int i = 0; i < stacks.size(); i++) {
+					Stack stack = stacks.get(i);
+					// show stack which contains CPSR register as default
+					if (stack.stackRegisterContainsCpsr()) 
+						selectedIndex  = i;
+					comboCallStack.add(stack.getStackType());
+					comboCallStack.setData(stack.getStackType(), stack);
+				}
+			}
+		}
+		
+		List<Stack> standAloneStacks = crashFile.getStandAloneStacks();
+		if (standAloneStacks != null && !standAloneStacks.isEmpty()) {
+			for (int i = 0; i < standAloneStacks.size(); i++) {
+				Stack stack = standAloneStacks.get(i);
+				if (stack.stackRegisterContainsCpsr())
+					selectedIndex = comboCallStack.getItemCount() + i;
+				comboCallStack.add(stack.getStackType());
+				comboCallStack.setData(stack.getStackType(), stack);
+			}
+		}
+
+		if (comboCallStack.getItemCount() > 0) {
+			comboCallStack.select(selectedIndex);
+			loadCallStackTable(true);
+		}
+	}
+	
+	/**
+	 * Loads call stack table according to which stack is
+	 * selected in combo. 
+	 */
+	void loadCallStackTable(boolean autoSizeCells) {
+		tableCallStack.removeAll();
+		labelStackWarning.setVisible(false);
+		
+		if (comboCallStack.getItemCount() < 1)
+			return;
+		
+		try {
+			Stack stack = (Stack)comboCallStack.getData(comboCallStack.getText());
+			boolean containsAccurate = stack.containsAccurateStackEntries();
+			labelStackWarning.setVisible(!containsAccurate);
+			List<StackEntry> stackEntries = stack.getStackEntries();
+			if (stackEntries != null && !stackEntries.isEmpty()) {
+				for (int i = 0; i < stackEntries.size(); i++) {
+					StackEntry stackEntry = stackEntries.get(i);
+					newStackTableItem(stackEntry, containsAccurate);
+				}
+				if (autoSizeCells)
+					AutoSizeCallStackTableCells();
+			}
+			
+			// nothing in stack
+			if (stackEntries == null || stackEntries.isEmpty()) {
+				disableStack();
+			}
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	/**
+	 * Disables stack UI elements
+	 */
+	void disableStack() {
+		labelStackWarning.setVisible(true);
+		labelStackWarning.setText("Symbols were not available while creating stack.");
+		buttonDecodeFile.setVisible(true);
+		comboCallStack.setEnabled(false);
+		buttonAllStackEntries.setEnabled(false);
+		buttonSymbolStackEntries.setEnabled(false);
+		tableCallStack.setEnabled(false);
+	}
+	
+	public void widgetDefaultSelected(SelectionEvent arg0) {
+		// no implementation required
+	}
+
+	public void widgetSelected(SelectionEvent event) {
+		// stack was changed in combo
+		if (event.widget == comboCallStack) {
+			loadCallStackTable(true);
+		// stack radio button changes
+		} else if (event.widget == buttonAllStackEntries || 
+					event.widget == buttonSymbolStackEntries) {
+			loadCallStackTable(false);
+		// decode button was pressed
+		} else if (event.widget == buttonDecodeFile) {
+			MainView mv = MainView.showAndReturnYourself(true);
+			mv.decodeFile(crashFile);
+		}
+	}
+	
+	/**
+	 * Adds new summary table row
+	 * @param header header text
+	 * @param value value text
+	 */
+	boolean newSummaryTableItem(String header, String value, boolean doNotDuplicate) {
+		if (!"".equals(value)) {
+			if (doNotDuplicate) {
+				for (int i = 0; i < tableSummary.getItemCount(); i++) {
+					TableItem it = tableSummary.getItem(i);
+					if (it.getText(0).equalsIgnoreCase(header))
+						return false;
+				}
+			}
+			TableItem item = new TableItem(tableSummary, SWT.NONE);
+			item.setText(new String[] {header, value});
+			return true;
+		}
+		
+		return false;
+	}
+	
+	/**
+	 * Adds new stack table row.
+	 * @param stackEntry row data
+	 * @param stackContainsAccurateEntries affects row colorings
+	 */
+	void newStackTableItem(StackEntry stackEntry, boolean stackContainsAccurateEntries) {
+		// if 'Show stack entries which have associated symbols' radio button is selected and
+		// if stack contains accurate stack entries, and this stack entry is not accurate
+		// don't add it to table (unless this stack entry is current stack pointer or register based)
+		if (buttonSymbolStackEntries.getSelection() &&
+			stackContainsAccurateEntries && 
+			!stackEntry.accurate() && 
+			!stackEntry.currentStackPointer() &&
+			!stackEntry.registerBased()) {
+			return;
+		// if 'Show stack entries which have associated symbols' radio button is selected
+		// if stack doesn't contain accurate stack entries, don't show current stack entry
+		// if it doesn't have associated symbol (unless this stack entry is current stack pointer or register based)
+		} else if (buttonSymbolStackEntries.getSelection() &&
+					!stackContainsAccurateEntries &&
+					"".equals(stackEntry.getSymbol()) &&
+					!stackEntry.currentStackPointer() &&
+					!stackEntry.registerBased())
+			return;
+
+		TableItem item = new TableItem(tableCallStack, SWT.NONE);
+		item.setText(new String[] {stackEntry.getAddress(),
+									stackEntry.getSymbol(),
+									stackEntry.getValue(),
+									stackEntry.getOffset(),
+									stackEntry.getObject(),
+									stackEntry.getText()});
+		
+		item.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+		item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
+		
+		// item is current stack pointer FG black, BG light pink
+		if (stackEntry.currentStackPointer()) {
+			item.setBackground(new Color(Display.getCurrent(), 255, 182, 193)); // light pink
+		// PC or LR
+		} else if (stackEntry.registerBased()) {
+			item.setBackground(new Color(Display.getCurrent(), 173, 216, 230)); // light blue
+		// item is out of stack bound FG gray, BG white
+		} else if (stackEntry.outsideStackBounds()) {
+			item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
+		// item has no symbols, FG black, BG white
+		} else if ("".equals(stackEntry.getSymbol())) {
+		} else
+			// if stack contains accurate entries, show "ghost" entries as gray
+			if (stackContainsAccurateEntries) {
+				// color accurate stack entries black or blue
+				if (stackEntry.accurate()) {
+					// ram loaded code (instead of execute-in-place code) FG blue
+					if (!stackEntry.xip()) {
+						item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
+					}
+				// not accurate stack entry FG gray
+				} else {
+					item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
+				}
+			// stack isn't accurate,
+			} else {
+				// ram loaded code (instead of execute-in-place code)
+				if (!stackEntry.xip()) {
+					item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
+			}
+		}
+		
+		item.setData(stackEntry);
+	}
+	
+	/**
+	 * Sets context sensitive help ids to UI elements
+	 */
+	void setHelps() {
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(tableCallStack,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(tableSummary,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(comboCallStack,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(buttonAllStackEntries,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(buttonDecodeFile,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(buttonSymbolStackEntries,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(browserPanicDescription,
+				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
+	}
+}