/*******************************************************************************
* Copyright (C) 2003, 2004, 2007, 2008, 2013, Guillaume Brocker
* Copyright (C) 2015-2016, Andre Bossert
*
* 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:
* Guillaume Brocker - Initial API and implementation
* Andre Bossert - Add ability to use Doxyfile not in project scope
*
******************************************************************************/
package eclox.ui.action;
import java.io.File;
import java.net.URI;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowPulldownDelegate;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.FileStoreEditorInput;
import eclox.core.doxyfiles.Doxyfile;
import eclox.core.doxygen.BuildJob;
import eclox.ui.DoxyfileSelector;
import eclox.ui.Plugin;
import eclox.ui.wizard.NewDoxyfileWizard;
/**
* Implement the action handling for the build action.
*
* @author gbrocker
*/
public class BuildActionDelegate implements IWorkbenchWindowPulldownDelegate {
/**
* Listens for the popup menu items pointing to doxyfiles to build.
*
* @author Guillaume Brocker
*/
private class MenuSelectionListener implements SelectionListener {
public void widgetSelected(SelectionEvent e) {
processData(e.widget.getData());
}
public void widgetDefaultSelected(SelectionEvent e) {
processData(e.widget.getData());
}
private void processData(Object data) {
Doxyfile doxyfile = null;
if(data != null) {
if (data instanceof Doxyfile) {
doxyfile = (Doxyfile)data;
} else if (data instanceof IFile) {
doxyfile = new Doxyfile((IFile)data, null);
} else if (data instanceof File) {
doxyfile = new Doxyfile(null, (File)data);
}
}
if (doxyfile != null) {
nextDoxyfile = doxyfile;
doRun(false);
} else {
doRun(true);
}
}
}
private Menu menu; ///< The managed contextual menu.
private Doxyfile nextDoxyfile; ///< Rembers the next doxyfile to build.
private IWorkbenchWindow window; ///< Holds the reference to the workbench window where the action takes place.
/**
* @see org.eclipse.ui.IWorkbenchWindowPulldownDelegate#getMenu(org.eclipse.swt.widgets.Control)
*/
public Menu getMenu(Control parent) {
disposeMenu();
this.menu = new Menu(parent);
// Fill it up with the build history items.
BuildJob[] buildJobs = Plugin.getDefault().getBuildManager().getRecentBuildJobs();
for( int i = buildJobs.length - 1; i >= 0; i-- ) {
MenuItem menuItem = new MenuItem(this.menu, SWT.PUSH);
Doxyfile currentDoxyfile = buildJobs[i].getDoxyfile();
menuItem.addSelectionListener( new MenuSelectionListener() );
menuItem.setData( currentDoxyfile );
menuItem.setText( currentDoxyfile.getName() + " [" + currentDoxyfile.getFullPath() + "]" );
}
// Add some sugar in the ui
if( buildJobs.length > 0 ) {
new MenuItem(this.menu, SWT.SEPARATOR);
}
// Add the fall-back menu item to let the user choose another doxyfile.
MenuItem chooseMenuItem = new MenuItem(this.menu, SWT.PUSH);
chooseMenuItem.addSelectionListener(new MenuSelectionListener());
chooseMenuItem.setText("Choose Doxyfile...");
// Job's done.
return this.menu;
}
/**
* Dispose the delegate.
*/
public void dispose() {
// Frees all resources and references.
disposeMenu();
nextDoxyfile = null;
window = null;
}
/**
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
*/
public void init(IWorkbenchWindow window) {
this.window = window;
}
/**
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
*/
public void run(IAction action) {
try {
doRun(false);
}
catch( Throwable throwable ) {
MessageDialog.openError(window.getShell(), "Unexpected Error", throwable.toString());
}
}
/**
* @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IAction action, ISelection selection) {
try {
// Retrieve the next doxyfile to build from the current selection.
IFile nextIFile = getDoxyfileFromSelection(selection);
// Retrieve the next doxyfile from the current editor.
if( nextIFile != null ) {
nextDoxyfile = new Doxyfile(nextIFile, null);
} else {
nextDoxyfile = getDoxyfileFromActiveEditor(window);
}
// If there is no next doxyfile to build and the history is not empty
// set the first history element as the next doxyfile.
if( nextDoxyfile == null ) {
BuildJob[] buildJobs = Plugin.getDefault().getBuildManager().getRecentBuildJobs();
int buildJobsCount = buildJobs.length;
if( buildJobsCount > 0 ) {
nextDoxyfile = buildJobs[buildJobsCount - 1].getDoxyfile();
}
}
// Check the existence of the doxyfile.
if( nextDoxyfile != null && nextDoxyfile.exists() == false ) {
nextDoxyfile = null;
}
// Update the tooltip.
String tooltipText = nextDoxyfile != null ?
"Build " + nextDoxyfile.getFullPath() :
"Choose Next Doxyfile";
action.setToolTipText(tooltipText);
}
catch(Throwable throwable) {
MessageDialog.openError(window.getShell(), "Unexpected Error", throwable.toString());
}
}
/**
* Uses the next doxyfile specified to determine what to do.
*
* @param forceChoose @c true to ask the user for a doxyfile to build.
*/
protected void doRun(boolean forceChoose) {
try {
Doxyfile doxyfile = (forceChoose == true) ? null : this.nextDoxyfile;
IFile doxyIFile = null;
DoxyfileSelector selector = new DoxyfileSelector(null);
// If there is no next doxyfile to build, ask the user for one.
if(doxyfile == null) {
selector.open();
doxyIFile = selector.getDoxyfile();
if (doxyIFile != null) {
doxyfile = new Doxyfile(doxyIFile, null);
}
}
// If there is no doxyfile,
// we will prompt the user to create one and then edit it.
if (doxyfile == null && selector.hadDoxyfiles() == false) {
doxyIFile = askUserToCreateDoxyfile();
if (doxyIFile != null) {
doxyfile = new Doxyfile(doxyIFile, null);
}
}
else if (doxyfile != null) {
Plugin.getDefault().getBuildManager().build( doxyfile );
}
}
catch( Throwable throwable ) {
MessageDialog.openError(window.getShell(), "Unexpected Error", throwable.toString());
}
}
/**
* Dispose the owned menu.
*/
private void disposeMenu() {
if(this.menu != null) {
this.menu.dispose();
this.menu = null;
}
}
/**
* Retrieves a doxyfile from the active editor.
*
* @param window a reference to a workbench window
*
* @return a doxfile retrieved from the active editor input.
*/
private static Doxyfile getDoxyfileFromActiveEditor( IWorkbenchWindow window ) {
IFile ifile = null;
File file = null;
IWorkbenchPage activePage = window.getActivePage();
IEditorPart activeEditorPart = activePage != null ? window.getActivePage().getActiveEditor() : null;
if(activeEditorPart != null) {
IEditorInput input = activeEditorPart.getEditorInput();
if (input instanceof IFileEditorInput) {
ifile = ((IFileEditorInput)input).getFile();
} else if (input instanceof IAdaptable) {
IAdaptable adaptable = (IAdaptable) input;
ifile = (IFile) adaptable.getAdapter(IFile.class);
if (ifile == null) {
if (adaptable instanceof FileStoreEditorInput) {
URI fileuri = ((FileStoreEditorInput) adaptable).getURI();
file = new File(fileuri.getPath());
} else {
file = (File) adaptable.getAdapter(File.class);
}
}
}
if (ifile != null && !Doxyfile.isDoxyfile(ifile)) {
ifile = null;
}
}
if (ifile != null || file != null) {
return new Doxyfile(ifile, file);
} else {
return null;
}
}
/**
* Retrieves a doxyfile from the specified selection.
*
* @return a doxyfile retrieved from the specified selection.
*/
private static IFile getDoxyfileFromSelection(ISelection selection) {
IFile doxyfile = null;
// Test if the current selection is not empty.
if(selection instanceof IStructuredSelection && selection.isEmpty() == false) {
IStructuredSelection structSel = (IStructuredSelection) selection;
Object element = structSel.getFirstElement();
if(element != null && element instanceof IFile) {
IFile fileElement = (IFile) element;
if(fileElement.exists() == true && Doxyfile.isDoxyfile(fileElement) == true) {
doxyfile = fileElement;
}
}
}
// Job's done.
return doxyfile;
}
/**
* Prompts the user to create a new doxyfile.
*
* @return a doxyfile, or null if none.
*/
private static IFile askUserToCreateDoxyfile() {
IFile doxyfile = null;
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
boolean wantDoxyfile = MessageDialog.openQuestion(shell, "No Doxyfile Found", "No doxyfile has been found in opened projects.\n\nDo you want to create a new doxyfile now ?" );
if( wantDoxyfile ) {
NewDoxyfileWizard wizard = new NewDoxyfileWizard();
ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
IStructuredSelection strcSelection = (selection != null && selection instanceof IStructuredSelection) ? (IStructuredSelection) selection : new StructuredSelection();
wizard.init(PlatformUI.getWorkbench(), strcSelection);
WizardDialog wizardDialog = new WizardDialog(shell, wizard);
wizardDialog.open();
doxyfile = wizard.getDoxyfile();
}
return doxyfile;
}
}