blob: 3f8c5536859d061c9dad66d5527cdefc465f23f3 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.r.ui;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.JFaceResources;
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.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
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 org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.ecommons.databinding.jface.DataBindingSupport;
import org.eclipse.statet.ecommons.preferences.core.Preference;
import org.eclipse.statet.ecommons.preferences.ui.ConfigurationBlock;
import org.eclipse.statet.ecommons.preferences.ui.ManagedConfigurationBlock;
import org.eclipse.statet.ecommons.preferences.ui.PropertyAndPreferencePage;
import org.eclipse.statet.ecommons.runtime.core.StatusChangeListener;
import org.eclipse.statet.ecommons.ui.util.LayoutUtil;
import org.eclipse.statet.internal.r.ui.buildpaths.RBuildpathsUIDescription;
import org.eclipse.statet.ltk.buildpaths.core.IBuildpathElement;
import org.eclipse.statet.ltk.buildpaths.ui.SourceContainerComponent;
import org.eclipse.statet.r.core.IRProject;
import org.eclipse.statet.r.core.RBuildpaths;
import org.eclipse.statet.r.core.RProjects;
import org.eclipse.statet.r.ui.RUI;
public class RProjectPropertyPage extends PropertyAndPreferencePage {
public RProjectPropertyPage() {
}
@Override
protected String getPreferencePageID() {
return null;
}
@Override
protected String getPropertyPageID() {
return "org.eclipse.statet.r.propertyPages.RProject"; //$NON-NLS-1$
}
@Override
protected ConfigurationBlock createConfigurationBlock() throws CoreException {
return new RProjectConfigurationBlock(getProject(), createStatusChangedListener());
}
@Override
protected boolean hasProjectSpecificSettings(final IProject project) {
return true;
}
}
class RProjectConfigurationBlock extends ManagedConfigurationBlock {
private final IRProject rProject;
private final RBuildpathsUIDescription buildpathUIDescription;
private final WritableList buildpathList;
private final SourceContainerComponent sourceFolders;
private Text pkgNameControl;
private RProjectContainerComposite projectComposite;
private REnvSelectionComposite rEnvControl;
public RProjectConfigurationBlock(final IProject project, final StatusChangeListener statusListener) {
super(project, statusListener);
this.rProject= RProjects.getRProject(project);
this.buildpathUIDescription= new RBuildpathsUIDescription();
this.buildpathList= new WritableList();
this.sourceFolders= new SourceContainerComponent(buildpathList,
RBuildpaths.R_SOURCE_TYPE, null, buildpathUIDescription );
}
@Override
protected void createBlockArea(final Composite pageComposite) {
final Map<Preference<?>, String> prefs= new HashMap<>();
prefs.put(IRProject.BASE_FOLDER_PATH_PREF, null);
prefs.put(IRProject.RENV_CODE_PREF, null);
setupPreferenceManager(prefs);
final Composite mainComposite= new Composite(pageComposite, SWT.NONE);
mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
mainComposite.setLayout(LayoutUtil.createCompositeGrid(2));
final TabFolder folder = new TabFolder(mainComposite, SWT.NONE);
folder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
{ final TabItem item = new TabItem(folder, SWT.NONE);
item.setText("&Main");
item.setControl(createMainTab(folder));
}
{ final TabItem item= new TabItem(folder, SWT.NONE);
item.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(
ISharedImages.IMG_OBJ_FOLDER ));
item.setText("&Source");
item.setControl(createSourceTab(folder));
}
{ final TabItem item= new TabItem(folder, SWT.NONE);
item.setImage(RUI.getImage(RUI.IMG_OBJ_R_RUNTIME_ENV));
item.setText("R &Environment");
item.setControl(createREnvTab(folder));
}
initBindings();
updateControls();
}
private Control createMainTab(final Composite parent) {
final Composite composite= new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(LayoutUtil.createTabGrid(2));
{ final Composite packageComposite= new Composite(composite, SWT.NONE);
packageComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
packageComposite.setLayout(LayoutUtil.createCompositeGrid(2));
final Label label= new Label(packageComposite, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
label.setText("Package &Name:");
this.pkgNameControl= new Text(packageComposite, SWT.BORDER);
this.pkgNameControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.pkgNameControl.setFont(JFaceResources.getTextFont());
LayoutUtil.addGDDummy(composite);
}
this.projectComposite= new RProjectContainerComposite(composite, getProject());
this.projectComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
this.projectComposite.setBackground(this.projectComposite.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
final Composite buttons= new Composite(composite, SWT.NONE);
buttons.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
buttons.setLayout(LayoutUtil.createCompositeGrid(1));
final Button setBase= new Button(buttons, SWT.PUSH);
setBase.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
setBase.setText("R &Base Folder");
setBase.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
RProjectConfigurationBlock.this.projectComposite.toggleBaseContainer();
}
});
return composite;
}
private Control createSourceTab(final Composite parent) {
final Composite composite= new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(LayoutUtil.createTabGrid(1));
{ final Control control= this.sourceFolders.create(composite);
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
return composite;
}
private Control createREnvTab(final Composite parent) {
final Composite composite= new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(LayoutUtil.createTabGrid(1));
{ final Label label= new Label(composite, SWT.NONE);
label.setText("R Envir&onment:");
}
this.rEnvControl= new REnvSelectionComposite(composite);
this.rEnvControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
return composite;
}
@Override
protected void addBindings(final DataBindingSupport db) {
db.getContext().bindValue(
this.rEnvControl.createObservable(Realm.getDefault()),
createObservable(IRProject.RENV_CODE_PREF),
new UpdateValueStrategy().setAfterGetValidator(
this.rEnvControl.createValidator(db.getContext()) ),
null );
this.sourceFolders.bind(db);
}
@Override
protected void updateControls() {
final String value= getPreferenceValue(IRProject.BASE_FOLDER_PATH_PREF);
if (value != null) {
final IPath basePath= Path.fromPortableString(value);
this.projectComposite.setBaseContainer(basePath);
}
else {
this.projectComposite.setBaseContainer(null);
}
final String packageName= this.rProject.getPackageName();
this.pkgNameControl.setText((packageName != null) ? packageName : ""); //$NON-NLS-1$
{ this.buildpathList.clear();
this.buildpathUIDescription.toListElements(getProject(), this.rProject.getRawBuildpath(),
this.buildpathList );
this.sourceFolders.init(getProject());
}
super.updateControls();
}
@Override
protected void updatePreferences() {
final IPath basePath= this.projectComposite.getBaseContainer();
if (basePath != null) {
setPrefValue(IRProject.BASE_FOLDER_PATH_PREF, basePath.toPortableString());
}
else {
setPrefValue(IRProject.BASE_FOLDER_PATH_PREF, null);
}
super.updatePreferences();
}
@Override
public void performApply() {
saveProjectConfig();
super.performApply();
}
@Override
public boolean performOk() {
saveProjectConfig();
return super.performOk();
}
private void saveProjectConfig() {
final ImList<IBuildpathElement> newBuildpath= this.buildpathUIDescription.toCoreElements(this.buildpathList);
RBuildpaths.set(getProject(), newBuildpath);
try {
final String packageName= this.pkgNameControl.getText();
this.rProject.setPackageConfig((packageName.trim().length() != 0) ? packageName : null);
}
catch (final CoreException e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, RUI.BUNDLE_ID, "Failed to apply R project configuration."), StatusManager.SHOW);
}
}
}