/*******************************************************************************
* Copyright (c) 2015 Bruno Medeiros and other Contributors.
* 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.ide.ui.launch;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import static melnorme.utilbox.core.CoreUtil.array;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.ILaunchShortcut;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import melnorme.lang.ide.core.utils.EclipseUtils;
import melnorme.lang.ide.ui.LangUIMessages;
import melnorme.lang.ide.ui.editor.EditorUtils;
import melnorme.lang.ide.ui.utils.ControlUtils;
import melnorme.lang.ide.ui.utils.UIOperationsStatusHandler;
import melnorme.lang.ide.ui.utils.WorkbenchUtils;
import melnorme.lang.ide.ui.utils.operations.CalculateValueUIOperation;
import melnorme.lang.tooling.common.ops.IOperationMonitor;
import melnorme.lang.ide.ui.utils.operations.BasicUIOperation;
import melnorme.utilbox.collections.ArrayList2;
import melnorme.utilbox.collections.HashSet2;
import melnorme.utilbox.collections.Indexable;
import melnorme.utilbox.concurrency.OperationCancellation;
import melnorme.utilbox.core.CommonException;
public abstract class BaseLaunchShortcut implements ILaunchShortcut {
public static interface ILaunchable {
String getFullLabel();
IProject getProject();
default String getProjectName() {
return getProject().getName();
}
boolean matchesLaunchConfiguration(ILaunchConfiguration config) throws CoreException;
ILaunchConfiguration createNewConfiguration() throws CoreException;
}
/* ----------------- ----------------- */
protected Shell getActiveShell() {
return WorkbenchUtils.getActiveWorkbenchShell();
}
protected ILaunchManager getLaunchManager() {
return DebugPlugin.getDefault().getLaunchManager();
}
@Override
public void launch(ISelection selection, String mode) {
if(selection instanceof IStructuredSelection) {
IStructuredSelection ssel = (IStructuredSelection) selection;
launchElements(ssel.toArray(), mode);
}
}
@Override
public void launch(IEditorPart editor, String mode) {
IFile editorFile = EditorUtils.findFileOfEditor(editor);
if(editorFile != null) {
launchElements(array(editorFile), mode);
} else {
UIOperationsStatusHandler.handleInternalError("Don't know how to launch editor.", null);
}
}
public void launchElements(Object[] elements, String mode) {
new CalculateValueUIOperation<ILaunchable[]>("Configuring launch") {
@Override
protected ILaunchable[] doBackgroundValueComputation(IOperationMonitor pm)
throws CommonException, OperationCancellation {
HashSet2<ILaunchable> launchables = new HashSet2<>();
for(Object element : elements) {
doFindLaunchables(launchables, element, pm);
}
return launchables.toArray(ILaunchable.class);
};
@Override
protected void handleComputationResult(ILaunchable[] result) throws CommonException {
handleFoundLaunchables(result, mode);
}
}.executeAndHandle();
}
/* ----------------- Find launchables from selection ----------------- */
protected void doFindLaunchables(HashSet2<ILaunchable> launchTargets, Object element, IOperationMonitor om)
throws CommonException, OperationCancellation {
ILaunchable launchTarget = getLaunchTargetForElement(element, om);
if(launchTarget != null) {
launchTargets.add(launchTarget);
}
}
protected abstract ILaunchable getLaunchTargetForElement(Object element, IOperationMonitor om)
throws CommonException, OperationCancellation;
/* ----------------- Handle found launchables ----------------- */
protected void handleFoundLaunchables(ILaunchable[] launchables, String mode)
throws CommonException {
ILaunchable launchableResource;
try {
launchableResource = getLaunchableResource(launchables);
} catch(OperationCancellation e) {
return;
}
launchTarget(launchableResource, mode);
}
/* ----------------- search for Launch targets ----------------- */
protected ILaunchable getLaunchableResource(ILaunchable[] launchables)
throws CommonException, OperationCancellation {
if(launchables == null || launchables.length == 0) {
throw new CommonException(LangUIMessages.LaunchShortcut_selectionContainsNoLaunchables);
} else if(launchables.length == 1) {
return launchables[0];
} else {
return chooseLaunchable(launchables);
}
}
/* ----------------- Choose launch target ----------------- */
protected ILaunchable chooseLaunchable(ILaunchable[] launchTargets) throws OperationCancellation {
ElementListSelectionDialog dialog = new ElementListSelectionDialog(getActiveShell(),
createLaunchTargetLabelProvider());
dialog.setTitle(LangUIMessages.LaunchShortcut_selectLaunchableToLaunch);
dialog.setMessage(LangUIMessages.LaunchShortcut_selectLaunchableToLaunch);
return ControlUtils.setElementsAndOpenDialog(dialog, launchTargets);
}
protected LabelProvider createLaunchTargetLabelProvider() {
return new LabelProvider() {
@Override
public String getText(Object element) {
ILaunchable launchable = (ILaunchable) element;
return launchable.getFullLabel();
}
};
}
/* ----------------- Launch launchable ----------------- */
public void launchTarget(ILaunchable launchTarget, String mode) {
new BasicUIOperation("Preparing launch") {
@Override
public void execute() throws CommonException, OperationCancellation {
try {
doLaunchTarget(launchTarget, mode);
} catch(CoreException e) {
throw EclipseUtils.createCommonException(e);
}
};
}.executeAndHandle();
}
protected void doLaunchTarget(ILaunchable launchTarget, String mode) throws CoreException, OperationCancellation {
ILaunchConfiguration config = findExistingLaunchConfiguration(launchTarget);
if(config == null) {
config = launchTarget.createNewConfiguration();
}
DebugUITools.launch(config, mode);
}
/* ----------------- Find existing config ----------------- */
protected ILaunchConfigurationType getLaunchConfigType() {
return assertNotNull(getLaunchManager().getLaunchConfigurationType(getLaunchTypeId()));
}
protected abstract String getLaunchTypeId();
protected ILaunchConfiguration findExistingLaunchConfiguration(ILaunchable launchable)
throws CoreException, OperationCancellation {
ILaunchConfiguration[] configs = getLaunchManager().getLaunchConfigurations(getLaunchConfigType());
ArrayList2<ILaunchConfiguration> matchingConfigs = new ArrayList2<>();
for(ILaunchConfiguration config : configs) {
if(launchable.matchesLaunchConfiguration(config)) {
matchingConfigs.add(config);
}
}
if(matchingConfigs.isEmpty()) {
return null;
} else if(matchingConfigs.size() == 1) {
return matchingConfigs.get(0);
} else {
return chooseConfiguration(matchingConfigs);
}
}
protected ILaunchConfiguration chooseConfiguration(Indexable<ILaunchConfiguration> configs)
throws OperationCancellation {
IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation();
try {
ElementListSelectionDialog dialog = new ElementListSelectionDialog(getActiveShell(), labelProvider);
dialog.setTitle(LangUIMessages.LaunchShortcut_selectLaunch_title);
dialog.setMessage(LangUIMessages.LaunchShortcut_selectLaunch_message);
dialog.setMultipleSelection(false);
return ControlUtils.setElementsAndOpenDialog(dialog, configs);
} finally {
labelProvider.dispose();
}
}
}