blob: f795a1a19b8acdd535a443abdb8edec5f56d14c7 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2010, 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.rhelp;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.Diffs;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.AbstractSWTObservableValue;
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.r.core.RCore;
@NonNullByDefault
public class RHelpPreferencePage extends ConfigurationBlockPreferencePage {
public RHelpPreferencePage() {
}
@Override
protected ConfigurationBlock createConfigurationBlock() throws CoreException {
return new RHelpConfigurationBlock(createStatusChangedListener());
}
}
@NonNullByDefault
class RHelpConfigurationBlock extends ManagedConfigurationBlock {
class HomeObservable extends AbstractSWTObservableValue<String>
implements SelectionListener, ModifyListener {
private boolean isCustom;
private String url;
private String lastCustom= "http://"; //$NON-NLS-1$
private boolean isUpdating;
public HomeObservable(final Realm realm) {
super(realm, RHelpConfigurationBlock.this.homeUrlControl);
RHelpConfigurationBlock.this.homeUrlControl.addModifyListener(this);
RHelpConfigurationBlock.this.homeBlankControl.addSelectionListener(this);
RHelpConfigurationBlock.this.homeREnvControl.addSelectionListener(this);
RHelpConfigurationBlock.this.homeCustomControl.addSelectionListener(this);
this.url= ""; //$NON-NLS-1$
}
@Override
public Object getValueType() {
return String.class;
}
@Override
protected String doGetValue() {
if (!this.isUpdating) {
this.isUpdating= true;
try {
updateUrl();
}
finally {
this.isUpdating= false;
}
}
return this.url;
}
@Override
protected void doSetValue(final @Nullable String value) {
this.isUpdating= true;
this.url= (value != null) ? value : "about:blank"; //$NON-NLS-1$
try {
if (this.url.equals("about:blank")) { //$NON-NLS-1$
RHelpConfigurationBlock.this.homeBlankControl.setSelection(true);
RHelpConfigurationBlock.this.homeREnvControl.setSelection(false);
RHelpConfigurationBlock.this.homeCustomControl.setSelection(false);
this.isCustom= false;
}
else if (this.url.equals(RCore.DEFAULT_RHELP_BROWSE_URL)) {
RHelpConfigurationBlock.this.homeBlankControl.setSelection(false);
RHelpConfigurationBlock.this.homeREnvControl.setSelection(true);
RHelpConfigurationBlock.this.homeCustomControl.setSelection(false);
this.isCustom= false;
}
else {
RHelpConfigurationBlock.this.homeBlankControl.setSelection(false);
RHelpConfigurationBlock.this.homeREnvControl.setSelection(false);
RHelpConfigurationBlock.this.homeCustomControl.setSelection(true);
this.isCustom= true;
this.lastCustom= this.url;
}
RHelpConfigurationBlock.this.homeUrlControl.setText(this.url);
}
finally {
this.isUpdating= false;
}
}
private void updateUrl() {
final String oldUrl= this.url;
if (RHelpConfigurationBlock.this.homeBlankControl.getSelection()) {
if (this.isCustom) {
this.lastCustom= RHelpConfigurationBlock.this.homeUrlControl.getText();
}
this.isCustom= false;
this.url= "about:blank"; //$NON-NLS-1$
}
else if (RHelpConfigurationBlock.this.homeREnvControl.getSelection()) {
if (this.isCustom) {
this.lastCustom= RHelpConfigurationBlock.this.homeUrlControl.getText();
}
this.isCustom= false;
this.url= RCore.DEFAULT_RHELP_BROWSE_URL;
}
else {
this.isCustom= true;
this.url= (this.lastCustom != null) ? this.lastCustom : ""; //$NON-NLS-1$
}
if (!this.url.equals(RHelpConfigurationBlock.this.homeUrlControl.getText())) {
RHelpConfigurationBlock.this.homeUrlControl.setText(this.url);
}
if (!this.url.equals(oldUrl)) {
fireValueChange(Diffs.createValueDiff(oldUrl, this.url));
}
}
@Override
public void widgetSelected(final SelectionEvent e) {
if (this.isUpdating) {
return;
}
this.isUpdating= true;
try {
updateUrl();
}
finally {
this.isUpdating= false;
}
}
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
}
@Override
public void modifyText(final ModifyEvent e) {
if (this.isUpdating) {
return;
}
this.isUpdating= true;
try {
RHelpConfigurationBlock.this.homeBlankControl.setSelection(false);
RHelpConfigurationBlock.this.homeREnvControl.setSelection(false);
RHelpConfigurationBlock.this.homeCustomControl.setSelection(true);
this.lastCustom= RHelpConfigurationBlock.this.homeUrlControl.getText();
updateUrl();
}
finally {
this.isUpdating= false;
}
}
}
private Button homeBlankControl;
private Button homeREnvControl;
private Button homeCustomControl;
private Text homeUrlControl;
private Button searchReusePageControl;
private Text searchMaxFragmentsControl;
protected RHelpConfigurationBlock(final @Nullable StatusChangeListener statusListener) {
super(null, statusListener);
}
@Override
protected void createBlockArea(final Composite pageComposite) {
final Map<Preference<?>, @Nullable String> prefs= new HashMap<>();
prefs.put(RHelpPreferences.HOMEPAGE_URL_PREF, null);
prefs.put(RHelpPreferences.SEARCH_REUSE_PAGE_ENABLED_PREF, null);
prefs.put(RHelpPreferences.SEARCH_PREVIEW_FRAGMENTS_MAX_PREF, null);
setupPreferenceManager(prefs);
final Composite appearanceOptions= createAppearanceOptions(pageComposite);
appearanceOptions.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
final Composite homeOptions= createHomeOptions(pageComposite);
homeOptions.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
final Composite searchOptions= createSearchOptions(pageComposite);
searchOptions.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
initBindings();
updateControls();
}
private Composite createAppearanceOptions(final Composite pageComposite) {
final Group group= new Group(pageComposite, SWT.NONE);
group.setText("Appearance" + ':');
group.setLayout(LayoutUtils.newGroupGrid(3));
final Link control= addLinkControl(group,
"See also settings for StatET > Documentation in <a href=\"org.eclipse.ui.preferencePages.ColorsAndFonts\">Color and Fonts</a>.");
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
return group;
}
private Composite createHomeOptions(final Composite pageComposite) {
final Group group= new Group(pageComposite, SWT.NONE);
group.setText("Home Page" + ':');
group.setLayout(LayoutUtils.newGroupGrid(3));
{ final Button button= new Button(group, SWT.RADIO);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
button.setText("&Blank page");
this.homeBlankControl= button;
}
{ final Button button= new Button(group, SWT.RADIO);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
button.setText("Default &R environment");
this.homeREnvControl= button;
}
{ final Button button= new Button(group, SWT.RADIO);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
button.setText("C&ustom");
this.homeCustomControl= button;
}
{ final Text text= new Text(group, SWT.BORDER);
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
text.setText(""); //$NON-NLS-1$
this.homeUrlControl= text;
}
return group;
}
private Composite createSearchOptions(final Composite pageComposite) {
final Group group= new Group(pageComposite, SWT.NONE);
group.setText("Search" + ':');
group.setLayout(LayoutUtils.newGroupGrid(2));
this.searchReusePageControl= new Button(group, SWT.CHECK);
this.searchReusePageControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.searchReusePageControl.setText("Reuse &page in R Help view to show matches.");
{ final Label label= new Label(group, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
label.setText("Maximum preview &fragments:");
final Text text= new Text(group, SWT.BORDER | SWT.RIGHT);
final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, false, false);
gd.widthHint= LayoutUtils.hintWidth(text, 5);
text.setLayoutData(gd);
this.searchMaxFragmentsControl= text;
}
return group;
}
@Override
protected void addBindings(final DataBindingSupport db) {
db.getContext().bindValue(
new HomeObservable(db.getRealm()),
createObservable(RHelpPreferences.HOMEPAGE_URL_PREF) );
db.getContext().bindValue(
WidgetProperties.buttonSelection()
.observe(this.searchReusePageControl),
createObservable(RHelpPreferences.SEARCH_REUSE_PAGE_ENABLED_PREF) );
db.getContext().bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.searchMaxFragmentsControl),
createObservable(RHelpPreferences.SEARCH_PREVIEW_FRAGMENTS_MAX_PREF),
new UpdateValueStrategy<String, Integer>()
.setAfterGetValidator(new IntegerValidator(1, 1000,
"Invalid maximum for preview fragments specified (1-1000).")),
null );
}
}