de.walware.statet.r.internal.console.ui.launching.RConsoleMainTab.java Source code

Java tutorial

Introduction

Here is the source code for de.walware.statet.r.internal.console.ui.launching.RConsoleMainTab.java

Source

/*=============================================================================#
 # Copyright (c) 2007-2015 Stephan Wahlbrink (WalWare.de) and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
 # http://www.eclipse.org/legal/epl-v10.html
 # 
 # Contributors:
 #     Stephan Wahlbrink - initial API and implementation
 #=============================================================================*/

package de.walware.statet.r.internal.console.ui.launching;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
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.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.TrayDialog;
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.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.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.ui.PlatformUI;
import org.eclipse.ui.statushandlers.StatusManager;

import de.walware.ecommons.debug.ui.HelpRequestor;
import de.walware.ecommons.debug.ui.InputArgumentsComposite;
import de.walware.ecommons.debug.ui.LaunchConfigTabWithDbc;
import de.walware.ecommons.debug.ui.LaunchConfigUtil;
import de.walware.ecommons.ui.SharedMessages;
import de.walware.ecommons.ui.util.DialogUtil;
import de.walware.ecommons.ui.util.LayoutUtil;
import de.walware.ecommons.ui.workbench.ResourceInputComposite;

import de.walware.statet.base.ui.StatetImages;

import de.walware.statet.r.console.ui.IRConsoleHelpContextIds;
import de.walware.statet.r.console.ui.launching.RConsoleLaunching;
import de.walware.statet.r.core.renv.IREnvConfiguration;
import de.walware.statet.r.core.renv.IREnvConfiguration.Exec;
import de.walware.statet.r.internal.console.ui.RConsoleMessages;
import de.walware.statet.r.internal.console.ui.RConsoleUIPlugin;
import de.walware.statet.r.launching.core.RLaunching;
import de.walware.statet.r.launching.ui.REnvTab;

/**
 * Main tab for R Console launch config.
 */
public class RConsoleMainTab extends LaunchConfigTabWithDbc {

    private class RArgumentsComposite extends InputArgumentsComposite {

        public RArgumentsComposite(final Composite parent) {
            super(parent);
        }

        @Override
        protected void fillMenu(final Menu menu) {
            super.fillMenu(menu);

            if (fWithHelp) {
                fHelpItem = new MenuItem(menu, SWT.PUSH);
                fHelpItem.setText(RConsoleMessages.RConsole_MainTab_RunHelp_label);
                fHelpItem.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(final SelectionEvent e) {
                        queryHelp();
                        getTextControl().setFocus();
                    }
                });
                checkHelp(fConfigCache);
            }
        }
    }

    private final RConsoleType[] fTypes;
    private final RConsoleType fDefaultType;

    private ComboViewer fTypesCombo;

    private ResourceInputComposite fWorkingDirectoryControl;
    private RArgumentsComposite fArgumentsControl;

    private WritableValue fTypeValue;
    private WritableValue fWorkingDirectoryValue;
    protected WritableValue fArgumentsValue;

    boolean fWithHelp = false;
    private MenuItem fHelpItem;
    private ILaunchConfigurationTab fREnvTab;
    private ILaunchConfiguration fConfigCache;

    public RConsoleMainTab() {
        super();
        fTypes = loadTypes();
        fDefaultType = fTypes[0];
    }

    protected RConsoleType[] loadTypes() {
        final List<RConsoleType> types = new ArrayList<RConsoleType>();
        types.add(new RConsoleType("RJ (default)", RConsoleLaunching.LOCAL_RJS, true, true)); //$NON-NLS-1$
        types.add(new RConsoleType("Rterm", RConsoleLaunching.LOCAL_RTERM, false, false)); //$NON-NLS-1$
        return types.toArray(new RConsoleType[types.size()]);
    }

    RConsoleType getSelectedType() {
        if (fTypeValue != null) {
            return (RConsoleType) fTypeValue.getValue();
        }
        return null;
    }

    @Override
    public String getName() {
        return RConsoleMessages.RConsole_MainTab_name;
    }

    @Override
    public Image getImage() {
        return StatetImages.getImage(StatetImages.LAUNCHCONFIG_MAIN);
    }

    @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());

        { // Type
            final Composite composite = new Composite(mainComposite, SWT.NONE);
            composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
            composite.setLayout(LayoutUtil.applyCompositeDefaults(new GridLayout(), 2));

            final Label label = new Label(composite, SWT.LEFT);
            label.setText(RConsoleMessages.RConsole_MainTab_LaunchType_label + ':');
            label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

            final String[] names = new String[fTypes.length];
            for (int i = 0; i < fTypes.length; i++) {
                names[i] = fTypes[i].getName();
            }
            fTypesCombo = new ComboViewer(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
            fTypesCombo.setContentProvider(new ArrayContentProvider());
            fTypesCombo.setLabelProvider(new LabelProvider() {
                @Override
                public String getText(final Object element) {
                    final RConsoleType type = (RConsoleType) element;
                    return type.getName();
                }
            });
            fTypesCombo.setInput(fTypes);
            fTypesCombo.getCombo().setVisibleItemCount(names.length);
            fTypesCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
            fTypesCombo.getControl().setEnabled(fTypes.length > 1);
        }

        final Composite detailGroup = createTypeDetailGroup(mainComposite);
        if (detailGroup != null) {
            detailGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        }

        final Composite commandGroup = createROptionsGroup(mainComposite);
        commandGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

        LayoutUtil.addSmallFiller(mainComposite, true);
        createFooter(mainComposite);

        Dialog.applyDialogFont(parent);
        initBindings();

        PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IRConsoleHelpContextIds.R_CONSOLE_LAUNCH);
    }

    private Composite createROptionsGroup(final Composite parent) {
        for (final ILaunchConfigurationTab tab : getLaunchConfigurationDialog().getTabs()) {
            if (tab instanceof REnvTab) {
                fREnvTab = tab;
                break;
            }
        }
        fWithHelp = (fREnvTab != null) && (getLaunchConfigurationDialog() instanceof TrayDialog);

        final Group group = new Group(parent, SWT.NONE);
        group.setLayout(LayoutUtil.applyGroupDefaults(new GridLayout(), 3));
        group.setText("R options:");

        fWorkingDirectoryControl = new ResourceInputComposite(group,
                ResourceInputComposite.STYLE_LABEL | ResourceInputComposite.STYLE_TEXT,
                ResourceInputComposite.MODE_DIRECTORY | ResourceInputComposite.MODE_OPEN,
                RConsoleMessages.RConsole_MainTab_WorkingDir_label);
        fWorkingDirectoryControl.setShowInsertVariable(true, DialogUtil.DEFAULT_INTERACTIVE_FILTERS, null);
        fWorkingDirectoryControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));

        fArgumentsControl = new RArgumentsComposite(group);
        fArgumentsControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));

        return group;
    }

    protected Composite createTypeDetailGroup(final Composite parent) {
        return null;
    }

    protected Composite getArgumentComposite() {
        return fArgumentsControl;
    }

    protected void createFooter(final Composite composite) {
        final Label note = new Label(composite, SWT.WRAP);
        note.setText(SharedMessages.Note_label + ": " + fArgumentsControl.getNoteText()); //$NON-NLS-1$
        note.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
    }

    @Override
    protected void addBindings(final DataBindingContext dbc, final Realm realm) {
        fTypeValue = new WritableValue(realm, RConsoleType.class);
        fWorkingDirectoryValue = new WritableValue(realm, null, String.class);
        fArgumentsValue = new WritableValue(realm, String.class);

        final IObservableValue typeSelection = ViewersObservables.observeSingleSelection(fTypesCombo);
        dbc.bindValue(typeSelection, fTypeValue, null, null);

        dbc.bindValue(SWTObservables.observeText(fArgumentsControl.getTextControl(), SWT.Modify), fArgumentsValue,
                null, null);

        fWorkingDirectoryControl.getValidator().setOnEmpty(IStatus.OK);
        dbc.bindValue(
                fWorkingDirectoryControl.getObservable(), fWorkingDirectoryValue, new UpdateValueStrategy()
                        .setAfterGetValidator(new SavableErrorValidator(fWorkingDirectoryControl.getValidator())),
                null);

        fTypeValue.addValueChangeListener(new IValueChangeListener() {
            @Override
            public void handleValueChange(final ValueChangeEvent event) {
                final Object newValue = event.diff.getNewValue();
                updateType((RConsoleType) newValue);
            }
        });
    }

    public RConsoleType getType() {
        return (RConsoleType) fTypeValue.getValue();
    }

    protected IObservableValue getTypeValue() {
        return fTypeValue;
    }

    /**
     * @param typeId
     */
    protected void updateType(final RConsoleType type) {
    }

    @Override
    public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) {
        configuration.setAttribute(RConsoleLaunching.ATTR_TYPE, fDefaultType.getId()); //s
        configuration.setAttribute(RConsoleLaunching.ATTR_OPTIONS, ""); //$NON-NLS-1$
        configuration.setAttribute(RConsoleLaunching.ATTR_PIN_CONSOLE, false);
    }

    @Override
    protected void doInitialize(final ILaunchConfiguration configuration) {
        String type = null;
        try {
            type = configuration.getAttribute(RConsoleLaunching.ATTR_TYPE, ""); //$NON-NLS-1$
            // convert old rterm to new rj
            if (type.equals("rterm")) { //$NON-NLS-1$
                type = RConsoleLaunching.LOCAL_RTERM;
            }
        } catch (final CoreException e) {
            type = ""; //$NON-NLS-1$
            logReadingError(e);
        }
        int i = 0;
        for (; i < fTypes.length; i++) {
            if (fTypes[i].getId().equals(type)) {
                fTypeValue.setValue(fTypes[i]);
                break;
            }
        }
        if (i >= fTypes.length) {
            fTypeValue.setValue(fDefaultType);
        }

        String wd = null;
        try {
            wd = REnvTab.readWorkingDirectory(configuration);
        } catch (final CoreException e) {
            wd = ""; //$NON-NLS-1$
            logReadingError(e);
        }
        fWorkingDirectoryValue.setValue(wd);

        String options = null;
        try {
            options = configuration.getAttribute(RConsoleLaunching.ATTR_OPTIONS, ""); //$NON-NLS-1$
        } catch (final CoreException e) {
            options = ""; //$NON-NLS-1$
            logReadingError(e);
        }
        fArgumentsValue.setValue(options);

        checkHelp(configuration);
    }

    @Override
    public void activated(final ILaunchConfigurationWorkingCopy workingCopy) {
        checkHelp(workingCopy);
        super.activated(workingCopy);
    }

    @Override
    protected void doSave(final ILaunchConfigurationWorkingCopy configuration) {
        configuration.setAttribute(RConsoleLaunching.ATTR_TYPE, ((RConsoleType) fTypeValue.getValue()).getId());
        if (fArgumentsControl.isEnabled()) {
            configuration.setAttribute(RConsoleLaunching.ATTR_OPTIONS, (String) fArgumentsValue.getValue());
        } else {
            configuration.removeAttribute(RConsoleLaunching.ATTR_OPTIONS);
        }

        REnvTab.setWorkingDirectory(configuration, (String) fWorkingDirectoryValue.getValue());
    }

    private void checkHelp(final ILaunchConfiguration configuration) {
        fConfigCache = configuration;
        if (fWithHelp && fHelpItem != null) {
            fHelpItem.setEnabled(fREnvTab.isValid(fConfigCache));
        }
    }

    private void queryHelp() {
        if (!fWithHelp) {
            return;
        }
        try {
            final List<String> cmdLine = new ArrayList<String>();
            final ILaunchConfigurationDialog dialog = getLaunchConfigurationDialog();

            // r env
            final IREnvConfiguration renv = RLaunching.getREnvConfig(fConfigCache, true);

            cmdLine.addAll(0, renv.getExecCommand(Exec.TERM));

            cmdLine.add("--help"); //$NON-NLS-1$
            final ProcessBuilder processBuilder = new ProcessBuilder(cmdLine);
            final HelpRequestor helper = new HelpRequestor(processBuilder, (TrayDialog) dialog);

            final Map<String, String> envp = processBuilder.environment();
            LaunchConfigUtil.configureEnvironment(envp, fConfigCache, renv.getEnvironmentsVariables());

            dialog.run(true, true, helper);
            updateLaunchConfigurationDialog();
        } catch (final CoreException e) {
            StatusManager.getManager()
                    .handle(new Status(IStatus.ERROR, RConsoleUIPlugin.PLUGIN_ID, -1,
                            RConsoleMessages.RConsole_MainTab_error_CannotRunHelp_message, e),
                            StatusManager.LOG | StatusManager.SHOW);
        } catch (final InvocationTargetException e) {
            StatusManager.getManager().handle(new Status(IStatus.ERROR, RConsoleUIPlugin.PLUGIN_ID, -1,
                    RConsoleMessages.RConsole_MainTab_error_WhileRunningHelp_message, e.getTargetException()),
                    StatusManager.LOG | StatusManager.SHOW);
        } catch (final InterruptedException e) {
            // canceled
        }
    }

    @Override
    public void dispose() {
        if (fWithHelp) {
            HelpRequestor.closeHelpTray((TrayDialog) getLaunchConfigurationDialog());
        }
        super.dispose();
    }

}