| /*=============================================================================# |
| # Copyright (c) 2017, 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.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.runtime.CoreException; |
| import org.eclipse.core.variables.IStringVariable; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.jface.databinding.swt.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.ecommons.databinding.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; |
| |
| |
| 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<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().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().setAfterGetValidator( |
| new UpdateableErrorValidator(new VariableTextValidator( |
| this.rSnippetVariableResolver, |
| Messages.Operation_StartApp_RCode_error_SpecInvalid_message ))), |
| null ); |
| dbc.bindValue( |
| WidgetProperties.selection().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) { |
| // { String path= ""; //$NON-NLS-1$ |
| // try { |
| // path= configuration.getAttribute(AppControlConfig.EXPL_SOURCE_PATH_ATTR_NAME, path); |
| // } |
| // catch (final CoreException e) { |
| // logReadingError(e); |
| // } |
| // this.appPathValue.setValue(path); |
| // } |
| |
| { String text= ""; //$NON-NLS-1$ |
| try { |
| text= configuration.getAttribute(AppControlConfigs.APP_HOST_ATTR_NAME, text); |
| } |
| catch (final CoreException e) { |
| logReadingError(e); |
| } |
| this.appHostValue.setValue(text); |
| } |
| { int port= 0; |
| try { |
| port= configuration.getAttribute(AppControlConfigs.APP_PORT_ATTR_NAME, port); |
| } |
| catch (final CoreException e) { |
| logReadingError(e); |
| } |
| this.appPortValue.setValue((port != 0) ? Integer.valueOf(port) : null); |
| } |
| |
| { int mode= 0; |
| try { |
| mode= configuration.getAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, mode); |
| } |
| catch (final CoreException e) { |
| logReadingError(e); |
| } |
| this.startStopRunningValue.setValue(mode > 0); |
| } |
| { String code= ""; //$NON-NLS-1$ |
| try { |
| code= configuration.getAttribute(AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME, code); |
| } |
| catch (final CoreException e) { |
| logReadingError(e); |
| } |
| this.startRSnippetValue.setValue(code); |
| } |
| { String code= ""; //$NON-NLS-1$ |
| try { |
| code= configuration.getAttribute(AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME, code); |
| } |
| catch (final CoreException e) { |
| logReadingError(e); |
| } |
| 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); |
| } |
| } |
| |
| } |