In progress: [ Issue 40 ] Add support for import resolution across multiple folders
https://code.google.com/p/protobuf-dt/issues/detail?id=40
Created superclass for pages that are both preference and property page. Cleaning up tests.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
index d16bb57..149e7b7 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
@@ -51,8 +51,8 @@
}
@Test public void should_fix_import_URI_even_if_overlapping_one_folder_only_with_resource_URI() {
- String fixed = fixer.fixUri("src/proto/read-only/address.proto", resourceUri, resourceChecker);
- assertThat(fixed, equalTo("platform:/resource/src/proto/read-only/address.proto"));
+ String uri = fixer.fixUri("src/proto/read-only/address.proto", resourceUri, resourceChecker);
+ assertThat(uri, equalTo("platform:/resource/src/proto/read-only/address.proto"));
}
private static class ResourceCheckerStub extends ResourceChecker {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/CompilerPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/CompilerPreferencePage.java
index a7d7199..fca2eba 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/CompilerPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/CompilerPreferencePage.java
@@ -14,20 +14,17 @@
import static org.eclipse.core.runtime.IStatus.OK;
import java.io.File;
-import java.util.Map;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
-import org.eclipse.ui.*;
-import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.IWorkbench;
import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
import com.google.inject.Inject;
@@ -37,12 +34,10 @@
*
* @author alruiz@google.com (Alex Ruiz)
*/
-public class CompilerPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IWorkbenchPropertyPage {
+public class CompilerPreferencePage extends PreferenceAndPropertyPage {
private static final String PREFERENCE_PAGE_ID = "com.google.eclipse.protobuf.ui.preferences.CompilerPreferencePage";
- private Button btnEnableProjectSettings;
- private Link lnkEnableWorkspaceSettings;
private Button btnCompileProtoFiles;
private TabFolder tabFolder;
private TabItem tbtmMain;
@@ -65,35 +60,16 @@
private Button btnRefreshOutputFolder;
private Label lblOutputFolderRelative;
- private IProject project;
-
- private final IPreferenceStoreAccess preferenceStoreAccess;
-
- private Map<String, Object> dataMap;
-
@Inject public CompilerPreferencePage(IPreferenceStoreAccess preferenceStoreAccess) {
- this.preferenceStoreAccess = preferenceStoreAccess;
+ super(preferenceStoreAccess);
}
/** {@inheritDoc} */
@Override protected Control createContents(Composite parent) {
// generated by WindowBuilder
- Composite contents = new Composite(parent, NONE);
+ Composite contents = contentsComposite(parent);
contents.setLayout(new GridLayout(3, false));
- if (isPropertyPage()) {
- btnEnableProjectSettings = new Button(contents, SWT.CHECK);
- btnEnableProjectSettings.setText(CompilerPreferencePage_enableProjectSettings);
-
- lnkEnableWorkspaceSettings = new Link(contents, SWT.NONE);
- lnkEnableWorkspaceSettings.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- lnkEnableWorkspaceSettings.setText("<a>" + CompilerPreferencePage_configureWorkspaceSettings + "</a>");
-
- Label label = new Label(contents, SWT.SEPARATOR | SWT.HORIZONTAL);
- label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
- }
- new Label(contents, SWT.NONE);
-
btnCompileProtoFiles = new Button(contents, SWT.CHECK);
btnCompileProtoFiles.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
btnCompileProtoFiles.setText(CompilerPreferencePage_compileOnSave);
@@ -127,6 +103,8 @@
btnProtocPathBrowse = new Button(grpCompilerLocation, SWT.NONE);
btnProtocPathBrowse.setText(CompilerPreferencePage_browseCustomPath);
+ new Label(grpCompilerLocation, SWT.NONE);
+ new Label(grpCompilerLocation, SWT.NONE);
grpTargetLanguage = new Group(cmpMain, SWT.NONE);
grpTargetLanguage.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
@@ -157,7 +135,7 @@
lblOutputFolderRelative = new Label(grpOutput, SWT.NONE);
lblOutputFolderRelative.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
- lblOutputFolderRelative.setText("* relative to the project's folder");
+ lblOutputFolderRelative.setText(CompilerPreferencePage_directChildOfProjectFolder);
tbtmRefresh = new TabItem(tabFolder, SWT.NONE);
tbtmRefresh.setText(CompilerPreferencePage_refreshTab);
@@ -181,6 +159,7 @@
btnRefreshOutputFolder = new Button(grpRefresh, SWT.RADIO);
btnRefreshOutputFolder.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btnRefreshOutputFolder.setText(CompilerPreferencePage_refreshOutputProject);
+ new Label(contents, SWT.NONE);
updateFromPreferenceStore();
addEventListeners();
@@ -205,8 +184,8 @@
boolean enableCompilerOptions = compileProtoFiles;
if (isPropertyPage()) {
boolean useProjectSettings = store.getBoolean(ENABLE_PROJECT_SETTINGS);
- btnEnableProjectSettings.setSelection(useProjectSettings);
- setPropertySpecificOptionsEnabled(useProjectSettings);
+ activateProjectSettings(useProjectSettings);
+ setProjectSpecificOptionsEnabled(useProjectSettings);
enableCompilerOptions = enableCompilerOptions && useProjectSettings;
}
setCompilerOptionsEnabled(enableCompilerOptions);
@@ -253,25 +232,6 @@
};
txtProtocFilePath.addModifyListener(modifyListener);
txtOutputFolderName.addModifyListener(modifyListener);
- if (isPropertyPage()) {
- btnEnableProjectSettings.addSelectionListener(new SelectionAdapter() {
- @Override public void widgetSelected(SelectionEvent e) {
- boolean useProjectSettings = btnEnableProjectSettings.getSelection();
- setPropertySpecificOptionsEnabled(useProjectSettings);
- setCompilerOptionsEnabled(isEnabledAndSelected(btnCompileProtoFiles));
- }
- });
- lnkEnableWorkspaceSettings.addSelectionListener(new SelectionAdapter() {
- @Override public void widgetSelected(SelectionEvent e) {
- openWorkspacePreferences(dataMap);
- }
- });
- }
- }
-
- private void openWorkspacePreferences(Object data) {
- String id = PREFERENCE_PAGE_ID;
- PreferencesUtil.createPreferenceDialogOn(getShell(), id, new String[] { id }, data).open();
}
private void checkState() {
@@ -331,17 +291,16 @@
boolean enableCompilerOptions = compileProtoFiles;
if (isPropertyPage()) {
boolean useProjectSettings = store.getDefaultBoolean(ENABLE_PROJECT_SETTINGS);
- btnEnableProjectSettings.setSelection(useProjectSettings);
- setPropertySpecificOptionsEnabled(useProjectSettings);
+ activateProjectSettings(useProjectSettings);
+ setProjectSpecificOptionsEnabled(useProjectSettings);
enableCompilerOptions = enableCompilerOptions && useProjectSettings;
}
setCompilerOptionsEnabled(enableCompilerOptions);
super.performDefaults();
}
- private void setPropertySpecificOptionsEnabled(boolean enabled) {
+ private void setProjectSpecificOptionsEnabled(boolean enabled) {
btnCompileProtoFiles.setEnabled(enabled);
- lnkEnableWorkspaceSettings.setEnabled(!enabled);
}
private void setCompilerOptionsEnabled(boolean enabled) {
@@ -408,7 +367,7 @@
private void savePreferences() {
IPreferenceStore store = getPreferenceStore();
if (isPropertyPage()) {
- store.setValue(ENABLE_PROJECT_SETTINGS, btnEnableProjectSettings.getSelection());
+ store.setValue(ENABLE_PROJECT_SETTINGS, areProjectSettingsActive());
}
store.setValue(COMPILE_PROTO_FILES, btnCompileProtoFiles.getSelection());
store.setValue(USE_PROTOC_IN_SYSTEM_PATH, btnUseProtocInSystemPath.getSelection());
@@ -422,34 +381,15 @@
store.setValue(REFRESH_PROJECT, btnRefreshProject.getSelection());
store.setValue(REFRESH_OUTPUT_FOLDER, btnRefreshOutputFolder.getSelection());
}
-
+
/** {@inheritDoc} */
- public IAdaptable getElement() {
- return project;
+ @Override protected void onProjectSettingsActivation(boolean projectSettingsEnabled) {
+ setProjectSpecificOptionsEnabled(projectSettingsEnabled);
+ setCompilerOptionsEnabled(isEnabledAndSelected(btnCompileProtoFiles));
}
-
+
/** {@inheritDoc} */
- public void setElement(IAdaptable element) {
- this.project = (IProject) element.getAdapter(IProject.class);
- }
-
- @Override protected IPreferenceStore doGetPreferenceStore() {
- if (isPropertyPage()) return preferenceStoreAccess.getWritablePreferenceStore(currentProject());
- return preferenceStoreAccess.getWritablePreferenceStore();
- }
-
- private boolean isPropertyPage() {
- return project != null;
- }
-
- private IProject currentProject() {
- if (project == null)
- throw new IllegalStateException("Not a property page case, but current project was requested.");
- return project;
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked") @Override public void applyData(Object data) {
- if (data instanceof Map) this.dataMap = (Map<String, Object>) data;
+ @Override protected String preferencePageId() {
+ return PREFERENCE_PAGE_ID;
}
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.java
index 89a0673..3940ab3 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.java
@@ -22,8 +22,9 @@
private Messages() {}
- public static String CompilerPreferencePage_enableProjectSettings;
- public static String CompilerPreferencePage_configureWorkspaceSettings;
+ public static String BasePreferencePage_enableProjectSettings;
+ public static String BasePreferencePage_configureWorkspaceSettings;
+
public static String CompilerPreferencePage_mainTab;
public static String CompilerPreferencePage_refreshTab;
public static String CompilerPreferencePage_browseCustomPath;
@@ -37,6 +38,7 @@
public static String CompilerPreferencePage_generatePython;
public static String CompilerPreferencePage_generatedCode;
public static String CompilerPreferencePage_outputFolderName;
+ public static String CompilerPreferencePage_directChildOfProjectFolder;
public static String CompilerPreferencePage_refreshResources;
public static String CompilerPreferencePage_refreshProject;
public static String CompilerPreferencePage_refreshOutputProject;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.properties
index b69400c..def9ed8 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/Messages.properties
@@ -1,5 +1,6 @@
-CompilerPreferencePage_enableProjectSettings=Enable project specific settings
-CompilerPreferencePage_configureWorkspaceSettings=Configure Workspace Settings...
+BasePreferencePage_enableProjectSettings=Enable project specific settings
+BasePreferencePage_configureWorkspaceSettings=Configure Workspace Settings...
+
CompilerPreferencePage_mainTab=&Main
CompilerPreferencePage_refreshTab=&Refresh
CompilerPreferencePage_browseCustomPath=&Browse...
@@ -13,6 +14,7 @@
CompilerPreferencePage_generatePython=&Python
CompilerPreferencePage_generatedCode=Generated Code
CompilerPreferencePage_outputFolderName=Folder Name: *
+CompilerPreferencePage_directChildOfProjectFolder=* Direct child of project folder
CompilerPreferencePage_refreshResources=Refresh resources upon completion.
CompilerPreferencePage_refreshProject=Project
CompilerPreferencePage_refreshOutputProject=Folder containing generated code
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
new file mode 100644
index 0000000..04481f4
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/PreferenceAndPropertyPage.java
@@ -0,0 +1,176 @@
+/*
+ * 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;
+
+import static com.google.eclipse.protobuf.ui.preferences.Messages.*;
+import static org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn;
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+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.widgets.*;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+
+import com.google.inject.Inject;
+
+/**
+ * Base class for pages that set up both "Workspace Preferences" and "Project Properties."
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public abstract class PreferenceAndPropertyPage extends PreferencePage implements IWorkbenchPreferencePage, IWorkbenchPropertyPage {
+
+ private Button btnEnableProjectSettings;
+ private Link lnkEnableWorkspaceSettings;
+
+ private IProject project;
+ private Map<String, Object> dataMap;
+
+ private final IPreferenceStoreAccess preferenceStoreAccess;
+
+ @Inject public PreferenceAndPropertyPage(IPreferenceStoreAccess preferenceStoreAccess) {
+ this.preferenceStoreAccess = preferenceStoreAccess;
+ }
+
+ /**
+ * Creates the <code>{@link Composite}</code> to be used as the base container in implementations of
+ * <code>{@link #createContents(Composite)}</code>.
+ * @param parent the parent {@code Composite}.
+ * @return the created {@code Composite}.
+ */
+ protected final Composite contentsComposite(Composite parent) {
+ // generated by WindowBuilder
+ Composite contents = new Composite(parent, NONE);
+ contents.setLayout(new GridLayout(3, false));
+ if (isPropertyPage()) {
+ btnEnableProjectSettings = new Button(contents, SWT.CHECK);
+ btnEnableProjectSettings.setText(BasePreferencePage_enableProjectSettings);
+
+ lnkEnableWorkspaceSettings = new Link(contents, SWT.NONE);
+ lnkEnableWorkspaceSettings.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ lnkEnableWorkspaceSettings.setText("<a>" + BasePreferencePage_configureWorkspaceSettings + "</a>");
+
+ Label label = new Label(contents, SWT.SEPARATOR | SWT.HORIZONTAL);
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ }
+ new Label(contents, SWT.NONE);
+ addEventListeners();
+ return contents;
+ }
+
+ private void addEventListeners() {
+ if (isPropertyPage()) {
+ btnEnableProjectSettings.addSelectionListener(new SelectionAdapter() {
+ @Override public void widgetSelected(SelectionEvent e) {
+ onProjectSettingsActivation(areProjectSettingsActive());
+ updateEnableWorkspaceSettingsLink();
+ }
+ });
+ lnkEnableWorkspaceSettings.addSelectionListener(new SelectionAdapter() {
+ @Override public void widgetSelected(SelectionEvent e) {
+ openWorkspacePreferences();
+ }
+ });
+ }
+ }
+
+ /**
+ * Notification that the "Enable project specific settings" check button has been selected.
+ * @param projectSettingsActive indicates the selection of the "Enable project specific settings" check button.
+ */
+ protected abstract void onProjectSettingsActivation(boolean projectSettingsActive);
+
+ private void openWorkspacePreferences() {
+ String preferencePageId = preferencePageId();
+ createPreferenceDialogOn(getShell(), preferencePageId , new String[] { preferencePageId }, dataMap).open();
+ }
+
+ /**
+ * Returns the id of this preference page.
+ * @return the id of this preference page.
+ */
+ protected abstract String preferencePageId();
+
+ /**
+ * Returns the <code>{@link IProject}</code> that owns the properties shown in this page.
+ * @return the project that owns the properties shown in this page.
+ */
+ public final IAdaptable getElement() {
+ return project;
+ }
+
+ /**
+ * Sets the <code>{@link IProject}</code> that owns the properties shown in this page.
+ * @param element the {@code IAdaptable} associated with the project that owns the properties shown in this page.
+ */
+ public final void setElement(IAdaptable element) {
+ this.project = (IProject) element.getAdapter(IProject.class);
+ }
+
+ /**
+ * Returns the preference store of this preference page.
+ * @return the preference store.
+ */
+ @Override protected final IPreferenceStore doGetPreferenceStore() {
+ if (isPropertyPage()) return preferenceStoreAccess.getWritablePreferenceStore(currentProject());
+ return preferenceStoreAccess.getWritablePreferenceStore();
+ }
+
+ /**
+ * Indicates whether this page is a "Project Properties" page or not.
+ * @return {@code true} if this page is a "Project Properties" page, or {@code false} if this page is a
+ * "Worspace Settings" page.
+ */
+ protected final boolean isPropertyPage() {
+ return project != null;
+ }
+
+ private IProject currentProject() {
+ if (project == null)
+ throw new IllegalStateException("Not a property page case, but current project was requested.");
+ return project;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public final void applyData(Object data) {
+ if (data instanceof Map) this.dataMap = (Map<String, Object>) data;
+ }
+
+ /**
+ * Activates or deactivates the project-specific settings.
+ * @param active indicates whether the project-specific settings should be active or not.
+ */
+ protected final void activateProjectSettings(boolean active) {
+ btnEnableProjectSettings.setSelection(active);
+ updateEnableWorkspaceSettingsLink();
+ }
+
+ private void updateEnableWorkspaceSettingsLink() {
+ lnkEnableWorkspaceSettings.setEnabled(!areProjectSettingsActive());
+ }
+
+ /**
+ * Indicates if the project-specific settings are active or not.
+ * @return {@code true} if the project-specific settings are active; {@code false} otherwise.
+ */
+ protected final boolean areProjectSettingsActive() {
+ return btnEnableProjectSettings.getSelection();
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/TargetLanguage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/TargetLanguage.java
index a1dcfef..af4d49b 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/TargetLanguage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/TargetLanguage.java
@@ -21,6 +21,7 @@
JAVA, CPP, PYTHON;
+ // TODO check if protoc can generate more than one language sources at the same time.
static TargetLanguage find(IPreferenceStore store) {
if (store.getBoolean(GENERATE_JAVA_CODE)) return JAVA;
if (store.getBoolean(GENERATE_CPP_CODE)) return CPP;