crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/ui/editors/SummaryPage.java
changeset 4 615035072f7e
parent 0 5ad7ad99af01
child 16 72f198be1c1d
equal deleted inserted replaced
3:431bbaccaec8 4:615035072f7e
    16 */
    16 */
    17 
    17 
    18 package com.nokia.s60tools.crashanalyser.ui.editors;
    18 package com.nokia.s60tools.crashanalyser.ui.editors;
    19 
    19 
    20 import org.eclipse.swt.events.SelectionEvent;
    20 import org.eclipse.swt.events.SelectionEvent;
    21 import org.eclipse.swt.events.SelectionListener;
       
    22 import org.eclipse.swt.layout.GridData;
    21 import org.eclipse.swt.layout.GridData;
    23 import org.eclipse.swt.SWT;
    22 import org.eclipse.swt.SWT;
    24 import org.eclipse.swt.layout.GridLayout;
    23 import org.eclipse.swt.layout.GridLayout;
    25 import org.eclipse.swt.widgets.*;
    24 import org.eclipse.swt.widgets.*;
    26 import org.eclipse.swt.browser.*;
    25 import org.eclipse.swt.browser.*;
    27 import org.eclipse.swt.graphics.Color;
       
    28 import org.eclipse.swt.custom.SashForm;
    26 import org.eclipse.swt.custom.SashForm;
       
    27 import org.eclipse.swt.custom.TableCursor;
    29 import org.eclipse.ui.PlatformUI;
    28 import org.eclipse.ui.PlatformUI;
    30 
    29 
    31 import com.nokia.s60tools.crashanalyser.files.*;
    30 import com.nokia.s60tools.crashanalyser.files.*;
       
    31 import com.nokia.s60tools.crashanalyser.files.SummaryFile.ContentType;
    32 import com.nokia.s60tools.crashanalyser.model.HtmlFormatter;
    32 import com.nokia.s60tools.crashanalyser.model.HtmlFormatter;
    33 import com.nokia.s60tools.crashanalyser.containers.Summary;
    33 import com.nokia.s60tools.crashanalyser.containers.Summary;
    34 import com.nokia.s60tools.crashanalyser.containers.Process;
    34 import com.nokia.s60tools.crashanalyser.containers.Process;
    35 import com.nokia.s60tools.crashanalyser.containers.Thread;
    35 import com.nokia.s60tools.crashanalyser.containers.Thread;
    36 import com.nokia.s60tools.crashanalyser.containers.Stack;
    36 import com.nokia.s60tools.crashanalyser.containers.Stack;
    37 import com.nokia.s60tools.crashanalyser.containers.StackEntry;
       
    38 import com.nokia.s60tools.crashanalyser.containers.RegisterSet;
    37 import com.nokia.s60tools.crashanalyser.containers.RegisterSet;
    39 import com.nokia.s60tools.crashanalyser.resources.HelpContextIDs;
    38 import com.nokia.s60tools.crashanalyser.resources.HelpContextIDs;
    40 import com.nokia.s60tools.crashanalyser.ui.viewers.*;
    39 
    41 import com.nokia.s60tools.crashanalyser.ui.views.*;
       
    42 import java.util.List;
    40 import java.util.List;
    43 import org.eclipse.jface.resource.FontRegistry;
    41 import org.eclipse.jface.resource.FontRegistry;
    44 import org.eclipse.swt.graphics.FontData;
    42 import org.eclipse.swt.graphics.FontData;
    45 
    43 
    46 /**
    44 /**
    47  * Crash Data page in Crash Visualiser editor. 
    45  * Crash Data page in Crash Visualiser editor. 
    48  *
    46  *
    49  */
    47  */
    50 public class SummaryPage implements SelectionListener {
    48 public class SummaryPage {
    51 	
    49 	
    52 	// summary group UI items
    50 	// summary group UI items
    53 	Table tableSummary;
    51 	Table tableSummary;
    54 
    52 
    55 	// exit info group UI items
    53 	// exit info group UI items
    56 	Label labelExitType;
    54 	Label labelExitType;
    57 	Label labelPanicSummary;
    55 	Label labelPanicSummary;
    58 	Browser browserPanicDescription;
    56 	Browser browserPanicDescription;
    59 	
    57 		
    60 	// call stack group UI items
       
    61 	Combo comboCallStack;
       
    62 	Label labelStackWarning;
       
    63 	Button buttonDecodeFile;
       
    64 	Table tableCallStack;
       
    65 	CallStackTableViewer tableViewerCallStack;
       
    66 	Button buttonAllStackEntries;
       
    67 	Button buttonSymbolStackEntries;
       
    68 	
       
    69 	SummaryFile crashFile = null;
    58 	SummaryFile crashFile = null;
    70 	FontRegistry fontRegistry;
    59 	FontRegistry fontRegistry;
    71 	Thread selectedThread = null;
    60 	Thread selectedThread = null;
    72 	
    61 	
    73 	/**
    62 	/**
    89 	public Composite createPage(Composite parent) {
    78 	public Composite createPage(Composite parent) {
    90 		return doCreate(parent);
    79 		return doCreate(parent);
    91 	}
    80 	}
    92 	
    81 	
    93 	public void update() {
    82 	public void update() {
    94 		AutoSizeCallStackTableCells();
    83 	//	AutoSizeCallStackTableCells();
    95 	}
    84 	}
    96 	
    85 	
    97 	/**
    86 	/**
    98 	 * Loads data from given file into UI elements.
    87 	 * Loads data from given file into UI elements.
    99 	 * @param file crash file
    88 	 * @param file crash file
   101 	public void setFile(CrashFile file) {
    90 	public void setFile(CrashFile file) {
   102 		if (file != null) {
    91 		if (file != null) {
   103 			crashFile = file;
    92 			crashFile = file;
   104 			loadSummaryTable();
    93 			loadSummaryTable();
   105 			loadExitInfo();
    94 			loadExitInfo();
   106 			initialCallStackTableLoad();
       
   107 		}
    95 		}
   108 	}
    96 	}
   109 	
    97 	
   110 	/**
    98 	/**
   111 	 * Creates all UI elements to the page
    99 	 * Creates all UI elements to the page
   119 		parent.setLayoutData(new GridData(GridData.FILL_BOTH));
   107 		parent.setLayoutData(new GridData(GridData.FILL_BOTH));
   120 		fontRegistry = new FontRegistry(Display.getCurrent());
   108 		fontRegistry = new FontRegistry(Display.getCurrent());
   121 		fontRegistry.put("monospace", new FontData[]{new FontData("Courier", 8, SWT.NORMAL)});
   109 		fontRegistry.put("monospace", new FontData[]{new FontData("Courier", 8, SWT.NORMAL)});
   122 		SashForm sashFormMain = new SashForm(parent, SWT.VERTICAL);
   110 		SashForm sashFormMain = new SashForm(parent, SWT.VERTICAL);
   123 		sashFormMain.setLayoutData(new GridData(GridData.FILL_BOTH));
   111 		sashFormMain.setLayoutData(new GridData(GridData.FILL_BOTH));
   124 		SashForm sashFormTop = new SashForm(sashFormMain, SWT.HORIZONTAL);
   112 		createSummaryGroup(sashFormMain);
   125 		createSummaryGroup(sashFormTop);
   113 		createExitInfoGroup(sashFormMain);
   126 		createExitInfoGroup(sashFormTop);
       
   127 		createCallStackGroup(sashFormMain);
       
   128 
       
   129 		sashFormMain.setWeights(new int[] {1,2});
       
   130 		
   114 		
   131 		setHelps();
   115 		setHelps();
   132 		
   116 		
   133 		return parent;
   117 		return parent;
   134 	}
   118 	}
   140 	void createSummaryGroup(Composite parent) {
   124 	void createSummaryGroup(Composite parent) {
   141 		Group groupSummary = new Group(parent, SWT.NONE);
   125 		Group groupSummary = new Group(parent, SWT.NONE);
   142 		GridLayout layout = new GridLayout();
   126 		GridLayout layout = new GridLayout();
   143 		layout.numColumns = 1;
   127 		layout.numColumns = 1;
   144 		groupSummary.setLayout(layout);
   128 		groupSummary.setLayout(layout);
   145 		groupSummary.setText("Summary");
   129 		groupSummary.setText("General");
   146 		GridData groupGD = new GridData(GridData.FILL_HORIZONTAL);
   130 		GridData groupGD = new GridData(GridData.FILL_HORIZONTAL);
   147 		groupGD.heightHint = 200;
   131 		groupGD.heightHint = 200;
   148 		groupSummary.setLayoutData(groupGD);
   132 		groupSummary.setLayoutData(groupGD);
   149 		
   133 		
   150 		tableSummary = new Table(groupSummary, SWT.BORDER);
   134 		tableSummary = new Table(groupSummary, SWT.BORDER  | SWT.FULL_SELECTION |  
       
   135 				SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY );
   151 		tableSummary.setHeaderVisible(true);
   136 		tableSummary.setHeaderVisible(true);
   152 		tableSummary.setLinesVisible(true);
   137 		tableSummary.setLinesVisible(true);
   153 		TableColumn col1 = new TableColumn(tableSummary, SWT.LEFT);
   138 		TableColumn col1 = new TableColumn(tableSummary, SWT.LEFT);
   154 		col1.setWidth(130);
   139 		col1.setWidth(130);
   155 		TableColumn col2 = new TableColumn(tableSummary, SWT.LEFT);
   140 		TableColumn col2 = new TableColumn(tableSummary, SWT.LEFT);
   156 		col2.setWidth(300);
   141 		col2.setWidth(300);
   157 		tableSummary.setLayoutData(new GridData(GridData.FILL_BOTH));
   142 		tableSummary.setLayoutData(new GridData(GridData.FILL_BOTH));
   158 		
   143 		
   159 		tableSummary.setFont(fontRegistry.get("monospace"));
   144 		tableSummary.setFont(fontRegistry.get("monospace"));
   160 
   145 		
       
   146 		
       
   147 		final TableCursor cursor = new TableCursor(tableSummary, SWT.NONE);
       
   148 		TableKeyListener keyListener = new TableKeyListener(tableSummary, cursor);
       
   149 		tableSummary.addKeyListener(keyListener);
       
   150 		cursor.addKeyListener(keyListener);
       
   151                         
   161 		loadSummaryTable();		
   152 		loadSummaryTable();		
   162 	}
   153 	}
   163 	
   154 	
   164 	/**
   155 	/**
   165 	 * Creates exit info group
   156 	 * Creates exit info group
   186 		browserPanicDescription.setLayoutData(new GridData(GridData.FILL_BOTH));
   177 		browserPanicDescription.setLayoutData(new GridData(GridData.FILL_BOTH));
   187 		
   178 		
   188 		loadExitInfo();
   179 		loadExitInfo();
   189 	}
   180 	}
   190 	
   181 	
   191 	/**
       
   192 	 * Creates call stack group
       
   193 	 * @param parent
       
   194 	 */
       
   195 	void createCallStackGroup(Composite parent) {
       
   196 		Group groupCallStack = new Group(parent, SWT.NONE);
       
   197 		GridLayout layout = new GridLayout();
       
   198 		layout.numColumns = 3;
       
   199 		groupCallStack.setLayout(layout);
       
   200 		GridData groupGD = new GridData(GridData.FILL_BOTH);
       
   201 		groupGD.horizontalSpan = 3;
       
   202 		groupCallStack.setText("Call Stack");
       
   203 		groupCallStack.setLayoutData(groupGD);
       
   204 		
       
   205 		comboCallStack = new Combo(groupCallStack, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
       
   206 		comboCallStack.addSelectionListener(this);
       
   207 		
       
   208 		labelStackWarning = new Label(groupCallStack, SWT.NONE);
       
   209 		labelStackWarning.setText("(selected stack is build with heuristic algorithm)");
       
   210 		labelStackWarning.setVisible(false);
       
   211 		
       
   212 		buttonDecodeFile = new Button(groupCallStack, SWT.PUSH);
       
   213 		buttonDecodeFile.setText("Decode");
       
   214 		buttonDecodeFile.setVisible(false);
       
   215 		buttonDecodeFile.addSelectionListener(this);
       
   216 
       
   217 		tableCallStack = new Table(groupCallStack, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | 
       
   218 													SWT.V_SCROLL | SWT.H_SCROLL);
       
   219 		tableCallStack.setHeaderVisible(true);
       
   220 		tableCallStack.setFont(fontRegistry.get("monospace"));
       
   221 		
       
   222 		GridData tableGD = new GridData(GridData.FILL_BOTH);
       
   223 		tableGD.horizontalSpan = 3;
       
   224 		tableCallStack.setLayoutData(tableGD);
       
   225 
       
   226 		GridData buttonGD = new GridData(GridData.FILL_HORIZONTAL);
       
   227 		buttonGD.horizontalSpan = 3;
       
   228 
       
   229 		buttonAllStackEntries = new Button(groupCallStack, SWT.RADIO);
       
   230 		buttonAllStackEntries.setText("Show all stack entries");
       
   231 		buttonAllStackEntries.addSelectionListener(this);
       
   232 		buttonAllStackEntries.setLayoutData(buttonGD);
       
   233 		
       
   234 		buttonSymbolStackEntries = new Button(groupCallStack, SWT.RADIO);
       
   235 		buttonSymbolStackEntries.setText("Show stack entries which have associated symbols");
       
   236 		buttonSymbolStackEntries.addSelectionListener(this);
       
   237 		buttonSymbolStackEntries.setLayoutData(buttonGD);
       
   238 		buttonSymbolStackEntries.setSelection(true);
       
   239 		
       
   240 		tableViewerCallStack = new CallStackTableViewer(tableCallStack);
       
   241 
       
   242 		initialCallStackTableLoad();
       
   243 		AutoSizeCallStackTableCells();
       
   244 	}
       
   245 	
   182 	
   246 	/**
   183 	/**
   247 	 * Packs all columns for given table
   184 	 * Packs all columns for given table
   248 	 * @param table table which columns are to be packed
   185 	 * @param table table which columns are to be packed
   249 	 */
   186 	 */
   251 		for (int i = 0; i < table.getColumnCount(); i++) {
   188 		for (int i = 0; i < table.getColumnCount(); i++) {
   252 			table.getColumn(i).pack();
   189 			table.getColumn(i).pack();
   253 		}
   190 		}
   254 	}
   191 	}
   255 	
   192 	
   256 	/**
       
   257 	 * Packs columns in call stack table nicely
       
   258 	 */
       
   259 	void AutoSizeCallStackTableCells() {
       
   260 		int tableWidth = tableCallStack.getBounds().width;
       
   261 		tableCallStack.getColumn(CallStackTableViewer.COLUMN_ADDRESS).setWidth(80);
       
   262 		tableCallStack.getColumn(CallStackTableViewer.COLUMN_VALUE).setWidth(80);
       
   263 		tableCallStack.getColumn(CallStackTableViewer.COLUMN_OFFSET).setWidth(65);
       
   264 		tableCallStack.getColumn(CallStackTableViewer.COLUMN_TEXT).setWidth(60);
       
   265 		int space = tableWidth - 80 - 80 - 65 - 60 - 25;
       
   266 		int object = space / 3;
       
   267 		if (object < 70)
       
   268 			object = 70;
       
   269 		tableCallStack.getColumn(CallStackTableViewer.COLUMN_OBJECT).setWidth(object);
       
   270 		tableCallStack.getColumn(CallStackTableViewer.COLUMN_SYMBOL).setWidth(object*2);
       
   271 	}
       
   272 
       
   273 	/**
   193 	/**
   274 	 * Loads data into summary table
   194 	 * Loads data into summary table
   275 	 */
   195 	 */
   276 	void loadSummaryTable() {
   196 	void loadSummaryTable() {
   277 		// if there is no crashFile given, we are waiting for data to be loaded.
   197 		// if there is no crashFile given, we are waiting for data to be loaded.
   282 		// we have crash data, load summary table
   202 		// we have crash data, load summary table
   283 		} else {
   203 		} else {
   284 			tableSummary.removeAll();
   204 			tableSummary.removeAll();
   285 		
   205 		
   286 			// show the data of crashed process
   206 			// show the data of crashed process
   287 			Process process = crashFile.getCrashedProcess();
   207 			Process process = null;
       
   208 			if (crashFile.getThread() != null) {
       
   209 				process = crashFile.getProcessByThread(crashFile.getThread().getId());
       
   210 			} else {
       
   211 				process = crashFile.getCrashedProcess();
       
   212 			}
       
   213 			
   288 			if (process != null) {
   214 			if (process != null) {
   289 				newSummaryTableItem("PROCESS", process.getName(), true);
   215 				newSummaryTableItem("PROCESS", process.getName(), true);
   290 				
   216 				
   291 				// current UI support only one thread, so show the first thread of first process
   217 				// current UI support only one thread, so show the first thread of first process
   292 				Thread thread = process.getFirstThread();
   218 				Thread thread = null;
       
   219 				if (crashFile.getThread() != null) {
       
   220 					// Show only thread information (no crash info)
       
   221 					thread = crashFile.getThread();
       
   222 				} else {
       
   223 					thread = crashFile.getCrashedThread();
       
   224 				}
       
   225 				
   293 				if (thread != null) {
   226 				if (thread != null) {
   294 					selectedThread = thread;
   227 					selectedThread = thread;
   295 					newSummaryTableItem("THREAD", thread.getFullName(), true);
   228 					newSummaryTableItem("THREAD", thread.getFullName(), true);
   296 					newSummaryTableItem("STACK POINTER", thread.getStackPointer(), true);
   229 					newSummaryTableItem("STACK POINTER", thread.getStackPointer(), true);
   297 					newSummaryTableItem("LINK REGISTER", thread.getLinkRegister(), true);
   230 					newSummaryTableItem("LINK REGISTER", thread.getLinkRegister(), true);
   299 				}
   232 				}
   300 			}
   233 			}
   301 			
   234 			
   302 			Summary crashSummary = crashFile.getSummary();
   235 			Summary crashSummary = crashFile.getSummary();
   303 			if (crashSummary != null) {
   236 			if (crashSummary != null) {
   304 				newSummaryTableItem("CRASH TIME", crashSummary.getCrashTime(), true);
       
   305 				newSummaryTableItem("CRASH DATE", crashSummary.getCrashDate(), true);
       
   306 				newSummaryTableItem("UPTIME", crashSummary.getUpTime(), true);
       
   307 				newSummaryTableItem("ROM ID", crashSummary.getRomId(), true);
       
   308 				// there can be several software version informations, show them all
   237 				// there can be several software version informations, show them all
   309 				String[] versions = crashSummary.getSwVersion();
   238 				String[] versions = crashSummary.getSwVersion();
   310 				if (versions != null && versions.length > 0) {
   239 				if (versions != null && versions.length > 0) {
   311 					for (int i = 0; i < versions.length; i++) {
   240 					for (int i = 0; i < versions.length; i++) {
   312 						newSummaryTableItem("SW VERSION", versions[i], false);
   241 						newSummaryTableItem("SW VERSION", versions[i], false);
   320 					}
   249 					}
   321 				}
   250 				}
   322 				newSummaryTableItem("PRODUCT TYPE", crashSummary.getProductType(), true);
   251 				newSummaryTableItem("PRODUCT TYPE", crashSummary.getProductType(), true);
   323 				newSummaryTableItem("PRODUCT CODE", crashSummary.getProductCode(), true);
   252 				newSummaryTableItem("PRODUCT CODE", crashSummary.getProductCode(), true);
   324 				newSummaryTableItem("LANGUAGE", crashSummary.getLanguage(), true);
   253 				newSummaryTableItem("LANGUAGE", crashSummary.getLanguage(), true);
   325 				newSummaryTableItem("SERIAL NUMBER", crashSummary.getSerialNumber(), true);
       
   326 				newSummaryTableItem("IMEI", crashSummary.getImei(), true);
   254 				newSummaryTableItem("IMEI", crashSummary.getImei(), true);
   327 				newSummaryTableItem("FREE RAM", crashSummary.getFreeRam(), true);
   255 				newSummaryTableItem("CRASH TIME", crashSummary.getCrashTime(), true);
       
   256 				newSummaryTableItem("CRASH DATE", crashSummary.getCrashDate(), true);
       
   257 				newSummaryTableItem("ROM ID", crashSummary.getRomId(), true);
       
   258 				newSummaryTableItem("AVAILABLE MEMORY", crashSummary.getFreeRam(), true);
       
   259 				newSummaryTableItem("PSN", crashSummary.getSerialNumber(), true);
       
   260 				newSummaryTableItem("UPTIME", crashSummary.getUpTime(), true);
       
   261 				newSummaryTableItem("MOBILECRASH CONFIGURATION", crashSummary.getProductionMode(), true);
       
   262 				newSummaryTableItem("CRASH SOURCE", crashSummary.getCrashSource(), true);
       
   263 				newSummaryTableItem("FREE DISK SPACE", crashSummary.getFreeDisk(), true);
       
   264 				
       
   265 				// Print defect hash if exist
       
   266 				List<Stack> stacks = null;
       
   267 				if (selectedThread != null)
       
   268 					stacks = selectedThread.getStacks();
       
   269 				
       
   270 				if (stacks != null && !stacks.isEmpty()) 
       
   271 				{
       
   272 					String defectHash = "";
       
   273 					for(Stack stack: stacks) {
       
   274 						defectHash = stack.getHash();
       
   275 						if(! "".equals(defectHash)) {
       
   276 							newSummaryTableItem("DEFECT HASH", defectHash, true);
       
   277 						}
       
   278 					}
       
   279 				}
   328 			}
   280 			}
   329 			
   281 			
   330 			// stand alone stacks don't belong to a thread, check if there are any 
   282 			// stand alone stacks don't belong to a thread, check if there are any 
   331 			// of these, and print SP, LR and PC if needed
   283 			// of these, and print SP, LR and PC if needed
   332 			List<Stack> standAloneStacks = crashFile.getStandAloneStacks();
   284 			List<Stack> standAloneStacks = crashFile.getStandAloneStacks();
   363 	 * Load exit information
   315 	 * Load exit information
   364 	 */
   316 	 */
   365 	void loadExitInfo() {
   317 	void loadExitInfo() {
   366 		if (crashFile == null)
   318 		if (crashFile == null)
   367 			return;
   319 			return;
   368 		
   320 					
   369 		String panicSummary = "";
   321 		String panicSummary = "";
   370 		String panicDescription = "";
   322 		String panicDescription = "";
       
   323 
       
   324 		if (crashFile.getContentType() == ContentType.REGMSG) {
       
   325 			labelPanicSummary.setText("Registration message");
       
   326 			panicDescription = HtmlFormatter.formatRegistrationMessage();
       
   327 			browserPanicDescription.setText(HtmlFormatter.formatHtmlStyle(labelPanicSummary.getFont(), 
       
   328 					panicDescription));
       
   329 			return;
       
   330 		} else if (crashFile.getContentType() == ContentType.REPORT) {
       
   331 			labelPanicSummary.setText("Report");
       
   332 			panicDescription = HtmlFormatter.formatReport();
       
   333 			browserPanicDescription.setText(HtmlFormatter.formatHtmlStyle(labelPanicSummary.getFont(), 
       
   334 					panicDescription));
       
   335 			return;
       
   336 		}
       
   337 		
   371 		if (selectedThread != null && !"".equals(selectedThread.getExitType())) {
   338 		if (selectedThread != null && !"".equals(selectedThread.getExitType())) {
   372 			panicDescription = selectedThread.getPanicDescription();
   339 			panicDescription = selectedThread.getPanicDescription();
   373 			panicSummary = selectedThread.getExitType();
   340 			panicSummary = selectedThread.getExitType();
   374 			if (!"".equals(selectedThread.getExitCategory()) && !"".equals(selectedThread.getExitReason())) {
   341 			if (!"".equals(selectedThread.getExitCategory()) && !"".equals(selectedThread.getExitReason())) {
   375 				// if crash was an exception
   342 				// if crash was an exception
   392 
   359 
   393 		browserPanicDescription.setText(HtmlFormatter.formatHtmlStyle(labelPanicSummary.getFont(), 
   360 		browserPanicDescription.setText(HtmlFormatter.formatHtmlStyle(labelPanicSummary.getFont(), 
   394 																		panicDescription));
   361 																		panicDescription));
   395 	}
   362 	}
   396 	
   363 	
   397 	/**
       
   398 	 * Loads stacks to combo, selects the correct stack as
       
   399 	 * default set and then loads stack's data to table.
       
   400 	 */
       
   401 	void initialCallStackTableLoad() {
       
   402 		int selectedIndex = 0;
       
   403 		if (selectedThread != null) {
       
   404 			List<Stack> stacks = selectedThread.getStacks();
       
   405 			if (stacks != null && !stacks.isEmpty()) {
       
   406 				// add all stacks into combo
       
   407 				for (int i = 0; i < stacks.size(); i++) {
       
   408 					Stack stack = stacks.get(i);
       
   409 					// show stack which contains CPSR register as default
       
   410 					if (stack.stackRegisterContainsCpsr()) 
       
   411 						selectedIndex  = i;
       
   412 					comboCallStack.add(stack.getStackType());
       
   413 					comboCallStack.setData(stack.getStackType(), stack);
       
   414 				}
       
   415 			}
       
   416 		}
       
   417 		
       
   418 		List<Stack> standAloneStacks = crashFile.getStandAloneStacks();
       
   419 		if (standAloneStacks != null && !standAloneStacks.isEmpty()) {
       
   420 			for (int i = 0; i < standAloneStacks.size(); i++) {
       
   421 				Stack stack = standAloneStacks.get(i);
       
   422 				if (stack.stackRegisterContainsCpsr())
       
   423 					selectedIndex = comboCallStack.getItemCount() + i;
       
   424 				comboCallStack.add(stack.getStackType());
       
   425 				comboCallStack.setData(stack.getStackType(), stack);
       
   426 			}
       
   427 		}
       
   428 
       
   429 		if (comboCallStack.getItemCount() > 0) {
       
   430 			comboCallStack.select(selectedIndex);
       
   431 			loadCallStackTable(true);
       
   432 		}
       
   433 	}
       
   434 	
       
   435 	/**
       
   436 	 * Loads call stack table according to which stack is
       
   437 	 * selected in combo. 
       
   438 	 */
       
   439 	void loadCallStackTable(boolean autoSizeCells) {
       
   440 		tableCallStack.removeAll();
       
   441 		labelStackWarning.setVisible(false);
       
   442 		
       
   443 		if (comboCallStack.getItemCount() < 1)
       
   444 			return;
       
   445 		
       
   446 		try {
       
   447 			Stack stack = (Stack)comboCallStack.getData(comboCallStack.getText());
       
   448 			boolean containsAccurate = stack.containsAccurateStackEntries();
       
   449 			labelStackWarning.setVisible(!containsAccurate);
       
   450 			List<StackEntry> stackEntries = stack.getStackEntries();
       
   451 			if (stackEntries != null && !stackEntries.isEmpty()) {
       
   452 				for (int i = 0; i < stackEntries.size(); i++) {
       
   453 					StackEntry stackEntry = stackEntries.get(i);
       
   454 					newStackTableItem(stackEntry, containsAccurate);
       
   455 				}
       
   456 				if (autoSizeCells)
       
   457 					AutoSizeCallStackTableCells();
       
   458 			}
       
   459 			
       
   460 			// nothing in stack
       
   461 			if (stackEntries == null || stackEntries.isEmpty()) {
       
   462 				disableStack();
       
   463 			}
       
   464 			
       
   465 		} catch (Exception e) {
       
   466 			e.printStackTrace();
       
   467 		}
       
   468 	}
       
   469 	
       
   470 	/**
       
   471 	 * Disables stack UI elements
       
   472 	 */
       
   473 	void disableStack() {
       
   474 		labelStackWarning.setVisible(true);
       
   475 		labelStackWarning.setText("Symbols were not available while creating stack.");
       
   476 		buttonDecodeFile.setVisible(true);
       
   477 		comboCallStack.setEnabled(false);
       
   478 		buttonAllStackEntries.setEnabled(false);
       
   479 		buttonSymbolStackEntries.setEnabled(false);
       
   480 		tableCallStack.setEnabled(false);
       
   481 	}
       
   482 	
       
   483 	public void widgetDefaultSelected(SelectionEvent arg0) {
   364 	public void widgetDefaultSelected(SelectionEvent arg0) {
   484 		// no implementation required
   365 		// no implementation required
   485 	}
   366 	}
   486 
   367 
   487 	public void widgetSelected(SelectionEvent event) {
       
   488 		// stack was changed in combo
       
   489 		if (event.widget == comboCallStack) {
       
   490 			loadCallStackTable(true);
       
   491 		// stack radio button changes
       
   492 		} else if (event.widget == buttonAllStackEntries || 
       
   493 					event.widget == buttonSymbolStackEntries) {
       
   494 			loadCallStackTable(false);
       
   495 		// decode button was pressed
       
   496 		} else if (event.widget == buttonDecodeFile) {
       
   497 			MainView mv = MainView.showAndReturnYourself(true);
       
   498 			mv.decodeFile(crashFile);
       
   499 		}
       
   500 	}
       
   501 	
   368 	
   502 	/**
   369 	/**
   503 	 * Adds new summary table row
   370 	 * Adds new summary table row
   504 	 * @param header header text
   371 	 * @param header header text
   505 	 * @param value value text
   372 	 * @param value value text
   520 		
   387 		
   521 		return false;
   388 		return false;
   522 	}
   389 	}
   523 	
   390 	
   524 	/**
   391 	/**
   525 	 * Adds new stack table row.
       
   526 	 * @param stackEntry row data
       
   527 	 * @param stackContainsAccurateEntries affects row colorings
       
   528 	 */
       
   529 	void newStackTableItem(StackEntry stackEntry, boolean stackContainsAccurateEntries) {
       
   530 		// if 'Show stack entries which have associated symbols' radio button is selected and
       
   531 		// if stack contains accurate stack entries, and this stack entry is not accurate
       
   532 		// don't add it to table (unless this stack entry is current stack pointer or register based)
       
   533 		if (buttonSymbolStackEntries.getSelection() &&
       
   534 			stackContainsAccurateEntries && 
       
   535 			!stackEntry.accurate() && 
       
   536 			!stackEntry.currentStackPointer() &&
       
   537 			!stackEntry.registerBased()) {
       
   538 			return;
       
   539 		// if 'Show stack entries which have associated symbols' radio button is selected
       
   540 		// if stack doesn't contain accurate stack entries, don't show current stack entry
       
   541 		// if it doesn't have associated symbol (unless this stack entry is current stack pointer or register based)
       
   542 		} else if (buttonSymbolStackEntries.getSelection() &&
       
   543 					!stackContainsAccurateEntries &&
       
   544 					"".equals(stackEntry.getSymbol()) &&
       
   545 					!stackEntry.currentStackPointer() &&
       
   546 					!stackEntry.registerBased())
       
   547 			return;
       
   548 
       
   549 		TableItem item = new TableItem(tableCallStack, SWT.NONE);
       
   550 		item.setText(new String[] {stackEntry.getAddress(),
       
   551 									stackEntry.getSymbol(),
       
   552 									stackEntry.getValue(),
       
   553 									stackEntry.getOffset(),
       
   554 									stackEntry.getObject(),
       
   555 									stackEntry.getText()});
       
   556 		
       
   557 		item.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
       
   558 		item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
       
   559 		
       
   560 		// item is current stack pointer FG black, BG light pink
       
   561 		if (stackEntry.currentStackPointer()) {
       
   562 			item.setBackground(new Color(Display.getCurrent(), 255, 182, 193)); // light pink
       
   563 		// PC or LR
       
   564 		} else if (stackEntry.registerBased()) {
       
   565 			item.setBackground(new Color(Display.getCurrent(), 173, 216, 230)); // light blue
       
   566 		// item is out of stack bound FG gray, BG white
       
   567 		} else if (stackEntry.outsideStackBounds()) {
       
   568 			item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
       
   569 		// item has no symbols, FG black, BG white
       
   570 		} else if ("".equals(stackEntry.getSymbol())) {
       
   571 		} else
       
   572 			// if stack contains accurate entries, show "ghost" entries as gray
       
   573 			if (stackContainsAccurateEntries) {
       
   574 				// color accurate stack entries black or blue
       
   575 				if (stackEntry.accurate()) {
       
   576 					// ram loaded code (instead of execute-in-place code) FG blue
       
   577 					if (!stackEntry.xip()) {
       
   578 						item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
       
   579 					}
       
   580 				// not accurate stack entry FG gray
       
   581 				} else {
       
   582 					item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
       
   583 				}
       
   584 			// stack isn't accurate,
       
   585 			} else {
       
   586 				// ram loaded code (instead of execute-in-place code)
       
   587 				if (!stackEntry.xip()) {
       
   588 					item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
       
   589 			}
       
   590 		}
       
   591 		
       
   592 		item.setData(stackEntry);
       
   593 	}
       
   594 	
       
   595 	/**
       
   596 	 * Sets context sensitive help ids to UI elements
   392 	 * Sets context sensitive help ids to UI elements
   597 	 */
   393 	 */
   598 	void setHelps() {
   394 	void setHelps() {
   599 		PlatformUI.getWorkbench().getHelpSystem().setHelp(tableCallStack,
       
   600 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
       
   601 		PlatformUI.getWorkbench().getHelpSystem().setHelp(tableSummary,
   395 		PlatformUI.getWorkbench().getHelpSystem().setHelp(tableSummary,
   602 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
       
   603 		PlatformUI.getWorkbench().getHelpSystem().setHelp(comboCallStack,
       
   604 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
       
   605 		PlatformUI.getWorkbench().getHelpSystem().setHelp(buttonAllStackEntries,
       
   606 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
       
   607 		PlatformUI.getWorkbench().getHelpSystem().setHelp(buttonDecodeFile,
       
   608 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
       
   609 		PlatformUI.getWorkbench().getHelpSystem().setHelp(buttonSymbolStackEntries,
       
   610 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
   396 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
   611 		PlatformUI.getWorkbench().getHelpSystem().setHelp(browserPanicDescription,
   397 		PlatformUI.getWorkbench().getHelpSystem().setHelp(browserPanicDescription,
   612 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
   398 				HelpContextIDs.CRASH_ANALYSER_HELP_CRASH_VISUALISER);	
   613 	}
   399 	}
   614 }
   400 }