blob: b32f06c9475e7131a41a3dcde3098dc044bd6e74 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2007, 2021 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.preferences;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
import org.eclipse.jface.databinding.viewers.typed.ViewerProperties;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.databinding.core.validation.IntegerValidator;
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.ConfigurationBlockPreferencePage;
import org.eclipse.statet.ecommons.preferences.ui.ManagedConfigurationBlock;
import org.eclipse.statet.ecommons.runtime.core.StatusChangeListener;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.internal.r.ui.RUIPreferenceInitializer;
import org.eclipse.statet.internal.r.ui.editors.DefaultRFoldingPreferences;
import org.eclipse.statet.ltk.ui.sourceediting.ISmartInsertSettings.TabAction;
import org.eclipse.statet.ltk.ui.sourceediting.SmartInsertSettingsUI;
import org.eclipse.statet.r.ui.editors.REditorBuild;
import org.eclipse.statet.r.ui.editors.REditorOptions;
/**
* Preference page for 'R Editor Options'
*/
@NonNullByDefault
public class REditorPreferencePage extends ConfigurationBlockPreferencePage {
public REditorPreferencePage() {
}
@Override
protected ConfigurationBlock createConfigurationBlock() {
return new REditorConfigurationBlock(createStatusChangedListener());
}
}
@NonNullByDefault
class REditorConfigurationBlock extends ManagedConfigurationBlock {
private Button smartInsertControl;
private ComboViewer smartInsertTabActionControl;
private Button[] smartInsertOnPasteControl;
private Button[] smartInsertCloseCurlyBracketsControl;
private Button[] smartInsertCloseRoundBracketsControl;
private Button[] smartInsertCloseSquareBracketsControl;
private Button[] smartInsertCloseSpecialControl;
private Button[] smartInsertCloseStringsControl;
private Button foldingEnableControl;
private Button foldingRestoreStateControl;
private Button foldingDefaultAllBlocksControl;
private Text foldingDefaultMinLines;
private Button foldingDefaultRoxygenControl;
private Button foldingDefaultRoxygenInitiallyControl;
private Text foldingDefaultRoxygenMinLines;
private Button markOccurrencesControl;
private Button problemsEnableControl;
private Button spellEnableControl;
public REditorConfigurationBlock(final @Nullable StatusChangeListener statusListener) {
super(null, statusListener);
}
@Override
protected void createBlockArea(final Composite pageComposite) {
final Map<Preference<?>, @Nullable String> prefs= new HashMap<>();
prefs.put(REditorOptions.SMARTINSERT_BYDEFAULT_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_TAB_ACTION_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_ONPASTE_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_CLOSECURLY_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_CLOSEROUND_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_CLOSESQUARE_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_CLOSESPECIAL_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.SMARTINSERT_CLOSESTRINGS_ENABLED_PREF, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSECURLY_ENABLED, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSEROUND_ENABLED, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSESQUARE_ENABLED, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSESPECIAL_ENABLED, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSESTRINGS_ENABLED, REditorOptions.SMARTINSERT_GROUP_ID);
prefs.put(REditorOptions.FOLDING_ENABLED_PREF, null);
prefs.put(REditorOptions.FOLDING_RESTORE_STATE_ENABLED_PREF, REditorOptions.FOLDING_SHARED_GROUP_ID);
prefs.put(DefaultRFoldingPreferences.PREF_OTHERBLOCKS_ENABLED, DefaultRFoldingPreferences.GROUP_ID);
prefs.put(DefaultRFoldingPreferences.PREF_MINLINES_NUM, DefaultRFoldingPreferences.GROUP_ID);
prefs.put(DefaultRFoldingPreferences.PREF_ROXYGEN_ENABLED, DefaultRFoldingPreferences.GROUP_ID);
prefs.put(DefaultRFoldingPreferences.PREF_ROXYGEN_COLLAPSE_INITIALLY_ENABLED, DefaultRFoldingPreferences.GROUP_ID);
prefs.put(DefaultRFoldingPreferences.PREF_ROXYGEN_MINLINES_NUM, DefaultRFoldingPreferences.GROUP_ID);
prefs.put(REditorOptions.PREF_MARKOCCURRENCES_ENABLED, null);
prefs.put(REditorBuild.PROBLEMCHECKING_ENABLED_PREF, REditorBuild.GROUP_ID);
prefs.put(REditorOptions.PREF_SPELLCHECKING_ENABLED, REditorOptions.GROUP_ID);
setupPreferenceManager(prefs);
// Controls
{ final Composite composite= createSmartInsertOptions(pageComposite);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
// Code Folding
LayoutUtils.addSmallFiller(pageComposite, false);
{ this.foldingEnableControl= new Button(pageComposite, SWT.CHECK);
this.foldingEnableControl.setText(Messages.REditorOptions_Folding_Enable_label);
this.foldingEnableControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
}
{ this.foldingRestoreStateControl= new Button(pageComposite, SWT.CHECK);
this.foldingRestoreStateControl.setText(Messages.REditorOptions_Folding_RestoreState_Enable_label);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.horizontalIndent= LayoutUtils.defaultIndent();
this.foldingRestoreStateControl.setLayoutData(gd);
}
final Composite foldingOptions= new Composite(pageComposite, SWT.NONE);
{ final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
gd.horizontalIndent= LayoutUtils.defaultIndent();
foldingOptions.setLayoutData(gd);
foldingOptions.setLayout(LayoutUtils.newCompositeGrid(2));
}
{ this.foldingDefaultAllBlocksControl= new Button(foldingOptions, SWT.CHECK);
this.foldingDefaultAllBlocksControl.setText(Messages.REditorOptions_Folding_EnableForAllBlocks_label);
this.foldingDefaultAllBlocksControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
}
{ final Label label= new Label(foldingOptions, SWT.LEFT);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, false, false);
gd.horizontalIndent= LayoutUtils.defaultIndent();
label.setLayoutData(gd);
label.setText(Messages.REditorOptions_Folding_MinNumOfLines_label);
}
{ this.foldingDefaultMinLines= new Text(foldingOptions, SWT.SINGLE | SWT.BORDER);
final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, false, false);
gd.widthHint= LayoutUtils.hintWidth(this.foldingDefaultMinLines, 2);
this.foldingDefaultMinLines.setLayoutData(gd);
}
{ this.foldingDefaultRoxygenControl= new Button(foldingOptions, SWT.CHECK);
this.foldingDefaultRoxygenControl.setText(Messages.REditorOptions_Folding_EnableForRoxygen_label);
this.foldingDefaultRoxygenControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
}
{ final Label label= new Label(foldingOptions, SWT.LEFT);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, false, false);
gd.horizontalIndent= LayoutUtils.defaultIndent();
label.setLayoutData(gd);
label.setText(Messages.REditorOptions_Folding_MinNumOfLines_label);
}
{ this.foldingDefaultRoxygenMinLines= new Text(foldingOptions, SWT.SINGLE | SWT.BORDER);
final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, false, false);
gd.widthHint= LayoutUtils.hintWidth(this.foldingDefaultRoxygenMinLines, 2);
this.foldingDefaultRoxygenMinLines.setLayoutData(gd);
}
{ this.foldingDefaultRoxygenInitiallyControl= new Button(foldingOptions, SWT.CHECK);
this.foldingDefaultRoxygenInitiallyControl.setText(Messages.REditorOptions_Folding_EnableForRoxygen_Initially_label);
final GridData gd= new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
gd.horizontalIndent= LayoutUtils.defaultIndent();
this.foldingDefaultRoxygenInitiallyControl.setLayoutData(gd);
}
// Annotation
LayoutUtils.addSmallFiller(pageComposite, false);
{ this.markOccurrencesControl= new Button(pageComposite, SWT.CHECK);
this.markOccurrencesControl.setText(Messages.REditorOptions_MarkOccurrences_Enable_label);
this.markOccurrencesControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
final Link link= addLinkControl(pageComposite, Messages.REditorOptions_MarkOccurrences_Appearance_info);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
gd.widthHint= 300;
gd.horizontalIndent= LayoutUtils.defaultIndent();
link.setLayoutData(gd);
}
LayoutUtils.addSmallFiller(pageComposite, false);
{ this.problemsEnableControl= new Button(pageComposite, SWT.CHECK);
this.problemsEnableControl.setText(Messages.REditorOptions_ProblemChecking_Enable_label);
this.problemsEnableControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
}
LayoutUtils.addSmallFiller(pageComposite, false);
{ this.spellEnableControl= new Button(pageComposite, SWT.CHECK);
this.spellEnableControl.setText(Messages.REditorOptions_SpellChecking_Enable_label);
this.spellEnableControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
final Link link= addLinkControl(pageComposite, Messages.REditorOptions_SpellChecking_note);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
gd.widthHint= 300;
gd.horizontalIndent= LayoutUtils.defaultIndent();
link.setLayoutData(gd);
}
// Binding
initBindings();
updateControls();
}
private Composite createSmartInsertOptions(final Composite pageComposite) {
final Group composite= new Group(pageComposite, SWT.NONE);
composite.setText(Messages.REditorOptions_SmartInsert_label+':');
final int n= 5;
composite.setLayout(LayoutUtils.newGroupGrid(n));
this.smartInsertControl= new Button(composite, SWT.CHECK);
this.smartInsertControl.setText(Messages.REditorOptions_SmartInsert_AsDefault_label);
this.smartInsertControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, n, 1));
{ final Link link= addLinkControl(composite, Messages.REditorOptions_SmartInsert_description);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false, n, 1);
gd.widthHint= 300;
link.setLayoutData(gd);
}
{ final Label label= new Label(composite, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
label.setText(Messages.REditorOptions_SmartInsert_TabAction_label);
this.smartInsertTabActionControl= new ComboViewer(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
this.smartInsertTabActionControl.getControl().setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, n-2, 1));
this.smartInsertTabActionControl.setContentProvider(new ArrayContentProvider());
this.smartInsertTabActionControl.setLabelProvider(new SmartInsertSettingsUI.SettingsLabelProvider());
this.smartInsertTabActionControl.setInput(new TabAction[] {
TabAction.INSERT_TAB_CHAR, TabAction.INSERT_INDENT_LEVEL,
});
LayoutUtils.addGDDummy(composite, true);
}
LayoutUtils.addGDDummy(composite);
LayoutUtils.addGDDummy(composite);
{ Label label= new Label(composite, SWT.CENTER);
label.setText(Messages.REditorOptions_SmartInsert_ForEditor_header);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
label= new Label(composite, SWT.CENTER);
label.setText(Messages.REditorOptions_SmartInsert_ForConsole_header);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
}
LayoutUtils.addGDDummy(composite, true);
this.smartInsertOnPasteControl= createSmartInsertOption(composite,
Messages.REditorOptions_SmartInsert_OnPaste_label,
null, false );
this.smartInsertCloseCurlyBracketsControl= createSmartInsertOption(composite,
Messages.REditorOptions_SmartInsert_CloseAuto_label,
Messages.REditorOptions_SmartInsert_CloseCurly_label, true );
this.smartInsertCloseRoundBracketsControl= createSmartInsertOption(composite, null,
Messages.REditorOptions_SmartInsert_CloseRound_label, true );
this.smartInsertCloseSquareBracketsControl= createSmartInsertOption(composite, null,
Messages.REditorOptions_SmartInsert_CloseSquare_label, true );
this.smartInsertCloseSpecialControl= createSmartInsertOption(composite, null,
Messages.REditorOptions_SmartInsert_ClosePercent_label, true );
this.smartInsertCloseStringsControl= createSmartInsertOption(composite, null,
Messages.REditorOptions_SmartInsert_CloseString_label, true );
return composite;
}
private Button[] createSmartInsertOption(final Composite composite,
final @Nullable String text1, final @Nullable String text2, final boolean console) {
GridData gd;
if (text1 != null) {
final Label label= new Label(composite, SWT.NONE);
if (text2 == null) {
label.setText(text1+':');
gd= new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1);
}
else {
label.setText(text1);
gd= new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
}
label.setLayoutData(gd);
}
else {
LayoutUtils.addGDDummy(composite);
}
if (text2 != null) {
final Label label= new Label(composite, SWT.NONE);
label.setText(text2 + "\u200A:"); //$NON-NLS-1$
gd= new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
label.setLayoutData(gd);
}
final Button button0= new Button(composite, SWT.CHECK);
gd= new GridData(SWT.CENTER, SWT.CENTER, false, false);
button0.setLayoutData(gd);
final Button button1= new Button(composite, SWT.CHECK);
gd= new GridData(SWT.CENTER, SWT.CENTER, false, false);
button1.setLayoutData(gd);
if (!console) {
button1.setEnabled(false);
}
LayoutUtils.addGDDummy(composite, true);
return new Button[] { button0, button1 };
}
@Override
protected void addBindings(final DataBindingSupport db) {
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertControl),
createObservable(REditorOptions.SMARTINSERT_BYDEFAULT_ENABLED_PREF) );
db.getContext().bindValue(
ViewerProperties.singleSelection(TabAction.class)
.observe(this.smartInsertTabActionControl),
createObservable(REditorOptions.SMARTINSERT_TAB_ACTION_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertOnPasteControl[0]),
createObservable(REditorOptions.SMARTINSERT_ONPASTE_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertOnPasteControl[0]),
createObservable(REditorOptions.SMARTINSERT_ONPASTE_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseCurlyBracketsControl[0]),
createObservable(REditorOptions.SMARTINSERT_CLOSECURLY_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseRoundBracketsControl[0]),
createObservable(REditorOptions.SMARTINSERT_CLOSEROUND_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseSquareBracketsControl[0]),
createObservable(REditorOptions.SMARTINSERT_CLOSESQUARE_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseSpecialControl[0]),
createObservable(REditorOptions.SMARTINSERT_CLOSESPECIAL_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseStringsControl[0]),
createObservable(REditorOptions.SMARTINSERT_CLOSESTRINGS_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseCurlyBracketsControl[1]),
createObservable(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSECURLY_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseRoundBracketsControl[1]),
createObservable(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSEROUND_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseSquareBracketsControl[1]),
createObservable(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSESQUARE_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseSpecialControl[1]),
createObservable(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSESPECIAL_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.smartInsertCloseStringsControl[1]),
createObservable(RUIPreferenceInitializer.CONSOLE_SMARTINSERT_CLOSESTRINGS_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.foldingEnableControl),
createObservable(REditorOptions.FOLDING_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.foldingRestoreStateControl),
createObservable(REditorOptions.FOLDING_RESTORE_STATE_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.foldingDefaultAllBlocksControl),
createObservable(DefaultRFoldingPreferences.PREF_OTHERBLOCKS_ENABLED) );
db.getContext().bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.foldingDefaultMinLines),
createObservable(DefaultRFoldingPreferences.PREF_MINLINES_NUM),
new UpdateValueStrategy<String, Integer>()
.setAfterGetValidator(new IntegerValidator(2, 1000,
Messages.REditorOptions_Folding_MinNumOfLines_error_message )),
null );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.foldingDefaultRoxygenControl),
createObservable(DefaultRFoldingPreferences.PREF_ROXYGEN_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.foldingDefaultRoxygenInitiallyControl),
createObservable(DefaultRFoldingPreferences.PREF_ROXYGEN_COLLAPSE_INITIALLY_ENABLED) );
db.getContext().bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.foldingDefaultRoxygenMinLines),
createObservable(DefaultRFoldingPreferences.PREF_ROXYGEN_MINLINES_NUM),
new UpdateValueStrategy<String, Integer>()
.setAfterGetValidator(new IntegerValidator(2, 1000,
Messages.REditorOptions_Folding_MinNumOfLines_error_message )),
null );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.markOccurrencesControl),
createObservable(REditorOptions.PREF_MARKOCCURRENCES_ENABLED) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.problemsEnableControl),
createObservable(REditorBuild.PROBLEMCHECKING_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.spellEnableControl),
createObservable(REditorOptions.PREF_SPELLCHECKING_ENABLED) );
}
}