blob: 8cec465d91f689e8869e168bf5ad3ae6e2fa2ff7 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2017, 2019 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.apps.ui.launching;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import static org.eclipse.statet.ecommons.databinding.core.observable.ObservableUtils.typed;
import static org.eclipse.statet.internal.r.apps.ui.launching.AppControlConfigs.VARIABLES_CODE_ATTR_NAME;
import static org.eclipse.statet.internal.r.apps.ui.launching.AppControlConfigs.VARIABLES_VIEWER_ACTION_ATTR_NAME;
import static org.eclipse.statet.internal.r.apps.ui.launching.AppControlConfigs.VIEWER_ID_ATTR_NAME;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
import org.eclipse.jface.databinding.viewers.typed.ViewerProperties;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.PlatformUI;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigTabWithDbc;
import org.eclipse.statet.ecommons.templates.TemplateVariableProcessor;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.internal.r.apps.ui.Messages;
import org.eclipse.statet.ltk.ui.sourceediting.SnippetEditor;
import org.eclipse.statet.ltk.ui.sourceediting.SnippetEditor1;
import org.eclipse.statet.r.apps.ui.RAppUIResources;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.launching.ui.RLaunchingUI;
import org.eclipse.statet.r.ui.sourceediting.RSourceViewerConfigurator;
import org.eclipse.statet.r.ui.sourceediting.RTemplateSourceViewerConfigurator;
@NonNullByDefault
public class AppControlConfigViewTab extends LaunchConfigTabWithDbc
implements IValueChangeListener<Object> {
static void initDefaults(final ILaunchConfigurationWorkingCopy config) {
config.setAttribute(AppControlConfigs.VIEWER_ID_ATTR_NAME, AppControlConfigs.WORKBENCH_VIEW_BROWSER_ID);
config.setAttribute(AppControlConfigs.VARIABLES_VIEWER_ACTION_ATTR_NAME, AppControlConfigs.SHOW_ACTION_ID);
}
private class ViewerItem {
private final @Nullable String id;
private final String label;
private @Nullable Composite detailControl;
public ViewerItem(final @Nullable String id, final String label) {
this.id= id;
this.label= label;
}
public @Nullable String getId() {
return this.id;
}
@Override // for LabelProvider
public String toString() {
return this.label;
}
public @Nullable Composite enable() {
Composite control= this.detailControl;
if (this.id != null) {
if (control == null) {
control= createControl(AppControlConfigViewTab.this.viewerDetailControl);
this.detailControl= control;
}
}
return control;
}
public void disable() {
}
protected Composite createControl(final Composite parent) {
final Composite composite= new Composite(parent, SWT.NONE);
return composite;
}
}
private ImList<ViewerItem> viewers;
private IObservableValue<ViewerItem> viewerValue;
private IObservableValue<String> variablesCodeValue;
private IObservableValue<Boolean> variablesActionValue;
private ComboViewer viewerSelectionViewer;
private StackLayout viewerDetailLayout;
private Composite viewerDetailControl;
private SnippetEditor variablesCodeEditor;
private Button variablesActionControl;
public AppControlConfigViewTab() {
final Realm realm= getRealm();
this.viewerValue= new WritableValue<>(realm, null, String.class);
this.viewerValue.addValueChangeListener(this);
this.viewers= ImCollections.newList(
new ViewerItem(null, Messages.Operation_Viewer_None_label),
new ViewerItem(AppControlConfigs.WORKBENCH_VIEW_BROWSER_ID,
Messages.Operation_Viewer_WorkbenchView_label),
new ViewerItem(AppControlConfigs.WORKBENCH_EXTERNAL_BROWSER_ID,
Messages.Operation_Viewer_WorkbenchExternal_label) {
@Override
protected Composite createControl(final Composite parent) {
final Composite composite= super.createControl(parent);
composite.setLayout(LayoutUtils.newCompositeGrid(1));
LayoutUtils.addSmallFiller(composite, true);
final Link link= new Link(composite, SWT.NONE);
link.setText("Global preferences: "
+ "<a href=\"org.eclipse.ui.browser.preferencePage\">Web Browser</a>.");
composite.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
link.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final PreferenceDialog dialog= org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn(null, e.text, null, null);
if (dialog != null) {
dialog.open();
}
}
});
return composite;
}
});
this.variablesCodeValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
this.variablesActionValue= new WritableValue<>(realm, true, Boolean.TYPE);
}
@Override
public Image getImage() {
return nonNullAssert(RAppUIResources.INSTANCE.getImage(RAppUIResources.TOOL_VIEW_IMAGE_ID));
}
@Override
public String getName() {
return Messages.Operation_ViewTab_name;
}
public String getLabel() {
return Messages.Operation_ViewTab_label;
}
@Override
public void createControl(final Composite parent) {
final Composite mainComposite= new Composite(parent, SWT.NONE);
setControl(mainComposite);
mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
mainComposite.setLayout(new GridLayout());
{ final Label label= new Label(mainComposite, SWT.NONE);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
label.setText(getLabel() + ':');
}
{ final Composite composite= createViewerSettings(mainComposite);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
{ final Composite composite= createVariablesSettings(mainComposite);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
Dialog.applyDialogFont(parent);
initBindings();
}
private ViewerItem getViewerItem(final String id) {
for (final ViewerItem item : this.viewers) {
if (item.getId() == id) {
return item;
}
}
return this.viewers.get(0);
}
private Composite createViewerSettings(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Operation_ViewTab_Operation_label + ':');
composite.setLayout(LayoutUtils.newGroupGrid(1));
{ final ComboViewer viewer= new ComboViewer(composite);
viewer.setLabelProvider(new LabelProvider());
viewer.setContentProvider(new ArrayContentProvider());
viewer.setInput(this.viewers);
viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.viewerSelectionViewer= viewer;
}
{ final Composite detailControl= new Composite(composite, SWT.NONE);
this.viewerDetailLayout= new StackLayout();
detailControl.setLayout(this.viewerDetailLayout);
detailControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
this.viewerDetailControl= detailControl;
}
return composite;
}
private Composite createVariablesSettings(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Operation_Variables_label + ':');
composite.setLayout(LayoutUtils.newGroupGrid(2));
{ final Label label= new Label(composite, SWT.NONE);
label.setText(Messages.Operation_Variables_RCode_label + ':');
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
final TemplateVariableProcessor templateVariableProcessor= new TemplateVariableProcessor();
final RSourceViewerConfigurator configurator= new RTemplateSourceViewerConfigurator(
RCore.getWorkbenchAccess(),
templateVariableProcessor );
final SnippetEditor1 editor= new SnippetEditor1(configurator, null,
PlatformUI.getWorkbench(), RLaunchingUI.LAUNCH_CONFIG_QUALIFIER );
editor.create(composite, SnippetEditor.DEFAULT_SINGLE_LINE_STYLE);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
gd.heightHint= LayoutUtils.hintHeight(editor.getSourceViewer().getTextWidget(), 1);
editor.getControl().setLayoutData(gd);
this.variablesCodeEditor= editor;
}
{ final Button button= new Button(composite, SWT.CHECK);
button.setText(Messages.Operation_Variables_ShowView_label);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.variablesActionControl= button;
}
return composite;
}
@Override
protected void addBindings(final DataBindingContext dbc) {
dbc.bindValue(
ViewerProperties.singleSelection()
.observe(this.viewerSelectionViewer),
this.viewerValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.variablesCodeEditor.getTextControl()),
this.variablesCodeValue );
dbc.bindValue(
WidgetProperties.buttonSelection()
.observe(this.variablesActionControl),
this.variablesActionValue );
}
@Override
public void handleValueChange(final ValueChangeEvent<?> event) {
if (event.getObservable() == this.viewerValue) {
final ViewerItem oldItem= typed(event, this.viewerValue).diff.getOldValue();
if (oldItem != null) {
oldItem.disable();
}
final ViewerItem newItem= typed(event, this.viewerValue).diff.getNewValue();
if (newItem != null) {
this.viewerDetailLayout.topControl= newItem.enable();
}
else {
this.viewerDetailLayout.topControl= null;
}
this.viewerDetailControl.layout();
}
}
@Override
public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) {
initDefaults(configuration);
}
@Override
protected void doInitialize(final ILaunchConfiguration configuration) {
{ final String id= readAttribute(configuration,
VIEWER_ID_ATTR_NAME,
"") //$NON-NLS-1$
.intern();
final ViewerItem item= getViewerItem(id);
this.viewerValue.setValue(item);
}
{ final String code= readAttribute(configuration,
VARIABLES_CODE_ATTR_NAME,
"" ); //$NON-NLS-1$
this.variablesCodeValue.setValue(code);
}
{ final String action= readAttribute(configuration,
VARIABLES_VIEWER_ACTION_ATTR_NAME,
""); //$NON-NLS-1$
this.variablesActionValue.setValue(action.equals(AppControlConfigs.SHOW_ACTION_ID));
}
}
@Override
protected void doSave(final ILaunchConfigurationWorkingCopy configuration) {
{ final ViewerItem item= this.viewerValue.getValue();
configuration.setAttribute(VIEWER_ID_ATTR_NAME, item.getId());
}
{ final String code= this.variablesCodeValue.getValue();
configuration.setAttribute(VARIABLES_CODE_ATTR_NAME, code);
}
{ final Boolean enabled= this.variablesActionValue.getValue();
configuration.setAttribute(VARIABLES_VIEWER_ACTION_ATTR_NAME,
(enabled) ? AppControlConfigs.SHOW_ACTION_ID : null );
}
}
}