Fixed: [ Issue 64 ] Project preferences are being shared, and they shouldn't
https://code.google.com/p/protobuf-dt/issues/detail?id=64

diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
index 380ffc4..349492d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
@@ -18,7 +18,7 @@
 import org.eclipse.xtext.ui.editor.*;
 import org.eclipse.xtext.ui.editor.model.XtextDocumentProvider;
 import org.eclipse.xtext.ui.editor.outline.actions.IOutlineContribution;
-import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreInitializer;
+import org.eclipse.xtext.ui.editor.preferences.*;
 import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator;
 
 import com.google.eclipse.protobuf.scoping.IFileUriResolver;
@@ -28,6 +28,7 @@
 import com.google.eclipse.protobuf.ui.editor.model.ProtobufDocumentProvider;
 import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.ProtobufSemanticHighlightingCalculator;
 import com.google.eclipse.protobuf.ui.outline.*;
+import com.google.eclipse.protobuf.ui.preferences.PreferenceStoreAccess;
 import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferenceStoreInitializer;
 import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferenceStoreInitializer;
 import com.google.eclipse.protobuf.ui.scoping.FileUriResolver;
@@ -96,4 +97,8 @@
   public void configureSemanticHighlightingCalculator(Binder binder) {
     binder.bind(ISemanticHighlightingCalculator.class).to(ProtobufSemanticHighlightingCalculator.class);
   }
+  
+  public void configurePreferenceStoreAccess(Binder binder) {
+    binder.bind(IPreferenceStoreAccess.class).to(PreferenceStoreAccess.class);
+  }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceAndPropertyPage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceAndPropertyPage.java
index a7c5518..523b149 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceAndPropertyPage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceAndPropertyPage.java
@@ -38,11 +38,7 @@
   private IProject project;
   private Map<String, Object> dataMap;
 
-  private final IPreferenceStoreAccess preferenceStoreAccess;
-
-  @Inject public PreferenceAndPropertyPage(IPreferenceStoreAccess preferenceStoreAccess) {
-    this.preferenceStoreAccess = preferenceStoreAccess;
-  }
+  @Inject private IPreferenceStoreAccess preferenceStoreAccess;
 
   /**
    * Creates the <code>{@link Composite}</code> to be used as the base container in implementations of
@@ -174,14 +170,26 @@
   public void init(IWorkbench workbench) {}
 
   @Override public final boolean performOk() {
-    savePreferences();
+    savePreferences(getPreferenceStore());
     return true;
   }
 
   /**
    * Saves the current settings.
+   * @param store the preference store used by this page.
    */
-  protected abstract void savePreferences();
+  protected abstract void savePreferences(IPreferenceStore store);
+
+  @Override protected final void performDefaults() {
+    performDefaults(getPreferenceStore());
+    super.performDefaults();
+  }
+
+  /**
+   * Performs special processing when this page's "Defaults" button has been pressed.
+   * @param store the preference store used by this page.
+   */
+  protected abstract void performDefaults(IPreferenceStore store);
 
   /**
    * Marks this page as "valid."
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceStoreAccess.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceStoreAccess.java
new file mode 100644
index 0000000..98b1424
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceStoreAccess.java
@@ -0,0 +1,81 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package com.google.eclipse.protobuf.ui.preferences;
+
+import com.google.eclipse.protobuf.ui.internal.ProtobufActivator;
+import com.google.inject.*;
+import com.google.inject.name.Named;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.preferences.*;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.xtext.Constants;
+import org.eclipse.xtext.ui.editor.preferences.*;
+
+/**
+ * Workaround for bug in Xtext where a project's preference store is never used.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton
+public class PreferenceStoreAccess implements IPreferenceStoreAccess {
+
+  private boolean initialized = false;
+
+  @Inject private IPreferenceStoreInitializer.CompositeImpl initializer;
+
+  private String qualifier;
+
+  public IPreferenceStore getContextPreferenceStore(Object context) {
+    lazyInitialize();
+    return new ChainedPreferenceStore(new IPreferenceStore[] { getWritablePreferenceStore(context),
+        ProtobufActivator.getInstance().getPreferenceStore(), EditorsUI.getPreferenceStore()});
+  }
+
+  public IPreferenceStore getPreferenceStore() {
+    lazyInitialize();
+    return new ChainedPreferenceStore(new IPreferenceStore[] { getWritablePreferenceStore(),
+        ProtobufActivator.getInstance().getPreferenceStore(), EditorsUI.getPreferenceStore()});
+  }
+
+  protected String getQualifier() {
+    return qualifier;
+  }
+
+  public IPreferenceStore getWritablePreferenceStore() {
+    lazyInitialize();
+    ScopedPreferenceStore result = new ScopedPreferenceStore(InstanceScope.INSTANCE, getQualifier());
+    result.setSearchContexts(new IScopeContext[] { InstanceScope.INSTANCE, ConfigurationScope.INSTANCE });
+    return result;
+  }
+
+  public IPreferenceStore getWritablePreferenceStore(Object context) {
+    lazyInitialize();
+    Object finalContext = context;
+    if (finalContext instanceof IFileEditorInput) {
+      finalContext = ((IFileEditorInput) context).getFile().getProject();
+    }
+    if (finalContext instanceof IProject) {
+      ProjectScope projectScope = new ProjectScope((IProject) finalContext);
+      ScopedPreferenceStore result = new ScopedPreferenceStore(projectScope, getQualifier());
+      result.setSearchContexts(new IScopeContext[] { projectScope, InstanceScope.INSTANCE, ConfigurationScope.INSTANCE });
+      return result;
+    }
+    return getWritablePreferenceStore();
+  }
+
+  protected void lazyInitialize() {
+    if (!initialized) {
+      initialized = true;
+      initializer.initialize(this);
+    }
+  }
+
+  @Inject public void setLanguageNameAsQualifier(@Named(Constants.LANGUAGE_NAME) String languageName) {
+    this.qualifier = languageName;
+  }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/RootPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/RootPreferencePage.java
index 559cfb6..af1538a 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/RootPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/RootPreferencePage.java
@@ -8,11 +8,9 @@
  */
 package com.google.eclipse.protobuf.ui.preferences;
 
+import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.*;
-import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
-
-import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -21,10 +19,6 @@
 
   private static final String PREFERENCE_PAGE_ID = RootPreferencePage.class.getName();
   
-  @Inject public RootPreferencePage(IPreferenceStoreAccess preferenceStoreAccess) {
-    super(preferenceStoreAccess);
-  }
-
   /** {@inheritDoc} */
   @Override protected Control createContents(Composite parent) {
     // generated by WindowBuilder
@@ -43,5 +37,8 @@
   }
 
   /** {@inheritDoc} */
-  @Override protected void savePreferences() {}
+  @Override protected void savePreferences(IPreferenceStore store) {}
+
+  /** {@inheritDoc} */
+  @Override protected void performDefaults(IPreferenceStore store) {}
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/CompilerPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/CompilerPreferencePage.java
index 6630528..0814dd4 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/CompilerPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/compiler/CompilerPreferencePage.java
@@ -14,21 +14,17 @@
 import static java.util.Arrays.asList;
 import static org.eclipse.xtext.util.Strings.isEmpty;
 
-import java.io.File;
+import com.google.eclipse.protobuf.ui.preferences.*;
+import com.google.inject.Inject;
 
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.swt.SWT;
-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.events.*;
+import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.xtext.ui.PluginImageHelper;
-import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 
-import com.google.eclipse.protobuf.ui.preferences.DataChangedListener;
-import com.google.eclipse.protobuf.ui.preferences.PreferenceAndPropertyPage;
-import com.google.inject.Inject;
+import java.io.File;
 
 /**
  * Preference page for protobuf compiler.
@@ -58,10 +54,6 @@
   @Inject private PluginImageHelper imageHelper;
   @Inject private CodeGenerationPreferencesProvider codeGenerationPreferencesProvider;
 
-  @Inject public CompilerPreferencePage(IPreferenceStoreAccess preferenceStoreAccess) {
-    super(preferenceStoreAccess);
-  }
-
   /** {@inheritDoc} */
   @Override protected Control createContents(Composite parent) {
     // generated by WindowBuilder
@@ -142,7 +134,7 @@
   }
 
   private void updateFromPreferenceStore() {
-    IPreferenceStore store = doGetPreferenceStore();
+    IPreferenceStore store = getPreferenceStore();
     boolean compileProtoFiles = store.getBoolean(COMPILE_PROTO_FILES);
     btnCompileProtoFiles.setSelection(compileProtoFiles);
     btnUseProtocInSystemPath.setSelection(store.getBoolean(USE_PROTOC_IN_SYSTEM_PATH));
@@ -226,8 +218,7 @@
   }
 
   /** {@inheritDoc} */
-  @Override protected void performDefaults() {
-    IPreferenceStore store = doGetPreferenceStore();
+  @Override protected void performDefaults(IPreferenceStore store) {
     boolean compileProtoFiles = store.getDefaultBoolean(COMPILE_PROTO_FILES);
     btnCompileProtoFiles.setSelection(compileProtoFiles);
     btnUseProtocInSystemPath.setSelection(store.getDefaultBoolean(USE_PROTOC_IN_SYSTEM_PATH));
@@ -302,8 +293,7 @@
   }
 
   /** {@inheritDoc} */
-  @Override protected void savePreferences() {
-    IPreferenceStore store = getPreferenceStore();
+  @Override protected void savePreferences(IPreferenceStore store) {
     if (isPropertyPage()) store.setValue(ENABLE_PROJECT_SETTINGS, areProjectSettingsActive());
     store.setValue(COMPILE_PROTO_FILES, btnCompileProtoFiles.getSelection());
     store.setValue(USE_PROTOC_IN_SYSTEM_PATH, btnUseProtocInSystemPath.getSelection());
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
index 48a35ce..bd15f7d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
@@ -15,8 +15,8 @@
 import static java.util.Collections.unmodifiableList;
 import static org.eclipse.xtext.util.Strings.*;
 
-import java.util.*;
-import java.util.List;
+import com.google.eclipse.protobuf.ui.preferences.*;
+import com.google.inject.Inject;
 
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.swt.SWT;
@@ -24,10 +24,9 @@
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.xtext.ui.PluginImageHelper;
-import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 
-import com.google.eclipse.protobuf.ui.preferences.*;
-import com.google.inject.Inject;
+import java.util.*;
+import java.util.List;
 
 /**
  * Preference page for import paths.
@@ -46,10 +45,6 @@
 
   @Inject private PluginImageHelper imageHelper;
 
-  @Inject public PathsPreferencePage(IPreferenceStoreAccess preferenceStoreAccess) {
-    super(preferenceStoreAccess);
-  }
-
   /** {@inheritDoc} */
   @Override protected Control createContents(Composite parent) {
     // generated by WindowBuilder
@@ -80,7 +75,7 @@
   }
 
   private void updateFromPreferenceStore() {
-    IPreferenceStore store = doGetPreferenceStore();
+    IPreferenceStore store = getPreferenceStore();
     btnOneFolderOnly.setSelection(store.getBoolean(FILES_IN_ONE_DIRECTORY_ONLY));
     btnMultipleFolders.setSelection(store.getBoolean(FILES_IN_MULTIPLE_DIRECTORIES));
     setDirectoryPaths(store.getString(DIRECTORY_PATHS));
@@ -115,8 +110,7 @@
     enableProjectOptions(active);
   }
 
-  @Override protected void performDefaults() {
-    IPreferenceStore store = doGetPreferenceStore();
+  @Override protected void performDefaults(IPreferenceStore store) {
     btnOneFolderOnly.setSelection(store.getDefaultBoolean(FILES_IN_ONE_DIRECTORY_ONLY));
     btnMultipleFolders.setSelection(store.getDefaultBoolean(FILES_IN_MULTIPLE_DIRECTORIES));
     setDirectoryPaths(store.getDefaultString(DIRECTORY_PATHS));
@@ -141,8 +135,7 @@
   }
 
   /** {@inheritDoc} */
-  @Override protected void savePreferences() {
-    IPreferenceStore store = getPreferenceStore();
+  @Override protected void savePreferences(IPreferenceStore store) {
     store.setValue(FILES_IN_ONE_DIRECTORY_ONLY, btnOneFolderOnly.getSelection());
     store.setValue(FILES_IN_MULTIPLE_DIRECTORIES, btnMultipleFolders.getSelection());
     store.setValue(DIRECTORY_PATHS, directoryNames());
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java
index 6c3dc6d..262203b 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java
@@ -19,7 +19,8 @@
 import org.eclipse.jface.preference.IPreferenceStore;
 
 /**
- * Paths preferences, retrieved from an <code>{@link IPreferenceStore}</code>.
+ * Paths preferences, retrieved from an <code>{@link IPreferenceStore}</code>. To create a new instance invoke
+ * <code>{@link PathsPreferencesProvider#getPreferences(org.eclipse.core.resources.IProject)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */