LaunchSelectionDialog.java
package com.codeaffine.extras.launch.internal.dialog;
import static com.codeaffine.extras.launch.internal.LaunchExtrasPlugin.PLUGIN_ID;
import static com.codeaffine.extras.launch.internal.dialog.LaunchConfigLabelProvider.LabelMode.DETAIL;
import static com.codeaffine.extras.launch.internal.dialog.LaunchConfigLabelProvider.LabelMode.LIST;
import static java.util.Arrays.stream;
import static org.eclipse.jface.action.IAction.ENABLED;
import static org.eclipse.jface.dialogs.IDialogConstants.CANCEL_ID;
import static org.eclipse.jface.dialogs.IDialogConstants.CANCEL_LABEL;
import static org.eclipse.jface.dialogs.IDialogConstants.OK_ID;
import static org.eclipse.jface.dialogs.IDialogConstants.OK_LABEL;
import java.util.Comparator;
import java.util.stream.Stream;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.ILaunchMode;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
import com.codeaffine.eclipse.swt.util.UIThreadSynchronizer;
import com.codeaffine.extras.launch.internal.LaunchExtrasPlugin;
import com.codeaffine.extras.launch.internal.dialog.LaunchConfigLabelProvider.LabelMode;
import com.codeaffine.extras.launch.internal.util.LaunchAdapter;
public class LaunchSelectionDialog extends FilteredItemsSelectionDialog implements DuplicatesDetector {
static final int EDIT_BUTTON_ID = IDialogConstants.CLIENT_ID + 2;
private final ILaunchManager launchManager;
private final EditLaunchConfigAction editLaunchConfigAction;
private final TerminateLaunchesAction terminateLaunchesAction;
private final LaunchConfigSelectionHistory launchConfigHistory;
public LaunchSelectionDialog( Shell shell ) {
super( shell, true );
launchManager = DebugPlugin.getDefault().getLaunchManager();
editLaunchConfigAction = new EditLaunchConfigAction( this );
editLaunchConfigAction.addPropertyChangeListener( new EditLaunchConfigActionListener() );
terminateLaunchesAction = new TerminateLaunchesAction();
launchConfigHistory = new LaunchConfigSelectionHistory();
setTitle( "Start Launch Configuration" );
setMessage( "Enter a &name pattern (? = any character, * = any string, CamelCase)" );
setListLabelProvider( createLaunchConfigLabelProvider( shell.getDisplay(), LIST ) );
setDetailsLabelProvider( createLaunchConfigLabelProvider( shell.getDisplay(), DETAIL ) );
setSelectionHistory( launchConfigHistory );
setSeparatorLabel( "Launch Configuration matches" );
}
public ILaunchConfiguration[] getSelectedLaunchConfigurations() {
return Stream.of( getResult() )
.map( element -> ( ILaunchConfiguration )element )
.toArray( ILaunchConfiguration[]::new );
}
public String getLaunchModeId() {
return new LaunchModeSetting( launchManager, getDialogSettings() ).getLaunchModeId();
}
public ILaunchMode getLaunchMode() {
return new LaunchModeSetting( launchManager, getDialogSettings() ).getLaunchMode();
}
@Override
public String getElementName( Object item ) {
ILaunchConfiguration configuration = ( ILaunchConfiguration )item;
return configuration.getName();
}
@Override
public void create() {
super.create();
registerLaunchConfigDecorationUpdater();
}
public void close( int returnCode ) {
setReturnCode( returnCode );
close();
}
@Override
protected void fillViewMenu( IMenuManager menuManager ) {
super.fillViewMenu( menuManager );
menuManager.add( new Separator() );
menuManager.add( new ToggleTerminateBeforeRelaunchAction() );
menuManager.add( createLaunchModeDropDownAction() );
}
@Override
protected void fillContextMenu( IMenuManager menuManager ) {
menuManager.add( editLaunchConfigAction );
menuManager.add( new Separator() );
menuManager.add( terminateLaunchesAction );
menuManager.add( new Separator() );
super.fillContextMenu( menuManager );
}
@Override
protected void createButtonsForButtonBar( Composite parent ) {
GridLayout parentLayout = ( GridLayout )parent.getLayout();
parentLayout.makeColumnsEqualWidth = false;
parentLayout.numColumns++;
Button editButton = createButton( parent, EDIT_BUTTON_ID, "&Edit...", false );
editButton.setEnabled( false );
setButtonLayoutData( editButton );
new Label( parent, SWT.NONE ).setLayoutData( new GridData( 5, 0 ) );
createButton( parent, OK_ID, OK_LABEL, true );
createButton( parent, CANCEL_ID, CANCEL_LABEL, false );
updateOkButtonLabel();
}
@Override
protected void buttonPressed( int buttonId ) {
if( buttonId == EDIT_BUTTON_ID ) {
editLaunchConfigAction.run();
} else {
super.buttonPressed( buttonId );
}
}
@Override
protected Control createExtendedContentArea( Composite parent ) {
return null;
}
@Override
protected IDialogSettings getDialogSettings() {
IDialogSettings dialogSettings = LaunchExtrasPlugin.getInstance().getDialogSettings();
return DialogSettings.getOrCreateSection( dialogSettings, "LaunchSelectionDialog" );
}
@Override
protected void handleSelected( StructuredSelection selection ) {
super.handleSelected( selection );
editLaunchConfigAction.setSelection( selection );
terminateLaunchesAction.setSelection( selection );
}
@Override
protected IStatus validateItem( Object item ) {
ILaunchMode preferredLaunchMode = getLaunchMode();
ILaunchConfiguration launchConfig = ( ILaunchConfiguration )item;
return new LaunchConfigValidator( launchConfig, preferredLaunchMode ).validate();
}
@Override
protected ItemsFilter createFilter() {
return new LaunchConfigItemsFilter();
}
@Override
protected Comparator<ILaunchConfiguration> getItemsComparator() {
return new LaunchConfigComparator( launchConfigHistory, getLaunchMode() );
}
@Override
protected void fillContentProvider( AbstractContentProvider contentProvider,
ItemsFilter itemsFilter,
IProgressMonitor progressMonitor )
throws CoreException
{
LaunchConfigProvider launchConfigProvider = new LaunchConfigProvider( launchManager );
stream( launchConfigProvider.getLaunchConfigurations() )
.forEach( launchConfig -> contentProvider.add( launchConfig, itemsFilter ) );
}
private void registerLaunchConfigDecorationUpdater() {
LaunchAdapter launchListener = new LaunchConfigDecorationUpdater();
launchManager.addLaunchListener( launchListener );
getShell().addListener( SWT.Dispose, event -> launchManager.removeLaunchListener( launchListener ) );
}
private ILabelProvider createLaunchConfigLabelProvider( Display display, LabelMode labelMode ) {
return new LaunchConfigLabelProvider( display, this, labelMode );
}
private LaunchModeDropDownAction createLaunchModeDropDownAction() {
LaunchModeSetting launchModeSetting = new LaunchModeSetting( launchManager, getDialogSettings() );
LaunchModeDropDownAction result = new LaunchModeDropDownAction( launchModeSetting );
result.addPropertyChangeListener( event -> {
updateOkButtonLabel();
updateStatus();
} );
return result;
}
private void updateOkButtonLabel() {
Button okButton = getButton( OK_ID );
LaunchModeSetting launchModeSetting = new LaunchModeSetting( launchManager, getDialogSettings() );
ILaunchMode launchMode = launchModeSetting.getLaunchMode();
if( okButton != null && launchMode != null ) {
okButton.setText( launchMode.getLabel() );
okButton.getParent().layout();
}
}
void updateStatus() {
IStatus totalStatus = ( IStatus )getSelectedItems().toList().stream()
.map( item -> validateItem( item ) )
.filter( status -> !( ( IStatus )status ).isOK() )
.findFirst()
.orElse( okStatus() );
updateStatus( totalStatus );
}
private static Status okStatus() {
return new Status( OK, PLUGIN_ID, "" );
}
public abstract static class AccessibleSelectionHistory extends SelectionHistory {
}
private class LaunchConfigItemsFilter extends ItemsFilter {
LaunchConfigItemsFilter() {
super( new LaunchConfigSearchPattern() );
}
@Override
public boolean matchItem( Object item ) {
boolean result = false;
if( item instanceof ILaunchConfiguration ) {
result = matchLaunchConfig( ( ILaunchConfiguration )item );
}
return result;
}
@Override
public boolean isConsistentItem( Object item ) {
boolean result = true;
if( item instanceof ILaunchConfiguration && !( ( ILaunchConfiguration )item ).exists() ) {
result = false;
}
return result;
}
private boolean matchLaunchConfig( ILaunchConfiguration launchConfig ) {
return matches( launchConfig.getName() );
}
}
private class LaunchConfigDecorationUpdater extends LaunchAdapter {
@Override
public void launchesAdded( ILaunch[] launches ) {
update();
}
@Override
public void launchesTerminated( ILaunch[] launches ) {
update();
}
private void update() {
new UIThreadSynchronizer().asyncExec( getShell(), LaunchSelectionDialog.this::refresh );
}
}
private class EditLaunchConfigActionListener implements IPropertyChangeListener {
@Override
public void propertyChange( PropertyChangeEvent event ) {
if( ENABLED.equals( event.getProperty() ) ) {
updateEditButtonEnablement( ( IAction )event.getSource() );
}
}
private void updateEditButtonEnablement( IAction action ) {
Button button = getButton( EDIT_BUTTON_ID );
if( button != null && !button.isDisposed() ) {
button.setEnabled( action.isEnabled() );
}
}
}
}