/*******************************************************************************
* Copyright (c) 2008 Vlad Dumitrescu and others.
* 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
*
* Contributors:
* Vlad Dumitrescu
*******************************************************************************/
package org.erlide.ui.prefs;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
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.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.dialogs.PropertyPage;
import org.erlide.core.builder.CompilerOption;
import org.erlide.core.builder.CompilerOption.PathsOption;
import org.erlide.core.builder.CompilerOptions;
import org.erlide.engine.ErlangEngine;
import org.erlide.engine.model.ErlModelException;
import org.erlide.engine.model.root.IErlModel;
import org.erlide.engine.model.root.IErlProject;
import org.erlide.util.ErlLogger;
import org.osgi.service.prefs.BackingStoreException;
import com.google.common.collect.Lists;
public class CompilerPreferencePage extends PropertyPage
implements IWorkbenchPreferencePage {
CompilerOptions prefs;
private Composite prefsComposite;
private IProject fProject;
private Button fUseProjectSettings;
private Link fChangeWorkspaceSettings;
protected ControlEnableState fBlockEnableState;
private final List<Button> optionButtons;
private Text includeDirsText;
private Text parseTransformText;
private Text customOptionsText;
public CompilerPreferencePage() {
super();
setTitle("Compiler options");
setDescription("Select the compiler options to be used.");
optionButtons = Lists.newArrayList();
}
@Override
protected Control createContents(final Composite parent) {
final Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new FillLayout(SWT.HORIZONTAL));
final TabFolder tabFolder = new TabFolder(composite, SWT.NONE);
// /////////////////////////////////////
final TabItem optionsTab = new TabItem(tabFolder, SWT.NONE);
optionsTab.setText("Options");
prefsComposite = new Composite(tabFolder, SWT.NONE);
optionsTab.setControl(prefsComposite);
final GridLayout gridLayout_1 = new GridLayout();
gridLayout_1.numColumns = 2;
prefsComposite.setLayout(gridLayout_1);
final Group optionsGroup = new Group(prefsComposite, SWT.NONE);
{
final GridData gd_optionsGroup = new GridData(SWT.FILL, SWT.CENTER, false,
false, 2, 1);
gd_optionsGroup.widthHint = 400;
optionsGroup.setLayoutData(gd_optionsGroup);
}
optionsGroup.setLayout(new GridLayout(2, true));
final Button b = newCheckButton(optionsGroup, CompilerOption.DEBUG_INFO);
b.setEnabled(false);
b.setSelection(true);
newCheckButton(optionsGroup, CompilerOption.ENCRYPT_DEBUG_INFO);
newCheckButton(optionsGroup, CompilerOption.COMPRESSED);
final Label lblNewLabel = new Label(prefsComposite, SWT.NONE);
lblNewLabel
.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblNewLabel.setText(CompilerOption.INCLUDE_DIRS.getDescription());
includeDirsText = new Text(prefsComposite, SWT.BORDER);
includeDirsText
.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
includeDirsText.setToolTipText(CompilerOption.INCLUDE_DIRS.getTooltip());
includeDirsText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
prefs.setPathOption(CompilerOption.INCLUDE_DIRS,
PathsOption.fromString(includeDirsText.getText()));
}
});
final Group warningsGroup = new Group(prefsComposite, SWT.NONE);
{
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, false, false, 2,
1);
gridData.widthHint = 400;
warningsGroup.setLayoutData(gridData);
}
warningsGroup.setText("Warnings");
final GridLayout gridLayout = new GridLayout(2, true);
warningsGroup.setLayout(gridLayout);
for (final CompilerOption option : CompilerOption.WARNINGS) {
newCheckButton(warningsGroup, option);
}
new Label(optionsGroup, SWT.NONE);
final Label lblNewLabel_1 = new Label(prefsComposite, SWT.NONE);
lblNewLabel_1
.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblNewLabel_1.setText(CompilerOption.PARSE_TRANSFORM.getDescription());
parseTransformText = new Text(prefsComposite, SWT.BORDER);
parseTransformText.setToolTipText(CompilerOption.PARSE_TRANSFORM.getTooltip());
parseTransformText
.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
parseTransformText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
prefs.setSimpleOption(CompilerOption.PARSE_TRANSFORM,
parseTransformText.getText());
}
});
new Label(prefsComposite, SWT.NONE);
new Label(prefsComposite, SWT.NONE);
final Label lblNewLabel_2 = new Label(prefsComposite, SWT.NONE);
lblNewLabel_2.setText("Custom options:");
customOptionsText = new Text(prefsComposite, SWT.BORDER | SWT.WRAP | SWT.MULTI);
final GridData gd_text_2 = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
gd_text_2.heightHint = 60;
customOptionsText.setLayoutData(gd_text_2);
customOptionsText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
prefs.setSimpleOption(CompilerOption.CUSTOM, customOptionsText.getText());
}
});
if (isProjectPreferencePage()) {
final boolean useProjectSettings = hasProjectSpecificOptions(fProject);
enableProjectSpecificSettings(useProjectSettings);
}
initPrefs();
return prefsComposite;
}
private void initPrefs() {
if (fProject == null) {
prefs = new CompilerOptions();
} else {
prefs = new CompilerOptions(fProject);
}
prefs.load();
updateUI();
}
protected boolean hasProjectSpecificOptions(final IProject project) {
final CompilerOptions p = new CompilerOptions(project);
return p.hasOptionsAtLowestScope();
}
private boolean isProjectPreferencePage() {
return fProject != null;
}
@Override
protected Label createDescriptionLabel(final Composite parent) {
createProjectSpecificSettingsCheckBoxAndLink(parent);
final Label lblSelectTheCompiler = super.createDescriptionLabel(parent);
final String suffix = isProjectPreferencePage() ? "in this project."
: "by default.";
lblSelectTheCompiler.setText("Select the compiler options to be used " + suffix);
return lblSelectTheCompiler;
}
protected void enableProjectSpecificSettings(
final boolean useProjectSpecificSettings) {
fUseProjectSettings.setSelection(useProjectSpecificSettings);
enablePreferenceContent(useProjectSpecificSettings);
fChangeWorkspaceSettings.setEnabled(!useProjectSpecificSettings);
// doStatusChanged();
}
private void enablePreferenceContent(final boolean useProjectSpecificSettings) {
if (useProjectSpecificSettings) {
if (fBlockEnableState != null) {
fBlockEnableState.restore();
fBlockEnableState = null;
}
} else {
if (fBlockEnableState == null) {
fBlockEnableState = ControlEnableState.disable(prefsComposite);
}
}
}
private void createProjectSpecificSettingsCheckBoxAndLink(final Composite parent) {
if (isProjectPreferencePage()) {
final Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
final GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout(layout);
composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// final IDialogFieldListener listener = new IDialogFieldListener()
// {
// public void dialogFieldChanged(final DialogField field) {
// final boolean enabled = ((SelectionButtonDialogField) field)
// .isSelected();
// enableProjectSpecificSettings(enabled);
//
// if (enabled && getData() != null) {
// applyData(getData());
// }
// }
// };
fUseProjectSettings = new Button(composite, SWT.CHECK);
fUseProjectSettings.setText("Enable project specific settings");
fUseProjectSettings.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final boolean sel = fUseProjectSettings.getSelection();
enableProjectSpecificSettings(sel);
super.widgetSelected(e);
}
});
// fUseProjectSettings.setDialogFieldListener(listener);
// fUseProjectSettings
// .setLabelText(PreferencesMessages.PropertyAndPreferencePage_useprojectsettings_label);
// LayoutUtil.setHorizontalGrabbing(fUseProjectSettings
// .getSelectionButton(null));
if (true) { // if (offerLink()) {
fChangeWorkspaceSettings = createLink(composite,
"Configure Workspace settings...");
fChangeWorkspaceSettings
.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false));
}
// else {
// LayoutUtil.setHorizontalSpan(fUseProjectSettings
// .getSelectionButton(null), 2);
// }
final Label horizontalLine = new Label(composite,
SWT.SEPARATOR | SWT.HORIZONTAL);
horizontalLine.setLayoutData(
new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1));
horizontalLine.setFont(composite.getFont());
} else { // if (supportsProjectSpecificOptions() && offerLink()) {
fChangeWorkspaceSettings = createLink(parent,
"Configure project specific settings..");
fChangeWorkspaceSettings
.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false));
}
}
private Link createLink(final Composite composite, final String theText) {
final Link link = new Link(composite, SWT.NONE);
link.setFont(composite.getFont());
link.setText("<A>" + theText + "</A>"); //$NON-NLS-1$//$NON-NLS-2$
link.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(final SelectionEvent e) {
doLinkActivated((Link) e.widget);
}
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
doLinkActivated((Link) e.widget);
}
});
return link;
}
void doLinkActivated(final Link widget) {
if (isProjectPreferencePage()) {
openWorkspacePreferences(null);
} else {
final List<IProject> erlProjects = new ArrayList<>();
final Set<IProject> projectsWithSpecifics = new HashSet<>();
final IErlModel model = ErlangEngine.getInstance().getModel();
try {
for (final IErlProject ep : model.getErlangProjects()) {
final IProject p = ep.getWorkspaceProject();
if (hasProjectSpecificOptions(p)) {
projectsWithSpecifics.add(p);
}
erlProjects.add(p);
}
} catch (final ErlModelException e) {
}
final ProjectSelectionDialog dialog = new ProjectSelectionDialog(getShell(),
erlProjects, projectsWithSpecifics);
if (dialog.open() == Window.OK) {
final IProject res = (IProject) dialog.getFirstResult();
openProjectProperties(res);
}
}
}
private void openProjectProperties(final IProject project) {
final String id = getPropertyPageID();
if (id != null) {
PreferencesUtil.createPropertyDialogOn(getShell(), project, id,
new String[] { id }, null).open();
}
}
protected final void openWorkspacePreferences(final Object data) {
final String id = getPreferencePageID();
PreferencesUtil
.createPreferenceDialogOn(getShell(), id, new String[] { id }, data)
.open();
}
protected String getPreferencePageID() {
return "org.erlide.ui.preferences.compiler";
}
protected String getPropertyPageID() {
return "org.erlide.ui.properties.compilerPreferencePage";
}
private Button newCheckButton(final Composite parent, final CompilerOption option) {
final Button b = new Button(parent, SWT.CHECK);
b.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
b.setText(option.getDescription());
b.setToolTipText(option.getTooltip());
b.setData(option);
b.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final Button button = (Button) e.widget;
prefs.setBooleanOption((CompilerOption) button.getData(),
button.getSelection());
}
});
optionButtons.add(b);
return b;
}
@Override
public boolean performOk() {
try {
if (fUseProjectSettings != null && !fUseProjectSettings.getSelection()
&& isProjectPreferencePage()) {
prefs.removeAllProjectSpecificSettings();
} else {
prefs.store();
}
} catch (final BackingStoreException e) {
ErlLogger.warn(e);
}
return super.performOk();
}
@Override
protected void performDefaults() {
if (fProject == null) {
prefs = new CompilerOptions();
} else {
prefs = new CompilerOptions(fProject);
}
updateUI();
super.performDefaults();
}
private void updateUI() {
for (final Button b : optionButtons) {
final CompilerOption key = (CompilerOption) b.getData();
b.setSelection(prefs.getBooleanOption(key));
}
final Iterable<String> paths = prefs.getPathsOption(CompilerOption.INCLUDE_DIRS);
if (paths != null) {
includeDirsText.setText(PathsOption.toString(paths));
}
final String parseTransform = prefs
.getSimpleOption(CompilerOption.PARSE_TRANSFORM);
if (parseTransform != null) {
parseTransformText.setText(parseTransform);
}
final String custom = prefs.getSimpleOption(CompilerOption.CUSTOM);
if (custom != null) {
customOptionsText.setText(custom);
}
}
@Override
public void setElement(final IAdaptable element) {
fProject = (IProject) element.getAdapter(IResource.class);
super.setElement(element);
}
@Override
public void init(final IWorkbench workbench) {
performDefaults();
}
@SuppressWarnings("unused")
private static class MacrosTableContentProvider
implements IStructuredContentProvider {
@Override
public Object[] getElements(final Object inputElement) {
return new Object[] { "aaa", "vvv" };
}
@Override
public void dispose() {
}
@Override
public void inputChanged(final Viewer viewer, final Object oldInput,
final Object newInput) {
}
}
@SuppressWarnings("unused")
private class MacrosTableLabelProvider extends LabelProvider
implements ITableLabelProvider {
@Override
public Image getColumnImage(final Object element, final int columnIndex) {
return null;
}
@Override
public String getColumnText(final Object element, final int columnIndex) {
return element.toString();
}
}
}