Permalink
Browse files

test suite creation with HTF support

  • Loading branch information...
1 parent 3350f66 commit 86398784e8f75f4b75036a1ec0cc1270b99b642f @JPMoresmau committed Nov 30, 2012
Showing with 2,818 additions and 1,789 deletions.
  1. +2 −0 docs/releasenotes/net.sf.eclipsefp.haskell_2.3.3.txt
  2. +13 −0 net.sf.eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/cabalmodel/CabalModelTest.java
  3. +8 −0 net.sf.eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/cabalmodel/TestSuiteOnly.cabal
  4. +200 −191 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/PackageDescription.java
  5. +8 −1 ...eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/PackageDescriptionLoader.java
  6. +47 −1 ...eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/PackageDescriptionStanza.java
  7. +83 −67 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/ValuePosition.java
  8. +16 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/code/ModuleCreationInfo.java
  9. +9 −4 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/code/SourceFileGenerator.java
  10. +26 −3 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/code/CodeGenerator.java
  11. +1 −0 ...clipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/ProjectModelFilesOp.java
  12. +58 −4 ...lipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/CorePreferenceInitializer.java
  13. +7 −0 ...sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/ICorePreferenceNames.java
  14. +4 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/TemplateVariables.java
  15. +95 −6 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/FolderSelectionDialog.java
  16. +8 −3 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/SourceFolderSelectionDialog.java
  17. +220 −220 ...efp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/CabalFormSection.java
  18. +425 −423 ...ell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/stanzas/FormEntryModules.java
  19. +419 −0 ...kell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/stanzas/TestSuiteDialog.java
  20. +506 −396 ...skell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/stanzas/TestSuitesPage.java
  21. +9 −2 ...clipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/preferences/NewHaskellProjectPP.java
  22. +26 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/UITexts.java
  23. +29 −3 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/uitexts.properties
  24. +599 −465 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/wizards/NewModuleWizardPage.java
View
2 docs/releasenotes/net.sf.eclipsefp.haskell_2.3.3.txt
@@ -20,6 +20,8 @@ Features:
- File templates for cabal file, setup.hs, new modules... (under Preferences -> Haskell -> New Project)
- Offers GHC suggested alternative on unresolved symbol
- Allow running executables from test suites without test-framework specific options, as normal executables
+ - Specific Haskell Test Results view: no more dependency on JDT
+ - Navigate Next Previous now works in Haskell Editor
Internal:
View
13 ...ipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/cabalmodel/CabalModelTest.java
@@ -762,6 +762,19 @@ public void testTestSuite(){
assertEquals("exitcode-stdio-1.0",ts.getProperties().get( CabalSyntax.FIELD_TYPE ));
}
+ public void testTestSuitePartial(){
+ String content3=getContent( "TestSuiteOnly.cabal" );
+ PackageDescription pd=PackageDescriptionLoader.load( content3 );
+ List<PackageDescriptionStanza> pdss=pd.getStanzas();
+ PackageDescriptionStanza ts=pdss.get( 1 );
+ assertEquals(CabalSyntax.SECTION_TESTSUITE,ts.getType());
+ assertEquals("exitcode-stdio-1.0",ts.getProperties().get( CabalSyntax.FIELD_TYPE ));
+ ts=PackageDescriptionLoader.loadStanza( content3 );
+ assertEquals(CabalSyntax.SECTION_TESTSUITE,ts.getType());
+ assertEquals("exitcode-stdio-1.0",ts.getProperties().get( CabalSyntax.FIELD_TYPE ));
+
+ }
+
public void testIfElse(){
String content3=getContent( "IfElse.cabal" );
PackageDescription pd=PackageDescriptionLoader.load( content3 );
View
8 ...ipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/cabalmodel/TestSuiteOnly.cabal
@@ -0,0 +1,8 @@
+test-suite testsuite-suite
+ type: exitcode-stdio-1.0
+ main-is: test.hs
+ Build-Depends: multiset >= 0.1 && < 0.3,
+ base
+ other-modules:
+ Test.HUnit.Base, Test.HUnit.Lang, Test.HUnit.Terminal,
+ Test.HUnit.Text, Test.HUnit
View
391 ...lipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/PackageDescription.java
@@ -1,191 +1,200 @@
-// Copyright (c) 2006 by Leif Frenzel <himself@leiffrenzel.de>
-// All rights reserved.
-// Copyright (c) 2011 by Alejandro Serrano
-package net.sf.eclipsefp.haskell.core.cabalmodel;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-import net.sf.eclipsefp.haskell.buildwrapper.types.Component;
-import net.sf.eclipsefp.haskell.buildwrapper.types.Component.ComponentType;
-
-/** <p>The root of the package description model, represents the contents of a
- * <code>.cabal</code> file.</p>
- *
- * @author Leif Frenzel
- * @author Alejandro Serrano
- */
-public class PackageDescription {
-
- private final List<PackageDescriptionStanza> stanzas;
-
- PackageDescription() {
- stanzas = new ArrayList<PackageDescriptionStanza>();
- }
-
- public PackageDescription(final String name){
- this();
- PackageDescriptionStanza pds = new PackagePropertiesStanza(this, 0 );
- stanzas.add( pds );
- pds.update( CabalSyntax.FIELD_NAME, name );
- }
-
- public List<PackageDescriptionStanza> getStanzas() {
- return stanzas;
- }
-
- public PackageDescriptionStanza getPackageStanza() {
- if (getStanzas().size()>0 && getStanzas().get(0) instanceof PackagePropertiesStanza){
- return getStanzas().get(0);
- }
- return null;
- }
-
- public PackageDescriptionStanza getLibraryStanza() {
- return getComponentStanza( new Component( ComponentType.LIBRARY, null, null, true ) );
- }
-
- public List<PackageDescriptionStanza> getExecutableStanzas() {
- Vector<PackageDescriptionStanza> result = new Vector<PackageDescriptionStanza>();
- for (PackageDescriptionStanza stanza : getStanzas()) {
- if (stanza.getType() == CabalSyntax.SECTION_EXECUTABLE) {
- result.add( stanza );
- }
- }
- return result;
- }
-
- public List<PackageDescriptionStanza> getTestSuiteStanzas() {
- Vector<PackageDescriptionStanza> result = new Vector<PackageDescriptionStanza>();
- for (PackageDescriptionStanza stanza : getStanzas()) {
- if (stanza.getType() == CabalSyntax.SECTION_TESTSUITE) {
- result.add( stanza );
- }
- }
- return result;
- }
-
- public PackageDescriptionStanza addStanza(final CabalSyntax type,final String name){
- int startLine=stanzas.get(stanzas.size()-1).getEndLine()+1;
- PackageDescriptionStanza pds=new PackageDescriptionStanza(this, type, name, startLine );
- pds.setEndLine( startLine+1 );
- stanzas.add( pds );
- return pds;
- }
-
- public void removeStanza(final PackageDescriptionStanza stanza) {
- boolean found = false;
- int diff = 0;
-
- for (PackageDescriptionStanza st : getStanzas()) {
- if (st == stanza) {
- diff = - (st.getEndLine() - st.getStartLine() + 1);
- found = true;
- continue;
- }
- if (found) {
- st.diffLine( diff );
- }
- }
- this.stanzas.remove( stanza );
- }
-
- public Map<String, List<PackageDescriptionStanza>> getStanzasBySourceDir(){
- Map<String, List<PackageDescriptionStanza>> ret=new HashMap<String, List<PackageDescriptionStanza>>();
-
- for (PackageDescriptionStanza pds:stanzas){
- Collection<String> sds=pds.getSourceDirs();
- for (String t:sds){
- if (t.length()>0){
- List<PackageDescriptionStanza> pdss=ret.get( t );
- if (pdss==null){
- pdss=new LinkedList<PackageDescriptionStanza>();
- ret.put( t, pdss );
- }
- pdss.add(pds);
- }
- }
-
- }
-
- return ret;
- }
-
- public Collection<String> getAllSourceDirs() {
- HashSet<String> result = new HashSet<String>();
- for (PackageDescriptionStanza pds:stanzas){
- Collection<String> sds=pds.getSourceDirs();
- result.addAll( sds );
- }
- return result;
- }
-
-
- public Collection<String> getAllNonHaskellFiles() {
- HashSet<String> result = new HashSet<String>();
- for (PackageDescriptionStanza pds:stanzas){
- Collection<String> sds=pds.getNonHaskellFiles();
- result.addAll( sds );
- }
- return result;
- }
-
- public void dump(final Writer w) throws IOException {
- for (PackageDescriptionStanza pds:stanzas){
- pds.dump( w, 0 );
- }
- }
-
- public String dump(){
- StringWriter sw=new StringWriter();
- try {
- dump( sw );
- String s=sw.toString();
- return s;
- } catch (IOException ioe){
- // cannot happen
- }
- return null;
- }
-
- public PackageDescriptionStanza getComponentStanza(final Component c){
- for (PackageDescriptionStanza pds:stanzas){
- if (CabalSyntax.SECTION_LIBRARY.equals( pds.getType()) && c.getType().equals( ComponentType.LIBRARY )){
- return pds;
- }
- if (CabalSyntax.SECTION_EXECUTABLE.equals(pds.getType()) && c.getType().equals( ComponentType.EXECUTABLE ) && pds.getName().equals(c.getName())){
- return pds;
- }
- if (CabalSyntax.SECTION_TESTSUITE.equals(pds.getType()) && c.getType().equals( ComponentType.TESTSUITE ) && pds.getName().equals(c.getName())){
- return pds;
- }
- }
- return null;
- }
-
- public PackageDescriptionStanza getSameStanza(final PackageDescriptionStanza p){
- for (PackageDescriptionStanza pds:stanzas){
- if (pds.getType()==null && p.getType()==null){
- return pds;
- }
- if (CabalSyntax.SECTION_LIBRARY.equals( pds.getType()) && CabalSyntax.SECTION_LIBRARY.equals( p.getType())){
- return pds;
- }
- if (CabalSyntax.SECTION_EXECUTABLE.equals(pds.getType()) && CabalSyntax.SECTION_EXECUTABLE.equals(p.getType() ) && pds.getName().equals(p.getName())){
- return pds;
- }
- if (CabalSyntax.SECTION_TESTSUITE.equals(pds.getType()) && CabalSyntax.SECTION_TESTSUITE.equals(p.getType() ) && pds.getName().equals(p.getName())){
- return pds;
- }
- }
- return null;
- }
-}
+// Copyright (c) 2006 by Leif Frenzel <himself@leiffrenzel.de>
+// All rights reserved.
+// Copyright (c) 2011 by Alejandro Serrano
+package net.sf.eclipsefp.haskell.core.cabalmodel;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import net.sf.eclipsefp.haskell.buildwrapper.types.Component;
+import net.sf.eclipsefp.haskell.buildwrapper.types.Component.ComponentType;
+
+/** <p>The root of the package description model, represents the contents of a
+ * <code>.cabal</code> file.</p>
+ *
+ * @author Leif Frenzel
+ * @author Alejandro Serrano
+ */
+public class PackageDescription {
+
+ private final List<PackageDescriptionStanza> stanzas;
+
+ PackageDescription() {
+ stanzas = new ArrayList<PackageDescriptionStanza>();
+ }
+
+ public PackageDescription(final String name){
+ this();
+ PackageDescriptionStanza pds = new PackagePropertiesStanza(this, 0 );
+ stanzas.add( pds );
+ pds.update( CabalSyntax.FIELD_NAME, name );
+ }
+
+ public List<PackageDescriptionStanza> getStanzas() {
+ return stanzas;
+ }
+
+ public PackageDescriptionStanza getPackageStanza() {
+ if (getStanzas().size()>0 && getStanzas().get(0) instanceof PackagePropertiesStanza){
+ return getStanzas().get(0);
+ }
+ return null;
+ }
+
+ public PackageDescriptionStanza getLibraryStanza() {
+ return getComponentStanza( new Component( ComponentType.LIBRARY, null, null, true ) );
+ }
+
+ public List<PackageDescriptionStanza> getExecutableStanzas() {
+ Vector<PackageDescriptionStanza> result = new Vector<PackageDescriptionStanza>();
+ for (PackageDescriptionStanza stanza : getStanzas()) {
+ if (stanza.getType() == CabalSyntax.SECTION_EXECUTABLE) {
+ result.add( stanza );
+ }
+ }
+ return result;
+ }
+
+ public List<PackageDescriptionStanza> getTestSuiteStanzas() {
+ Vector<PackageDescriptionStanza> result = new Vector<PackageDescriptionStanza>();
+ for (PackageDescriptionStanza stanza : getStanzas()) {
+ if (stanza.getType() == CabalSyntax.SECTION_TESTSUITE) {
+ result.add( stanza );
+ }
+ }
+ return result;
+ }
+
+ public PackageDescriptionStanza addStanza(final CabalSyntax type,final String name){
+ int startLine=stanzas.get(stanzas.size()-1).getEndLine()+1;
+ PackageDescriptionStanza pds=new PackageDescriptionStanza(this, type, name, startLine );
+ pds.setEndLine( startLine+1 );
+ stanzas.add( pds );
+ return pds;
+ }
+
+ /**
+ * add the existing stanza from another description to this description
+ * @param pds
+ */
+ public void addStanza(final PackageDescriptionStanza pds){
+ pds.move( this );
+
+ }
+
+ public void removeStanza(final PackageDescriptionStanza stanza) {
+ boolean found = false;
+ int diff = 0;
+
+ for (PackageDescriptionStanza st : getStanzas()) {
+ if (st == stanza) {
+ diff = - (st.getEndLine() - st.getStartLine() + 1);
+ found = true;
+ continue;
+ }
+ if (found) {
+ st.diffLine( diff );
+ }
+ }
+ this.stanzas.remove( stanza );
+ }
+
+ public Map<String, List<PackageDescriptionStanza>> getStanzasBySourceDir(){
+ Map<String, List<PackageDescriptionStanza>> ret=new HashMap<String, List<PackageDescriptionStanza>>();
+
+ for (PackageDescriptionStanza pds:stanzas){
+ Collection<String> sds=pds.getSourceDirs();
+ for (String t:sds){
+ if (t.length()>0){
+ List<PackageDescriptionStanza> pdss=ret.get( t );
+ if (pdss==null){
+ pdss=new LinkedList<PackageDescriptionStanza>();
+ ret.put( t, pdss );
+ }
+ pdss.add(pds);
+ }
+ }
+
+ }
+
+ return ret;
+ }
+
+ public Collection<String> getAllSourceDirs() {
+ HashSet<String> result = new HashSet<String>();
+ for (PackageDescriptionStanza pds:stanzas){
+ Collection<String> sds=pds.getSourceDirs();
+ result.addAll( sds );
+ }
+ return result;
+ }
+
+
+ public Collection<String> getAllNonHaskellFiles() {
+ HashSet<String> result = new HashSet<String>();
+ for (PackageDescriptionStanza pds:stanzas){
+ Collection<String> sds=pds.getNonHaskellFiles();
+ result.addAll( sds );
+ }
+ return result;
+ }
+
+ public void dump(final Writer w) throws IOException {
+ for (PackageDescriptionStanza pds:stanzas){
+ pds.dump( w, 0 );
+ }
+ }
+
+ public String dump(){
+ StringWriter sw=new StringWriter();
+ try {
+ dump( sw );
+ String s=sw.toString();
+ return s;
+ } catch (IOException ioe){
+ // cannot happen
+ }
+ return null;
+ }
+
+ public PackageDescriptionStanza getComponentStanza(final Component c){
+ for (PackageDescriptionStanza pds:stanzas){
+ if (CabalSyntax.SECTION_LIBRARY.equals( pds.getType()) && c.getType().equals( ComponentType.LIBRARY )){
+ return pds;
+ }
+ if (CabalSyntax.SECTION_EXECUTABLE.equals(pds.getType()) && c.getType().equals( ComponentType.EXECUTABLE ) && pds.getName().equals(c.getName())){
+ return pds;
+ }
+ if (CabalSyntax.SECTION_TESTSUITE.equals(pds.getType()) && c.getType().equals( ComponentType.TESTSUITE ) && pds.getName().equals(c.getName())){
+ return pds;
+ }
+ }
+ return null;
+ }
+
+ public PackageDescriptionStanza getSameStanza(final PackageDescriptionStanza p){
+ for (PackageDescriptionStanza pds:stanzas){
+ if (pds.getType()==null && p.getType()==null){
+ return pds;
+ }
+ if (CabalSyntax.SECTION_LIBRARY.equals( pds.getType()) && CabalSyntax.SECTION_LIBRARY.equals( p.getType())){
+ return pds;
+ }
+ if (CabalSyntax.SECTION_EXECUTABLE.equals(pds.getType()) && CabalSyntax.SECTION_EXECUTABLE.equals(p.getType() ) && pds.getName().equals(p.getName())){
+ return pds;
+ }
+ if (CabalSyntax.SECTION_TESTSUITE.equals(pds.getType()) && CabalSyntax.SECTION_TESTSUITE.equals(p.getType() ) && pds.getName().equals(p.getName())){
+ return pds;
+ }
+ }
+ return null;
+ }
+}
View
9 ...p.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/PackageDescriptionLoader.java
@@ -48,7 +48,6 @@ public static PackageDescription load( final IFile file ) throws CoreException{
return result;
}
- // TODO lf also used in folding -> eliminate
public static PackageDescription load( final String content ) {
PackageDescription result = new PackageDescription();
if( content != null && content.trim().length() > 0 ) {
@@ -64,6 +63,14 @@ public static PackageDescription load( final String content ) {
return result;
}
+ public static PackageDescriptionStanza loadStanza( final String content ) {
+ PackageDescription pd=load( content );
+ if (pd!=null && pd.getStanzas().size()>1){
+ return pd.getStanzas().get(1);
+ }
+ return null;
+ }
+
public static List<String> parseList(final String value,final String seps){
List<String> ret=new LinkedList<String>();
View
48 ...p.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/PackageDescriptionStanza.java
@@ -83,13 +83,51 @@ public PackageDescription getPackageDescription(){
return this.pd;
}
+ /**
+ * clone and add the stanza to the given description
+ * @param desc
+ * @return
+ */
+ public PackageDescriptionStanza move(final PackageDescription desc){
+ int startLine=desc.getStanzas().get(desc.getStanzas().size()-1).getEndLine()+1;
+ int diff=startLine-getStartLine();
+ PackageDescriptionStanza npds= move(diff,this,desc);
+ desc.getStanzas().add( npds );
+ return npds;
+ }
+
+ private static PackageDescriptionStanza move(final int diff,final PackageDescriptionStanza me,final PackageDescription desc){
+ PackageDescriptionStanza pds=new PackageDescriptionStanza(desc,me.getType(),me.getName(),me.getStartLine()+diff);
+ pds.endLine=me.endLine+diff;
+ pds.indent=me.indent;
+ pds.realTypeName=me.realTypeName;
+ pds.needNL=me.needNL;
+ pds.properties.putAll( me.properties );
+ pds.realNames.putAll( me.realNames );
+
+ for (String entry : me.positions.keySet()) {
+ ValuePosition vp = me.positions.get( entry ).clone();
+ vp.diffLine( diff );
+ pds.positions.put( entry, vp);
+ }
+
+ for (PackageDescriptionStanza cpds:me.stanzas){
+ PackageDescriptionStanza ncpds=move(diff,cpds,desc);
+ pds.stanzas.add(ncpds);
+ }
+ return pds;
+ }
+
public void diffLine ( final int diff ) {
this.startLine += diff;
this.endLine += diff;
for (String entry : positions.keySet()) {
ValuePosition vp = positions.get( entry );
vp.diffLine( diff );
}
+ for (PackageDescriptionStanza pds:stanzas){
+ pds.diffLine( diff );
+ }
}
public void diffLineIf ( final int diff, final int linePos ) {
@@ -508,19 +546,27 @@ public void dump(final Writer w,final int indent) throws IOException {
try {
String line=br.readLine();
while (line!=null){
+ String line2=br.readLine();
if (!first){
for (int a=0;a<vp.getSubsequentIndent();a++){
w.write(" "); //$NON-NLS-1$
}
} else {
first=false;
+ // multiple lines: start on next line
+ if (line2!=null){
+ w.write(PlatformUtil.NL);
+ for (int a=0;a<vp.getSubsequentIndent();a++){
+ w.write(" "); //$NON-NLS-1$
+ }
+ }
}
if (line.trim().length()==0){
line= "."+line ; //$NON-NLS-1$
}
w.write(line);
w.write(PlatformUtil.NL);
- line=br.readLine();
+ line=line2;
}
} catch (IOException ignore){
View
150 ...sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/cabalmodel/ValuePosition.java
@@ -1,67 +1,83 @@
-package net.sf.eclipsefp.haskell.core.cabalmodel;
-
-
-public class ValuePosition {
- private int startLine=-1;
- private int endLine=-1;
- private int initialIndent=-1;
- private int subsequentIndent=-1;
-
-
- public ValuePosition() {
- super();
- }
-
- public ValuePosition( final int startLine, final int endLine, final int indent ) {
- super();
- this.startLine = startLine;
- this.endLine = endLine;
- this.initialIndent = indent;
- }
-
- public int getStartLine() {
- return startLine;
- }
-
- public int getEndLine() {
- return endLine;
- }
-
- public int getInitialIndent() {
- return initialIndent;
- }
-
-
- public void setStartLine( final int startLine ) {
- this.startLine = startLine;
- }
-
-
- public void setEndLine( final int endLine ) {
- this.endLine = endLine;
- }
-
-
- public void setInitialIndent( final int indent ) {
- this.initialIndent = indent;
- }
-
- public void diffLine ( final int diff ) {
- this.startLine += diff;
- this.endLine += diff;
- }
-
- public int getSubsequentIndent() {
- return subsequentIndent;
- }
-
-
- public void setSubsequentIndent( final int subsequentIndent ) {
- this.subsequentIndent = subsequentIndent;
- }
-
- @Override
- public String toString() {
- return getStartLine()+"->"+getEndLine()+"("+getInitialIndent()+","+getSubsequentIndent()+")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
- }
-}
+/**
+ * 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.core.cabalmodel;
+
+/**
+ * Position of a value in a cabal file
+ * @author JP Moresmau
+ *
+ */
+public class ValuePosition implements Cloneable{
+ private int startLine=-1;
+ private int endLine=-1;
+ private int initialIndent=-1;
+ private int subsequentIndent=-1;
+
+
+ public ValuePosition() {
+ super();
+ }
+
+ public ValuePosition( final int startLine, final int endLine, final int indent ) {
+ super();
+ this.startLine = startLine;
+ this.endLine = endLine;
+ this.initialIndent = indent;
+ }
+
+ @Override
+ protected ValuePosition clone() {
+ ValuePosition vp= new ValuePosition( startLine, endLine, initialIndent );
+ vp.subsequentIndent=subsequentIndent;
+ return vp;
+ }
+
+ public int getStartLine() {
+ return startLine;
+ }
+
+ public int getEndLine() {
+ return endLine;
+ }
+
+ public int getInitialIndent() {
+ return initialIndent;
+ }
+
+
+ public void setStartLine( final int startLine ) {
+ this.startLine = startLine;
+ }
+
+
+ public void setEndLine( final int endLine ) {
+ this.endLine = endLine;
+ }
+
+
+ public void setInitialIndent( final int indent ) {
+ this.initialIndent = indent;
+ }
+
+ public void diffLine ( final int diff ) {
+ this.startLine += diff;
+ this.endLine += diff;
+ }
+
+ public int getSubsequentIndent() {
+ return subsequentIndent;
+ }
+
+
+ public void setSubsequentIndent( final int subsequentIndent ) {
+ this.subsequentIndent = subsequentIndent;
+ }
+
+ @Override
+ public String toString() {
+ return getStartLine()+"->"+getEndLine()+"("+getInitialIndent()+","+getSubsequentIndent()+")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+ }
+}
View
16 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/code/ModuleCreationInfo.java
@@ -3,6 +3,7 @@
import java.util.Set;
import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
+import net.sf.eclipsefp.haskell.core.preferences.ICorePreferenceNames;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -31,6 +32,11 @@
*/
private boolean foldersQualify=true;
+ /**
+ * the name of the preference defining the module template
+ */
+ private String templatePreferenceName=ICorePreferenceNames.TEMPLATE_MODULE;
+
private IProject project;
// attribute setters and getters
@@ -153,4 +159,14 @@ public void setProject( final IProject project ) {
}
+ public String getTemplatePreferenceName() {
+ return templatePreferenceName;
+ }
+
+
+ public void setTemplatePreferenceName( final String templatePreferenceName ) {
+ this.templatePreferenceName = templatePreferenceName;
+ }
+
+
}
View
13 ...sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/code/SourceFileGenerator.java
@@ -100,16 +100,21 @@ private IFile createFile( final ModuleCreationInfo info,
final String[] segments = getPathSegments( info );
final String moduleName = info.getModuleName();
final EHaskellCommentStyle style = info.getCommentStyle();
- String pName=info.getProject()!=null?info.getProject().getName():"";
+ String pName=info.getProject()!=null?info.getProject().getName():""; //$NON-NLS-1$
+ String pref=info.getTemplatePreferenceName();
String fileContent = fCodeGenerator.createModuleContent( pName,segments,
moduleName,
- style );
+ style,pref );
String fileName = createFileName( style, moduleName );
IFile result = destFolder.getFile( new Path( fileName ) );
try {
InputStream isContent = new ByteArrayInputStream( fileContent.getBytes(destFolder.getDefaultCharset( true )) );
SubProgressMonitor subMon = monitor==null?null:new SubProgressMonitor( monitor, 4 );
- result.create( isContent, true, subMon );
+ if (!result.exists()){
+ result.create( isContent, true, subMon );
+ } else {
+ result.setContents( isContent,true,true,subMon);
+ }
return result;
} catch (UnsupportedEncodingException uee){
throw new CoreException( new Status(IStatus.ERROR,HaskellCorePlugin.getPluginId(),uee.getLocalizedMessage(),uee) );
@@ -121,7 +126,7 @@ private IFile createFile( final ModuleCreationInfo info,
return ( path == null || !info.isFoldersQualify() ) ? new String[ 0 ] : path.segments();
}
- private static String createFileName(final EHaskellCommentStyle style, final String moduleName ) {
+ protected String createFileName(final EHaskellCommentStyle style, final String moduleName ) {
return moduleName + "." + style.getFileExtension(); //$NON-NLS-1$
}
}
View
29 ...eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/code/CodeGenerator.java
@@ -19,11 +19,24 @@
public class CodeGenerator {
public String createModuleContent( final String projectName,
+ final String[] folderNames,
+ final String name,
+ final EHaskellCommentStyle style ) {
+ return createModuleContent( projectName, folderNames, name, style, ICorePreferenceNames.TEMPLATE_MODULE );
+ }
+
+ protected void addVariables(final Map<String,String> vars){
+ // NOOP
+ }
+
+ public String createModuleContent( final String projectName,
final String[] folderNames,
final String name,
- final EHaskellCommentStyle style ) {
+ final EHaskellCommentStyle style,
+ String pref) {
StringBuilder sb = new StringBuilder();
- sb.append( PlatformUtil.NL );
+ // why start with a new line?
+ //sb.append( PlatformUtil.NL );
sb.append(getPrefixFor( style ));
StringBuilder module=new StringBuilder();
StringBuilder src=new StringBuilder();
@@ -41,9 +54,19 @@ public String createModuleContent( final String projectName,
vars.put( TemplateVariables.PROJECT_NAME, projectName );
vars.put( TemplateVariables.SRC, src.toString() );
vars.put( TemplateVariables.USER_NAME, PlatformUtil.getCurrentUser() );
+ addVariables(vars);
+ if (pref==null){
+ pref=ICorePreferenceNames.TEMPLATE_MODULE;
+ }
+ if(!pref.equals( ICorePreferenceNames.TEMPLATE_MODULE )){
+ String mod1=HaskellCorePlugin.populateTemplate( ICorePreferenceNames.TEMPLATE_MODULE, vars );
+ vars.put( TemplateVariables.MODULE, mod1 );
+ addVariables(vars);
+ }
- String mod=HaskellCorePlugin.populateTemplate( ICorePreferenceNames.TEMPLATE_MODULE, vars );
+ String mod=HaskellCorePlugin.populateTemplate( pref, vars );
sb.append(mod);
+
// sb.append( "module " ); //$NON-NLS-1$
// for( int i = 0; i < folderNames.length; i++ ) {
// sb.append( folderNames[ i ] );
View
1 ....haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/ProjectModelFilesOp.java
@@ -89,6 +89,7 @@ protected String getMainFileContent(final Map<String,String> vars ) {
String mod=HaskellCorePlugin.populateTemplate( ICorePreferenceNames.TEMPLATE_MODULE, vars );
/** get content **/
vars.put( TemplateVariables.MODULE, mod );
+ vars.put( TemplateVariables.IMPORTS, "" );
return HaskellCorePlugin.populateTemplate( ICorePreferenceNames.TEMPLATE_MAIN, vars );
//return "module Main where"+PlatformUtil.NL+PlatformUtil.NL+"main::IO()"+PlatformUtil.NL+"main = undefined"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
View
62 ...haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/CorePreferenceInitializer.java
@@ -55,21 +55,58 @@ public void initializeDefaultPreferences() {
coreNode.put( TEMPLATE_CABAL_EXE,
CabalSyntax.SECTION_EXECUTABLE.getCabalName()+" ${"+TemplateVariables.PROJECT_NAME+"}"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
" "+CabalSyntax.FIELD_HS_SOURCE_DIRS+": ${"+TemplateVariables.SRC+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- " "+CabalSyntax.FIELD_MAIN_IS+": Main.hs"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
- " "+CabalSyntax.FIELD_BUILD_DEPENDS+": base >= 4"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
- " "+CabalSyntax.FIELD_GHC_OPTIONS+": -Wall"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_MAIN_IS+": Main.hs"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_BUILD_DEPENDS+": base >= 4"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_GHC_OPTIONS+": -Wall"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
""); //$NON-NLS-1$
coreNode.put( TEMPLATE_CABAL_SETUP,
"import Distribution.Simple"+PlatformUtil.NL+"main = defaultMain"+PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
);
+ coreNode.put( TEMPLATE_CABAL_HTF,
+ CabalSyntax.SECTION_TESTSUITE+ " ${"+TemplateVariables.SECTION_NAME+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_TYPE+": "+CabalSyntax.VALUE_EXITCODE_STDIO_1_0+ PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ //" "+CabalSyntax.FIELD_HS_SOURCE_DIRS+": ${"+TemplateVariables.SRC+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ " "+CabalSyntax.FIELD_MAIN_IS+": Main.hs"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_GHC_OPTIONS+": -Wall -rtsopts" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_BUILD_DEPENDS+": base >= 4, HTF > 0.9"+PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
+ );
+
+ coreNode.put( TEMPLATE_CABAL_TF,
+ CabalSyntax.SECTION_TESTSUITE+ " ${"+TemplateVariables.SECTION_NAME+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_TYPE+": "+CabalSyntax.VALUE_EXITCODE_STDIO_1_0 + PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ //" "+CabalSyntax.FIELD_HS_SOURCE_DIRS+": ${"+TemplateVariables.SRC+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ " "+CabalSyntax.FIELD_X_USES_TEST_FRAMEWORK+": true" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_GHC_OPTIONS+": -Wall -rtsopts" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_BUILD_DEPENDS+": base >= 4, HUnit >= 1.2 && < 2, QuickCheck >= 2.4, test-framework >= 0.4.1, test-framework-quickcheck2, test-framework-hunit"+PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
+ );
+
+ coreNode.put( TEMPLATE_CABAL_STDIO,
+ CabalSyntax.SECTION_TESTSUITE+ " ${"+TemplateVariables.SECTION_NAME+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_TYPE+": "+CabalSyntax.VALUE_EXITCODE_STDIO_1_0 + PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ // " "+CabalSyntax.FIELD_HS_SOURCE_DIRS+": ${"+TemplateVariables.SRC+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ " "+CabalSyntax.FIELD_GHC_OPTIONS+": -Wall -rtsopts" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_BUILD_DEPENDS+": base >= 4"+PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
+ );
+
+ coreNode.put( TEMPLATE_CABAL_DETAILED,
+ CabalSyntax.SECTION_TESTSUITE+ " ${"+TemplateVariables.SECTION_NAME+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_TYPE+": "+CabalSyntax.VALUE_DETAILED_0_9 + PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ // " "+CabalSyntax.FIELD_HS_SOURCE_DIRS+": ${"+TemplateVariables.SRC+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ " "+CabalSyntax.FIELD_GHC_OPTIONS+": -Wall -rtsopts" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ " "+CabalSyntax.FIELD_BUILD_DEPENDS+": base >= 4"+PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
+ );
+
+
coreNode.put( TEMPLATE_MODULE,
- "module ${"+TemplateVariables.MODULE_NAME+"} where"+PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
+ "module ${"+TemplateVariables.MODULE_NAME+"} where"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ "${"+TemplateVariables.IMPORTS+"}" +PlatformUtil.NL //$NON-NLS-1$ //$NON-NLS-2$
);
coreNode.put( TEMPLATE_MAIN,
"${"+TemplateVariables.MODULE+"}"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ "${"+TemplateVariables.IMPORTS+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
"main::IO()"+PlatformUtil.NL+ //$NON-NLS-1$
"main = undefined" //$NON-NLS-1$
);
@@ -90,5 +127,22 @@ public void initializeDefaultPreferences() {
" widgetShowAll window"+PlatformUtil.NL+ //$NON-NLS-1$
" mainGUI"+PlatformUtil.NL //$NON-NLS-1$
);
+
+ coreNode.put( TEMPLATE_MODULE_HTF,
+ "{-# OPTIONS_GHC -F -pgmF htfpp #-}"+PlatformUtil.NL+ //$NON-NLS-1$
+ "${"+TemplateVariables.MODULE+"}"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ "import Test.Framework" +PlatformUtil.NL //$NON-NLS-1$
+ );
+
+ coreNode.put( TEMPLATE_MAIN_HTF,
+ "${"+TemplateVariables.MODULE_HTF+"}"+PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ "${"+TemplateVariables.IMPORTS_HTF+"}" +PlatformUtil.NL+ //$NON-NLS-1$ //$NON-NLS-2$
+ "main :: IO()"+PlatformUtil.NL+ //$NON-NLS-1$
+ "main = htfMain htf_importedTests"+PlatformUtil.NL //$NON-NLS-1$
+ );
+
+ coreNode.put( TEMPLATE_IMPORT_HTF,
+ "import {-@ HTF_TESTS @-} ${"+TemplateVariables.MODULE_NAME+"}" +PlatformUtil.NL //$NON-NLS-1$" //$NON-NLS-2$"
+ );
}
}
View
7 ...sefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/ICorePreferenceNames.java
@@ -40,4 +40,11 @@
String TEMPLATE_MAIN="TEMPLATE_MAIN"; //$NON-NLS-1$
String TEMPLATE_GTK="TEMPLATE_GTK"; //$NON-NLS-1$
+ String TEMPLATE_MAIN_HTF="TEMPLATE_MAIN_HTF"; //$NON-NLS-1$
+ String TEMPLATE_MODULE_HTF="TEMPLATE_MODULE_HTF"; //$NON-NLS-1$
+ String TEMPLATE_IMPORT_HTF="TEMPLATE_IMPORT_HTF"; //$NON-NLS-1$
+ String TEMPLATE_CABAL_HTF="TEMPLATE_CABAL_HTF"; //$NON-NLS-1$
+ String TEMPLATE_CABAL_STDIO="TEMPLATE_CABAL_STDIO"; //$NON-NLS-1$
+ String TEMPLATE_CABAL_DETAILED="TEMPLATE_CABAL_DETAILED"; //$NON-NLS-1$
+ String TEMPLATE_CABAL_TF="TEMPLATE_CABAL_TF"; //$NON-NLS-1$
}
View
4 ...lipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/TemplateVariables.java
@@ -20,4 +20,8 @@
public static final String EXECUTABLE="executable"; //$NON-NLS-1$
public static final String MODULE="module"; //$NON-NLS-1$
public static final String MODULE_NAME="module_name"; //$NON-NLS-1$
+ public static final String MODULE_HTF="module_htf"; //$NON-NLS-1$
+ public static final String IMPORTS_HTF="imports_htf"; //$NON-NLS-1$
+ public static final String IMPORTS="imports"; //$NON-NLS-1$
+ public static final String SECTION_NAME="section_name"; //$NON-NLS-1$
}
View
101 ...sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/FolderSelectionDialog.java
@@ -1,24 +1,113 @@
// Copyright (c) 2003-2005 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.ui.dialog;
+import java.util.HashSet;
+import java.util.Set;
+import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
+import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
/** <p>a dialog that allows the user to select from all folders in
* a Haskell project, starting from a given source folder.</p>
- *
+ *
* @author Leif Frenzel
*/
public class FolderSelectionDialog extends ElementTreeSelectionDialog {
- public FolderSelectionDialog( final Shell shell,
- final IContainer rootContainer ) {
+ public FolderSelectionDialog( final Shell shell,
+ final IContainer rootContainer ) {
+ this(shell,rootContainer,false);
+ }
+
+ private boolean addAllowed=false;
+
+ public FolderSelectionDialog( final Shell shell,
+ final IContainer rootContainer ,final boolean addAllowed) {
super( shell, new DialogLabelProvider(), new FolderCP() );
setInput( rootContainer );
- setTitle( "Folder Selection" );
- setMessage( "Choose a folder:" );
- setEmptyListMessage( "No folder to select." );
+ setTitle( UITexts.folder_title );
+ setMessage( UITexts.folder_message );
+ setEmptyListMessage( UITexts.folder_empty );
+ this.addAllowed=addAllowed;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.dialogs.ElementTreeSelectionDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected Control createDialogArea( final Composite parent ) {
+ Composite composite=(Composite) super.createDialogArea( parent );
+
+ if (addAllowed){
+ final Button bAdd=new Button(composite,SWT.PUSH);
+ bAdd.setText( UITexts.folder_add );
+ bAdd.addSelectionListener( new SelectionAdapter() {
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected( final SelectionEvent e ) {
+ IStructuredSelection sel=(IStructuredSelection)getTreeViewer().getSelection();
+ Object o=sel.getFirstElement();
+ if (!(o instanceof IContainer)){
+ o=getTreeViewer().getInput();
+ }
+ if (o instanceof IContainer){
+ final IContainer f=(IContainer)o;
+ final Set<String> names=new HashSet<String>();
+ try {
+ for (IResource r:f.members()){
+ names.add( r.getName() );
+ }
+
+ InputDialog id=new InputDialog( getShell(), UITexts.folder_add_title, UITexts.folder_add_title, "", new IInputValidator() {
+
+ @Override
+ public String isValid( final String arg0 ) {
+ String s=arg0.trim();
+ if (s.length()==0){
+ return UITexts.folder_add_empty;
+ } else if (names.contains( s )){
+ return UITexts.folder_add_duplicate;
+ }
+ return null;
+ }
+ } );
+ if (Window.OK==id.open()){
+ String s=id.getValue().trim();
+ IFolder f2=f.getFolder(new Path(s ));
+ f2.create( false, true,new NullProgressMonitor() );
+ getTreeViewer().refresh( f );
+ getTreeViewer().setSelection( new StructuredSelection( f2 ) );
+ }
+ }catch (CoreException ce){
+ HaskellUIPlugin.log( ce );
+ }
+ }
+ }
+ } );
+
+ }
+
+ return composite;
}
}
View
11 ...ipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/SourceFolderSelectionDialog.java
@@ -1,23 +1,28 @@
// Copyright (c) 2003-2005 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.ui.dialog;
+import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
/** <p>a dialog that allows the user to select from all source folders in
* all Haskell projects.</p>
- *
+ *
* @author Leif Frenzel
*/
public class SourceFolderSelectionDialog extends ElementTreeSelectionDialog {
public SourceFolderSelectionDialog( final Shell shell ) {
+// this( shell, ResourcesPlugin.getWorkspace().getRoot(),false);
super( shell, new DialogLabelProvider(), new SourceFolderCP() );
setValidator( new SourceFolderValidator() );
setInput( ResourcesPlugin.getWorkspace().getRoot() );
- setTitle( "Source folder selection" );
- setMessage( "Choose a folder:" );
+ setTitle( UITexts.source_folder_title );
+ setMessage(UITexts.source_folder_msg);
}
+
+
+
}
View
440 ...ell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/CabalFormSection.java
@@ -1,220 +1,220 @@
-// Copyright (c) 2008 by Leif Frenzel - see http://leiffrenzel.de
-// 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
-// Copyright (c) 2011 by Alejandro Serrano
-package net.sf.eclipsefp.haskell.ui.internal.editors.cabal.forms;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import net.sf.eclipsefp.haskell.core.cabalmodel.CabalSyntax;
-import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
-import net.sf.eclipsefp.haskell.core.cabalmodel.RealValuePosition;
-import net.sf.eclipsefp.haskell.ui.internal.editors.cabal.CabalFormEditor;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jface.action.IStatusLineManager;
-import org.eclipse.jface.text.DocumentEvent;
-import org.eclipse.jface.text.IDocumentListener;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.ui.forms.SectionPart;
-import org.eclipse.ui.forms.editor.IFormPage;
-import org.eclipse.ui.forms.widgets.ExpandableComposite;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.Section;
-
-/**
- * <p>
- * form section super class - encapsulates some common functionality.
- * </p>
- *
- * @author Leif Frenzel, serras
- */
-public abstract class CabalFormSection extends SectionPart {
-
- protected final CabalFormEditor editor;
- protected PackageDescriptionStanza stanza = null;
- protected final ArrayList<FormEntry> entries;
- private final IProject project;
-
- protected CabalFormSection( final IFormPage page, final Composite parent,
- final CabalFormEditor editor, final String text, final IProject project ) {
- super( parent, page.getManagedForm().getToolkit(), Section.DESCRIPTION
- | ExpandableComposite.TITLE_BAR );
- this.editor = editor;
- entries = new ArrayList<FormEntry>();
- this.project = project;
- initialize( page.getManagedForm() );
- getSection().clientVerticalSpacing = 6;
- getSection().setData( "part", this );
-
- getSection().setText( text );
- createClient( page.getManagedForm().getToolkit() );
- fillInValues( true );
- editor.getModel().addDocumentListener( new IDocumentListener() {
-
- @Override
- public void documentAboutToBeChanged( final DocumentEvent event ) {
- // unused
- }
-
- @Override
- public void documentChanged( final DocumentEvent event ) {
- fillInValues( false );
- }
- } );
- }
-
- protected abstract void createClient( FormToolkit toolkit );
-
- protected IProject getProject() {
- return project;
- }
-
- public PackageDescriptionStanza getStanza() {
- return stanza;
- }
-
- public void setStanza( final PackageDescriptionStanza stanza, final boolean first ) {
- this.stanza = stanza;
- fillInValues( first );
- this.setAllEditable( stanza != null );
- }
-
- IStatusLineManager getStatusLineManager() {
- return editor.getEditorSite().getActionBars().getStatusLineManager();
- }
-
- protected FormEntry createCustomFormEntry(final FormEntry customEntry, final CabalSyntax property,
- final FormToolkit toolkit, final Composite container, final String label, final boolean showLabelAbove, final int style) {
- FormEntryDecorator decorator = new FormEntryDecorator( label, showLabelAbove, customEntry );
- decorator.init( project, container, toolkit, style );
- decorator.setProperty( property );
- decorator.addFormEntryListener( createFormEntryListener() );
- entries.add( decorator );
- return decorator;
- }
-
- protected FormEntry createCustomFormEntry(final FormEntry customEntry, final CabalSyntax property,
- final FormToolkit toolkit, final Composite container, final String label, final int style) {
- return createCustomFormEntry( customEntry, property, toolkit, container, label, false, style );
- }
-
- protected FormEntry createFormEntry( final CabalSyntax property,
- final FormToolkit toolkit, final Composite container, final String label ) {
- return createCustomFormEntry( new FormEntryText(), property, toolkit, container, label, SWT.NONE );
- }
-
- protected FormEntry createMultiLineFormEntry( final CabalSyntax property,
- final FormToolkit toolkit, final Composite container, final String label ) {
- return createCustomFormEntry( new FormEntryText(), property, toolkit, container, label, SWT.MULTI );
- }
-
- protected <T> FormEntry createComboFormEntry( final CabalSyntax property,
- final Choice<T> choices, final FormToolkit toolkit,
- final Composite container, final String label ) {
- return createCustomFormEntry( new FormEntryCombo<T>( choices ), property, toolkit, container, label, SWT.NONE );
- }
-
- protected FormEntry createFileFormEntry (final CabalSyntax property, final FormToolkit toolkit, final Composite container) {
- FormEntryFile entry = new FormEntryFile(FormEntryFile.FILES);
- setCustomFormEntry( entry, property, toolkit, container );
- return entry;
- }
-
- protected FormEntry createDirFormEntry (final CabalSyntax property, final FormToolkit toolkit, final Composite container) {
- FormEntryFile entry = new FormEntryFile(FormEntryFile.DIRECTORIES);
- setCustomFormEntry( entry, property, toolkit, container );
- return entry;
- }
-
- protected FormEntry createSourceDirEntry (final FormToolkit toolkit, final Composite container) {
- FormEntryFile entry = new FormEntryFile(FormEntryFile.DIRECTORIES){
- @Override
- public void setValue( final String value, final boolean blockNotification ) {
- ignoreModify=true;
- Set<String> s=getStanza()!=null?new HashSet<String>(getStanza().getSourceDirs()):Collections.<String>emptySet();
-
- setValues(s);
- ignoreModify = false;
- }
- };
- setCustomFormEntry( entry, CabalSyntax.FIELD_HS_SOURCE_DIRS, toolkit, container );
- return entry;
- }
-
- protected FormEntry createCheckBoxEntry (final CabalSyntax property, final String title, final FormToolkit toolkit, final Composite container) {
- FormEntryCheckBox entry = new FormEntryCheckBox( title );
- setCustomFormEntry( entry, property, toolkit, container );
- return entry;
- }
-
- protected void setCustomFormEntry (final FormEntry entry, final CabalSyntax property, final FormToolkit toolkit, final Composite container) {
- entry.init( project, container, toolkit, SWT.NONE );
- entry.setProperty( property );
- entry.addFormEntryListener( createFormEntryListener() );
- entries.add( entry );
- }
-
- // helping functions
- // //////////////////
-
- protected void fillInValues( final boolean first ) {
- // try {
- setAllEditable( true );
- getStatusLineManager().setErrorMessage( null );
- for( FormEntry entry: entries ) {
- fillValue( entry, entry.getProperty(), first );
- }
- /*
- * } catch( final InvalidCabalFileException icfex ) { setAllEditable( false
- * ); getStatusLineManager().setErrorMessage( icfex.getMessage() ); } catch(
- * final CoreException cex ) { HaskellUIPlugin.log( cex ); }
- */
- }
-
- protected void fillValue( final FormEntry entry, final CabalSyntax acc,
- final boolean first ) {
- if( stanza != null ) {
- String value = stanza.getProperties().get( acc );
- entry.setValue( value, first );
- } else {
- entry.setValue( "", first ); //$NON-NLS-1$
- }
- }
-
- public void setAllEditable( final boolean editable ) {
- for( FormEntry entry: entries ) {
- entry.setEditable( editable );
- }
- }
-
- protected void setNewValue( final FormEntry text, final CabalSyntax mutator ) {
- setNewValue( text.getValue(), mutator );
- }
-
- protected void setNewValue( final String newValue, final CabalSyntax mutator ) {
- if (this.stanza != null) {
- String oldValue = stanza.getProperties().get( mutator.getCabalName() );
- oldValue = oldValue == null ? "" : oldValue;
-
- if (!newValue.equals( oldValue )) {
- //stanza.getProperties().put( mutator.getCabalName(), newValue );
- RealValuePosition vp = stanza.update( mutator, newValue );
- vp.updateDocument( editor.getModel() );
- }
- }
- }
-
- private IFormEntryListener createFormEntryListener() {
- return new FormEntryAdapter() {
-
- @Override
- public void textValueChanged( final FormEntry formEntry ) {
- setNewValue( formEntry, formEntry.getProperty() );
- }
- };
- }
-
-}
+// Copyright (c) 2008 by Leif Frenzel - see http://leiffrenzel.de
+// 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
+// Copyright (c) 2011 by Alejandro Serrano
+package net.sf.eclipsefp.haskell.ui.internal.editors.cabal.forms;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import net.sf.eclipsefp.haskell.core.cabalmodel.CabalSyntax;
+import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
+import net.sf.eclipsefp.haskell.core.cabalmodel.RealValuePosition;
+import net.sf.eclipsefp.haskell.ui.internal.editors.cabal.CabalFormEditor;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.SectionPart;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Section;
+
+/**
+ * <p>
+ * form section super class - encapsulates some common functionality.
+ * </p>
+ *
+ * @author Leif Frenzel, serras
+ */
+public abstract class CabalFormSection extends SectionPart {
+
+ protected final CabalFormEditor editor;
+ protected PackageDescriptionStanza stanza = null;
+ protected final ArrayList<FormEntry> entries;
+ private final IProject project;
+
+ protected CabalFormSection( final IFormPage page, final Composite parent,
+ final CabalFormEditor editor, final String text, final IProject project ) {
+ super( parent, page.getManagedForm().getToolkit(), Section.DESCRIPTION
+ | ExpandableComposite.TITLE_BAR );
+ this.editor = editor;
+ entries = new ArrayList<FormEntry>();
+ this.project = project;
+ initialize( page.getManagedForm() );
+ getSection().clientVerticalSpacing = 6;
+ getSection().setData( "part", this );
+
+ getSection().setText( text );
+ createClient( page.getManagedForm().getToolkit() );
+ fillInValues( true );
+ editor.getModel().addDocumentListener( new IDocumentListener() {
+
+ @Override
+ public void documentAboutToBeChanged( final DocumentEvent event ) {
+ // unused
+ }
+
+ @Override
+ public void documentChanged( final DocumentEvent event ) {
+ fillInValues( true ); // document's been changed, we don't want to trigger a change when we're just reacting to it
+ }
+ } );
+ }
+
+ protected abstract void createClient( FormToolkit toolkit );
+
+ public IProject getProject() {
+ return project;
+ }
+
+ public PackageDescriptionStanza getStanza() {
+ return stanza;
+ }
+
+ public void setStanza( final PackageDescriptionStanza stanza, final boolean first ) {
+ this.stanza = stanza;
+ fillInValues( first );
+ this.setAllEditable( stanza != null );
+ }
+
+ IStatusLineManager getStatusLineManager() {
+ return editor.getEditorSite().getActionBars().getStatusLineManager();
+ }
+
+ protected FormEntry createCustomFormEntry(final FormEntry customEntry, final CabalSyntax property,
+ final FormToolkit toolkit, final Composite container, final String label, final boolean showLabelAbove, final int style) {
+ FormEntryDecorator decorator = new FormEntryDecorator( label, showLabelAbove, customEntry );
+ decorator.init( project, container, toolkit, style );
+ decorator.setProperty( property );
+ decorator.addFormEntryListener( createFormEntryListener() );
+ entries.add( decorator );
+ return decorator;
+ }
+
+ protected FormEntry createCustomFormEntry(final FormEntry customEntry, final CabalSyntax property,
+ final FormToolkit toolkit, final Composite container, final String label, final int style) {
+ return createCustomFormEntry( customEntry, property, toolkit, container, label, false, style );
+ }
+
+ protected FormEntry createFormEntry( final CabalSyntax property,
+ final FormToolkit toolkit, final Composite container, final String label ) {
+ return createCustomFormEntry( new FormEntryText(), property, toolkit, container, label, SWT.NONE );
+ }
+
+ protected FormEntry createMultiLineFormEntry( final CabalSyntax property,
+ final FormToolkit toolkit, final Composite container, final String label ) {
+ return createCustomFormEntry( new FormEntryText(), property, toolkit, container, label, SWT.MULTI );
+ }
+
+ protected <T> FormEntry createComboFormEntry( final CabalSyntax property,
+ final Choice<T> choices, final FormToolkit toolkit,
+ final Composite container, final String label ) {
+ return createCustomFormEntry( new FormEntryCombo<T>( choices ), property, toolkit, container, label, SWT.NONE );
+ }
+
+ protected FormEntry createFileFormEntry (final CabalSyntax property, final FormToolkit toolkit, final Composite container) {
+ FormEntryFile entry = new FormEntryFile(FormEntryFile.FILES);
+ setCustomFormEntry( entry, property, toolkit, container );
+ return entry;
+ }
+
+ protected FormEntry createDirFormEntry (final CabalSyntax property, final FormToolkit toolkit, final Composite container) {
+ FormEntryFile entry = new FormEntryFile(FormEntryFile.DIRECTORIES);
+ setCustomFormEntry( entry, property, toolkit, container );
+ return entry;
+ }
+
+ protected FormEntry createSourceDirEntry (final FormToolkit toolkit, final Composite container) {
+ FormEntryFile entry = new FormEntryFile(FormEntryFile.DIRECTORIES){
+ @Override
+ public void setValue( final String value, final boolean blockNotification ) {
+ ignoreModify=true;
+ Set<String> s=getStanza()!=null?new HashSet<String>(getStanza().getSourceDirs()):Collections.<String>emptySet();
+
+ setValues(s);
+ ignoreModify = false;
+ }
+ };
+ setCustomFormEntry( entry, CabalSyntax.FIELD_HS_SOURCE_DIRS, toolkit, container );
+ return entry;
+ }
+
+ protected FormEntry createCheckBoxEntry (final CabalSyntax property, final String title, final FormToolkit toolkit, final Composite container) {
+ FormEntryCheckBox entry = new FormEntryCheckBox( title );
+ setCustomFormEntry( entry, property, toolkit, container );
+ return entry;
+ }
+
+ protected void setCustomFormEntry (final FormEntry entry, final CabalSyntax property, final FormToolkit toolkit, final Composite container) {
+ entry.init( project, container, toolkit, SWT.NONE );
+ entry.setProperty( property );
+ entry.addFormEntryListener( createFormEntryListener() );
+ entries.add( entry );
+ }
+
+ // helping functions
+ // //////////////////
+
+ protected void fillInValues( final boolean first ) {
+ // try {
+ setAllEditable( true );
+ getStatusLineManager().setErrorMessage( null );
+ for( FormEntry entry: entries ) {
+ fillValue( entry, entry.getProperty(), first );
+ }
+ /*
+ * } catch( final InvalidCabalFileException icfex ) { setAllEditable( false
+ * ); getStatusLineManager().setErrorMessage( icfex.getMessage() ); } catch(
+ * final CoreException cex ) { HaskellUIPlugin.log( cex ); }
+ */
+ }
+
+ protected void fillValue( final FormEntry entry, final CabalSyntax acc,
+ final boolean first ) {
+ if( stanza != null ) {
+ String value = stanza.getProperties().get( acc );
+ entry.setValue( value, first );
+ } else {
+ entry.setValue( "", first ); //$NON-NLS-1$
+ }
+ }
+
+ public void setAllEditable( final boolean editable ) {
+ for( FormEntry entry: entries ) {
+ entry.setEditable( editable );
+ }
+ }
+
+ protected void setNewValue( final FormEntry text, final CabalSyntax mutator ) {
+ setNewValue( text.getValue(), mutator );
+ }
+
+ protected void setNewValue( final String newValue, final CabalSyntax mutator ) {
+ if (this.stanza != null) {
+ String oldValue = stanza.getProperties().get( mutator.getCabalName() );
+ oldValue = oldValue == null ? "" : oldValue;
+
+ if (!newValue.equals( oldValue )) {
+ //stanza.getProperties().put( mutator.getCabalName(), newValue );
+ RealValuePosition vp = stanza.update( mutator, newValue );
+ vp.updateDocument( editor.getModel() );
+ }
+ }
+ }
+
+ private IFormEntryListener createFormEntryListener() {
+ return new FormEntryAdapter() {
+
+ @Override
+ public void textValueChanged( final FormEntry formEntry ) {
+ setNewValue( formEntry, formEntry.getProperty() );
+ }
+ };
+ }
+
+}
View
848 ...rc/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/stanzas/FormEntryModules.java
@@ -1,423 +1,425 @@
-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.HashMap;
-import java.util.List;
-import java.util.Vector;
-import net.sf.eclipsefp.haskell.core.cabalmodel.CabalSyntax;
-import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
-import net.sf.eclipsefp.haskell.ui.internal.editors.cabal.forms.FormEntry;
-import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
-import net.sf.eclipsefp.haskell.util.PlatformUtil;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceVisitor;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.TableEditor;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-/**
- * Form entry for selecting modules from a project.
- * @author Alejandro Serrano
- *
- */
-public class FormEntryModules extends FormEntry {
-
- static final int EXPOSED_COL = 0;
- static final int OTHER_COL = 1;
- static final int NAME_COL = 2;
-
- private final ArrayList<IOtherValueEntryListener> otherListeners = new ArrayList<IOtherValueEntryListener>();
-
- ArrayList<String> prevElements;
- boolean onlyOne;
- String exposedString;
- FormToolkit toolkit;
- Table table;
- ArrayList<String> exposed;
- ArrayList<String> other;
- boolean ignoreModify = false;
- HashMap<String, Button> exposedBoxes;
- HashMap<String, Button> otherBoxes;
-
- public FormEntryModules( final String exposedString ) {
- this( exposedString, false );
- }
-
- public FormEntryModules( final String exposedString, final boolean onlyOne ) {
- super();
- this.exposedString = exposedString;
- this.onlyOne = onlyOne;
- this.exposed = new ArrayList<String>();
- this.other = new ArrayList<String>();
- this.exposedBoxes = new HashMap<String, Button>();
- this.otherBoxes = new HashMap<String, Button>();
- this.prevElements = new ArrayList<String>();
- }
-
-
- @Override
- public void init( final IProject project, final Composite parent,
- final FormToolkit toolkit, final int style ) {
- this.toolkit = toolkit;
-
- table = toolkit.createTable( parent, SWT.SINGLE );
- table.setHeaderVisible( true );
-
- TableColumn exposedCol = new TableColumn( table, SWT.NULL );
- exposedCol.setText( exposedString );
- exposedCol.pack();
- TableColumn otherCol = new TableColumn( table, SWT.NULL );
- otherCol.setText( UITexts.cabalEditor_other_modules );
- otherCol.pack();
- TableColumn nameCol = new TableColumn( table, SWT.NULL );
- nameCol.setText( UITexts.cabalEditor_module );
- nameCol.pack();
- }
-
- public void changeExposedColumnName( final String newName ) {
- TableColumn exposedCol = table.getColumn( EXPOSED_COL );
- exposedCol.setText( newName );
- }
-
- @Override
- public Control getControl() {
- return table;
- }
-
- @Override
- public int heightHint() {
- return 170;
- }
-
- @SuppressWarnings ( "unchecked" )
- public synchronized void setSourceFolders( final FormEntryModulesRoot root,
- final boolean blockNotification ) {
- synchronized( this ) {
- if( root == null ) {
- // If we have no data
- table.clearAll();
- for( Button b: exposedBoxes.values() ) {
- b.dispose();
- }
- exposedBoxes.clear();
- for( Button b: otherBoxes.values() ) {
- b.dispose();
- }
- otherBoxes.clear();
- prevElements.clear();
- return;
- }
-
- Collection<String> sourceDirs = null;
- if( root.getStanza().getProperties()
- .containsKey( CabalSyntax.FIELD_HS_SOURCE_DIRS.getCabalName() ) ) {
- //sourceDirs = root.getStanza().getProperties()
- // .get( CabalSyntax.FIELD_HS_SOURCE_DIRS.getCabalName() );
- sourceDirs=root.getStanza().getSourceDirs();
- } else {
- sourceDirs = Collections.emptyList();
- }
-
- ArrayList<String> modules = new ArrayList<String>();
- ModulesVisitor visitor = new ModulesVisitor( modules, sourceDirs );
- try {
- root.getProject().accept( visitor );
- } catch( CoreException e ) {
- modules.clear();
- }
-
- PackageDescriptionStanza pkg = root.getDescription().getPackageStanza();
- if( pkg != null ) {
- if( pkg.getProperties().containsKey( CabalSyntax.FIELD_DATA_FILES.getCabalName() ) ) {
- // There are data files, so Paths_package is also provided
- modules.add( "Paths_"
- + pkg.getProperties().get( CabalSyntax.FIELD_NAME.getCabalName() ) );
- }
- }
-
- // Show the items in alphabetical order
- Collections.sort( modules );
-
- // Check if it is the same
- if( !getValueFrom( modules ).equals( getValueFrom( prevElements ) ) ) {
- prevElements = modules;
- // Set the new values for exposed and others
- boolean changeToExposed = false;
- boolean changeToOther = false;
- for( String s: ( ArrayList<String> )exposed.clone() ) {
- if( !modules.contains( s ) ) {
- changeToExposed = true;
- exposed.remove( s );
- }
- }
- for( String s: ( ArrayList<String> )other.clone() ) {
- if( !modules.contains( s ) ) {
- changeToOther = true;
- other.remove( s );
- }
- }
-
- // Add the items to table
- table.removeAll();
-
- for( Button b: exposedBoxes.values() ) {
- b.dispose();
- }
- exposedBoxes.clear();
- for( Button b: otherBoxes.values() ) {
- b.dispose();
- }
- otherBoxes.clear();
-
- for( String mod: modules ) {
- final TableItem item = new TableItem( table, SWT.NULL );
- item.setText( new String[] { "", "", mod } );
- // Add "exposed" check box
- Button exposedButton = toolkit.createButton( table, "", SWT.CHECK );
- exposedButton.setSelection( exposed.contains( mod ) );
- exposedButton.pack();
- exposedButton.addSelectionListener( new SelectionListener() {
-
- @Override
- public void widgetSelected( final SelectionEvent e ) {
- if( !ignoreModify ) {
- String mod = item.getText( NAME_COL );
- if( exposed.contains( mod ) ) {
- exposed.remove( mod );
- } else {
- if (onlyOne && exposed.size() > 0) {
- // We have to deselect the other one
- boolean previousIgnoreModify = ignoreModify;
- ignoreModify = true;
- for (String it : exposed) {
- exposedBoxes.get( it ).setSelection( false );
- }
- ignoreModify = previousIgnoreModify;
- exposed.clear();
- exposed.add(mod);
- } else {
- exposed.add( mod );
- Collections.sort( exposed );
- }
- }
- FormEntryModules.this.notifyTextValueChanged();
- }
- }
-
- @Override
- public void widgetDefaultSelected( final SelectionEvent e ) {
- // Do nothing
- }
- } );
- exposedBoxes.put( mod, exposedButton );
- TableEditor exposedEditor = new TableEditor( table );
- exposedEditor.minimumWidth = exposedButton.getSize().x;
- exposedEditor.horizontalAlignment = SWT.CENTER;
- exposedEditor.setEditor( exposedButton, item, EXPOSED_COL );
- // Add "other" check box
- Button otherButton = toolkit.createButton( table, "", SWT.CHECK );
- otherButton.setSelection( other.contains( mod ) );
- otherButton.pack();
- otherButton.addSelectionListener( new SelectionListener() {
-
- @Override
- public void widgetSelected( final SelectionEvent e ) {
- if( !ignoreModify ) {
- String mod = item.getText( NAME_COL );
- if( other.contains( mod ) ) {
- other.remove( mod );
- } else {
- other.add( mod );
- Collections.sort( other );
- }
- FormEntryModules.this.notifyOtherValueChanged();
- }
- }
-
- @Override
- public void widgetDefaultSelected( final SelectionEvent e ) {
- // Do nothing
- }
- } );
- otherBoxes.put( mod, otherButton );
- TableEditor otherEditor = new TableEditor( table );
- otherEditor.minimumWidth = otherButton.getSize().x;
- otherEditor.horizontalAlignment = SWT.CENTER;
- otherEditor.setEditor( otherButton, item, OTHER_COL );
- }
- // ensure module names are visible
- table.getColumn( 2 ).pack();
- // Tell modifications
- if( changeToExposed && !blockNotification ) {
- notifyTextValueChanged();
- }
- if( changeToOther && !blockNotification ) {
- notifyOtherValueChanged();
- }
- }
- }
- }
-
- public ArrayList<String> getOrderedValue( final String value ) {
- // Get ordered value
- String newValue = value == null ? "" : value;
- String[] elementsA = newValue.split( "," );
- ArrayList<String> elements = new ArrayList<String>();
- for( String e: elementsA ) {
- elements.add( e.trim() );
- }
- Collections.sort( elements );
- return elements;
- }
-
- @Override
- public synchronized void setValue( final String value,
- final boolean blockNotification ) {
- synchronized( this ) {
- List<String> newValue = getOrderedValue( value );
- if( getValueFrom( newValue ).equals( getValue() ) ) {
- // We have the same value
- return;
- }
-
- ignoreModify = true;
- exposed.clear();
- for( TableItem item: table.getItems() ) {
- String mod = item.getText( NAME_COL );
- if (exposedBoxes.containsKey( mod )) {
- exposedBoxes.get( mod ).setSelection( newValue.contains( mod ) );
- }
- if( newValue.contains( mod ) ) {
- exposed.add( mod );
- }
- }
- ignoreModify = false;
-
- if( !blockNotification ) {
- this.notifyTextValueChanged();
- }
- }
- }
-
- public synchronized void setOtherModulesValue( final String value,
- final boolean blockNotification ) {
- synchronized( this ) {
- List<String> newValue = getOrderedValue( value );
- if( getValueFrom( newValue ).equals( getOtherModulesValue() ) ) {
- // We have the same value
- return;
- }
-
- ignoreModify = true;
- other.clear();
- for( TableItem item: table.getItems() ) {
- String mod = item.getText( NAME_COL );
- if (otherBoxes.containsKey( mod )) {
- otherBoxes.get( mod ).setSelection( newValue.contains( mod ) );
- }
- if( newValue.contains( mod ) ) {
- other.add( mod );
- }
- }
- ignoreModify = false;
-
- if( !blockNotification ) {
- this.notifyOtherValueChanged();
- }
- }
- }
-
- String getValueFrom( final List<String> strings ) {
- StringBuilder builder = new StringBuilder();
- for( String s: strings ) {
- if( builder.length() > 0 ) {
- builder.append( ","+PlatformUtil.NL );
- }
- builder.append( s );
- }
- return builder.toString();
- }
-
- @Override
- public String getValue() {
- return getValueFrom( exposed );
- }
-
- public String getOtherModulesValue() {
- return getValueFrom( other );
- }
-
- @Override
- public void setEditable( final boolean editable ) {
- if (!editable) {
- setSourceFolders( null, true );
- }
- table.setEnabled( editable );
- }
-
- public void addOtherValueListener( final IOtherValueEntryListener listener ) {
- this.otherListeners.add( listener );
- }
-
- public void removeOtherValueListener( final IOtherValueEntryListener listener ) {
- this.otherListeners.remove( listener );
- }
-
- protected void notifyOtherValueChanged() {
- for( IOtherValueEntryListener listener: otherListeners ) {
- listener.otherTextValueChanged( this );
- }
- }
-
-
- public class ModulesVisitor implements IResourceVisitor {
-
- public ArrayList<String> elts;
- public Vector<String> possiblePrefixes;
-
- public ModulesVisitor( final ArrayList<String> whereAdd,
- final Collection<String> dirs ) {
- this.elts = whereAdd;
- this.possiblePrefixes = new Vector<String>();
- for( String dir: dirs ) {
- this.possiblePrefixes.add( dir.trim() + "/" );
- }
- }
-
- @Override
- public boolean visit( final IResource resource ) {
- String path = resource.getProjectRelativePath().toString();
- if( resource instanceof IFile ) {
- for( String dir: possiblePrefixes ) {
- if( path.startsWith( dir ) ) {
- String filePath = path.substring( dir.length() );
- if( filePath.endsWith( ".hs" ) ) {
- String module = filePath.substring( 0, filePath.length() - 3 )
- .replace( '/', '.' );
- this.elts.add( module );
- } else if( filePath.endsWith( ".lhs" ) ) {
- String module = filePath.substring( 0, filePath.length() - 4 )
- .replace( '/', '.' );
- this.elts.add( module );
- }
- }
- }
- }
- return true;
- }
- }
-
-}
+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.HashMap;
+import java.util.List;
+import java.util.Vector;
+import net.sf.eclipsefp.haskell.core.cabalmodel.CabalSyntax;
+import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
+import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
+import net.sf.eclipsefp.haskell.ui.internal.editors.cabal.forms.FormEntry;
+import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
+import net.sf.eclipsefp.haskell.util.PlatformUtil;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * Form entry for selecting modules from a project.
+ * @author Alejandro Serrano
+ *
+ */
+public class FormEntryModules extends FormEntry {
+
+ static final int EXPOSED_COL = 0;
+ static final int OTHER_COL = 1;
+ static final int NAME_COL = 2;
+
+ private final ArrayList<IOtherValueEntryListener> otherListeners = new ArrayList<IOtherValueEntryListener>();
+
+ ArrayList<String> prevElements;
+ boolean onlyOne;
+ String exposedString;
+ FormToolkit toolkit;
+ Table table;
+ ArrayList<String> exposed;
+ ArrayList<String> other;
+ boolean ignoreModify = false;
+ HashMap<String, Button> exposedBoxes;
+ HashMap<String, Button> otherBoxes;
+
+ public FormEntryModules( final String exposedString ) {
+ this( exposedString, false );
+ }
+
+ public FormEntryModules( final String exposedString, final boolean onlyOne ) {
+ super();
+ this.exposedString = exposedString;
+ this.onlyOne = onlyOne;
+ this.exposed = new ArrayList<String>();
+ this.other = new ArrayList<String>();
+ this.exposedBoxes = new HashMap<String, Button>();
+ this.otherBoxes = new HashMap<String, Button>();
+ this.prevElements = new ArrayList<String>();
+ }
+
+
+ @Override
+ public void init( final IProject project, final Composite parent,
+ final FormToolkit toolkit, final int style ) {
+ this.toolkit = toolkit;
+
+ table = toolkit.createTable( parent, SWT.SINGLE );
+ table.setHeaderVisible( true );
+
+ TableColumn exposedCol = new TableColumn( table, SWT.NULL );
+ exposedCol.setText( exposedString );
+ exposedCol.pack();
+ TableColumn otherCol = new TableColumn( table, SWT.NULL );
+ otherCol.setText( UITexts.cabalEditor_other_modules );
+ otherCol.pack();
+ TableColumn nameCol = new TableColumn( table, SWT.NULL );
+ nameCol.setText( UITexts.cabalEditor_module );
+ nameCol.pack();
+ }
+
+ public void changeExposedColumnName( final String newName ) {
+ TableColumn exposedCol = table.getColumn( EXPOSED_COL );
+ exposedCol.setText( newName );
+ }
+
+ @Override
+ public Control getControl() {
+ return table;
+ }
+
+ @Override
+ public int heightHint() {
+ return 170;
+ }
+
+ @SuppressWarnings ( "unchecked" )
+ public synchronized void setSourceFolders( final FormEntryModulesRoot root,
+ final boolean blockNotification ) {
+ synchronized( this ) {
+ if( root == null ) {
+ // If we have no data
+ table.clearAll();
+ for( Button b: exposedBoxes.values() ) {
+ b.dispose();
+ }
+ exposedBoxes.clear();
+ for( Button b: otherBoxes.values() ) {
+ b.dispose();
+ }
+ otherBoxes.clear();
+ prevElements.clear();
+ return;
+ }
+
+ Collection<String> sourceDirs = null;
+ if( root.getStanza().getProperties()
+ .containsKey( CabalSyntax.FIELD_HS_SOURCE_DIRS.getCabalName() ) ) {
+ //sourceDirs = root.getStanza().getProperties()
+ // .get( CabalSyntax.FIELD_HS_SOURCE_DIRS.getCabalName() );
+ sourceDirs=root.getStanza().getSourceDirs();
+ } else {
+ sourceDirs = Collections.emptyList();
+ }
+
+ ArrayList<String> modules = new ArrayList<String>();
+ ModulesVisitor visitor = new ModulesVisitor( modules, sourceDirs );
+ try {
+ root.getProject().accept( visitor );
+ } catch( CoreException e ) {
+ HaskellUIPlugin.log( e );
+ }
+
+ PackageDescriptionStanza pkg = root.getDescription().getPackageStanza();
+ if( pkg != null ) {
+ if( pkg.getProperties().containsKey( CabalSyntax.FIELD_DATA_FILES.getCabalName() ) ) {
+ // There are data files, so Paths_package is also provided
+ modules.add( "Paths_"
+ + pkg.getProperties().get( CabalSyntax.FIELD_NAME.getCabalName() ) );
+ }
+ }
+
+ // Show the items in alphabetical order
+ Collections.sort( modules );
+
+ // Check if it is the same
+ if( !getValueFrom( modules ).equals( getValueFrom( prevElements ) ) ) {
+ prevElements = modules;
+ // Set the new values for exposed and others
+ boolean changeToExposed = false;
+ boolean changeToOther = false;
+ for( String s: ( ArrayList<String> )exposed.clone() ) {
+ if( !modules.contains( s ) ) {
+ changeToExposed = true;
+ exposed.remove( s );
+ }
+ }
+ for( String s: ( ArrayList<String> )other.clone() ) {
+ if( !modules.contains( s ) ) {
+ changeToOther = true;
+ other.remove( s );
+ }
+ }
+
+ // Add the items to table
+ table.removeAll();
+
+ for( Button b: exposedBoxes.values() ) {
+ b.dispose();
+ }
+ exposedBoxes.clear();
+ for( Button b: otherBoxes.values() ) {
+ b.dispose();
+ }
+ otherBoxes.clear();
+
+ for( String mod: modules ) {
+ final TableItem item = new TableItem( table, SWT.NULL );
+ item.setText( new String[] { "", "", mod } );
+ // Add "exposed" check box
+ Button exposedButton = toolkit.createButton( table, "", SWT.CHECK );
+ exposedButton.setSelection( exposed.contains( mod ) );
+ exposedButton.pack();
+ exposedButton.addSelectionListener( new SelectionListener() {
+
+ @Override
+ public void widgetSelected( final SelectionEvent e ) {
+ if( !ignoreModify ) {
+ String mod = item.getText( NAME_COL );
+ if( exposed.contains( mod ) ) {
+ exposed.remove( mod );
+ } else {
+ if (onlyOne && exposed.size() > 0) {
+ // We have to deselect the other one
+ boolean previousIgnoreModify = ignoreModify;
+ ignoreModify = true;
+ for (String it : exposed) {
+ exposedBoxes.get( it ).setSelection( false );
+ }
+ ignoreModify = previousIgnoreModify;
+ exposed.clear();
+ exposed.add(mod);
+ } else {
+ exposed.add( mod );
+ Collections.sort( exposed );
+ }
+ }
+ FormEntryModules.this.notifyTextValueChanged();
+ }
+ }
+
+ @Override
+ public void widgetDefaultSelected( final SelectionEvent e ) {
+ // Do nothing
+ }
+ } );
+ exposedBoxes.put( mod, exposedButton );
+ TableEditor exposedEditor = new TableEditor( table );
+ exposedEditor.minimumWidth = exposedButton.getSize().x;