blob: 177c420409ff232b1e45b239d26f118e09028d79 [file] [log] [blame]
/*
* 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.compiler;
import static org.eclipse.xtext.util.Strings.isEmpty;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.browseCustomPath;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.compileOnSave;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.descriptorLocation;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.errorInvalidDescriptor;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.errorInvalidProtoc;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.errorNoLanguageSelected;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.errorNoSelection;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.protocInCustomPath;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.protocInSystemPath;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.protocLocation;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.refreshOutputProject;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.refreshProject;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.refreshResources;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.tabMain;
import static com.google.eclipse.protobuf.ui.preferences.compiler.Messages.tabRefresh;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.COMPILE_PROTO_FILES;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.CPP_CODE_GENERATION_ENABLED;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.CPP_OUTPUT_DIRECTORY;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.DESCRIPTOR_FILE_PATH;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.ENABLE_PROJECT_SETTINGS_PREFERENCE_NAME;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.JAVA_CODE_GENERATION_ENABLED;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.JAVA_OUTPUT_DIRECTORY;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.PROTOC_FILE_PATH;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.PYTHON_CODE_GENERATION_ENABLED;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.PYTHON_OUTPUT_DIRECTORY;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.REFRESH_OUTPUT_DIRECTORY;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.REFRESH_PROJECT;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.REFRESH_RESOURCES;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.USE_PROTOC_IN_CUSTOM_PATH;
import static com.google.eclipse.protobuf.ui.preferences.compiler.PreferenceNames.USE_PROTOC_IN_SYSTEM_PATH;
import static com.google.eclipse.protobuf.ui.preferences.pages.ButtonGroup.with;
import static com.google.eclipse.protobuf.ui.preferences.pages.LabelWidgets.setEnabled;
import static com.google.eclipse.protobuf.ui.preferences.pages.TextWidgets.setEditable;
import static com.google.eclipse.protobuf.ui.preferences.pages.TextWidgets.setEnabled;
import static com.google.eclipse.protobuf.ui.preferences.pages.binding.BindingToButtonSelection.bindSelectionOf;
import static com.google.eclipse.protobuf.ui.preferences.pages.binding.BindingToTextValue.bindTextOf;
import java.io.File;
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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import com.google.eclipse.protobuf.ui.preferences.pages.PreferenceAndPropertyPage;
import com.google.eclipse.protobuf.ui.preferences.pages.binding.PreferenceBinder;
import com.google.eclipse.protobuf.ui.preferences.pages.binding.PreferenceFactory;
/**
* Preference page for protobuf compiler.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class CompilerPreferencePage extends PreferenceAndPropertyPage {
private static final String PREFERENCE_PAGE_ID = CompilerPreferencePage.class.getName();
private Button btnCompileProtoFiles;
private TabFolder tabFolder;
private TabItem tbtmMain;
private TabItem tbtmRefresh;
private TabItem tbtmOptions;
private Group grpCompilerLocation;
private Button btnUseProtocInSystemPath;
private Button btnUseProtocInCustomPath;
private Text txtProtocFilePath;
private Button btnProtocPathBrowse;
private Group grpDescriptorLocation;
private Text txtDescriptorFilePath;
private Button btnDescriptorPathBrowse;
private Button btnGenerateJava;
private Label lblJavaOutputDirectory;
private Text txtJavaOutputDirectory;
private Button btnGenerateCpp;
private Label lblCppOutputDirectory;
private Text txtCppOutputDirectory;
private Button btnGeneratePython;
private Label lblPythonOutputDirectory;
private Text txtPythonOutputDirectory;
private Group grpRefresh;
private Button btnRefreshResources;
private Button btnRefreshProject;
private Button btnRefreshOutputDirectory;
@Override protected void doCreateContents(Composite parent) {
btnCompileProtoFiles = new Button(parent, SWT.CHECK);
btnCompileProtoFiles.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
btnCompileProtoFiles.setText(compileOnSave);
tabFolder = new TabFolder(parent, SWT.NONE);
tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
tbtmMain = new TabItem(tabFolder, SWT.NONE);
tbtmMain.setText(tabMain);
Composite cmpMain = new Composite(tabFolder, SWT.NONE);
tbtmMain.setControl(cmpMain);
cmpMain.setLayout(new GridLayout(1, false));
grpCompilerLocation = new Group(cmpMain, SWT.NONE);
grpCompilerLocation.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
grpCompilerLocation.setLayout(new GridLayout(2, false));
grpCompilerLocation.setText(protocLocation);
btnUseProtocInSystemPath = new Button(grpCompilerLocation, SWT.RADIO);
btnUseProtocInSystemPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
btnUseProtocInSystemPath.setText(protocInSystemPath);
btnUseProtocInCustomPath = new Button(grpCompilerLocation, SWT.RADIO);
btnUseProtocInCustomPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
btnUseProtocInCustomPath.setText(protocInCustomPath);
txtProtocFilePath = new Text(grpCompilerLocation, SWT.BORDER);
txtProtocFilePath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
setEditable(txtProtocFilePath, false);
btnProtocPathBrowse = new Button(grpCompilerLocation, SWT.NONE);
btnProtocPathBrowse.setText(browseCustomPath);
grpDescriptorLocation = new Group(cmpMain, SWT.NONE);
grpDescriptorLocation.setText(descriptorLocation);
grpDescriptorLocation.setLayout(new GridLayout(2, false));
grpDescriptorLocation.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
txtDescriptorFilePath = new Text(grpDescriptorLocation, SWT.BORDER);
txtDescriptorFilePath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
setEditable(txtDescriptorFilePath, false);
btnDescriptorPathBrowse = new Button(grpDescriptorLocation, SWT.NONE);
btnDescriptorPathBrowse.setText(browseCustomPath);
tbtmOptions = new TabItem(tabFolder, SWT.NONE);
tbtmOptions.setText("&Options");
Composite cmpOptions = new Composite(tabFolder, SWT.NONE);
tbtmOptions.setControl(cmpOptions);
cmpOptions.setLayout(new GridLayout(2, false));
btnGenerateJava = new Button(cmpOptions, SWT.CHECK);
btnGenerateJava.setEnabled(false);
btnGenerateJava.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 3, 1));
btnGenerateJava.setText("Generate Java");
lblJavaOutputDirectory = new Label(cmpOptions, SWT.NONE);
lblJavaOutputDirectory.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblJavaOutputDirectory.setText("Java Output Directory:");
txtJavaOutputDirectory = new Text(cmpOptions, SWT.BORDER);
txtJavaOutputDirectory.setEnabled(false);
txtJavaOutputDirectory.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btnGenerateCpp = new Button(cmpOptions, SWT.CHECK);
btnGenerateCpp.setEnabled(false);
btnGenerateCpp.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
btnGenerateCpp.setText("Generate C++");
lblCppOutputDirectory = new Label(cmpOptions, SWT.NONE);
lblCppOutputDirectory.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblCppOutputDirectory.setText("C++ Output Directory:");
txtCppOutputDirectory = new Text(cmpOptions, SWT.BORDER);
txtCppOutputDirectory.setEnabled(false);
txtCppOutputDirectory.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
btnGeneratePython = new Button(cmpOptions, SWT.CHECK);
btnGeneratePython.setEnabled(false);
btnGeneratePython.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
btnGeneratePython.setText("Generate Python");
lblPythonOutputDirectory = new Label(cmpOptions, SWT.NONE);
lblPythonOutputDirectory.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblPythonOutputDirectory.setText("Python Output Directory:");
txtPythonOutputDirectory = new Text(cmpOptions, SWT.BORDER);
txtPythonOutputDirectory.setEnabled(false);
txtPythonOutputDirectory.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
tbtmRefresh = new TabItem(tabFolder, SWT.NONE);
tbtmRefresh.setText(tabRefresh);
Composite cmpRefresh = new Composite(tabFolder, SWT.NONE);
tbtmRefresh.setControl(cmpRefresh);
cmpRefresh.setLayout(new GridLayout(1, false));
btnRefreshResources = new Button(cmpRefresh, SWT.CHECK);
btnRefreshResources.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btnRefreshResources.setText(refreshResources);
grpRefresh = new Group(cmpRefresh, SWT.NONE);
grpRefresh.setLayout(new GridLayout(1, false));
grpRefresh.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btnRefreshProject = new Button(grpRefresh, SWT.RADIO);
btnRefreshProject.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btnRefreshProject.setText(refreshProject);
btnRefreshOutputDirectory = new Button(grpRefresh, SWT.RADIO);
btnRefreshOutputDirectory.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btnRefreshOutputDirectory.setText(refreshOutputProject);
new Label(parent, SWT.NONE);
addEventListeners();
}
private void addEventListeners() {
btnCompileProtoFiles.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
boolean selected = btnCompileProtoFiles.getSelection();
enableCompilerSettings(selected);
checkState();
}
});
with(btnUseProtocInCustomPath, btnUseProtocInSystemPath).add(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
boolean selected = btnUseProtocInCustomPath.getSelection();
enableCompilerCustomPathSettings(selected);
checkState();
}
});
btnProtocPathBrowse.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(getShell(), SWT.OPEN | SWT.SHEET);
String file = dialog.open();
if (file != null) {
txtProtocFilePath.setText(file);
}
checkState();
}
});
btnDescriptorPathBrowse.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(getShell(), SWT.OPEN | SWT.SHEET);
dialog.setFilterExtensions(new String[] { "*.proto" });
String file = dialog.open();
if (file != null) {
txtDescriptorFilePath.setText(file);
}
checkState();
}
});
btnGenerateJava.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
enableJavaOutputDirectory(btnGenerateJava.getSelection());
checkState();
}
});
btnGenerateCpp.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
enableCppOutputDirectory(btnGenerateCpp.getSelection());
checkState();
}
});
btnGeneratePython.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
enablePythonOutputDirectory(btnGeneratePython.getSelection());
checkState();
}
});
btnRefreshResources.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
refreshResourcesSettingsEnabled(btnRefreshResources.getSelection());
}
});
}
@Override protected String enableProjectSettingsPreferenceName() {
return ENABLE_PROJECT_SETTINGS_PREFERENCE_NAME;
}
@Override protected void setupBinding(PreferenceBinder binder, PreferenceFactory factory) {
binder.addAll(
bindSelectionOf(btnCompileProtoFiles).to(factory.newBooleanPreference(COMPILE_PROTO_FILES)),
bindSelectionOf(btnUseProtocInSystemPath).to(factory.newBooleanPreference(USE_PROTOC_IN_SYSTEM_PATH)),
bindSelectionOf(btnUseProtocInCustomPath).to(factory.newBooleanPreference(USE_PROTOC_IN_CUSTOM_PATH)),
bindTextOf(txtProtocFilePath).to(factory.newStringPreference(PROTOC_FILE_PATH)),
bindTextOf(txtDescriptorFilePath).to(factory.newStringPreference(DESCRIPTOR_FILE_PATH)),
bindSelectionOf(btnGenerateJava).to(factory.newBooleanPreference(JAVA_CODE_GENERATION_ENABLED)),
bindTextOf(txtJavaOutputDirectory).to(factory.newStringPreference(JAVA_OUTPUT_DIRECTORY)),
bindSelectionOf(btnGenerateCpp).to(factory.newBooleanPreference(CPP_CODE_GENERATION_ENABLED)),
bindTextOf(txtCppOutputDirectory).to(factory.newStringPreference(CPP_OUTPUT_DIRECTORY)),
bindSelectionOf(btnGeneratePython).to(factory.newBooleanPreference(PYTHON_CODE_GENERATION_ENABLED)),
bindTextOf(txtPythonOutputDirectory).to(factory.newStringPreference(PYTHON_OUTPUT_DIRECTORY)),
bindSelectionOf(btnRefreshResources).to(factory.newBooleanPreference(REFRESH_RESOURCES)),
bindSelectionOf(btnRefreshProject).to(factory.newBooleanPreference(REFRESH_PROJECT)),
bindSelectionOf(btnRefreshOutputDirectory).to(factory.newBooleanPreference(REFRESH_OUTPUT_DIRECTORY))
);
}
@Override protected void updateContents() {
boolean compileProtoFiles = btnCompileProtoFiles.getSelection();
boolean shouldEnableCompilerOptions = compileProtoFiles;
if (isPropertyPage()) {
boolean useProjectSettings = areProjectSettingsActive();
activateProjectSettings(useProjectSettings);
enableProjectSpecificSettings(useProjectSettings);
shouldEnableCompilerOptions = shouldEnableCompilerOptions && useProjectSettings;
}
enableCompilerSettings(shouldEnableCompilerOptions);
}
@Override protected void onProjectSettingsActivation(boolean active) {
enableProjectSpecificSettings(active);
enableCompilerSettings(isEnabledAndSelected(btnCompileProtoFiles));
checkState();
}
private void enableProjectSpecificSettings(boolean enabled) {
btnCompileProtoFiles.setEnabled(enabled);
}
private void enableCompilerSettings(boolean enabled) {
enableCompilerPathSettings(enabled);
enableDescriptorPathSettings(enabled);
enableOptionsSettings(enabled);
enableRefreshSettings(enabled);
}
private void enableCompilerPathSettings(boolean enabled) {
grpCompilerLocation.setEnabled(enabled);
btnUseProtocInSystemPath.setEnabled(enabled);
btnUseProtocInCustomPath.setEnabled(enabled);
enableCompilerCustomPathSettings(customPathOptionSelectedAndEnabled());
}
private void enableCompilerCustomPathSettings(boolean enabled) {
txtProtocFilePath.setEnabled(enabled);
btnProtocPathBrowse.setEnabled(enabled);
}
private void enableDescriptorPathSettings(boolean enabled) {
grpDescriptorLocation.setEnabled(enabled);
txtDescriptorFilePath.setEnabled(enabled);
btnDescriptorPathBrowse.setEnabled(enabled);
}
private boolean customPathOptionSelectedAndEnabled() {
return isEnabledAndSelected(btnUseProtocInCustomPath);
}
private void enableOptionsSettings(boolean enabled) {
btnGenerateJava.setEnabled(enabled);
enableJavaOutputDirectory(isEnabledAndSelected(btnGenerateJava));
btnGenerateCpp.setEnabled(enabled);
enableCppOutputDirectory(isEnabledAndSelected(btnGenerateCpp));
btnGeneratePython.setEnabled(enabled);
enablePythonOutputDirectory(isEnabledAndSelected(btnGeneratePython));
}
private void enableJavaOutputDirectory(boolean enabled) {
setEnabled(txtJavaOutputDirectory, enabled);
setEnabled(lblJavaOutputDirectory, enabled);
}
private void enableCppOutputDirectory(boolean enabled) {
setEnabled(txtCppOutputDirectory, enabled);
setEnabled(lblCppOutputDirectory, enabled);
}
private void enablePythonOutputDirectory(boolean enabled) {
setEnabled(txtPythonOutputDirectory, enabled);
setEnabled(lblPythonOutputDirectory, enabled);
}
private void enableRefreshSettings(boolean enabled) {
btnRefreshResources.setEnabled(enabled);
refreshResourcesSettingsEnabled(isEnabledAndSelected(btnRefreshResources));
}
private boolean isEnabledAndSelected(Button button) {
return button.isEnabled() && button.getSelection();
}
private void refreshResourcesSettingsEnabled(boolean enabled) {
grpRefresh.setEnabled(enabled);
btnRefreshProject.setEnabled(enabled);
btnRefreshOutputDirectory.setEnabled(enabled);
}
private void checkState() {
if (isPropertyPage() && !areProjectSettingsActive()) {
// the page is a 'project property' page and the 'enable project settings' check-box is not selected
pageIsNowValid();
return;
}
if (!btnCompileProtoFiles.getSelection()) {
// all the options of this page are disabled
pageIsNowValid();
return;
}
if (!atLeastOneTargetLanguageIsSelected()) {
pageIsNowInvalid(errorNoLanguageSelected);
return;
}
if (customPathOptionSelectedAndEnabled()) {
String protocPath = txtProtocFilePath.getText();
if (isEmpty(protocPath)) {
pageIsNowInvalid(errorNoSelection);
return;
}
File protoc = new File(protocPath);
if (!protoc.isFile()) {
pageIsNowInvalid(errorInvalidProtoc);
return;
}
}
String descriptorPath = txtDescriptorFilePath.getText();
if (!isEmpty(descriptorPath) && !isFileWithName(descriptorPath, "descriptor.proto")) {
pageIsNowInvalid(errorInvalidDescriptor);
return;
}
pageIsNowValid();
}
private boolean atLeastOneTargetLanguageIsSelected() {
return btnGenerateJava.getSelection() || btnGenerateCpp.getSelection() || btnGeneratePython.getSelection();
}
private boolean isFileWithName(String filePath, String expectedFileName) {
File file = new File(filePath);
if (!file.isFile()) {
return false;
}
String fileName = file.getName();
return expectedFileName.equals(fileName);
}
@Override protected String preferencePageId() {
return PREFERENCE_PAGE_ID;
}
}