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;