crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/ui/editors/RegistersPage.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 "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 java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import com.nokia.s60tools.crashanalyser.containers.Process;
import com.nokia.s60tools.crashanalyser.containers.Register;
import com.nokia.s60tools.crashanalyser.containers.RegisterBit;
import com.nokia.s60tools.crashanalyser.containers.RegisterDetails;
import com.nokia.s60tools.crashanalyser.containers.RegisterSet;
import com.nokia.s60tools.crashanalyser.containers.Thread;
import com.nokia.s60tools.crashanalyser.files.CrashFile;
import com.nokia.s60tools.crashanalyser.files.SummaryFile;
import com.nokia.s60tools.crashanalyser.resources.HelpContextIDs;
public class RegistersPage implements SelectionListener {
// registers group UI items
Combo comboRegisters;
Table tableRegisters;
// CPSR details group UI items
Group groupCpsrEmpty;
Combo comboCpsrDetails;
Table tableCpsrDetails;
FontRegistry fontRegistry;
SummaryFile crashFile;
Process selectedProcess = null;
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 doCreatePage(parent);
}
/**
* Creates the page
* @param parent composite
* @return composite
*/
public Composite createPage(Composite parent) {
return doCreatePage(parent);
}
/**
* Loads data from given file into UI elements.
* @param file crash file
*/
public void setFile(CrashFile file) {
if (file != null) {
crashFile = file;
initialUserRegistersTableLoad();
initialCpsrDetailsTableLoad();
}
}
/**
* Creates all UI elements to the page
* @param parent
* @return composite
*/
Composite doCreatePage(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);
createRegistersGroup(sashFormMain);
// createCodeSegmentsGroup(sashFormTop);
// SashForm sashFormBottom = new SashForm(sashFormMain, SWT.HORIZONTAL);
// createEventLogGroup(sashFormBottom);
createCpsrDetailsGroup(sashFormMain);
// sashFormTop.setWeights(new int[]{3,2});
// sashFormBottom.setWeights(new int[]{3,7});
setHelps();
return parent;
}
/**
* Creates registers group
* @param parent
*/
void createRegistersGroup(Composite parent) {
Group groupRegisters = new Group(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
groupRegisters.setLayout(layout);
groupRegisters.setText("Registers");
GridData groupGD = new GridData(GridData.FILL_HORIZONTAL);
groupRegisters.setLayoutData(groupGD);
comboRegisters = new Combo(groupRegisters, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
GridData comboGD = new GridData();
comboGD.horizontalSpan = 2;
comboRegisters.setLayoutData(comboGD);
comboRegisters.addSelectionListener(this);
tableRegisters = new Table(groupRegisters, SWT.BORDER);
tableRegisters.setHeaderVisible(true);
tableRegisters.setLinesVisible(true);
TableColumn col = new TableColumn(tableRegisters, SWT.LEFT);
col.setWidth(100);
col.setText("Register");
col = new TableColumn(tableRegisters, SWT.LEFT);
col.setWidth(100);
col.setText("Value");
col = new TableColumn(tableRegisters, SWT.LEFT);
col.setWidth(100);
col.setText("Symbol");
col = new TableColumn(tableRegisters, SWT.LEFT);
col.setWidth(100);
col.setText("Comment");
tableRegisters.setFont(fontRegistry.get("monospace"));
GridData tableGd = new GridData(GridData.FILL_BOTH);
tableGd.horizontalSpan = 2;
tableRegisters.setLayoutData(tableGd);
initialUserRegistersTableLoad();
}
/**
* Creates cpsr details group
* @param parent
*/
void createCpsrDetailsGroup(Composite parent) {
Group groupCpsrDetails = new Group(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
groupCpsrDetails.setLayout(layout);
groupCpsrDetails.setText("CPSR Details");
GridData groupGD = new GridData(GridData.FILL_VERTICAL);
groupCpsrDetails.setLayoutData(groupGD);
comboCpsrDetails = new Combo(groupCpsrDetails, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
comboCpsrDetails.addSelectionListener(this);
// Empty group
groupCpsrEmpty = new Group(groupCpsrDetails, SWT.NONE);
FormLayout fl = new FormLayout();
fl.marginRight = 5;
fl.marginLeft = 5;
fl.marginBottom = 5;
groupCpsrEmpty.setLayout(fl);
GridData groupCpsrEmptyGd = new GridData(GridData.FILL_HORIZONTAL);
groupCpsrEmptyGd.horizontalAlignment = SWT.FILL;
groupCpsrEmptyGd.grabExcessHorizontalSpace = true;
groupCpsrEmpty.setLayoutData(groupCpsrEmptyGd);
// create 32 empty text boxes
for (int i = 0; i < 32; i++) {
Text text = new Text(groupCpsrEmpty, SWT.READ_ONLY | SWT.BORDER | SWT.NO_FOCUS | SWT.CENTER);
text.setFont(fontRegistry.get("monospace"));
FormData textFd = new FormData();
textFd.left = new FormAttachment(0,i*20);
textFd.top = new FormAttachment(8, 15);
textFd.width = 8;
text.setLayoutData(textFd);
}
tableCpsrDetails = new Table(groupCpsrDetails, SWT.BORDER);
tableCpsrDetails.setLinesVisible(true);
tableCpsrDetails.setHeaderVisible(true);
TableColumn col = new TableColumn(tableCpsrDetails, SWT.LEFT);
col.setWidth(380);
col.setText("Name");
col = new TableColumn(tableCpsrDetails, SWT.LEFT);
col.setWidth(220);
col.setText("Value");
GridData tableGd = new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL);
tableGd.horizontalAlignment = SWT.FILL;
tableGd.grabExcessHorizontalSpace = true;
tableCpsrDetails.setLayoutData(tableGd);
tableCpsrDetails.setFont(fontRegistry.get("monospace"));
initialCpsrDetailsTableLoad();
}
/**
* Loads register sets to combo, selects the correct set as
* default set and then loads set's registers to table.
*/
void initialUserRegistersTableLoad() {
if (crashFile == null)
return;
int defaultSelectionIndex = 0;
// show the data of crashed process
if (crashFile.getThread() != null) {
selectedProcess = crashFile.getProcessByThread(crashFile.getThread().getId());
} else {
selectedProcess = crashFile.getCrashedProcess();
}
if (selectedProcess != null) {
// current UI support only one thread, so show the first thread of first process
if(crashFile.getThread() != null) {
selectedThread = crashFile.getThread();
} else {
selectedThread = crashFile.getCrashedThread();
}
if (selectedThread != null) {
List<RegisterSet> registerSets = selectedThread.getRegisters();
if (registerSets != null && !registerSets.isEmpty()) {
// load all register sets to combo
for (int i = 0; i < registerSets.size(); i++) {
RegisterSet registerSet = registerSets.get(i);
// default register to show is the one that contains CPSR register
if (registerSet.containsCPSR())
defaultSelectionIndex = i;
comboRegisters.add(registerSet.getName());
comboRegisters.setData(registerSet.getName(), registerSet);
}
}
}
}
List<RegisterSet> standAloneRegisters = crashFile.getStandAloneRegisterSets();
if (standAloneRegisters != null && !standAloneRegisters.isEmpty()) {
for (int i = 0; i < standAloneRegisters.size(); i++) {
RegisterSet regSet = standAloneRegisters.get(i);
if (regSet.containsCPSR())
defaultSelectionIndex = comboRegisters.getItemCount() + i;
comboRegisters.add(regSet.getName());
comboRegisters.setData(regSet.getName(), regSet);
}
}
if (comboRegisters.getItemCount() > 0) {
comboRegisters.select(defaultSelectionIndex);
loadRegistersTable();
}
}
/**
* Loads user registers table according to which registers set is
* selected in combo.
*/
void loadRegistersTable() {
tableRegisters.removeAll();
if (comboRegisters.getItemCount() < 1)
return;
try {
RegisterSet registerSet = (RegisterSet)comboRegisters.getData(comboRegisters.getText());
List<Register> registers = registerSet.getRegisters();
if (registers != null && !registers.isEmpty()) {
// show all register values in selected register set
for (int i = 0; i < registers.size(); i++) {
Register register = registers.get(i);
newRegistersTableItem(register);
}
AutoSizeTableCells(tableRegisters);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Loads cprs types to combo, selects first type and then loads it's
* data to table.
*/
void initialCpsrDetailsTableLoad() {
if (crashFile == null)
return;
List<RegisterDetails> registerDetails = crashFile.getRegisterDetails();
if (registerDetails != null && !registerDetails.isEmpty()) {
for (int i = 0; i < registerDetails.size(); i++) {
RegisterDetails regDetails = registerDetails.get(i);
if (regDetails.getDescription().contains("CPSR")) {
comboCpsrDetails.add(regDetails.getDescription());
comboCpsrDetails.setData(regDetails.getDescription(), regDetails);
}
}
comboCpsrDetails.select(0);
loadCpsrDetailsTable();
}
}
/**
* Loads currently selected cprs's details into table.
*/
void loadCpsrDetailsTable() {
try {
tableCpsrDetails.removeAll();
RegisterDetails registerDetails = null;
if (comboRegisters.getSelectionIndex() >= 0)
registerDetails = (RegisterDetails)comboCpsrDetails.getData(comboCpsrDetails.getText());
if (registerDetails != null) {
boolean bitStartFromRight = registerDetails.bitsStartFromRight();
Map<String, String> categories = new HashMap<String, String>();
// go through all 32 text boxes, and see if there is a bit for each box
for (int i = 0, j = 31; i < 32; i++, j--) {
Text box = (Text)groupCpsrEmpty.getChildren().clone()[j];
// bits can start from the right or left (endianess)
if (!bitStartFromRight)
box = (Text)groupCpsrEmpty.getChildren().clone()[i];
RegisterBit bit = registerDetails.getBit(i);
// there's no bit for this box
if (bit == null) {
box.setText("");
box.setToolTipText("");
// there is a bit for this box
} else {
String regChar = bit.getRegisterChar();
String category = bit.getCategory();
String interpretation = bit.getInterpretation();
// if this bit contains a longer description, it should be shown in the table also
if (!"".equals(interpretation) && !categories.containsKey(category)) {
categories.put(category, interpretation);
}
box.setText(regChar);
box.setToolTipText(category);
}
}
// load table
for (int i = 0; i < categories.size(); i++) {
newCpsrDetailsTableItem(categories.keySet().toArray()[i].toString(),
categories.values().toArray()[i].toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Adds a new table row for registers table
* @param register row data
*/
void newRegistersTableItem(Register register) {
TableItem item = new TableItem(tableRegisters, SWT.NONE);
item.setText(new String[] {register.getName(),
register.getValue(),
register.getSymbol(),
register.getComments()});
}
/**
* Adds a new table row for cpsr details table
* @param header header text
* @param value value text
*/
void newCpsrDetailsTableItem(String header, String value) {
TableItem item = new TableItem(tableCpsrDetails, SWT.NONE);
item.setText(new String[] {header, value});
}
/**
* 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();
}
}
public void widgetDefaultSelected(SelectionEvent arg0) {
// No implementation needed
}
public void widgetSelected(SelectionEvent event) {
// cpsr was changed in combo
if (event.widget == comboCpsrDetails) {
loadCpsrDetailsTable();
// register set was changed in combo
} else if (event.widget == comboRegisters) {
loadRegistersTable();
}
}
/**
* Sets context sensitive help ids to UI elements
*/
void setHelps() {
PlatformUI.getWorkbench().getHelpSystem().setHelp(tableCpsrDetails,
HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);
PlatformUI.getWorkbench().getHelpSystem().setHelp(tableRegisters,
HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);
PlatformUI.getWorkbench().getHelpSystem().setHelp(tableRegisters,
HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);
PlatformUI.getWorkbench().getHelpSystem().setHelp(comboCpsrDetails,
HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);
PlatformUI.getWorkbench().getHelpSystem().setHelp(comboRegisters,
HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);
}
}