Office: Replaced selectSheet popup with dynamic context menu

Change-Id: Ic67a297533ef6d3520c7752c80c32582d0e574e7
Signed-off-by: Dusan Kalanj <kalanj@chalmers.se>
diff --git a/org.eclipse.capra.ui.office/plugin.xml b/org.eclipse.capra.ui.office/plugin.xml
index f88463a..a519c22 100644
--- a/org.eclipse.capra.ui.office/plugin.xml
+++ b/org.eclipse.capra.ui.office/plugin.xml
@@ -40,10 +40,6 @@
             id="org.eclipse.capra.ui.office.openfile"
             name="Open File">
       </command>
-      <command
-            id="org.eclipse.capra.ui.office.selectsheet"
-            name="Select Sheet">
-      </command>
    </extension>
    <extension
          point="org.eclipse.ui.handlers">
@@ -59,10 +55,6 @@
             class="org.eclipse.capra.ui.office.handlers.OpenFileHandler"
             commandId="org.eclipse.capra.ui.office.openfile">
       </handler>
-      <handler
-            class="org.eclipse.capra.ui.office.handlers.SelectSheetHandler"
-            commandId="org.eclipse.capra.ui.office.selectsheet">
-      </handler>
    </extension>
    <extension
          point="org.eclipse.ui.menus">
@@ -74,16 +66,19 @@
                style="push"
                tooltip="Triggers the file selection dialog">
          </command>
-         <command
-         	   commandId="org.eclipse.capra.ui.office.selectsheet"
+         <menu
                label="Select Sheet"
-               style="push"
-               tooltip="Select which sheet in the Excel workbook to display">
+               tooltip="Select the Excel sheet that you want to work with.">
+            <dynamic
+                  class="org.eclipse.capra.ui.office.views.SelectSheetDynamicMenu"
+                  id="org.eclipse.capra.ui.office.views.SelectSheetDynamicMenu">
+            </dynamic>
             <visibleWhen>
-    		   <reference
-    		   	   definitionId="org.eclipse.capra.ui.office.utils.isExcelObjectExpression"/>
-			</visibleWhen>
-         </command>
+               <reference
+                     definitionId="org.eclipse.capra.ui.office.utils.isExcelObjectExpression">
+               </reference>
+            </visibleWhen>
+         </menu>
          <command
                commandId="org.eclipse.capra.ui.office.clearselection"
                label="Clear Selection"
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/handlers/SelectSheetHandler.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/handlers/SelectSheetHandler.java
deleted file mode 100644
index 8c17250..0000000
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/handlers/SelectSheetHandler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
- * 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:
- * 	    Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
- *******************************************************************************/
-
-package org.eclipse.capra.ui.office.handlers;
-
-import org.eclipse.capra.ui.office.views.OfficeView;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-
-/**
- * A handler for displaying a dialog that prompts the user to select which Excel
- * sheet to display.
- *
- * @author Dusan Kalanj
- *
- */
-public class SelectSheetHandler extends AbstractHandler {
-
-	@Override
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		OfficeView.getOpenedView().selectSheet();
-		return null;
-	}
-}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java
index 45216ba..52e0f45 100644
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java
@@ -77,6 +77,7 @@
 import org.eclipse.ui.part.ViewPart;
 import org.eclipse.ui.services.ISourceProviderService;
 
+import com.google.common.base.Strings;
 import com.google.common.io.Files;
 
 /**
@@ -95,19 +96,6 @@
 	public static final String ID = "org.eclipse.capra.ui.views.OfficeView";
 
 	/**
-	 * A constant that is used to specify that the user should be prompted to
-	 * select a sheet when opening an excel document.
-	 */
-	public static final boolean SHEET_SELECT_REQUIRED = true;
-
-	/**
-	 * A constant that is used to specify that the user doesn't have to be
-	 * prompted to select a sheet and the currently active sheet will be
-	 * displayed.
-	 */
-	public static final boolean SHEET_SELECT_NOT_REQUIRED = false;
-
-	/**
 	 * The caption that is shown when a message dialog appears describing an
 	 * error.
 	 */
@@ -124,6 +112,16 @@
 	private List<CapraOfficeObject> selection = new ArrayList<CapraOfficeObject>();
 
 	/**
+	 * The names of all the sheets, contained in the selected workbook.
+	 */
+	private String[] sheetNames;
+
+	/**
+	 * The name of the sheet that is currently displayed in the Office view.
+	 */
+	private String selectedSheetName;
+
+	/**
 	 * Instance of OfficeSourceProvider (used for hiding context menu options)
 	 */
 	private OfficeSourceProvider provider = (OfficeSourceProvider) ((ISourceProviderService) PlatformUI.getWorkbench()
@@ -265,15 +263,6 @@
 	}
 
 	/**
-	 * Getter method for the selection that is displayed by the view.
-	 * 
-	 * @return currently displayed selection
-	 */
-	public List<CapraOfficeObject> getSelection() {
-		return this.selection;
-	}
-
-	/**
 	 * A method that is called when the user drags a file into the OfficeView.
 	 * Its main task is to parse the dragged file and display its contents in
 	 * the OfficeView. It only parses the file if it is of type xlsx, xls, or
@@ -296,13 +285,11 @@
 		String fileExtension = Files.getFileExtension(file.getName());
 
 		if (fileExtension.equals(CapraOfficeObject.XLSX) || fileExtension.equals(CapraOfficeObject.XLS))
-			parseExcelDocument(file, SHEET_SELECT_NOT_REQUIRED);
+			parseExcelDocument(file, null);
 		else if (fileExtension.equals(CapraOfficeObject.DOCX))
 			parseWordDocument(file);
 		else
 			throw new CapraOfficeFileNotSupportedException(fileExtension);
-
-		viewer.refresh();
 	}
 
 	/**
@@ -310,12 +297,14 @@
 	 *
 	 * @param officeFile
 	 *            the File object pointing to the Excel document that was
-	 *            dragged into the view.
-	 * @param sheetSelect
-	 *            true if the user has to be prompted to select a sheet, false
-	 *            otherwise
+	 *            dragged into the view
+	 * @param sheetName
+	 *            the name of the sheet that should be displayed in the Office
+	 *            view. If null, the currently active sheet will be displayed.
 	 */
-	private void parseExcelDocument(File officeFile, boolean sheetSelect) {
+	private void parseExcelDocument(File officeFile, String sheetName) {
+
+		clearSelection();
 
 		String fileType = Files.getFileExtension(officeFile.getAbsolutePath());
 		Workbook workBook;
@@ -333,9 +322,7 @@
 			return;
 		}
 
-		String selectedSheetName = "";
-		if (!sheetSelect || selection.isEmpty()) {
-
+		if (Strings.isNullOrEmpty(sheetName)) {
 			// This try block is necessary as there is a bug in the
 			// Workbook.getActiveSheetIndex() and Workbook.getFirstVisibleTab()
 			// methods; they throw a NullPointerException whenever the
@@ -350,12 +337,12 @@
 					activeSheetIndex = workBook.getFirstVisibleTab();
 				} catch (NullPointerException e2) {
 					e2.printStackTrace();
-					activeSheetIndex = 0;					
+					activeSheetIndex = 0;
 				}
 			}
 
 			try {
-				selectedSheetName = workBook.getSheetName(activeSheetIndex);
+				sheetName = workBook.getSheetName(activeSheetIndex);
 			} catch (NullPointerException e) {
 				e.printStackTrace();
 				String url = "https://bugs.eclipse.org/bugs/show_bug.cgi?id=503313#add_comment";
@@ -364,42 +351,15 @@
 				showErrorMessage(ERROR_TITLE, hyperlinkMessage, url);
 				return;
 			}
-
-			// If sheet is empty, prompt user to select another
-			if (workBook.getSheet(selectedSheetName).getLastRowNum() == 0)
-				sheetSelect = true;
 		}
 
-		if (sheetSelect) {
-			String activeSheetName;
-			if (selectedSheetName.isEmpty())
-				activeSheetName = ((CapraExcelRow) selection.get(0)).getSheetName();
-			else
-				activeSheetName = selectedSheetName;
-
-			String[] sNames = new String[workBook.getNumberOfSheets()];
-
-			// Fill sNames with sheetNames, with the active sheet at index 0
-			int counter = 0;
-			sNames[counter++] = activeSheetName;
-			for (int i = 0; i < sNames.length; i++) {
-				String sName = workBook.getSheetName(i);
-				if (sName.equals(activeSheetName))
-					continue;
-				sNames[counter++] = workBook.getSheetName(i);
-			}
-
-			selectedSheetName = new SelectSheetDialog(viewer.getControl().getShell(),
-					SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL, sNames).open();
-		}
-
-		if (selectedSheetName.isEmpty())
+		if (Strings.isNullOrEmpty(sheetName))
 			return;
+		else
+			selectedSheetName = sheetName;
 
-		Sheet sheet = workBook.getSheet(selectedSheetName);
-
-		clearSelection();
-
+		// Populate the view with Excel rows
+		Sheet sheet = workBook.getSheet(sheetName);
 		String idColumn = Activator.getDefault().getPreferenceStore().getString(OfficePreferences.EXCEL_COLUMN_VALUE);
 		for (int i = 0; i <= sheet.getLastRowNum(); i++) {
 			Row row = sheet.getRow(i);
@@ -410,8 +370,16 @@
 			}
 		}
 
+		// Save info about the type of the data displayed in the Office view.
 		if (!selection.isEmpty())
 			provider.setResource(selection.get(0));
+
+		// Fill sheetNames to correctly populate the select sheet menu.
+		sheetNames = new String[workBook.getNumberOfSheets()];
+		for (int i = 0; i < sheetNames.length; i++)
+			sheetNames[i] = workBook.getSheetName(i);
+
+		viewer.refresh();
 	}
 
 	/**
@@ -422,8 +390,10 @@
 	 *            into the view.
 	 */
 	private void parseWordDocument(File officeFile) {
-		List<XWPFParagraph> paragraphs;
 
+		clearSelection();
+
+		List<XWPFParagraph> paragraphs;
 		try (FileInputStream fs = new FileInputStream(officeFile)) {
 			XWPFDocument xwpfDoc = new XWPFDocument(fs);
 			paragraphs = (xwpfDoc).getParagraphs();
@@ -437,8 +407,6 @@
 			return;
 		}
 
-		clearSelection();
-
 		for (int i = 0; i < paragraphs.size(); i++) {
 			XWPFParagraph paragraph = paragraphs.get(i);
 			if (paragraph != null) {
@@ -450,6 +418,8 @@
 
 		if (!selection.isEmpty())
 			provider.setResource(selection.get(0));
+
+		viewer.refresh();
 	}
 
 	/**
@@ -493,12 +463,14 @@
 	}
 
 	/**
-	 * Clears the OfficeView.
+	 * Clears the OfficeView as well as all the static variables.
 	 */
 	public void clearSelection() {
 		selection.clear();
 		viewer.refresh();
 		provider.setResource(null);
+		selectedSheetName = null;
+		sheetNames = null;
 	}
 
 	/**
@@ -520,23 +492,41 @@
 					e.printStackTrace();
 					showErrorMessage(ERROR_TITLE, e.getMessage(), null);
 				}
-				viewer.refresh();
 			}
 		}
 	}
 
 	/**
-	 * Opens a pop-up window that allows the user to select which excel sheet
-	 * should be displayed.
+	 * Displays the provided sheet from the current workbook.
+	 * 
+	 * @param sheetName
+	 *            the name of the sheet to be displayed in the Office view.
 	 */
-	public void selectSheet() {
+	public void selectSheet(String sheetName) {
 
 		if (selection.isEmpty())
 			return;
-		else if (selection.get(0) instanceof CapraExcelRow) {
-			parseExcelDocument(selection.get(0).getFile(), SHEET_SELECT_REQUIRED);
-			viewer.refresh();
-		}
+		else if (selection.get(0) instanceof CapraExcelRow)
+			parseExcelDocument(selection.get(0).getFile(), sheetName);
+	}
+
+	/**
+	 * Getter method for the names of sheets contained in the current workbook.
+	 * 
+	 * @return names of all the sheets contained in the current workbook or null
+	 *         if a workbook isn't opened.
+	 */
+	public String[] getSheetNames() {
+		return sheetNames;
+	}
+
+	/**
+	 * Getter method for the name of currently displayed sheet.
+	 * 
+	 * @return name of currently displayed sheet or null if none is displayed.
+	 */
+	public String getSelectedSheetName() {
+		return selectedSheetName;
 	}
 
 	/**
@@ -554,14 +544,18 @@
 		return null;
 	}
 
+	/**
+	 * Refreshes the Office view.
+	 */
 	public void refreshView() {
 
 		if (selection.isEmpty())
 			return;
-		else if (selection.get(0) instanceof CapraExcelRow)
-			parseExcelDocument(selection.get(0).getFile(), SHEET_SELECT_NOT_REQUIRED);
 
-		viewer.refresh();
+		if (selection.get(0) instanceof CapraExcelRow)
+			parseExcelDocument(selection.get(0).getFile(), selectedSheetName);
+		else if (selection.get(0) instanceof CapraWordRequirement)
+			parseWordDocument(selection.get(0).getFile());
 	}
 
 	private void hookContextMenu() {
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDialog.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDialog.java
deleted file mode 100644
index 902fd37..0000000
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDialog.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package org.eclipse.capra.ui.office.views;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Dialog;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.ToolBar;
-import org.eclipse.swt.widgets.ToolItem;
-
-/**
- * A class that extends Dialog in order to prompt the user for which excel sheet
- * to display.
- * 
- * Code adapted from:
- * http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/Howtocreateyourowndialogclasses.htm
- * 
- * @author Dusan Kalanj
- *
- */
-public class SelectSheetDialog extends Dialog {
-
-	/**
-	 * Strings that are displayed in the Dialog.
-	 */
-	private static final String PROMPT_MESSAGE = "Please select the sheet to display.";
-	private static final String SELECT_TIP = "Click here to select the sheet.";
-	private static final String OK = "OK";
-	private static final String CANCEL = "Cancel";
-
-	/**
-	 * Top margin between elements in the dialog.
-	 */
-	private static final int VERTICAL_INDENT = 10;
-
-	private String[] sheetNames;
-	private String selectedSheetName;
-
-	/**
-	 * SelectSheetDialog constructor.
-	 * 
-	 * @param parentShell
-	 *            the shell that will accommodate the dialog.
-	 * @param style
-	 *            the style used by the dialog
-	 * @param currentSheet
-	 *            the currently displayed sheet
-	 * @param totalNumOfSheets
-	 *            the sheet that was selected in the dialog.
-	 */
-	public SelectSheetDialog(Shell parentShell, int style, String[] sheetNames) {
-		super(parentShell, style);
-		this.sheetNames = sheetNames;
-		this.selectedSheetName = sheetNames[0];
-	}
-
-	/**
-	 * Opens the dialog and returns the index of the selected sheet.
-	 * 
-	 * @return the number of the sheet to display
-	 */
-	public String open() {
-		Shell shell = new Shell(getParent(), getStyle());
-		createContents(shell);
-
-		Rectangle shellBounds = getParent().getBounds();
-
-		shell.setLocation(shellBounds.x + shellBounds.width / 2, shellBounds.y + shellBounds.height / 2);
-		shell.pack();
-		shell.open();
-
-		Display display = getParent().getDisplay();
-		while (!shell.isDisposed()) {
-			if (!display.readAndDispatch()) {
-				display.sleep();
-			}
-		}
-
-		return selectedSheetName;
-	}
-
-	/**
-	 * Fills the dialog window with content.
-	 * 
-	 * @param shell
-	 *            the window of the dialog
-	 */
-	private void createContents(final Shell shell) {
-
-		GridLayout gridLayout = new GridLayout(2, true);
-		shell.setLayout(gridLayout);
-
-		Label label = new Label(shell, SWT.NONE);
-		label.setText(PROMPT_MESSAGE);
-		GridData data = new GridData(GridData.FILL_HORIZONTAL);
-		data.horizontalSpan = 2;
-		label.setLayoutData(data);
-
-		final ToolBar toolBar = new ToolBar(shell, SWT.NONE);
-		data = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1);
-		data.verticalIndent = VERTICAL_INDENT;
-		data.horizontalSpan = 2;
-		toolBar.setLayoutData(data);
-		final ToolItem itemDropDown = new ToolItem(toolBar, SWT.DROP_DOWN);
-		final Menu menu = new Menu(shell, SWT.POP_UP);
-
-		itemDropDown.setText(sheetNames[0]);
-		itemDropDown.setToolTipText(SELECT_TIP);
-
-		for (int i = 0; i < sheetNames.length; i++) {
-			MenuItem item = new MenuItem(menu, SWT.PUSH);
-			item.setText(sheetNames[i]);
-			item.addSelectionListener(new SelectionListener() {
-
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					selectedSheetName = item.getText();
-					itemDropDown.setText(selectedSheetName);
-
-					toolBar.pack();
-				}
-
-				@Override
-				public void widgetDefaultSelected(SelectionEvent e) {
-					selectedSheetName = item.getText();
-					itemDropDown.setText(selectedSheetName);
-					toolBar.pack();
-				}
-			});
-		}
-
-		itemDropDown.addListener(SWT.Selection, new Listener() {
-			public void handleEvent(Event event) {
-				Rectangle bounds = itemDropDown.getBounds();
-				Point point = toolBar.toDisplay(bounds.x, bounds.y + bounds.height);
-				menu.setLocation(point);
-				menu.setVisible(true);
-			}
-		});
-
-		Button ok = new Button(shell, SWT.PUSH);
-		ok.setText(OK);
-		data = new GridData(GridData.FILL_HORIZONTAL);
-		data.verticalIndent = VERTICAL_INDENT;
-		data.horizontalSpan = 1;
-		ok.setLayoutData(data);
-		ok.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent event) {
-				shell.close();
-			}
-		});
-
-		Button cancel = new Button(shell, SWT.PUSH);
-		cancel.setText(CANCEL);
-		data = new GridData(GridData.FILL_HORIZONTAL);
-		data.verticalIndent = VERTICAL_INDENT;
-		data.horizontalSpan = 1;
-		cancel.setLayoutData(data);
-		cancel.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent event) {
-				selectedSheetName = sheetNames[0];
-				shell.close();
-			}
-		});
-
-		shell.setDefaultButton(ok);
-	}
-}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDynamicMenu.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDynamicMenu.java
new file mode 100644
index 0000000..aef3abc
--- /dev/null
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDynamicMenu.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	   Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.capra.ui.office.views;
+
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * A class tasked with dynamically filling the sheet-select context menu with
+ * names of all the sheets contained in the currently opened Excel workbook.
+ * 
+ * @author Dusan Kalanj
+ *
+ */
+public class SelectSheetDynamicMenu extends ContributionItem {
+
+	@Override
+	public void fill(Menu menu, int index) {
+
+		String[] sheetNames = getSheetNames();
+
+		for (String sheetName : sheetNames) {
+			MenuItem menuItem = new MenuItem(menu, SWT.CHECK, index);
+			menuItem.setText(sheetName);
+			menuItem.addSelectionListener(new SelectionListener() {
+
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					OfficeView.getOpenedView().selectSheet(menuItem.getText());
+				}
+
+				@Override
+				public void widgetDefaultSelected(SelectionEvent e) {
+					OfficeView.getOpenedView().selectSheet(menuItem.getText());
+				}
+			});
+
+			if (OfficeView.getOpenedView().getSelectedSheetName().contentEquals(sheetName))
+				menuItem.setSelection(true);
+		}
+	}
+
+	/**
+	 * Gets all the sheet names contained in the currently opened workbook.
+	 * 
+	 * @return Array of all sheet names from the current workbook.
+	 */
+	private String[] getSheetNames() {
+		return OfficeView.getOpenedView().getSheetNames();
+	}
+}
\ No newline at end of file