// Copyright (c) 2003-2008 by Leif Frenzel. All rights reserved. // This code is made available under the terms of the Eclipse Public License, // version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html package net.sf.eclipsefp.haskell.debug.ui.internal.launch; import java.io.File; import net.sf.eclipsefp.haskell.debug.core.internal.launch.AbstractHaskellLaunchDelegate; import net.sf.eclipsefp.haskell.debug.core.internal.launch.IInteractiveLaunchOperationDelegate; import net.sf.eclipsefp.haskell.debug.core.internal.launch.ILaunchAttributes; import net.sf.eclipsefp.haskell.debug.ui.internal.util.UITexts; import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin; import net.sf.eclipsefp.haskell.ui.util.HaskellUIImages; import net.sf.eclipsefp.haskell.ui.util.IImageNames; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; 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.DirectoryDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ContainerSelectionDialog; /** <p>The arguments tab for configuring Haskell launch configurations.</p> * * @author Leif Frenzel */ public class HaskellArgumentsTab extends AbstractLaunchConfigurationTab { private Text txtWorkDirectory; private Button btnWorkingDirFile; private Button btnWorkingDirWorkspace; private Button runBackgroundButton; private Button syncStreamsButton; private Text argumentField; private Text fullArgumentField; private SelectionAdapter selectionAdapter; private String forcedArguments=ILaunchAttributes.EMPTY; private final ModifyListener modifyListener = new ModifyListener() { @Override public void modifyText( final ModifyEvent e ) { updateLaunchConfigurationDialog(); } }; // interface methods of ILaunchConfigurationTab /////////////////////////////////////////////// @Override public void createControl( final Composite parent ) { Composite mainComposite = new Composite( parent, SWT.NONE ); setControl( mainComposite ); GridLayout layout = new GridLayout(); layout.numColumns = 2; GridData gridData = new GridData( GridData.FILL_HORIZONTAL ); mainComposite.setLayout( layout ); mainComposite.setLayoutData( gridData ); mainComposite.setFont( parent.getFont() ); createWorkDirectoryComponent( mainComposite ); createArgumentComponent( mainComposite ); createVerticalSpacer( mainComposite, 2 ); createRunBackgroundComponent( mainComposite ); createSyncStreamsComponent( mainComposite ); } @Override public void setDefaults( final ILaunchConfigurationWorkingCopy configWc ) { configWc.setAttribute( ILaunchAttributes.RUN_IN_BACKGROUND, true ); configWc.setAttribute( ILaunchAttributes.WORKING_DIRECTORY, ILaunchAttributes.EMPTY ); configWc.setAttribute( ILaunchAttributes.EXTRA_ARGUMENTS, ILaunchAttributes.EMPTY ); configWc.setAttribute( ILaunchAttributes.SYNC_STREAMS, true ); } @Override public void initializeFrom( final ILaunchConfiguration configuration ) { updateWorkingDirectory( configuration ); updateArgument( configuration ); updateRunBackground( configuration ); updateSyncStreams ( configuration ); } @Override public void performApply( final ILaunchConfigurationWorkingCopy configWc ) { String workingDirectory = txtWorkDirectory.getText().trim(); if( workingDirectory.length() == 0 ) { configWc.setAttribute( ILaunchAttributes.WORKING_DIRECTORY, ( String )null ); } else { configWc.setAttribute( ILaunchAttributes.WORKING_DIRECTORY, workingDirectory ); } setAttribute( ILaunchAttributes.RUN_IN_BACKGROUND, configWc, runBackgroundButton.getSelection(), true ); setAttribute( ILaunchAttributes.SYNC_STREAMS, configWc, syncStreamsButton.getSelection(), true ); String arguments = argumentField.getText().trim(); if( arguments.length() == 0 ) { configWc.setAttribute( ILaunchAttributes.EXTRA_ARGUMENTS, ( String )null ); } else { configWc.setAttribute( ILaunchAttributes.EXTRA_ARGUMENTS, arguments ); } } @Override public boolean isValid( final ILaunchConfiguration launchConfig ) { setErrorMessage( null ); setMessage( null ); return validateWorkDirectory(); } @Override public String getName() { return UITexts.haskellArgumentsTab_name; } @Override public Image getImage() { return HaskellUIImages.getImage( IImageNames.LAUNCH_TAB_ARGUMENTS ); } @Override public boolean canSave() { return isValid( null ); } // UI creation methods ////////////////////// private void createWorkDirectoryComponent( final Composite parent ) { Font font = parent.getFont(); Composite composite = new Composite( parent, SWT.NONE ); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; layout.numColumns = 1; GridData gridData = new GridData( GridData.FILL_HORIZONTAL ); composite.setLayout( layout ); composite.setLayoutData( gridData ); Label label = new Label( composite, SWT.NONE ); label.setText( UITexts.haskellArgumentsTab_workDir ); label.setFont( font ); txtWorkDirectory = new Text( composite, SWT.BORDER ); GridData data = new GridData( GridData.FILL_HORIZONTAL ); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; txtWorkDirectory.setLayoutData( data ); txtWorkDirectory.setFont( font ); createButtonComposite( parent, font ); } private void createButtonComposite( final Composite parent, final Font font ) { Composite buttonComposite = new Composite( parent, SWT.NONE ); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; layout.numColumns = 1; GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_END ); buttonComposite.setLayout( layout ); buttonComposite.setLayoutData( gridData ); buttonComposite.setFont( font ); createVerticalSpacer( buttonComposite, 1 ); String browseWS = UITexts.haskellArgumentsTab_browseWs; btnWorkingDirWorkspace = createPushButton( buttonComposite, browseWS, null ); btnWorkingDirWorkspace.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent evt ) { handleWorkspaceWorkingDirectoryButtonSelected(); } } ); String browseFs = UITexts.haskellArgumentsTab_browseFs; btnWorkingDirFile = createPushButton( buttonComposite, browseFs, null ); btnWorkingDirFile.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent evt ) { handleFileWorkingDirectoryButtonSelected(); } } ); } private void createArgumentComponent( final Composite parent ) { Font font = parent.getFont(); Label label = new Label( parent, SWT.NONE ); label.setText( UITexts.haskellArgumentsTab_lblArguments ); GridData data = new GridData( GridData.HORIZONTAL_ALIGN_FILL ); data.horizontalSpan = 2; label.setLayoutData( data ); label.setFont( font ); int style = SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL; argumentField = new Text( parent, style ); data = new GridData( GridData.FILL_BOTH ); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; data.heightHint = 40; argumentField.setLayoutData( data ); argumentField.setFont( font ); argumentField.addModifyListener( modifyListener ); Label instruction = new Label( parent, SWT.NONE ); instruction.setText( UITexts.haskellArgumentsTab_noteQuote ); data = new GridData( GridData.HORIZONTAL_ALIGN_FILL ); data.horizontalSpan = 2; instruction.setLayoutData( data ); instruction.setFont( font ); label = new Label( parent, SWT.NONE ); label.setText( UITexts.haskellArgumentsTab_lblFullArguments ); data = new GridData( GridData.HORIZONTAL_ALIGN_FILL ); data.horizontalSpan = 2; label.setLayoutData( data ); label.setFont( font ); style = SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY; fullArgumentField = new Text( parent, style ); data = new GridData( GridData.FILL_BOTH ); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; data.heightHint = 40; fullArgumentField.setLayoutData( data ); fullArgumentField.setFont( font ); argumentField.addModifyListener( new ModifyListener() { @Override public void modifyText( final ModifyEvent e ) { fullArgumentField.setText( argumentField.getText()+" "+forcedArguments); //$NON-NLS-1$ } }); } private void createRunBackgroundComponent( final Composite parent ) { runBackgroundButton = new Button( parent, SWT.CHECK ); runBackgroundButton.setText( UITexts.haskellArgumentsTab_background ); GridData data = new GridData( GridData.HORIZONTAL_ALIGN_FILL ); data.horizontalSpan = 2; runBackgroundButton.setLayoutData( data ); runBackgroundButton.setFont( parent.getFont() ); runBackgroundButton.addSelectionListener( getSelectionAdapter() ); } private void createSyncStreamsComponent( final Composite parent ) { syncStreamsButton = new Button( parent, SWT.CHECK ); syncStreamsButton.setText( UITexts.haskellArgumentsTab_syncStreams ); GridData data = new GridData( GridData.HORIZONTAL_ALIGN_FILL ); data.horizontalSpan = 2; syncStreamsButton.setLayoutData( data ); syncStreamsButton.setFont( parent.getFont() ); syncStreamsButton.addSelectionListener( getSelectionAdapter() ); } // helping methods ////////////////// private void updateWorkingDirectory( final ILaunchConfiguration config ) { String workingDir= ILaunchAttributes.EMPTY; try { workingDir = config.getAttribute( ILaunchAttributes.WORKING_DIRECTORY, ILaunchAttributes.EMPTY ); } catch( CoreException ce ) { HaskellUIPlugin.log( UITexts.error_read_configuration, ce ); } txtWorkDirectory.setText( workingDir ); txtWorkDirectory.addModifyListener( modifyListener ); } private void updateArgument( final ILaunchConfiguration configuration ) { String arguments= ILaunchAttributes.EMPTY; String fullArguments = ILaunchAttributes.EMPTY; try { String att = ILaunchAttributes.EXTRA_ARGUMENTS; arguments = configuration.getAttribute( att, ILaunchAttributes.EMPTY ); IInteractiveLaunchOperationDelegate delegate=AbstractHaskellLaunchDelegate.getDelegate( configuration ); forcedArguments=InteractiveLaunchOperation.concatenate( AbstractHaskellLaunchDelegate.getDelegateArguments( configuration, delegate,"run" )); //$NON-NLS-1$ //configuration.getAttribute( ILaunchAttributes.ARGUMENTS, ILaunchAttributes.EMPTY ); fullArguments=arguments+" "+forcedArguments; //$NON-NLS-1$ } catch( CoreException ce ) { HaskellUIPlugin.log( UITexts.error_read_configuration, ce ); } argumentField.setText( arguments ); fullArgumentField.setText( fullArguments ); } private void updateRunBackground( final ILaunchConfiguration config ) { boolean runInBackground = true; try { runInBackground = config.getAttribute( ILaunchAttributes.RUN_IN_BACKGROUND, true ); } catch( CoreException ce ) { HaskellUIPlugin.log( UITexts.error_read_configuration, ce ); } runBackgroundButton.setSelection( runInBackground ); } private void updateSyncStreams( final ILaunchConfiguration config ) { boolean syncStreams = true; try { syncStreams = config.getAttribute( ILaunchAttributes.SYNC_STREAMS, true ); } catch( CoreException ce ) { HaskellUIPlugin.log( UITexts.error_read_configuration, ce ); } syncStreamsButton.setSelection( syncStreams ); } /** validates the content of the working directory field. */ private boolean validateWorkDirectory() { boolean result = true; String value = txtWorkDirectory.getText().trim(); if( value.length() > 0 ) { File file = new File( value ); if( !file.exists() ) { setErrorMessage( UITexts.haskellArgumentsTab_noWorkDir ); result = false; } else if( !file.isDirectory() ) { String msg = UITexts.haskellArgumentsTab_noDir; setErrorMessage( NLS.bind( msg, file.toString() ) ); result = false; } } return result; } /** prompts the user for a working directory location within the * workspace and sets the working directory. */ private void handleWorkspaceWorkingDirectoryButtonSelected() { ContainerSelectionDialog containerDialog; IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot(); String msg = UITexts.haskellArgumentsTab_selectDir; containerDialog = new ContainerSelectionDialog( getShell(), wsRoot, false, msg ); containerDialog.open(); Object[] resource = containerDialog.getResult(); String text = null; if( resource != null && resource.length > 0 ) { IPath path = ( IPath )resource[ 0 ]; text = wsRoot.getLocation().append( path ).toOSString(); } if( text != null ) { txtWorkDirectory.setText( text ); } } private void handleFileWorkingDirectoryButtonSelected() { DirectoryDialog dialog = new DirectoryDialog( getShell(), SWT.SAVE ); dialog.setMessage( UITexts.haskellArgumentsTab_selectDir ); dialog.setFilterPath( txtWorkDirectory.getText() ); String text = dialog.open(); if( text != null ) { txtWorkDirectory.setText( text ); } } private SelectionListener getSelectionAdapter() { if( selectionAdapter == null ) { selectionAdapter= new SelectionAdapter() { @Override public void widgetSelected( final SelectionEvent e ) { updateLaunchConfigurationDialog(); } }; } return selectionAdapter; } }