In progress: [ Issue 40 ] Add support for import resolution across multiple folders
https://code.google.com/p/protobuf-dt/issues/detail?id=40

Finished implementing preference page for paths.
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/Messages.properties
index 59972f5..3ba605e 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/Messages.properties
@@ -7,7 +7,7 @@
 generateCpp=&C++
 generateJava=&Java
 generatePython=&Python
-outputFolderChildOfProjectFolder=* Direct child of project folder
+outputFolderChildOfProjectFolder=*direct child of project folder
 outputFolderName=Folder Name: *
 protocInCustomPath=Use protoc &in:
 protocInSystemPath=Use protoc in &PATH
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/PreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/PreferencePage.java
index 6dedd47..0a1d451 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/PreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/PreferencePage.java
@@ -226,7 +226,7 @@
   }
 
   private void checkState() {
-    String folderName = txtOutputFolderName.getText();
+    String folderName = txtOutputFolderName.getText().trim();
     if (isEmpty(folderName)) {
       pageIsNowInvalid(errorNoOutputFolderName);
       return;
@@ -345,9 +345,7 @@
   /** {@inheritDoc} */
   @Override protected void savePreferences() {
     IPreferenceStore store = getPreferenceStore();
-    if (isPropertyPage()) {
-      store.setValue(ENABLE_PROJECT_SETTINGS, areProjectSettingsActive());
-    }
+    if (isPropertyPage()) store.setValue(ENABLE_PROJECT_SETTINGS, areProjectSettingsActive());
     store.setValue(COMPILE_PROTO_FILES, btnCompileProtoFiles.getSelection());
     store.setValue(USE_PROTOC_IN_SYSTEM_PATH, btnUseProtocInSystemPath.getSelection());
     store.setValue(USE_PROTOC_IN_CUSTOM_PATH, btnUseProtocInCustomPath.getSelection());
@@ -355,7 +353,7 @@
     store.setValue(GENERATE_JAVA_CODE, btnJava.getSelection());
     store.setValue(GENERATE_CPP_CODE, btnCpp.getSelection());
     store.setValue(GENERATE_PYTHON_CODE, btnPython.getSelection());
-    store.setValue(OUTPUT_FOLDER_NAME, txtOutputFolderName.getText());
+    store.setValue(OUTPUT_FOLDER_NAME, txtOutputFolderName.getText().trim());
     store.setValue(REFRESH_RESOURCES, btnRefreshResources.getSelection());
     store.setValue(REFRESH_PROJECT, btnRefreshProject.getSelection());
     store.setValue(REFRESH_OUTPUT_FOLDER, btnRefreshOutputFolder.getSelection());
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/FileResolutionType.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/FileResolutionType.java
new file mode 100644
index 0000000..f451f97
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/FileResolutionType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */package com.google.eclipse.protobuf.ui.preferences.paths;
+
+import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.ALL_PROTOS_IN_ONE_FOLDER_ONLY;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Types of file resolution.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public enum FileResolutionType {
+
+  SINGLE_FOLDER, MULTIPLE_FOLDERS;
+  
+  static FileResolutionType find(IPreferenceStore store) {
+    if (store.getBoolean(ALL_PROTOS_IN_ONE_FOLDER_ONLY)) return SINGLE_FOLDER;
+    return MULTIPLE_FOLDERS;
+  }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
index b18ade9..7b99fad 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
@@ -1,5 +1,11 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
 package com.google.eclipse.protobuf.ui.preferences.paths;
 
 import org.eclipse.osgi.util.NLS;
@@ -12,6 +18,7 @@
   public static String allProtosInMultipleFolders;
   public static String allProtosInOneFolder;
   public static String errorNoFolderNames;
+  public static String folderNameHint;
   public static String importedFilesResolution;
 
   static {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
index 5aa3ead..3cb933a 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
@@ -1,4 +1,5 @@
-allProtosInMultipleFolders=Look for imported files in folders:
+allProtosInMultipleFolders=Look for imported files in folders:*
 allProtosInOneFolder=One folder for all .proto files
 errorNoFolderNames=Enter the name of the folders
+folderNameHint=*comma-separated values (e.g. 'src, src-gen, src-readonly')
 importedFilesResolution=Resolution of imported files
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferencePage.java
index e6c6f55..7f45f3d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferencePage.java
@@ -10,7 +10,9 @@
 
 import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.*;
 import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.*;
+import static com.google.eclipse.protobuf.ui.util.Strings.CSV_PATTERN;
 import static org.eclipse.core.runtime.IStatus.OK;
+import static org.eclipse.xtext.util.Strings.isEmpty;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jface.preference.IPreferenceStore;
@@ -20,7 +22,6 @@
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
-import org.eclipse.xtext.util.Strings;
 
 import com.google.eclipse.protobuf.ui.preferences.PreferenceAndPropertyPage;
 import com.google.eclipse.protobuf.ui.util.FolderNameValidator;
@@ -66,6 +67,9 @@
     
     txtFolderNames = new Text(grpResolutionOfImported, SWT.BORDER);
     txtFolderNames.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+    
+    Label label = new Label(grpResolutionOfImported, SWT.NONE);
+    label.setText(folderNameHint);
     new Label(contents, SWT.NONE);
     
     updateFromPreferenceStore();
@@ -105,13 +109,12 @@
 
   private void checkState() {
     if (txtFolderNames.isEnabled()) {
-      String folderNamesTogether = txtFolderNames.getText();
-      if (Strings.isEmpty(folderNamesTogether)) {
+      String folderNames = txtFolderNames.getText().trim();
+      if (isEmpty(folderNames)) {
         pageIsNowInvalid(errorNoFolderNames);
         return;
       }
-      String[] folderNames = folderNamesTogether.split("[\\s]*,[\\s]*"); //$NON-NLS-1$
-      for (String folderName : folderNames) {
+      for (String folderName : folderNames.split(CSV_PATTERN)) {
         IStatus validFolderName = folderNameValidator.validateFolderName(folderName);
         if (validFolderName.getCode() != OK) {
           pageIsNowInvalid(validFolderName.getMessage());
@@ -126,6 +129,21 @@
   @Override protected void onProjectSettingsActivation(boolean active) {
     enableProjectOptions(active);
   }
+
+  @Override protected void performDefaults() {
+    IPreferenceStore store = doGetPreferenceStore();
+    btnOneFolderOnly.setSelection(store.getDefaultBoolean(ALL_PROTOS_IN_ONE_FOLDER_ONLY));
+    btnMultipleFolders.setSelection(store.getDefaultBoolean(PROTOS_IN_MULTIPLE_FOLDERS));
+    txtFolderNames.setText(store.getDefaultString(FOLDER_NAMES));
+    boolean shouldEnablePathsOptions = true;
+    if (isPropertyPage()) {
+      boolean useProjectSettings = store.getDefaultBoolean(ENABLE_PROJECT_SETTINGS);
+      activateProjectSettings(useProjectSettings);
+      shouldEnablePathsOptions = shouldEnablePathsOptions & useProjectSettings;
+    }
+    enableProjectOptions(shouldEnablePathsOptions);
+    super.performDefaults();
+  }
   
   private void enableProjectOptions(boolean enabled) {
     grpResolutionOfImported.setEnabled(enabled);
@@ -133,14 +151,18 @@
     btnMultipleFolders.setEnabled(enabled);
     txtFolderNames.setEnabled(btnMultipleFolders.getSelection() && enabled);
   }
+  
+  /** {@inheritDoc} */
+  @Override protected void savePreferences() {
+    IPreferenceStore store = getPreferenceStore();
+    if (isPropertyPage()) store.setValue(ENABLE_PROJECT_SETTINGS, areProjectSettingsActive());
+    store.setValue(ALL_PROTOS_IN_ONE_FOLDER_ONLY, btnOneFolderOnly.getSelection());
+    store.setValue(PROTOS_IN_MULTIPLE_FOLDERS, btnMultipleFolders.getSelection());
+    store.setValue(FOLDER_NAMES, txtFolderNames.getText().trim());
+  }
 
   /** {@inheritDoc} */
   @Override protected String preferencePageId() {
     return PREFERENCE_PAGE_ID;
   }
-
-  /** {@inheritDoc} */
-  @Override protected void savePreferences() {
-    // TODO Auto-generated method stub
-  }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Preferences.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Preferences.java
new file mode 100644
index 0000000..a478679
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Preferences.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.preferences.paths;
+
+import static com.google.eclipse.protobuf.ui.preferences.paths.FileResolutionType.SINGLE_FOLDER;
+import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.*;
+import static com.google.eclipse.protobuf.ui.util.Strings.CSV_PATTERN;
+import static java.util.Arrays.asList;
+import static java.util.Collections.*;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+
+/**
+ * Paths preferences, retrieved from an <code>{@link IPreferenceStore}</code>.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Preferences {
+
+  public final FileResolutionType fileResolutionType;
+  public final List<String> folderNames; 
+  
+  public static Preferences loadPreferences(IPreferenceStoreAccess access, IProject project) {
+    IPreferenceStore store = access.getWritablePreferenceStore(project);
+    boolean useProjectPreferences = store.getBoolean(ENABLE_PROJECT_SETTINGS);
+    if (!useProjectPreferences) store = access.getWritablePreferenceStore();
+    return new Preferences(store);
+  }
+  
+  private Preferences(IPreferenceStore store) {
+    fileResolutionType = FileResolutionType.find(store);
+    folderNames = folderNames(fileResolutionType, store);
+  }
+  
+  private static List<String> folderNames(FileResolutionType types, IPreferenceStore store) {
+    if (types.equals(SINGLE_FOLDER)) return emptyList();
+    String[] folderNames = store.getString(FOLDER_NAMES).split(CSV_PATTERN);
+    return unmodifiableList(asList(folderNames));
+  }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java
index 645dee6..4b66918 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java
@@ -20,6 +20,9 @@
 @Singleton
 public class Strings {
 
+  /** Pattern to split CSVs. */
+  public static final String CSV_PATTERN = "[\\s]*,[\\s]*";
+
   /**
    * Returns a {@code String} with the same content as the given one, but with the first character in lower case.
    * @param s the original {@code String}
@@ -32,5 +35,4 @@
     chars[0] = toLowerCase(chars[0]);
     return new String(chars);
   }
-
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
index d337115..4b1dc5c 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
@@ -1,5 +1,11 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
 package com.google.eclipse.protobuf.scoping;
 
 import static org.eclipse.emf.common.util.URI.createURI;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java
index 20c9a19..4742208 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java
@@ -1,5 +1,11 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
 package com.google.eclipse.protobuf.scoping;
 
 import static org.eclipse.emf.common.util.URI.createURI;