/**
* Copyright (c) 2012 by JP Moresmau
* 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.ui.internal.editors.cabal.forms.stanzas;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sf.eclipsefp.haskell.core.cabalmodel.CabalSyntax;
import net.sf.eclipsefp.haskell.core.cabalmodel.ModuleInclusionType;
import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescription;
import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
import net.sf.eclipsefp.haskell.ui.dialog.FolderSelectionDialog;
import net.sf.eclipsefp.haskell.ui.internal.editors.cabal.forms.stanzas.FormEntryModules.ModulesVisitor;
import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.window.Window;
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.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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.model.WorkbenchViewerComparator;
/**
* Dialog to create a new test suite
* @author JP Moresmau
*
*/
public class TestSuiteDialog extends StatusDialog {
/**
* data for the test suite
* @author JP Moresmau
*
*/
public class TestSuiteDef{
/**
* name
*/
private String name="";
/**
* source folder
*/
private IContainer src=null;
/**
* modules to test
*/
private final Set<ModuleDef> modules=new HashSet<>();
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the src
*/
public IContainer getSrc() {
return src;
}
/**
* @return the modules
*/
public Set<ModuleDef> getModules() {
return modules;
}
}
/*public TestSuiteDialog( final List execsList) {
super( execsList.getShell(), UITexts.cabalEditor_newTestSuiteString,
UITexts.cabalEditor_newTestSuiteString,
"", new IInputValidator() {
@Override
public String isValid( final String newText ) {
String value = newText.trim();
if (value.length()==0) {
return UITexts.cabalEditor_newTestSuiteBlankError;
}
for (String s : execsList.getItems()) {
if (s.equals( value )) {
return UITexts.cabalEditor_newTestSuiteAlreadyExistsError;
}
}
return null;
}
} );
}*/
private final Set<String> usedNames;
private final IProject project;
private final TestSuiteDef def=new TestSuiteDef();
private final PackageDescription pkgDesc;
/**
* should we overwrite existing files?
*/
private boolean overwrite=true;
public TestSuiteDialog(final Shell shell,final IProject project,final PackageDescription desc, final Set<String> names){
super(shell);
usedNames=names;
this.project=project;
this.pkgDesc=desc;
}
/**
* @return the def
*/
public TestSuiteDef getDefinition() {
return def;
}
/* (non-Javadoc)
* @see org.eclipse.jface.window.Window#getShellStyle()
*/
@Override
protected int getShellStyle() {
return super.getShellStyle() | SWT.RESIZE;
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.StatusDialog#configureShell(org.eclipse.swt.widgets.Shell)
*/
@Override
protected void configureShell( final Shell shell ) {
super.configureShell( shell );
shell.setText( UITexts.cabalEditor_newTestSuiteString );
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea( final Composite parent ) {
Composite composite = (Composite) super.createDialogArea( parent );
Label lName=new Label(composite,SWT.WRAP);
lName.setText( UITexts.cabalEditor_newTestSuiteString );
final Text tName=new Text(composite,SWT.SINGLE | SWT.BORDER);
tName.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
| GridData.HORIZONTAL_ALIGN_FILL));
tName.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
def.name= tName.getText().trim();
validateInput();
}
});
Label lSrc=new Label(composite,SWT.WRAP);
lSrc.setText( UITexts.cabalEditor_newTestSuite_src );
Composite cSrc=new Composite(composite,SWT.NONE);
GridLayout glSrc=new GridLayout( 2, false ) ;
glSrc.marginLeft=0;
glSrc.marginRight=0;
cSrc.setLayout(glSrc );
cSrc.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
| GridData.HORIZONTAL_ALIGN_FILL));
final Text tSrc=new Text(cSrc,SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
tSrc.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
| GridData.HORIZONTAL_ALIGN_FILL));
Button bSrc=new Button(cSrc,SWT.PUSH);
bSrc.setText( UITexts.dots );
bSrc.addSelectionListener( new SelectionAdapter() {
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected( final SelectionEvent e ) {
/*ContainerSelectionDialog csd=new ContainerSelectionDialog( getShell(), project, true, UITexts.source_folder_msg );
csd.setTitle( UITexts.source_folder_title );
if(Window.OK==csd.open()){
src=(IPath)csd.getResult()[0];
tSrc.setText(src.toPortableString());
}*/
FolderSelectionDialog fsd=new FolderSelectionDialog( getShell(), project,true );
if(Window.OK==fsd.open()){
def.src=(IContainer)fsd.getFirstResult();
tSrc.setText(def.src.getProjectRelativePath().toPortableString());
validateInput();
}
}
} );
final Button bOverwrite=new Button(composite,SWT.CHECK);
bOverwrite.setText( UITexts.option_overwrite );
bOverwrite.setSelection( true );
bOverwrite.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
overwrite=bOverwrite.getSelection();
}
} );
Label lMods=new Label(composite,SWT.WRAP);
lMods.setText( UITexts.cabalEditor_newTestSuite_modules);
Set<ModuleDef> modules = new HashSet<>();
for (PackageDescriptionStanza stz:pkgDesc.getStanzas()){
if (CabalSyntax.SECTION_LIBRARY.equals( stz.getType()) || CabalSyntax.SECTION_EXECUTABLE.equals( stz.getType() )){
Collection<String> sourceDirs = new HashSet<>();
if( stz.getProperties()
.containsKey( CabalSyntax.FIELD_HS_SOURCE_DIRS.getCabalName() ) ) {
//sourceDirs = root.getStanza().getProperties()
// .get( CabalSyntax.FIELD_HS_SOURCE_DIRS.getCabalName() );
sourceDirs.addAll(stz.getSourceDirs());
} else {
sourceDirs.add("");
}
for (String s:sourceDirs){
List<String> thisModules=new ArrayList<>();
ModulesVisitor visitor = new ModulesVisitor( thisModules, Collections.singletonList( s ) );
try {
project.accept( visitor );
} catch( CoreException e ) {
HaskellUIPlugin.log( e );
}
for (String mod:thisModules){
// check we're in library AND the module is exposed
boolean isLib=CabalSyntax.SECTION_LIBRARY.equals( stz.getType()) && ModuleInclusionType.EXPOSED.equals(stz.getModuleInclusionType( mod ));
modules.add(new ModuleDef( mod, s, isLib ));
}
}
}
}
Table tMods=new Table( composite, SWT.V_SCROLL | SWT.BORDER | SWT.CHECK);
CheckboxTableViewer tvMods=new CheckboxTableViewer( tMods );
tMods.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL
| GridData.VERTICAL_ALIGN_FILL));
tvMods.setContentProvider( new ArrayContentProvider() );
tvMods.setComparator( new WorkbenchViewerComparator() );
tvMods.addCheckStateListener( new ICheckStateListener() {
@Override
public void checkStateChanged( final CheckStateChangedEvent arg0 ) {
ModuleDef d=(ModuleDef)arg0.getElement();
if (arg0.getChecked()){
def.modules.add( d );
} else {
def.modules.remove( d );
}
}
} );
/*tvMods.getTable().setHeaderVisible( true );
TableColumn exposedCol = new TableColumn( tvMods.getTable(), SWT.NULL );
exposedCol.setText( UITexts.cabalEditor_newTestSuite_modules_col_test );
exposedCol.pack();
TableColumn otherCol = new TableColumn( tvMods.getTable(), SWT.NULL );
otherCol.setText( UITexts.cabalEditor_newTestSuite_modules_col_mod );
otherCol.pack();
*/
tvMods.setInput( modules );
validateInput();
applyDialogFont(composite);
return composite;
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.StatusDialog#create()
*/
@Override
public void create() {
super.create();
// override Eclipse policy of no error on showing dialog
validateInput();
}
private void validateInput(){
if (def.getName().length()==0) {
updateStatus( new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(), UITexts.cabalEditor_newTestSuiteBlankError ) );
return;
}
if (usedNames.contains( def.getName() )) {
updateStatus( new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(), UITexts.cabalEditor_newTestSuiteAlreadyExistsError ) );
return;
}
if (def.getSrc()==null){
updateStatus( new Status( IStatus.ERROR, HaskellUIPlugin.getPluginId(), UITexts.cabalEditor_newTestSuite_src_blank) );
return;
}
updateStatus(new Status(IStatus.OK,HaskellUIPlugin.getPluginId(),""));
}
/**
* a definition of a module to maybe test
* @author JP Moresmau
*
*/
public static class ModuleDef {
/**
* module qualified name
*/
private String module;
/**
* source container
*/
private String srcPath;
/**
* are we exposed from a library
*/
private boolean library;
public ModuleDef( final String module, final String srcPath, final boolean library ) {
super();
this.module = module;
this.srcPath = srcPath;
this.library = library;
}
public String getModule() {
return module;
}
public void setModule( final String module ) {
this.module = module;
}
public String getSrcPath() {
return srcPath;
}
public void setSrcPath( final String srcPath ) {
this.srcPath = srcPath;
}
public boolean isLibrary() {
return library;
}
public void setLibrary( final boolean library ) {
this.library = library;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return module;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( ( module == null ) ? 0 : module.hashCode() );
result = prime * result + ( ( srcPath == null ) ? 0 : srcPath.hashCode() );
return result;
}
@Override
public boolean equals( final Object obj ) {
if( this == obj ) {
return true;
}
if( obj == null ) {
return false;
}
if( getClass() != obj.getClass() ) {
return false;
}
ModuleDef other = ( ModuleDef )obj;
if( module == null ) {
if( other.module != null ) {
return false;
}
} else if( !module.equals( other.module ) ) {
return false;
}
if( srcPath == null ) {
if( other.srcPath != null ) {
return false;
}
} else if( !srcPath.equals( other.srcPath ) ) {
return false;
}
return true;
}
}
public boolean isOverwrite() {
return overwrite;
}
}