blob: 06aafd05b79979db4e1bef1b82fbd781db633a2b [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2017, 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.apps.ui.launching;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.variables.IStringVariable;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
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.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.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
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.core.validation.UpdateableErrorValidator;
import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigPresets;
import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigTabWithPresets;
import org.eclipse.statet.ecommons.templates.TemplateVariableProcessor;
import org.eclipse.statet.ecommons.ui.SharedMessages;
import org.eclipse.statet.ecommons.ui.SharedUIResources;
import org.eclipse.statet.ecommons.ui.components.CustomizableVariableSelectionDialog;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.util.VariableFilterUtils;
import org.eclipse.statet.ecommons.variables.core.VariableText2;
import org.eclipse.statet.ecommons.variables.core.VariableTextValidator;
import org.eclipse.statet.ecommons.variables.core.VariableUtils;
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.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 AppControlConfigMainTab extends LaunchConfigTabWithPresets {
static void initDefaults(final ILaunchConfigurationWorkingCopy config) {
config.setAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, 1);
}
private final IObservableValue<String> appPathValue;
private final IObservableValue<String> appHostValue;
private final IObservableValue<@Nullable Integer> appPortValue;
private final IObservableValue<Boolean> startStopRunningValue;
private final IObservableValue<String> startRSnippetValue;
private final IObservableValue<String> stopRSnippetValue;
// private ResourceInputComposite appPathControl;
private Text sHostControl;
private Text sPortControl;
private Button startStopRunningControl;
private VariableText2 rSnippetVariableResolver;
private SnippetEditor startRSnippetEditor;
private SnippetEditor stopRSnippetEditor;
public AppControlConfigMainTab(final LaunchConfigPresets presets) {
final Realm realm= getRealm();
this.appHostValue= new WritableValue<>(realm, null, String.class);
this.appPortValue= new WritableValue<>(realm, null, Integer.class);
this.appPathValue= new WritableValue<>(realm, null, String.class);
this.startRSnippetValue= new WritableValue<>(realm, null, String.class);
this.startStopRunningValue= new WritableValue<>(realm, null, Boolean.class);
this.stopRSnippetValue= new WritableValue<>(realm, null, String.class);
setPresets(presets);
}
@Override
public Image getImage() {
return SharedUIResources.getImages().get(SharedUIResources.OBJ_MAIN_TAB_ID);
}
@Override
public String getName() {
return Messages.Operation_MainTab_name;
}
@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(LayoutUtils.newTabGrid(1));
addPresetsButton(mainComposite);
{ final Composite composite= createAddressSettings(mainComposite);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
{ final Composite composite= createSnippetSettings(mainComposite);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
Dialog.applyDialogFont(parent);
initBindings();
}
private Composite createAddressSettings(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Operation_MainTab_AppAddress_group);
composite.setLayout(LayoutUtils.newGroupGrid(4));
{ // Address
final Label label= new Label(composite, SWT.LEFT);
label.setText(Messages.Operation_MainTab_AppHost_label + ':');
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
final Text text= new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.LEFT);
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.sHostControl= text;
final Label info= new Label(composite, SWT.LEFT);
info.setText(Messages.Operation_AppHost_info);
info.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
}
{ // Port
final Label label= new Label(composite, SWT.LEFT);
label.setText(Messages.Operation_MainTab_AppPort_label + ':');
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
final Text number= new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.LEFT);
final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, false, false);
gd.widthHint= LayoutUtils.hintWidth(number, 5);
number.setLayoutData(gd);
this.sPortControl= number;
final Label info= new Label(composite, SWT.LEFT);
info.setText(Messages.Operation_AppPort_info);
info.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
}
return composite;
}
private Map<String, IStringVariable> createSnippetVariables() {
final Map<String, IStringVariable> variables= new HashMap<>();
VariableUtils.add(variables, AppControlConfigs.APP_HOST_VAR);
VariableUtils.add(variables, AppControlConfigs.APP_PORT_VAR);
return variables;
}
private Composite createSnippetSettings(final Composite parent) {
final Group composite= new Group(parent, SWT.NONE);
composite.setText(Messages.Operation_MainTab_Start_group);
composite.setLayout(LayoutUtils.newGroupGrid(1));
// { final Label label= new Label(composite, SWT.NONE);
// label.setText(Messages.Operation_MainTab_AppFolder_label + ' ' +
// Messages.Operation_AppFolder_info + ':' );
// label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
//
// final ResourceInputComposite input= new ResourceInputComposite(composite,
// ResourceInputComposite.STYLE_TEXT,
// ResourceInputComposite.MODE_DIRECTORY | ResourceInputComposite.MODE_OPEN
// | ResourceInputComposite.MODE_WS_ONLY,
// Messages.Operation_MainTab_AppFolder_label );
// input.getValidator().setOnEmpty(IStatus.OK);
// input.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// this.appPathControl= input;
// }
this.rSnippetVariableResolver= new VariableText2(createSnippetVariables());
{ final Label label= new Label(composite, SWT.NONE);
label.setText(Messages.Operation_StartApp_RCode_label + ':');
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, 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, true ) {
@Override
protected void fillToolMenu(final Menu menu) {
{ final MenuItem item= new MenuItem(menu, SWT.PUSH);
item.setText(SharedMessages.InsertVariable_label);
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final CustomizableVariableSelectionDialog dialog= new CustomizableVariableSelectionDialog(getTextControl().getShell());
dialog.addVariableFilter(VariableFilterUtils.EXCLUDE_JAVA_FILTER);
dialog.setAdditionals(AppControlConfigMainTab
.this.rSnippetVariableResolver.getExtraVariables().values() );
if (dialog.open() != Dialog.OK) {
return;
}
final String variable= dialog.getVariableExpression();
if (variable == null) {
return;
}
getTextControl().insert(variable);
getTextControl().setFocus();
}
});
}
}
};
editor.create(composite, SnippetEditor.DEFAULT_MULTI_LINE_STYLE);
final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
gd.heightHint= LayoutUtils.hintHeight(editor.getSourceViewer().getTextWidget(), 8);
editor.getControl().setLayoutData(gd);
this.startRSnippetEditor= editor;
}
{ final Button button= new Button(composite, SWT.CHECK);
button.setText(Messages.Operation_StartApp_StopRunningApp_label);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
this.startStopRunningControl= button;
}
LayoutUtils.addSmallFiller(composite, false);
{ final Label label= new Label(composite, SWT.NONE);
label.setText(Messages.Operation_StopApp_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.stopRSnippetEditor= editor;
}
return composite;
}
@Override
protected void addBindings(final DataBindingContext dbc) {
// dbc.bindValue(
// this.appPathControl.getObservable(),
// this.appPathValue,
// new UpdateValueStrategy().setAfterGetValidator(this.appPathControl.getValidator()),
// null );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.sHostControl),
this.appHostValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.sPortControl),
this.appPortValue,
new UpdateValueStrategy<String, Integer>()
.setAfterGetValidator(
new IntegerValidator(0, 65535, true,
Messages.Operation_AppPort_error_SpecInvalid_message )),
null );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.startRSnippetEditor.getTextControl()),
this.startRSnippetValue,
new UpdateValueStrategy<String, String>()
.setAfterGetValidator(new UpdateableErrorValidator<>(
new VariableTextValidator(
this.rSnippetVariableResolver,
Messages.Operation_StartApp_RCode_error_SpecInvalid_message ))),
null );
dbc.bindValue(
WidgetProperties.buttonSelection()
.observe(this.startStopRunningControl),
this.startStopRunningValue );
dbc.bindValue(
WidgetProperties.text(SWT.Modify)
.observe(this.stopRSnippetEditor.getTextControl()),
this.stopRSnippetValue );
}
@Override
public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) {
initDefaults(configuration);
}
@Override
protected void doInitialize(final ILaunchConfiguration configuration) {
// this.appPathValue.setValue(readAttribute(configuration, AppControlConfigs.EXPL_SOURCE_PATH_ATTR_NAME,
// "" )); //$NON-NLS-1$
{ final String text= readAttribute(configuration,
AppControlConfigs.APP_HOST_ATTR_NAME,
"" ); //$NON-NLS-1$
this.appHostValue.setValue(text);
}
{ final int port= readAttribute(configuration,
AppControlConfigs.APP_PORT_ATTR_NAME,
0 );
this.appPortValue.setValue((port != 0) ? Integer.valueOf(port) : null);
}
{ final int mode= readAttribute(configuration,
AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME,
0 );
this.startStopRunningValue.setValue(mode > 0);
}
{ final String code= readAttribute(configuration,
AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME,
"" ); //$NON-NLS-1$
this.startRSnippetValue.setValue(code);
}
{ final String code= readAttribute(configuration,
AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME,
"" ); //$NON-NLS-1$
this.stopRSnippetValue.setValue(code);
}
}
@Override
protected void doSave(final ILaunchConfigurationWorkingCopy configuration) {
// { final String path= this.appPathValue.getValue();
// configuration.setAttribute(AppControlConfig.EXPL_SOURCE_PATH_ATTR_NAME, path);
// }
{ final String text= this.appHostValue.getValue();
configuration.setAttribute(AppControlConfigs.APP_HOST_ATTR_NAME, text);
}
{ final Integer port= this.appPortValue.getValue();
if (port != null) {
configuration.setAttribute(AppControlConfigs.APP_PORT_ATTR_NAME, port.intValue());
}
else {
configuration.removeAttribute(AppControlConfigs.APP_PORT_ATTR_NAME);
}
}
{ final int mode= (this.startStopRunningValue.getValue()) ? 1 : 0;
configuration.setAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, mode);
}
{ final String code= this.startRSnippetValue.getValue();
configuration.setAttribute(AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME, code);
}
{ final String code= this.stopRSnippetValue.getValue();
configuration.setAttribute(AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME, code);
}
}
}