/*******************************************************************************
 * Copyright (c) 2009, 2013 University of Utah School of Computing
 * 50 S Central Campus Dr. 3190 Salt Lake City, UT 84112
 * http://www.cs.utah.edu/formal_verification/
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Alan Humphrey - Initial API and implementation
 *    Christopher Derrick - Initial API and implementation
 *    Prof. Ganesh Gopalakrishnan - Project Advisor
 *******************************************************************************/

package org.eclipse.ptp.internal.gem.views;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ptp.internal.gem.GemPlugin;
import org.eclipse.ptp.internal.gem.messages.Messages;
import org.eclipse.ptp.internal.gem.preferences.PreferenceConstants;
import org.eclipse.ptp.internal.gem.util.Envelope;
import org.eclipse.ptp.internal.gem.util.GemUtilities;
import org.eclipse.ptp.internal.gem.util.InternalIssueOrderSorter;
import org.eclipse.ptp.internal.gem.util.ListElement;
import org.eclipse.ptp.internal.gem.util.ProgramOrderSorter;
import org.eclipse.ptp.internal.gem.util.Transitions;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
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.Button;
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.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;

/**
 * The GEM Analyzer View.
 */
public class GemAnalyzer extends ViewPart {

	// Listens for double-clicks and jumps to that line of code in the editor
	private class DoubleClickListener implements IDoubleClickListener {

		public void doubleClick(DoubleClickEvent event) {
			final ISelection selection = event.getSelection();
			final StructuredSelection structure = (StructuredSelection) selection;
			final ListElement element = (ListElement) structure.getFirstElement();
			if (element != null) {
				final IFile sourceFile = element.getFile();
				final int lineNumber = element.getLineNumber();
				openEditor(lineNumber, sourceFile);
			}
		}
	}

	// The ID for this view
	public static final String ID = "org.eclipse.ptp.gem.views.GemAnalyzer"; //$NON-NLS-1$

	// Data structures and more complex members
	private Transitions transitions;
	private LinkedList<Shell> activeShells;

	// Container objects and viewers
	private Composite parent;
	private ListViewer leftViewer;
	private ListViewer rightViewer;
	private Action getHelp;
	private Action terminateButton;

	// Simple members
	private int numRanks;
	private int lockedRank;
	private IFile currLeftFile;
	private IFile currRightFile;

	// SWT Buttons
	private Button firstTransitionButton;
	private Button previousTransitionButton;
	private Button nextTransitionButton;
	private Button lastTransitionButton;
	private Button firstInterleavingButton;
	private Button previousInterleavingButton;
	private Button nextInterleavingButton;
	private Button lastInterleavingButton;
	private Button deadlockInterleavingButton;
	private Button internalIssueOrderButton;
	private Button programOrderButton;
	private Button launchHpvButton;
	private Button browseCallsButton;
	private Button runGemButton;
	private Combo lockRanksComboList;
	private Combo setNumProcsComboList;

	// Groups that need to be accessed multiple times
	private Group interleavingsGroup;
	private Group transitionsGroup;
	private Group stepOrderGroup;

	// SWT Labels
	private Label errorMessageLabel;
	private Label leftCodeWindowLabel;
	private Label rightCodeWindowLabel;
	private CLabel leftCodeWindowExplenationLabel;
	private CLabel rightCodeWindowExplenationLabel;

	// Used for the transition label
	private int transitionLabelIndex;
	private int transitionLabelCount;

	// Things for highlighting the appropriate line in the code windows
	private int leftIndex;
	private int rightIndex;
	private int previousLeftIndex;

	// Listeners for the code viewers
	private SelectionListener singleListener;
	private DoubleClickListener doubleListener;

	// The active file resource needed for various operations
	private IFile activeFile;

	// Threads
	private Thread analyzerUpdateThread;
	private Thread clearAnalyzerThread;
	private Thread disableTerminateButtonThread;

	// Misc
	private int leftLines;
	private int rightLines;
	private boolean aborted;

	/**
	 * Constructor.
	 * 
	 * @param none
	 */
	public GemAnalyzer() {
		this.lockedRank = -1;
		this.aborted = false;
	}

	/**
	 * Brings this ViewPart to the front and gives it focus.
	 * 
	 * @param none
	 * @return none
	 */
	public void activate() {
		final Thread activationThread = new Thread() {
			@Override
			public void run() {
				final IWorkbench wb = PlatformUI.getWorkbench();
				final IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
				final IWorkbenchPage page = window.getActivePage();
				if (page != null) {
					page.activate(GemAnalyzer.this);
				}
			}
		};

		// We need to switch to the thread that is allowed to change the UI
		Display.getDefault().syncExec(activationThread);
	}

	/**
	 * Runs a thread that clears the Analyzer view.
	 * 
	 * @param none
	 * @return void
	 */
	public void clear() {
		Display.getDefault().syncExec(this.clearAnalyzerThread);
		this.aborted = false;
	}

	/*
	 * Calls finer grained methods, populating the view action bar.
	 */
	private void contributeToActionBars() {
		final IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	/*
	 * Helper method called by createPartControl.
	 */
	private void createCodeWindowsGroup(Composite parent) {
		// Get images for buttons from image cache
		final Image sourceCallImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/source-call.gif")); //$NON-NLS-1$
		final Image matchCallImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/match-call.gif")); //$NON-NLS-1$

		// Create the layout for the Analyzer windows and call info labels
		final Group codeWindowsGroup = new Group(parent, SWT.NONE | SWT.SHADOW_IN);
		codeWindowsGroup.setText(Messages.GemAnalyzer_0);
		final GridLayout codeWindowsLayout = new GridLayout();
		codeWindowsLayout.numColumns = 2;
		codeWindowsLayout.marginHeight = 10;
		codeWindowsLayout.marginWidth = 10;
		codeWindowsLayout.horizontalSpacing = 15;
		codeWindowsGroup.setLayout(codeWindowsLayout);
		codeWindowsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));

		// Create code window labels and their respective layouts, etc.
		final String newline = System.getProperty("line.separator"); //$NON-NLS-1$
		this.leftCodeWindowLabel = new Label(codeWindowsGroup, SWT.WRAP);
		this.leftCodeWindowLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		final Font leftCodeWindowLabelFont = setFontSize(this.leftCodeWindowLabel.getFont(), 9);
		this.leftCodeWindowLabel.setFont(leftCodeWindowLabelFont);
		this.leftCodeWindowLabel.setText(newline);
		this.rightCodeWindowLabel = new Label(codeWindowsGroup, SWT.WRAP);
		this.rightCodeWindowLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		final Font rightCodeWindowLabelFont = setFontSize(this.rightCodeWindowLabel.getFont(), 9);
		this.rightCodeWindowLabel.setFont(rightCodeWindowLabelFont);
		this.rightCodeWindowLabel.setText(newline);

		// The short explanations of each of the code windows
		this.leftCodeWindowExplenationLabel = new CLabel(codeWindowsGroup, SWT.WRAP | SWT.NULL);
		this.rightCodeWindowExplenationLabel = new CLabel(codeWindowsGroup, SWT.WRAP | SWT.NULL);
		this.leftCodeWindowExplenationLabel.setImage(sourceCallImage);
		this.rightCodeWindowExplenationLabel.setImage(matchCallImage);
		this.leftCodeWindowExplenationLabel.setText(Messages.GemAnalyzer_1);
		this.rightCodeWindowExplenationLabel.setText(Messages.GemAnalyzer_2);

		// Create the Analyzer list viewers
		this.leftViewer = new ListViewer(codeWindowsGroup, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		this.rightViewer = new ListViewer(codeWindowsGroup, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		final Font leftViewerFont = setFontSize(this.leftViewer.getControl().getFont(), 8);
		final Font rightViewerFont = setFontSize(this.rightViewer.getControl().getFont(), 8);
		this.leftViewer.getControl().setFont(leftViewerFont);
		this.rightViewer.getControl().setFont(rightViewerFont);
		this.leftViewer.getList().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		this.rightViewer.getList().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		/*
		 * Create two listeners for these viewers. SelectionListener is to
		 * prevent user from changing the selected line. DoubleListener maps
		 * selected line to the editor view
		 */
		this.singleListener = new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				final org.eclipse.swt.widgets.List list = (org.eclipse.swt.widgets.List) e.getSource();
				final String entry = list.getItem(0).toString();

				// Determine if collective call clicked in the Right Viewer
				if (!entry.contains(Messages.GemAnalyzer_3) || !entry.contains(Messages.GemAnalyzer_4)) {
					updateSelectedLine(false);
				}
			}
		};

		// SelectionListener prevents user from changing selected viewer line
		this.doubleListener = new DoubleClickListener();
		this.leftViewer.getList().addSelectionListener(this.singleListener);
		this.rightViewer.getList().addSelectionListener(this.singleListener);
		this.leftViewer.addDoubleClickListener(this.doubleListener);
		this.rightViewer.addDoubleClickListener(this.doubleListener);
	}

	/*
	 * Helper method called by createPartControl.
	 */
	private void createInterleavingsGroup(Composite parent) {
		// Get images for buttons from image cache
		final Image firstItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/first-item.gif")); //$NON-NLS-1$
		final Image lastItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/last-item.gif")); //$NON-NLS-1$
		final Image prevItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/prev-item.gif")); //$NON-NLS-1$
		final Image nextItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/next-item.gif")); //$NON-NLS-1$
		final Image deadlockImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/deadlock.gif")); //$NON-NLS-1$

		// Group and FormLayout data for interleaving buttons and labels
		this.interleavingsGroup = new Group(parent, SWT.SHADOW_IN);
		this.interleavingsGroup.setText(Messages.GemAnalyzer_5);
		this.interleavingsGroup.setToolTipText(Messages.GemAnalyzer_6);
		final FormData interleavingsFormData = new FormData();
		interleavingsFormData.bottom = new FormAttachment(100, -5);
		interleavingsFormData.left = new FormAttachment(44, 0);
		this.interleavingsGroup.setLayoutData(interleavingsFormData);
		this.interleavingsGroup.setLayout(new FormLayout());

		// First interleaving button
		this.firstInterleavingButton = new Button(this.interleavingsGroup, SWT.PUSH);
		this.firstInterleavingButton.setImage(firstItemImage);
		this.firstInterleavingButton.setToolTipText(Messages.GemAnalyzer_7);
		this.firstInterleavingButton.setEnabled(false);
		final FormData ifirstFormData = new FormData();
		ifirstFormData.left = new FormAttachment(0, 5);
		ifirstFormData.bottom = new FormAttachment(100, -5);
		this.firstInterleavingButton.setLayoutData(ifirstFormData);

		// Previous interleaving button
		this.previousInterleavingButton = new Button(this.interleavingsGroup, SWT.PUSH);
		this.previousInterleavingButton.setImage(prevItemImage);
		this.previousInterleavingButton.setToolTipText(Messages.GemAnalyzer_8);
		this.previousInterleavingButton.setEnabled(false);
		final FormData iprevFormData = new FormData();
		iprevFormData.left = new FormAttachment(this.firstInterleavingButton, 3);
		iprevFormData.bottom = new FormAttachment(100, -5);
		this.previousInterleavingButton.setLayoutData(iprevFormData);

		// Next interleaving button
		this.nextInterleavingButton = new Button(this.interleavingsGroup, SWT.PUSH);
		this.nextInterleavingButton.setImage(nextItemImage);
		this.nextInterleavingButton.setToolTipText(Messages.GemAnalyzer_9);
		this.nextInterleavingButton.setEnabled(false);
		final FormData inextFormData = new FormData();
		inextFormData.left = new FormAttachment(this.previousInterleavingButton, 3);
		inextFormData.bottom = new FormAttachment(100, -5);
		this.nextInterleavingButton.setLayoutData(inextFormData);

		// Last interleaving button
		this.lastInterleavingButton = new Button(this.interleavingsGroup, SWT.PUSH);
		this.lastInterleavingButton.setImage(lastItemImage);
		this.lastInterleavingButton.setToolTipText(Messages.GemAnalyzer_10);
		this.lastInterleavingButton.setEnabled(false);
		final FormData ilastFormData = new FormData();
		ilastFormData.left = new FormAttachment(this.nextInterleavingButton, 3);
		ilastFormData.bottom = new FormAttachment(100, -5);
		this.lastInterleavingButton.setLayoutData(ilastFormData);

		// Deadlock interleaving button
		this.deadlockInterleavingButton = new Button(this.interleavingsGroup, SWT.PUSH);
		this.deadlockInterleavingButton.setImage(deadlockImage);
		this.deadlockInterleavingButton.setToolTipText(Messages.GemAnalyzer_11);
		this.deadlockInterleavingButton.setEnabled(false);
		final FormData deadlockButtonFormData = new FormData();
		deadlockButtonFormData.left = new FormAttachment(this.lastInterleavingButton, 3);
		deadlockButtonFormData.bottom = new FormAttachment(100, -5);
		deadlockButtonFormData.right = new FormAttachment(100, -5);
		this.deadlockInterleavingButton.setLayoutData(deadlockButtonFormData);
	}

	/**
	 * Callback that allows us to create the viewer and initialize it.
	 * 
	 * @param parent
	 *            The parent Composite for this View.
	 * @return void
	 */
	@Override
	public void createPartControl(Composite parent) {
		this.parent = parent;

		// Create layout for the parent Composite
		final GridLayout parentLayout = new GridLayout();
		parentLayout.numColumns = 1;
		parentLayout.marginHeight = 10;
		parentLayout.marginWidth = 10;
		parent.setLayout(parentLayout);

		// Create container for transition and interleaving button groups
		final Composite runtimeComposite = new Composite(parent, SWT.NULL);
		runtimeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		runtimeComposite.setLayout(new FormLayout());
		final Composite buttonGroupsComposite = new Composite(parent, SWT.NULL);
		buttonGroupsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		buttonGroupsComposite.setLayout(new FormLayout());

		// Create groups and selection listeners
		createRuntimeGroup(runtimeComposite);
		createTransitionsGroup(buttonGroupsComposite);
		createInterleavingsGroup(buttonGroupsComposite);
		createStepOrderGroup(buttonGroupsComposite);
		createCodeWindowsGroup(parent);
		createSelectionListeners();

		// create actions & connect to buttons, context menus and pull-downs
		makeActions();
		hookContextMenu();
		contributeToActionBars();
	}

	/*
	 * Helper method called by createPartControl.
	 */
	private void createRuntimeGroup(Composite parent) {
		// Get images for buttons from image cache
		final Image noErrorImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/no-error.gif")); //$NON-NLS-1$
		final Image hbvImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/hbv-trident.gif")); //$NON-NLS-1$
		final Image trident = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/trident.gif")); //$NON-NLS-1$

		// Runtime information group
		final Group runtimeInfoGroup = new Group(parent, SWT.SHADOW_IN);
		runtimeInfoGroup.setText(Messages.GemAnalyzer_12);
		final FormData grid = new FormData();
		grid.left = new FormAttachment(0, 0);
		grid.right = new FormAttachment(100, -5);
		grid.bottom = new FormAttachment(100, -5);
		runtimeInfoGroup.setLayoutData(grid);
		runtimeInfoGroup.setLayout(new FormLayout());

		// Error message label
		this.errorMessageLabel = new Label(runtimeInfoGroup, SWT.NONE);
		final FormData deadlockMessageFormData = new FormData();
		deadlockMessageFormData.left = new FormAttachment(0, 5);
		deadlockMessageFormData.top = new FormAttachment(0, 5);
		deadlockMessageFormData.width = 300;
		this.errorMessageLabel.setLayoutData(deadlockMessageFormData);
		final Font errorMessageLabelFont = setFontSize(this.errorMessageLabel.getFont(), 10);
		this.errorMessageLabel.setFont(errorMessageLabelFont);

		// Browse calls button
		this.browseCallsButton = new Button(runtimeInfoGroup, SWT.PUSH);
		this.browseCallsButton.setImage(noErrorImage);
		this.browseCallsButton.setText(Messages.GemAnalyzer_79);
		this.browseCallsButton.setToolTipText(Messages.GemAnalyzer_14);
		this.browseCallsButton.setEnabled(false);
		final FormData browseCallsFormData = new FormData();
		browseCallsFormData.right = new FormAttachment(100, -5);
		browseCallsFormData.bottom = new FormAttachment(100, -5);
		this.browseCallsButton.setLayoutData(browseCallsFormData);

		// Launch ispUI button
		this.launchHpvButton = new Button(runtimeInfoGroup, SWT.PUSH);
		this.launchHpvButton.setImage(hbvImage);
		this.launchHpvButton.setText(Messages.GemAnalyzer_15);
		this.launchHpvButton.setToolTipText(Messages.GemAnalyzer_16);
		this.launchHpvButton.setEnabled(false);
		final FormData launchIspUIFormData = new FormData();
		launchIspUIFormData.right = new FormAttachment(this.browseCallsButton, -5);
		launchIspUIFormData.bottom = new FormAttachment(100, -5);
		this.launchHpvButton.setLayoutData(launchIspUIFormData);

		// Run GEM button
		this.runGemButton = new Button(runtimeInfoGroup, SWT.PUSH);
		this.runGemButton.setImage(trident);
		this.runGemButton.setToolTipText(Messages.GemAnalyzer_17);
		final FormData runGemFormData = new FormData();
		runGemFormData.right = new FormAttachment(this.launchHpvButton, -20);
		runGemFormData.bottom = new FormAttachment(100, -5);
		this.runGemButton.setLayoutData(runGemFormData);
		this.runGemButton.setEnabled(true);

		// Set number of processes button
		this.setNumProcsComboList = new Combo(runtimeInfoGroup, SWT.DROP_DOWN);
		final Font setRankComboFont = setFontSize(this.setNumProcsComboList.getFont(), 9);
		this.setNumProcsComboList.setFont(setRankComboFont);
		final String[] items = new String[] {};
		this.setNumProcsComboList.setItems(items);
		this.setNumProcsComboList.setText(" "); //$NON-NLS-1$
		this.setNumProcsComboList.setToolTipText(Messages.GemAnalyzer_18);
		final FormData setRankFormData = new FormData();
		setRankFormData.width = 50;
		setRankFormData.right = new FormAttachment(this.runGemButton, -5);
		setRankFormData.bottom = new FormAttachment(100, -5);
		this.setNumProcsComboList.setLayoutData(setRankFormData);
		this.setNumProcsComboList.setEnabled(true);
		setNumProcItems();
		updateDropDown();

		// Font for the buttons
		final Font buttonFont = setFontSize(this.errorMessageLabel.getFont(), 8);
		this.launchHpvButton.setFont(buttonFont);
		this.browseCallsButton.setFont(buttonFont);
		this.setNumProcsComboList.setFont(buttonFont);
	}

	/*
	 * Helper method called by createPartControl.
	 */
	private void createSelectionListeners() {
		// SelectionListeners for transitions group buttons
		this.firstTransitionButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				updateFirstTransition(true);
			}
		});

		this.previousTransitionButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						updatePreviousTransition();
					}
				});

		this.nextTransitionButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				updateNextTransition(true);
			}
		});

		this.lastTransitionButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				updateLastTransition();
			}
		});

		this.lockRanksComboList.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				if (GemAnalyzer.this.lockRanksComboList.getText() == null) {
					return;
				}

				try {
					final int selectionIndex = GemAnalyzer.this.lockRanksComboList.getSelectionIndex();
					final String selectionText = GemAnalyzer.this.lockRanksComboList.getItems()[selectionIndex];
					final Pattern rankPattern = Pattern.compile("^([a-zA-Z]+?)\\s+([0-9]+?)\\s+([a-zA-Z]+?)$"); //$NON-NLS-1$
					final Matcher rankPatternMatcher = rankPattern.matcher(selectionText);
					if (rankPatternMatcher.matches()) {
						final String rankStr = rankPatternMatcher.group(2);
						GemAnalyzer.this.lockedRank = Integer.parseInt(rankStr);
					} else {
						GemAnalyzer.this.lockedRank = -1;
					}
					updateTransitionLabels(true);
				} catch (final Exception e) {
					GemUtilities.logExceptionDetail(e);
					GemAnalyzer.this.lockedRank = -1;
				}
			}
		});

		// SelectionListeners for interleavings group buttons
		this.firstInterleavingButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						if (GemAnalyzer.this.transitions.hasPreviousInterleaving()) {
							while (GemAnalyzer.this.transitions.setPreviousInterleaving()) {
								// do nothing
							}
							updateTransitionLabels(true);
						} else {
							GemUtilities.showInformationDialog(Messages.GemAnalyzer_19);
						}
					}
				});

		this.previousInterleavingButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						if (GemAnalyzer.this.transitions.hasPreviousInterleaving()) {
							GemAnalyzer.this.transitions.setPreviousInterleaving();
							updateTransitionLabels(true);
						} else {
							GemUtilities.showInformationDialog(Messages.GemAnalyzer_20);
						}
					}
				});

		this.nextInterleavingButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						if (GemAnalyzer.this.transitions.hasNextInterleaving()) {
							GemAnalyzer.this.transitions.setNextInterleaving();
							updateTransitionLabels(true);
						} else {
							GemUtilities.showInformationDialog(Messages.GemAnalyzer_21);
						}
					}
				});

		this.lastInterleavingButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						while (GemAnalyzer.this.transitions.hasNextInterleaving()) {
							GemAnalyzer.this.transitions.setNextInterleaving();
						}
						updateTransitionLabels(true);
					}
				});

		this.deadlockInterleavingButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						GemAnalyzer.this.transitions.deadlockInterleaving();
						updateTransitionLabels(true);
					}
				});

		// Selection listeners for step order group
		this.internalIssueOrderButton
				.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						if (GemAnalyzer.this.internalIssueOrderButton.getSelection()) {
							if (GemAnalyzer.this.transitions != null) {
								final ArrayList<ArrayList<Envelope>> tlists = GemAnalyzer.this.transitions.getTransitionList();
								// Sort by internal issue order
								final int size = tlists.size();
								for (int i = 0; i < size; i++) {
									Collections.sort(tlists.get(i), new InternalIssueOrderSorter());
								}
							}

							// Reset preference store value for this preference
							GemPlugin.getDefault().getPreferenceStore()
									.setValue(PreferenceConstants.GEM_PREF_STEP_ORDER, "issueOrder"); //$NON-NLS-1$
							reset();
						}
					}
				});

		this.programOrderButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (GemAnalyzer.this.programOrderButton.getSelection()) {
					// Sort by internal issue order
					if (GemAnalyzer.this.transitions != null) {
						final ArrayList<ArrayList<Envelope>> tlists = GemAnalyzer.this.transitions.getTransitionList();
						final int size = tlists.size();
						for (int i = 0; i < size; i++) {
							Collections.sort(tlists.get(i), new ProgramOrderSorter());
						}
					}

					// Reset preference store value for this preference
					GemPlugin.getDefault().getPreferenceStore()
							.setValue(PreferenceConstants.GEM_PREF_STEP_ORDER, "programOrder"); //$NON-NLS-1$
					reset();
				}
			}
		});

		// To conveniently run GEM from this view
		this.runGemButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				final IPreferenceStore pstore = GemPlugin.getDefault().getPreferenceStore();
				URI inputLocation = null;
				IPath path = null;

				try {
					inputLocation = new URI(pstore.getString(PreferenceConstants.GEM_PREF_MOST_RECENT_FILE));
				} catch (final URISyntaxException e) {
					GemUtilities.logExceptionDetail(e);
				}
				if (inputLocation != null) {
					path = new Path(inputLocation.getPath());
				}
				if (GemAnalyzer.this.activeFile == null) {
					GemUtilities.setTaskStatus(GemUtilities.TaskStatus.ABORTED);
					return;
				}
				final IFile file = GemUtilities.getCurrentProject(GemAnalyzer.this.activeFile).getFile(path.lastSegment());
				path = file.getFullPath();
				final String extension = file.getFileExtension();
				boolean isSourceFile = false;

				if (extension != null) {
					// The most common C & C++ source file extensions
					isSourceFile = extension.equals("c") //$NON-NLS-1$
							|| extension.equals("cpp") || extension.equals("c++") //$NON-NLS-1$ //$NON-NLS-2$
							|| extension.equals("cc") || extension.equals("cp"); //$NON-NLS-1$ //$NON-NLS-2$
				}

				// ask for command line arguments
				GemUtilities.setCommandLineArgs();

				// Open Analyzer and Browser Views in preference order
				// Find the active editor
				final IWorkbench wb = PlatformUI.getWorkbench();
				final IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
				final IWorkbenchPage page = window.getActivePage();

				try {
					final String activeView = pstore.getString(PreferenceConstants.GEM_ACTIVE_VIEW);
					if (activeView.equals("analyzer")) { //$NON-NLS-1$
						page.showView(GemBrowser.ID);
						page.showView(GemAnalyzer.ID);
					} else {
						page.showView(GemAnalyzer.ID);
						page.showView(GemBrowser.ID);
					}
					GemUtilities.initGemViews(file, isSourceFile, true);
				} catch (final PartInitException e) {
					GemUtilities.logExceptionDetail(e);
				}
			}
		});

		// Selection listeners for runtime information group buttons
		this.setNumProcsComboList.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				if (GemAnalyzer.this.setNumProcsComboList.getText() == null) {
					return;
				}

				final int selectionIndex = GemAnalyzer.this.setNumProcsComboList.getSelectionIndex();
				final String nprocsStr = GemAnalyzer.this.setNumProcsComboList.getItems()[selectionIndex];
				final int newNumProcs = Integer.parseInt(nprocsStr);

				// Reset the numProcs value in the preference store
				GemPlugin.getDefault().getPreferenceStore().setValue(PreferenceConstants.GEM_PREF_NUMPROCS, newNumProcs);

				// If the browser is open updates its drop down
				try {
					final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
					final IViewPart browserPart = window.getActivePage().findView(GemBrowser.ID);
					final GemBrowser browser = (GemBrowser) browserPart;
					browser.updateDropDown();
				} catch (final Exception e) {
					GemUtilities.logExceptionDetail(e);
				}
			}
		});

		this.launchHpvButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				final URI uri = GemUtilities.getMostRecentURI();
				IPath sourceFilePath = null;
				IFile sourceFile = null;

				if (uri != null) {
					sourceFilePath = new Path(uri.getPath());
				}

				final IProject currentProject = GemUtilities.getProjectLogFile().getProject();
				final String currentProjectPath = currentProject.getLocationURI().getPath();
				if (sourceFilePath != null) {
					sourceFilePath = sourceFilePath.makeRelativeTo(new Path(currentProjectPath));
					sourceFile = currentProject.getFile(sourceFilePath);
				}

				if (sourceFile != null) {
					if (GemUtilities.isRemoteProject(GemAnalyzer.this.activeFile)
							|| GemUtilities.isSynchronizedProject(GemAnalyzer.this.activeFile)) {
						GemUtilities.showInformationDialog(Messages.GemAnalyzer_23);
						return;
					}

					// Otherwise launch the HB viewer
					GemUtilities.doHbv(sourceFile);
				} else {
					// There was a local error while creating the log file.
					final String message = Messages.GemAnalyzer_13;
					// GemUtilities.showErrorDialog(message);
				}
			}
		});

		this.browseCallsButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (GemAnalyzer.this.transitions == null) {
					final String message = Messages.GemAnalyzer_24;
					GemUtilities.showErrorDialog(message);
					return;
				}
				final class CallBrowserDisplay implements Runnable {
					public void run() {
						final IWorkbench wb = PlatformUI.getWorkbench();
						final Display display = wb.getDisplay();
						final Shell shell = new Shell();
						shell.setText(Messages.GemAnalyzer_68);
						shell.setImage(GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/magnified-trident.gif"))); //$NON-NLS-1$
						shell.setLayout(new GridLayout());
						final CLabel fileNameLabel = new CLabel(shell, SWT.BORDER_SOLID);
						fileNameLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
						final CLabel numProcsLabel = new CLabel(shell, SWT.BORDER_SOLID);
						numProcsLabel.setImage(GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/processes.gif"))); //$NON-NLS-1$
						numProcsLabel.setText(Messages.GemAnalyzer_69 + GemAnalyzer.this.numRanks);
						numProcsLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

						final Tree tree = new Tree(shell, SWT.BORDER);
						tree.setLinesVisible(true);
						tree.setLayoutData(new GridData(GridData.FILL_BOTH));
						tree.setFont(setFontSize(tree.getFont(), 8));

						// Declare everything we'll be working with
						TreeItem interleavingItem = null;
						TreeItem callItem = null;
						final int currentInter = GemAnalyzer.this.transitions.getCurrentInterleaving();

						// Loop over all interleavings
						final int numInterleavings = GemAnalyzer.this.transitions.getTotalInterleavings() + 1; // 0-based
						for (int currentInterleaving = 1; currentInterleaving < numInterleavings; currentInterleaving++) {

							// Create a root node for each interleaving
							interleavingItem = new TreeItem(tree, SWT.NULL);
							interleavingItem.setText(Messages.GemAnalyzer_70 + currentInterleaving);

							// Loop over all envelopes (transitions) in the current interleaving
							final ArrayList<Envelope> envelopes = GemAnalyzer.this.transitions
									.getInterleavingEnvelopes(currentInterleaving);
							final int listSize = envelopes.size();
							Envelope env = null;
							String functionName = null;
							String fileName = null;
							int lineNumber = -1;
							int envRank = -1;

							try {
								for (int envIndex = 0; envIndex < listSize; envIndex++) {
									env = envelopes.get(envIndex);

									// Don't display resource leaks
									if (env.isLeak()) {
										continue;
									}

									// Create the leaf node representing the call
									callItem = new TreeItem(interleavingItem, SWT.NULL);
									functionName = env.getFunctionName();
									fileName = new Path(env.getFilePath()).lastSegment().toString();
									lineNumber = env.getLinenumber();
									envRank = env.getRank();

									// make all calls have same name length
									while (functionName.length() < 12) {
										functionName += " "; //$NON-NLS-1$
									}

									final StringBuffer stringBuffer = new StringBuffer();
									stringBuffer.append("Rank: "); //$NON-NLS-1$
									stringBuffer.append(envRank);
									stringBuffer.append("\t\t"); //$NON-NLS-1$
									stringBuffer.append(functionName);
									stringBuffer.append("\t\t"); //$NON-NLS-1$
									stringBuffer.append(fileName);
									stringBuffer.append(":"); //$NON-NLS-1$
									stringBuffer.append(lineNumber);
									final String callItemText = stringBuffer.toString();
									callItem.setText(callItemText);

									// Mark the calls with errors red
									if (env.getIssueIndex() == -1) {
										callItem.setForeground(new Color(null, 255, 0, 0));
									}

									// Mark the current call(s) blue
									String currentFile = null;
									int currentLine = -1;
									if (GemAnalyzer.this.transitions.getCurrentTransition() != null) {
										currentFile = GemAnalyzer.this.transitions.getCurrentTransition().getFilePath();
										currentLine = GemAnalyzer.this.transitions.getCurrentTransition().getLinenumber();
									}
									if (currentFile != null) {
										if (currentLine == env.getLinenumber() && currentFile.equals(env.getFilePath())
												&& currentInter == env.getInterleaving()) {
											callItem.setForeground(new Color(null, 0, 0, 255));
											// Comment this out if you don't want items expanded
											revealTreeItem(callItem);
										}
									}
								}
							} catch (final Exception e) {
								GemUtilities.logExceptionDetail(e);
							}
						}

						// Open up the Call Browser window with the specified size
						shell.setSize(550, 550);
						shell.open();

						if (GemAnalyzer.this.activeShells == null) {
							GemAnalyzer.this.activeShells = new LinkedList<Shell>();
						}
						GemAnalyzer.this.activeShells.add(shell);

						// Set up the event loop for disposal
						while (!shell.isDisposed()) {
							if (!display.readAndDispatch()) {
								display.sleep();
							}
						}
					}
				}
				final CallBrowserDisplay browser = new CallBrowserDisplay();
				Display.getDefault().syncExec(browser);
			}
		});
	}

	/*
	 * Helper method called by createPartControl.
	 */
	private void createStepOrderGroup(Composite parent) {
		// Group and FormLayout data for step order radio buttons
		this.stepOrderGroup = new Group(parent, SWT.SHADOW_IN);
		this.stepOrderGroup.setText(Messages.GemAnalyzer_25);
		this.stepOrderGroup.setToolTipText(Messages.GemAnalyzer_26);
		final FormData stepOrderFormData = new FormData();
		// stepOrderFormData.left = new FormAttachment(this.interleavingsGroup,
		// 20);
		stepOrderFormData.right = new FormAttachment(100, -5);
		stepOrderFormData.bottom = new FormAttachment(100, -5);
		this.stepOrderGroup.setLayoutData(stepOrderFormData);
		this.stepOrderGroup.setLayout(new GridLayout(3, false));

		// Step order radio buttons
		this.internalIssueOrderButton = new Button(this.stepOrderGroup, SWT.RADIO);
		this.internalIssueOrderButton.setText(Messages.GemAnalyzer_27);
		this.internalIssueOrderButton.setToolTipText(Messages.GemAnalyzer_28);
		this.programOrderButton = new Button(this.stepOrderGroup, SWT.RADIO);
		this.programOrderButton.setText(Messages.GemAnalyzer_29);
		this.programOrderButton.setToolTipText(Messages.GemAnalyzer_30);

		// Choose which one is to be enabled from the Preference Store setting
		final String stepOrder = GemPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.GEM_PREF_STEP_ORDER);
		if (stepOrder.equals("issueOrder")) { //$NON-NLS-1$
			this.internalIssueOrderButton.setSelection(true);
		} else {
			this.programOrderButton.setSelection(true);
		}

		// Font for the radio buttons
		final Font buttonFont = setFontSize(this.programOrderButton.getFont(), 8);
		this.internalIssueOrderButton.setFont(buttonFont);
		this.programOrderButton.setFont(buttonFont);
	}

	/*
	 * Helper method called by createPartControl.
	 */
	private void createTransitionsGroup(Composite parent) {
		// Get images for buttons from image cache
		final Image firstItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/first-item.gif")); //$NON-NLS-1$
		final Image lastItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/last-item.gif")); //$NON-NLS-1$
		final Image prevItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/prev-item.gif")); //$NON-NLS-1$
		final Image nextItemImage = GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/next-item.gif")); //$NON-NLS-1$

		// Group and FormLayout data for transition buttons and labels
		this.transitionsGroup = new Group(parent, SWT.SHADOW_IN);
		this.transitionsGroup.setText(Messages.GemAnalyzer_32);
		this.transitionsGroup.setToolTipText(Messages.GemAnalyzer_33);
		final FormData transitionsFormData = new FormData();
		transitionsFormData.left = new FormAttachment(0, 0);
		transitionsFormData.bottom = new FormAttachment(100, -5);
		this.transitionsGroup.setLayoutData(transitionsFormData);
		this.transitionsGroup.setLayout(new FormLayout());

		// First transition button
		this.firstTransitionButton = new Button(this.transitionsGroup, SWT.PUSH);
		this.firstTransitionButton.setImage(firstItemImage);
		this.firstTransitionButton.setToolTipText(Messages.GemAnalyzer_34);
		this.firstTransitionButton.setEnabled(false);
		final FormData tfirstFormData = new FormData();
		tfirstFormData.left = new FormAttachment(0, 5);
		tfirstFormData.bottom = new FormAttachment(100, -5);
		this.firstTransitionButton.setLayoutData(tfirstFormData);

		// Previous transition button
		this.previousTransitionButton = new Button(this.transitionsGroup, SWT.PUSH);
		this.previousTransitionButton.setImage(prevItemImage);
		this.previousTransitionButton.setToolTipText(Messages.GemAnalyzer_35);
		this.previousTransitionButton.setEnabled(false);
		final FormData tprevFormData = new FormData();
		tprevFormData.left = new FormAttachment(this.firstTransitionButton, 3);
		tprevFormData.bottom = new FormAttachment(100, -5);
		this.previousTransitionButton.setLayoutData(tprevFormData);

		// Next transition buttons
		this.nextTransitionButton = new Button(this.transitionsGroup, SWT.PUSH);
		this.nextTransitionButton.setImage(nextItemImage);
		this.nextTransitionButton.setToolTipText(Messages.GemAnalyzer_36);
		this.nextTransitionButton.setEnabled(false);
		final FormData tnextFormData = new FormData();
		tnextFormData.left = new FormAttachment(this.previousTransitionButton, 3);
		tnextFormData.bottom = new FormAttachment(100, -5);
		this.nextTransitionButton.setLayoutData(tnextFormData);

		// Last transition button
		this.lastTransitionButton = new Button(this.transitionsGroup, SWT.PUSH);
		this.lastTransitionButton.setImage(lastItemImage);
		this.lastTransitionButton.setToolTipText(Messages.GemAnalyzer_37);
		this.lastTransitionButton.setEnabled(false);
		final FormData tlastFormData = new FormData();
		tlastFormData.left = new FormAttachment(this.nextTransitionButton, 3);
		tlastFormData.bottom = new FormAttachment(100, -5);
		this.lastTransitionButton.setLayoutData(tlastFormData);

		// Lock ranks button
		this.lockRanksComboList = new Combo(this.transitionsGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
		final Font lockRanksComboFont = setFontSize(this.lockRanksComboList.getFont(), 8);
		this.lockRanksComboList.setFont(lockRanksComboFont);
		final String[] items = new String[] { Messages.GemAnalyzer_83 };
		this.lockRanksComboList.setItems(items);
		this.lockRanksComboList.setToolTipText(Messages.GemAnalyzer_39);
		final FormData lockRanksFormData = new FormData();
		lockRanksFormData.left = new FormAttachment(this.lastTransitionButton, 10);
		lockRanksFormData.right = new FormAttachment(100, -5);
		lockRanksFormData.bottom = new FormAttachment(100, -5);
		this.lockRanksComboList.setLayoutData(lockRanksFormData);
	}

	/*
	 * Uses the right code window to display all calls associated with the
	 * collective operation displayed in the left code view window.
	 */
	private void displayCollectiveInfo() {
		final Envelope env = this.transitions.getCurrentTransition();
		final ArrayList<Envelope> matches = env.getCommunicator_matches();

		if (matches != null) {
			final int listSize = matches.size();
			for (int i = 0; i < listSize; i++) {
				final Envelope currentMatchEnvelope = matches.get(i);
				final String matchFilePathString = currentMatchEnvelope.getFilePath();
				final IFile sourceFile = GemUtilities.getSourceFile(matchFilePathString, this.activeFile);

				// Add the match to the right code view window
				this.rightViewer.add(new ListElement(sourceFile, sourceFile.getName() + Messages.GemAnalyzer_40
						+ currentMatchEnvelope.getLinenumber()
						+ Messages.GemAnalyzer_41
						+ currentMatchEnvelope.getRank(), currentMatchEnvelope.getLinenumber(), false));
			}
		}
	}

	/*
	 * Displays the specified envelope and it's matches if they exist.
	 */
	private void displayEnvelopes(Envelope env) {
		// If the envelope is null, it's a new interleaving, start over
		if (env == null) {
			return;
		}

		// Set the indexes for the highlighted line updater
		this.leftIndex = env.getLinenumber();
		boolean hasMatch = true;
		try {
			final Envelope match = env.getMatch_envelope();
			if (match != null) {
				this.rightIndex = match.getLinenumber();
			} else {
				hasMatch = false;
			}
		} catch (final Exception e) {
			GemUtilities.logExceptionDetail(e);
		}

		// Set font color for code window labels
		Color textColor = new Color(this.parent.getShell().getDisplay(), new RGB(0, 0, 255));
		this.leftCodeWindowLabel.setForeground(textColor);
		this.rightCodeWindowLabel.setForeground(textColor);

		// Build up the Strings for the Label text
		final String leftResult = getCallText(env, true);
		this.leftCodeWindowLabel.setText(leftResult);

		// If a match exists update the right side
		if (hasMatch) {
			final Envelope match = env.getMatch_envelope();
			final String rightResult = getCallText(match, false);
			this.rightCodeWindowLabel.setText(rightResult);
		} else {
			this.rightIndex = -1;
			this.rightViewer.getList().deselectAll();
			this.rightCodeWindowLabel.setText(""); //$NON-NLS-1$
		}

		if (env.getIssueIndex() == -1) {
			textColor = new Color(this.parent.getShell().getDisplay(), new RGB(255, 0, 0));
			this.rightCodeWindowLabel.setForeground(textColor);
			if (env.getFunctionName().equals("MPI_Abort")) { //$NON-NLS-1$
				this.rightCodeWindowLabel.setText(""); //$NON-NLS-1$
			} else if (this.transitions.hasDeadlock()) {
				this.rightCodeWindowLabel.setText(Messages.GemAnalyzer_46);
			} else {
				this.rightCodeWindowLabel.setText(Messages.GemAnalyzer_47);
			}
		}
	}

	/**
	 * Disposes of all shell windows when the instance of Eclipse that created
	 * them exits.
	 * 
	 * @param none
	 * @return void
	 */
	@Override
	public void dispose() {
		if (this.activeShells != null) {
			for (final Shell s : this.activeShells) {
				if (s != null) {
					s.dispose();
				}
			}
		}
		super.dispose();
	}

	/*
	 * Populates the view context menu.
	 */
	private void fillContextMenu(IMenuManager manager) {
		manager.add(this.terminateButton);
		this.terminateButton.setText(Messages.GemAnalyzer_48);
		manager.add(this.getHelp);
		this.getHelp.setText(Messages.GemAnalyzer_49);

		// Other plug-ins can contribute their actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	/*
	 * Populates the view pull-down menu.
	 */
	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(this.terminateButton);
		this.terminateButton.setText(Messages.GemAnalyzer_50);
		manager.add(new Separator());
		manager.add(this.getHelp);
		this.getHelp.setText(Messages.GemAnalyzer_51);
		manager.add(new Separator());

		// Other plug-ins can contribute their actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	/*
	 * Contributes icons and actions to the tool bar.
	 */
	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(this.terminateButton);
		manager.add(this.getHelp);

		// Other plug-ins can contribute their actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	/*
	 * Returns a String representing all information relative to a particular
	 * successful MPI call.
	 */
	private String getCallText(Envelope env, boolean isLeft) {
		final String newline = System.getProperty("line.separator"); //$NON-NLS-1$
		final String sourceFilePathString = env.getFilePath();
		final IFile sourceFile = GemUtilities.getSourceFile(sourceFilePathString, this.activeFile);
		final String fileName = sourceFile.getName();
		final StringBuffer stringBuffer = new StringBuffer();

		// determine which ranks are involved; by default only call's rank
		String ranks = Messages.GemAnalyzer_53 + env.getRank()
				+ (System.getProperty("os.name").contains("Windows") ? "\t" : newline); //$NON-NLS-1$  //$NON-NLS-2$  //$NON-NLS-3$
		if (env.isCollective() && this.lockedRank == -1) {

			// If it was a group call then discover who else is here
			final int numRanksInvolved[] = new int[1];
			if (this.lockedRank == -1) {
				// Also see if we're looking at a single rank or not
				ranks = this.transitions.getRanksInvolved(numRanksInvolved);
			}

			// This is currently the max #processes GEM drop-down boxes allow
			final int MAX = 16;
			if (numRanksInvolved[0] > MAX) {
				// display only first ten ranks
				String tempRanks = ranks;
				int total = 0;
				for (int i = 0; i < MAX; i++) {
					// May be multi-digit numbers, hence this code
					total += tempRanks.indexOf(",") + 1; //$NON-NLS-1$
					tempRanks = tempRanks.substring(tempRanks.indexOf(",") + 1); //$NON-NLS-1$
				}
				stringBuffer.append(Messages.GemAnalyzer_22);
				stringBuffer.append(ranks.substring(0, total - 1));
				stringBuffer.append("..."); //$NON-NLS-1$
				stringBuffer.append(newline);
			} else {
				stringBuffer.append(Messages.GemAnalyzer_55);
				stringBuffer.append(ranks);
				stringBuffer.append(newline);
			}

			// count number of ":" to determine how many ranks involved
			int ranksCommunicatedTo = 0;
			String communicator = env.getCommunicator_ranks_string();
			while (communicator != null && communicator.contains(":")) { //$NON-NLS-1$
				communicator = communicator.substring(communicator.indexOf(":") + 1); //$NON-NLS-1$
				ranksCommunicatedTo++;
			}

			if (ranksCommunicatedTo != 0 && numRanksInvolved[0] / ranksCommunicatedTo > 1) {
				stringBuffer.append(Messages.GemAnalyzer_56);
				stringBuffer.append(numRanksInvolved[0] / ranksCommunicatedTo);
				stringBuffer.append(Messages.GemAnalyzer_57);
				stringBuffer.append(ranksCommunicatedTo);
				stringBuffer.append(Messages.GemAnalyzer_58);
			}
		}
		if (!env.isCollective()) {
			stringBuffer.append(ranks);
		}
		stringBuffer.append(Messages.GemAnalyzer_60);
		stringBuffer.append(fileName);
		stringBuffer.append("\t"); //$NON-NLS-1$
		stringBuffer.append(Messages.GemAnalyzer_61);
		stringBuffer.append(isLeft ? this.leftIndex : this.rightIndex);

		return stringBuffer.toString();
	}

	/*
	 * Adds MenuListeners to hook selections from the context menu.
	 */
	private void hookContextMenu() {
		final MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				GemAnalyzer.this.fillContextMenu(manager);
			}
		});
		final Menu leftMenu = menuMgr.createContextMenu(this.leftViewer.getControl());
		this.leftViewer.getControl().setMenu(leftMenu);
		getSite().registerContextMenu(menuMgr, this.leftViewer);

		final Menu rightMenu = menuMgr.createContextMenu(this.rightViewer.getControl());
		this.rightViewer.getControl().setMenu(rightMenu);
		getSite().registerContextMenu(menuMgr, this.rightViewer);
	}

	/**
	 * Initializing everything and creates threads to be used by the main UI
	 * thread to do updates.
	 * 
	 * @param resource
	 *            The resource to initialize this view with.
	 * @return void
	 */
	public void init(IResource resource) {

		this.activeFile = GemUtilities.adaptResource(resource);

		this.analyzerUpdateThread = new Thread() {
			@Override
			public void run() {
				// If just aborted then don't fill viewers with incomplete data
				if (GemAnalyzer.this.aborted) {
					Display.getDefault().syncExec(GemAnalyzer.this.disableTerminateButtonThread);
					Display.getDefault().syncExec(GemAnalyzer.this.clearAnalyzerThread);
					GemAnalyzer.this.aborted = false;
					return;
				}

				// if the log file contained no MPI calls
				if (GemAnalyzer.this.activeFile == null) {
					Display.getDefault().syncExec(GemAnalyzer.this.disableTerminateButtonThread);
					clear();
					return;
				}

				reset();
				parseSourceFile(GemAnalyzer.this.activeFile, GemAnalyzer.this.activeFile);
				Display.getDefault().syncExec(GemAnalyzer.this.disableTerminateButtonThread);
			}
		};

		this.clearAnalyzerThread = new Thread() {
			@Override
			public void run() {
				final String emptyString = ""; //$NON-NLS-1$
				GemAnalyzer.this.transitionsGroup.setText("Transition:" + " 0/0"); //$NON-NLS-1$ //$NON-NLS-2$
				GemAnalyzer.this.interleavingsGroup.setText("Interleaving:" + " 0/0"); //$NON-NLS-1$ //$NON-NLS-2$
				GemAnalyzer.this.firstTransitionButton.setEnabled(false);
				GemAnalyzer.this.previousTransitionButton.setEnabled(false);
				GemAnalyzer.this.nextTransitionButton.setEnabled(false);
				GemAnalyzer.this.lastTransitionButton.setEnabled(false);
				GemAnalyzer.this.firstInterleavingButton.setEnabled(false);
				GemAnalyzer.this.previousInterleavingButton.setEnabled(false);
				GemAnalyzer.this.nextInterleavingButton.setEnabled(false);
				GemAnalyzer.this.lastInterleavingButton.setEnabled(false);
				GemAnalyzer.this.deadlockInterleavingButton.setEnabled(false);
				GemAnalyzer.this.internalIssueOrderButton.setEnabled(false);
				GemAnalyzer.this.programOrderButton.setEnabled(false);
				GemAnalyzer.this.launchHpvButton.setEnabled(false);
				GemAnalyzer.this.browseCallsButton.setEnabled(false);
				GemAnalyzer.this.terminateButton.setEnabled(false);
				GemAnalyzer.this.errorMessageLabel.setText(emptyString);
				GemAnalyzer.this.transitions = null;
				GemAnalyzer.this.leftViewer.refresh();
				GemAnalyzer.this.rightViewer.refresh();
				GemAnalyzer.this.leftCodeWindowLabel.setText(emptyString);
				GemAnalyzer.this.rightCodeWindowLabel.setText(emptyString);
				final String[] items = new String[] { emptyString };
				GemAnalyzer.this.lockRanksComboList.setItems(items);
				GemUtilities.setTaskStatus(GemUtilities.TaskStatus.IDLE);
				GemAnalyzer.this.runGemButton.setEnabled(true);
			}
		};

		this.disableTerminateButtonThread = new Thread() {
			@Override
			public void run() {
				GemAnalyzer.this.terminateButton.setEnabled(false);
				GemAnalyzer.this.runGemButton.setEnabled(true);
				GemAnalyzer.this.internalIssueOrderButton.setEnabled(true);
				GemAnalyzer.this.programOrderButton.setEnabled(true);
			}
		};

		// start things up now
		this.terminateButton.setEnabled(true);
		this.runGemButton.setEnabled(false);
	}

	/*
	 * Launches the call browser as a separate shell window. This will yield a
	 * list of MPI calls sorted by interleaving -> rank -> MPI call. Calls are
	 * also color coded to distinguish the currently selected line in analyzer
	 * code windows (blue), as well as uncompleted calls due to a deadlock in
	 * the particular interleaving (red).
	 */

	/*
	 * Creates the actions associated with the action bar buttons and context
	 * menu items.
	 */
	private void makeActions() {
		this.getHelp = new Action() {
			@Override
			public void run() {
				PlatformUI.getWorkbench().getHelpSystem().displayHelpResource("/org.eclipse.ptp.gem.help/html/analyzerView.html"); //$NON-NLS-1$
			}
		};
		this.getHelp.setToolTipText(Messages.GemAnalyzer_73);
		this.getHelp.setImageDescriptor(GemPlugin.getImageDescriptor("icons/help-contents.gif")); //$NON-NLS-1$

		this.terminateButton = new Action() {
			@Override
			public void run() {
				GemAnalyzer.this.aborted = true;
				GemUtilities.terminateOperation();
			}
		};
		this.terminateButton.setImageDescriptor(GemPlugin.getImageDescriptor("icons/progress_stop.gif")); //$NON-NLS-1$
		this.terminateButton.setToolTipText(Messages.GemAnalyzer_74);
		this.terminateButton.setEnabled(false);
	}

	/*
	 * Opens the editor with the current source file active and jump to the line
	 * number that is passed in.
	 */
	private void openEditor(int lineNum, IFile sourceFile) {
		try {
			final IEditorPart editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(),
					sourceFile, true);
			final IMarker marker = sourceFile.createMarker(IMarker.MARKER);
			marker.setAttribute(IMarker.LINE_NUMBER, lineNum);
			IDE.gotoMarker(editor, marker);
		} catch (final Exception e) {
			GemUtilities.logExceptionDetail(e);
		}
	}

	/*
	 * Returns whether or not the specified String has a matching number of left
	 * and right. parenthesis.
	 */
	private boolean parenthesesMatched(String call) {
		int numRightParens = 0;
		int numLeftParens = 0;

		call = removeComments(call);
		for (int i = 0; i < call.length(); i++) {
			if (call.charAt(i) == '(') {
				numLeftParens++;
			}
			if (call.charAt(i) == ')') {
				numRightParens++;
			}
		}
		return (numRightParens == numLeftParens);
	}

	/**
	 * Reads in the contents of the specified file and populates the
	 * ListViewers.
	 * 
	 * @param leftSourceFile
	 *            The handle on the file resource for the left code view window.
	 * @param rightSourceFile
	 *            The handle on the file resource for the right code view
	 *            window.
	 * @return void
	 */
	public void parseSourceFile(IFile leftSourceFile, IFile rightSourceFile) {

		final Boolean updateLeftFile = this.currLeftFile == null || !this.currLeftFile.equals(leftSourceFile);
		final Boolean updateRightFile = this.currRightFile == null || rightSourceFile == null
				|| !this.currRightFile.equals(rightSourceFile);
		this.currLeftFile = leftSourceFile;
		this.currRightFile = rightSourceFile;

		// Clear the left viewer list
		if (updateLeftFile) {
			this.leftViewer.getList().removeAll();
		}

		boolean isCollective = false;
		if (this.transitions != null && this.transitions.getCurrentTransition() != null) {
			isCollective = this.transitions.getCurrentTransition().isCollective();
		}

		// Clear the right viewer list
		if (isCollective || updateRightFile) {
			this.rightViewer.getList().removeAll();
		}

		// Populate the viewers with the source file contents
		InputStream leftSourceFileStream = null;
		InputStream rightSourceFileStream = null;
		String line = ""; //$NON-NLS-1$

		// Populate the left code window
		try {
			leftSourceFileStream = leftSourceFile.getContents(true);
			final Scanner s = new Scanner(leftSourceFileStream);
			int lineNum = 0;
			while (updateLeftFile && s.hasNext()) {
				lineNum++;
				line = s.nextLine();
				this.leftViewer.add(new ListElement(leftSourceFile, line, lineNum, false));
			}
		} catch (final CoreException e) {
			GemUtilities.logExceptionDetail(e);
			this.leftViewer.add(new ListElement(null, Messages.GemAnalyzer_76, -1, false));
		}

		// Populate the right code window
		try {
			if (rightSourceFile != null) {
				rightSourceFileStream = rightSourceFile.getContents();
				final Scanner s = new Scanner(rightSourceFileStream);
				int lineNum = 0;
				while (s.hasNext()) {
					lineNum++;
					line = s.nextLine();
					this.rightViewer.add(new ListElement(rightSourceFile, line, lineNum, false));
				}
			} else {
				final Envelope env = this.transitions.getCurrentTransition();
				if (env.isCollective()) {
					displayCollectiveInfo();
				} else {
					this.rightViewer.add(new ListElement(null, "", -1, false)); //$NON-NLS-1$
				}
			}
		} catch (final Exception e) {
			GemUtilities.logExceptionDetail(e);
			this.rightViewer.add(new ListElement(null, Messages.GemAnalyzer_78, -1, false));
		}

		// Close the open InputStreams
		try {
			if (leftSourceFileStream != null) {
				leftSourceFileStream.close();
			}
			if (rightSourceFileStream != null) {
				rightSourceFileStream.close();
			}
		} catch (final IOException e) {
			GemUtilities.logExceptionDetail(e);
		}
	}

	/*
	 * Removes comments from the specified call String.
	 */
	private String removeComments(String call) {
		// remove any c-style comments
		while (call.contains("/*")) { //$NON-NLS-1$
			if (!call.contains("*/")) { //$NON-NLS-1$
				break;
			}
			call = call.substring(0, call.indexOf("/*")) + call.substring(call.indexOf("*/") + 2); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// remove any c++-style comments
		while (call.contains("//")) { //$NON-NLS-1$
			call = call.substring(0, call.indexOf("//")); //$NON-NLS-1$
		}
		return call;
	}

	/*
	 * Resets everything to default values. Used when a new file is analyzed.
	 */
	private void reset() {
		// By making the current files null we force the code viewers to update
		this.currLeftFile = null;
		this.currRightFile = null;
		this.transitions.currentInterleaving = 0;
		this.transitions.currentTransitionIndex = 0;

		// Update labels and combo lists
		setMessageLabelText();
		setLockRankItems();
		setNumProcItems();

		// Update global indices
		this.leftIndex = 0;
		this.rightIndex = 0;
		this.lockedRank = -1;

		// Runtime group buttons
		this.deadlockInterleavingButton.setEnabled(this.transitions.getDeadlockInterleavings() != null);
		this.browseCallsButton.setEnabled(true);
		this.browseCallsButton.setImage(GemPlugin.getImage(GemPlugin.getImageDescriptor("icons/browse.gif"))); //$NON-NLS-1$
		this.launchHpvButton.setEnabled(true);

		// Update transition related items w/o displaying
		updateTransitionLabels(false);

		// TODO Let's clean this up
		// This section is needed since the scroll bars are unresponsive
		// until the view is fully created. For this reason we need to back up
		// to Transition 0 and update the labels.
		this.transitionLabelIndex = 0;
		this.transitionsGroup.setText("Transition " + this.transitionLabelIndex + "/" + this.transitionLabelCount); //$NON-NLS-1$ //$NON-NLS-2$ 
		this.transitions.currentTransitionIndex = -1;
		this.leftIndex = 0;
		this.rightIndex = 0;
		this.previousLeftIndex = 0;
		setButtonEnabledState();
		updateSelectedLine(true);
		setMessageLabelText();
		GemUtilities.setTaskStatus(GemUtilities.TaskStatus.IDLE);
	}

	/*
	 * To make an item visible we must expand each of its parents. Sadly the
	 * root must be expanded first and work its way down to the goal. So we
	 * recursively find parents and then expand once all of the current item's
	 * parents has been expanded.
	 */
	private void revealTreeItem(TreeItem callItem) {
		if (callItem.getParentItem() == null) {
			callItem.setExpanded(true);
		} else {
			revealTreeItem(callItem.getParentItem());
			callItem.setExpanded(true);
		}
	}

	/*
	 * Sets the enabled property of all buttons to the appropriate state.
	 */
	private void setButtonEnabledState() {
		this.firstTransitionButton.setEnabled(this.transitions.hasValidPreviousTransition(this.lockedRank));
		this.previousTransitionButton.setEnabled(this.transitions.hasValidPreviousTransition(this.lockedRank));
		this.nextTransitionButton.setEnabled(this.transitions.hasValidNextTransition(this.lockedRank));
		this.lastTransitionButton.setEnabled(this.transitions.hasValidNextTransition(this.lockedRank));
		this.firstInterleavingButton.setEnabled(this.transitions.hasPreviousInterleaving());
		this.previousInterleavingButton.setEnabled(this.transitions.hasPreviousInterleaving());
		this.nextInterleavingButton.setEnabled(this.transitions.hasNextInterleaving());
		this.lastInterleavingButton.setEnabled(this.transitions.hasNextInterleaving());
		this.deadlockInterleavingButton.setEnabled(this.transitions.getDeadlockInterleavings() != null);

	}

	/**
	 * see org.eclipse.ui.IWorkbenchPart
	 */
	@Override
	public void setFocus() {
		this.runGemButton.setFocus();
	}

	/*
	 * Given the initial Font, this helper method returns that Font with the new
	 * specified size.
	 */
	private Font setFontSize(Font font, int size) {
		final FontData[] fontData = font.getFontData();
		for (final FontData element : fontData) {
			element.setHeight(size);
		}
		return new Font(this.parent.getDisplay(), fontData);
	}

	/*
	 * Populates the lock ranks combo-box with the correct number of entries for
	 * the current analyzation.
	 */
	private void setLockRankItems() {
		final String[] ranks = new String[this.numRanks + 1];
		ranks[0] = Messages.GemAnalyzer_83;
		for (int i = 1; i <= this.numRanks; i++) {
			final StringBuffer stringBuffer = new StringBuffer();
			stringBuffer.append(Messages.GemAnalyzer_84);
			stringBuffer.append((Integer) (i - 1));
			stringBuffer.append(Messages.GemAnalyzer_85);
			ranks[i] = stringBuffer.toString();
		}
		this.lockRanksComboList.setItems(ranks);
		this.lockRanksComboList.setText(ranks[0]);
	}

	/*
	 * Sets the label text in the interleavings buttons group.
	 */
	private void setMessageLabelText() {
		// This is for foreground coloring
		final Display display = this.parent.getShell().getDisplay();
		final Color RED = new Color(display, new RGB(255, 0, 0));
		final Color GREEN = new Color(display, new RGB(0, 200, 0));
		final Color BLUE = new Color(display, new RGB(0, 0, 255));

		// Interleaving label
		this.interleavingsGroup.setText("Interleaving: " + this.transitions.getCurrentInterleaving() + "/" //$NON-NLS-1$ //$NON-NLS-2$
				+ this.transitions.getTotalInterleavings());

		// Transition Label
		this.transitionsGroup.setText("Transition: " + this.transitionLabelIndex + "/" + this.transitionLabelCount); //$NON-NLS-1$ //$NON-NLS-2$

		// Error message label
		if (this.transitions.hasDeadlock()) {
			this.errorMessageLabel.setForeground(RED);
			final ArrayList<Integer> deadlockList = this.transitions.getDeadlockInterleavings();
			String deadlocks = ""; //$NON-NLS-1$
			if (deadlockList.size() == 1) {
				deadlocks = deadlockList.get(0).toString();
			} else {
				for (int i = 0; i < deadlockList.size(); i++) {
					final String num = deadlockList.get(i).toString();
					deadlocks += (i != deadlockList.size() - 1) ? num + ", " : num; //$NON-NLS-1$
				}
			}
			String errorMsg = Messages.GemAnalyzer_89;
			errorMsg += deadlocks.length() == 1 ? " " : "s "; //$NON-NLS-1$ //$NON-NLS-2$
			this.errorMessageLabel.setText(errorMsg + deadlocks);
		} else if (this.transitions.hasAssertion()) {
			this.errorMessageLabel.setForeground(RED);
			this.errorMessageLabel.setText(Messages.GemAnalyzer_91 + this.transitions.getTotalInterleavings());
		} else if (this.transitions.hasError()) {
			this.errorMessageLabel.setForeground(RED);
			this.errorMessageLabel.setText(Messages.GemAnalyzer_92);
		} else {
			if (this.transitions.hasResourceLeak() || this.transitions.hasFIB()) {
				this.errorMessageLabel.setForeground(BLUE);
				this.errorMessageLabel.setText(Messages.GemAnalyzer_93);
			} else {
				this.errorMessageLabel.setForeground(GREEN);
				this.errorMessageLabel.setText(Messages.GemAnalyzer_31);
			}
		}
	}

	/*
	 * Populates the num-procs combo-box with choices the user can use to set
	 * the number of processes for the next analyzer run.
	 */
	private void setNumProcItems() {
		final String[] ranks = new String[16];
		for (int i = 1; i <= 16; i++) {
			ranks[i - 1] = ((Integer) i).toString();
		}
		this.setNumProcsComboList.setItems(ranks);
		final Integer nprocs = GemPlugin.getDefault().getPreferenceStore().getInt(PreferenceConstants.GEM_PREF_NUMPROCS);
		this.setNumProcsComboList.setText(nprocs.toString());
	}

	/*
	 * This method eliminates displaying of redundant collective call
	 * information in the Analyzer code windows. If you are moving forward
	 * direction should be 1, if backward -1, otherwise the behavior is
	 * undefined.
	 */
	private Envelope skipRepeats(int direction) {
		Envelope env = this.transitions.getCurrentTransition();
		while (true) {
			if (env == null) {
				return null;
			}
			if (env.getLinenumber() == this.previousLeftIndex) {
				if (direction == 1) {
					env = this.transitions.getNextTransition(this.lockedRank);
				} else {
					env = this.transitions.getPreviousTransition(this.lockedRank);
				}
			} else {
				break;
			}
		}
		return env;
	}

	/**
	 * Updates the Analyzer view.
	 * 
	 * @param sourceFile
	 *            The source file resource to display in the Analyzer View's
	 *            code windows.
	 * @param transitions
	 *            The Transitions object holding holding all transitions per
	 *            interleaving.
	 * @return void
	 */
	public void update(IFile sourceFile, Transitions transitions) {
		if (transitions == null) {
			clear();
			return;
		}
		this.transitions = transitions;
		this.numRanks = transitions.getNumRanks();
		this.activeFile = sourceFile;
		Display.getDefault().syncExec(this.analyzerUpdateThread);
	}

	/*
	 * Only changes the code windows content, does not change the highlighting.
	 * First time through, current Envelope is null, no update needed.
	 */
	private void updateCodeViewers() {
		final String emptyString = ""; //$NON-NLS-1$
		Envelope env = this.transitions.getCurrentTransition();
		if (env != null) {
			final String nextLeftFileInfo = env.getFilePath();
			String nextRightFileInfo = emptyString;

			env = this.transitions.getCurrentTransition().getMatch_envelope();
			if (env != null) {
				nextRightFileInfo = env.getFilePath();
			}

			final IPath nextLeftFilePath = new Path(nextLeftFileInfo);
			final String nextLeftFileName = nextLeftFilePath.lastSegment();
			String nextRightFileName = emptyString;

			if (nextRightFileInfo.length() != 0) {
				final IPath nextRightFilePath = new Path(nextRightFileInfo);
				nextRightFileName = nextRightFilePath.lastSegment();
			}

			final boolean updateWindowContent = this.currLeftFile == null || this.currRightFile == null
					|| !nextLeftFileName.equals(this.currLeftFile.getName())
					|| !nextRightFileName.equals(this.currRightFile.getName()) || nextRightFileInfo.equals(emptyString);

			if (updateWindowContent) {
				final String projectName = this.activeFile.getProject().getName();
				final IProject currentProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);

				// Get the next left and right source files for the code viewers
				final IFile nextLeftSourceFile = GemUtilities.getSourceFile(nextLeftFileInfo, this.activeFile);
				if (!nextLeftSourceFile.exists()) {
					GemUtilities.refreshProject(currentProject);
				}

				IFile nextRightSourceFile = null;
				final boolean isEmptyPath = nextRightFileInfo.length() == 0;
				if (!isEmptyPath) {
					nextRightSourceFile = GemUtilities.getSourceFile(nextRightFileInfo, this.activeFile);
					if (!nextRightSourceFile.exists()) {
						GemUtilities.refreshProject(currentProject);
					}
				}

				// Now parse the files for new code viewer window content
				parseSourceFile(nextLeftSourceFile, (isEmptyPath) ? null : nextRightSourceFile);
			}
		}
	}

	/**
	 * Calling this method will update the drop down so that it has the correct
	 * number of processes displayed. This method is used when another location
	 * changes the number of processes preference.
	 * 
	 * @param none
	 * @return void
	 */
	public void updateDropDown() {
		final Integer nprocs = GemPlugin.getDefault().getPreferenceStore().getInt(PreferenceConstants.GEM_PREF_NUMPROCS);
		this.setNumProcsComboList.setText(nprocs.toString());
	}

	/*
	 * Goes to the First Transition and updates all relevant data
	 */
	private void updateFirstTransition(boolean update) {
		// Goes to null
		Envelope env = this.transitions.getFirstTransition(this.lockedRank);
		env = this.transitions.getCurrentTransition();

		if (env != null) {
			this.previousLeftIndex = env.getLinenumber();
		}

		if (env == null) {
			GemUtilities.showInformationDialog(Messages.GemAnalyzer_94);
			return;
		}

		if (update) {
			setButtonEnabledState();
			updateCodeViewers();
			displayEnvelopes(env);
			updateSelectedLine(true);
			this.transitionLabelIndex = 1;
			setMessageLabelText();
		}
	}

	/*
	 * Goes to the last transition and updates relevant information
	 */
	private void updateLastTransition() {
		Envelope env = this.transitions.getLastTransition(this.lockedRank);

		// stepToLastTransition puts us at the last iteration of Finalize
		// other code always assumes we are on the first iteration of
		// each call though, so here we go back to the first iteration
		if (env.getFunctionName().equals("MPI_Finalize")) { //$NON-NLS-1$
			while (true) {
				env = this.transitions.getPreviousTransition(this.lockedRank);

				if (env == null) {
					GemUtilities.showInformationDialog(Messages.GemAnalyzer_95);
					return;
				}
				// If there was only one finalize go back to it
				if (!env.getFunctionName().equals("MPI_Finalize")) { //$NON-NLS-1$
					env = this.transitions.getNextTransition(this.lockedRank);
					break;
				}
			}
		}

		if (env == null) {
			GemUtilities.showInformationDialog(Messages.GemAnalyzer_96);
			return;
		}
		this.previousLeftIndex = env.getLinenumber();
		setButtonEnabledState();
		updateCodeViewers();
		displayEnvelopes(env);
		updateSelectedLine(true);
		this.transitionLabelIndex = this.transitionLabelCount;
		setMessageLabelText();
	}

	/*
	 * This method is used to highlight ALL lines involved in a call when the
	 * call is spread over multiple lines in the source code file.
	 */
	private void updateLineCount() {
		final List leftList = this.leftViewer.getList();
		final List rightList = this.rightViewer.getList();
		final String emptyString = ""; //$NON-NLS-1$

		String curr = emptyString;
		this.leftLines = 1;
		if (this.leftIndex <= 0) {
			this.leftLines = 0;
			return;
		}
		while (this.leftLines < this.leftIndex + 1) {
			// Get current string
			curr = emptyString;
			for (int i = this.leftLines; i > 0; i--) {
				curr += leftList.getItem(this.leftIndex - i);
				curr = removeComments(curr);
			}

			if (this.parenthesesMatched(curr)) {
				break;
			}
			this.leftLines++;
		}
		// Be sure to include the MPI Call
		curr = curr.substring(0, curr.indexOf("(") - 1); //$NON-NLS-1$
		if (curr.trim().length() == 0) {
			this.leftLines++;
		}

		if (this.rightIndex == -1) {
			return;
		}
		this.rightLines = 1;

		while (this.rightLines < this.rightIndex + 1) {
			// Get current string
			curr = emptyString;
			for (int i = this.rightLines; i > 0; i--) {
				curr += rightList.getItem(this.rightIndex - i);
				curr = removeComments(curr);
			}

			if (this.parenthesesMatched(curr)) {
				break;
			}
			this.rightLines++;
		}
		curr = curr.substring(0, curr.indexOf("(") - 1); //$NON-NLS-1$
		if (curr.trim().length() == 0) {
			this.rightLines++;
		}
	}

	/*
	 * Go to the next transition. Returns 1 if successful, -1 if there was no
	 * where to go.
	 */
	private int updateNextTransition(boolean update) {
		int returnValue = 1;
		Envelope env = this.transitions.getNextTransition(this.lockedRank);

		if (env.isCollective() && this.lockedRank == -1) {
			env = skipRepeats(1);
		}

		if (env == null) {
			returnValue = -1;
		} else {
			this.previousLeftIndex = env.getLinenumber();
		}

		if (update) {
			setButtonEnabledState();
			updateCodeViewers();
			displayEnvelopes(env);
			updateSelectedLine(true);
			this.transitionLabelIndex++;
			setMessageLabelText();
		}
		return returnValue;
	}

	/*
	 * Goes to the previous transition and updates relevant data
	 */
	private void updatePreviousTransition() {
		Envelope env = this.transitions.getPreviousTransition(this.lockedRank);
		this.previousLeftIndex = env.getLinenumber();

		// Go back until you reach the first call or beginning
		if (env.isCollective() && this.lockedRank == -1) {
			while (true) {
				env = this.transitions.getPreviousTransition(this.lockedRank);
				if (env == null) {
					updateFirstTransition(true);
					return;
				}
				if (env.getLinenumber() != this.previousLeftIndex) {
					env = this.transitions.getNextTransition(this.lockedRank);
					break;
				}
			}
		}

		this.previousLeftIndex = env.getLinenumber();
		setButtonEnabledState();
		updateCodeViewers();
		displayEnvelopes(env);
		updateSelectedLine(true);
		this.transitionLabelIndex--;
		setMessageLabelText();
	}

	/*
	 * Updates the relative position of the scroll bar for the list viewers in
	 * the code windows.
	 */
	private void updateScrollBars() {
		final List leftList = this.leftViewer.getList();
		final List rightList = this.rightViewer.getList();

		try {
			if (leftList != null && leftList.getSelection().length != 0) {
				this.leftViewer.reveal(this.leftViewer.getElementAt(0));
				this.leftViewer.reveal(this.leftViewer.getElementAt(this.leftIndex - 1));
			}
			if (rightList != null && rightList.getSelection().length != 0) {
				this.rightViewer.reveal(this.rightViewer.getElementAt(0));
				this.rightViewer.reveal(this.rightViewer.getElementAt(this.rightIndex - 1));
			}
		} catch (final Exception e) {
			GemUtilities.logExceptionDetail(e);
		}
	}

	/*
	 * Updates which line of the log file that is currently in focus.
	 */
	private void updateSelectedLine(Boolean scroll) {
		updateCodeViewers();

		// Deselect Everything
		final List leftList = this.leftViewer.getList();
		final List rightList = this.rightViewer.getList();
		leftList.deselectAll();
		rightList.deselectAll();

		updateLineCount();

		// Update left view (-1, 0-based)
		for (int i = 0; i < this.leftLines; i++) {
			leftList.select((this.leftIndex - i) - 1);
		}

		// Update right view (-1, 0-based)
		for (int i = 0; i < this.rightLines; i++) {
			rightList.select((this.rightIndex - i) - 1);
		}

		if (scroll) {
			updateScrollBars();
		}
	}

	// ONLY CALL WHEN YOU HAVE STARTED A NEW INTERLEAVING!!!
	// As it searches it will never display the envelope
	// displayEnvelope decides whether or not the final destination is displayed
	private void updateTransitionLabels(boolean displayEnvelope) {
		updateFirstTransition(false);

		// because only incremented if next transition is also valid
		this.transitionLabelCount = 1;
		final Envelope env = this.transitions.getCurrentTransition();

		int test = 1;
		while (test == 1 && env != null) {
			if (this.transitions.hasValidNextTransition(this.lockedRank)) {
				this.transitionLabelCount++;
				test = updateNextTransition(false);
			} else {
				break;
			}
		}
		updateFirstTransition(displayEnvelope);
	}
}
