Java tutorial
/*=============================================================================# # 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.cmd.ui.launching; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.Map; import org.eclipse.core.databinding.Binding; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.beans.BeansObservables; 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.databinding.validation.IValidator; import org.eclipse.core.databinding.validation.ValidationStatus; 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.debug.ui.StringVariableSelectionDialog.VariableFilter; 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.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.statushandlers.StatusManager; import de.walware.ecommons.AbstractSettingsModelObject; import de.walware.ecommons.collections.ConstArrayList; 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.cmd.ui.launching.RCmdLaunching; 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.RConsoleUIPlugin; import de.walware.statet.r.launching.core.RLaunching; import de.walware.statet.r.launching.ui.REnvTab; /** * Main tab to configure R CMD tool launch configs. */ public class RCmdMainTab extends LaunchConfigTabWithDbc { public static final String NS = "de.walware.statet.r.debug/RCmd/"; //$NON-NLS-1$ private static class Cmd extends AbstractSettingsModelObject { public final static int PACKAGE_DIR = 1; public final static int PACKAGE_DIR_OR_ARCHIVE = 2; public final static int DOC = 3; public final static int DOC_OR_DIR = 4; public final static int CUSTOM = 5; private final String fName; private String fCommand; private final int fType; public Cmd(final String name, final String command, final int type) { fName = name; fCommand = command; fType = type; } public String getName() { return fName; } public int getType() { return fType; } public void setCommand(final String command) { fCommand = command.trim(); } public String getCommand() { return fCommand; } } private Cmd[] fCommands; private Cmd fCustomCommand; private ComboViewer fCmdCombo; private Text fCmdText; private Button fHelpButton; private InputArgumentsComposite fArgumentsControl; private ResourceInputComposite fResourceControl; private WritableValue fCmdValue; private WritableValue fArgumentsValue; private WritableValue fResourceValue; boolean fWithHelp = false; private ILaunchConfigurationTab fREnvTab; private ILaunchConfiguration fConfigCache; public RCmdMainTab() { super(); createCommands(); } private void createCommands() { final List<Cmd> commands = new ArrayList<Cmd>(); commands.add(new Cmd(RCmdMessages.RCmd_CmdCheck_name, "CMD check", Cmd.PACKAGE_DIR_OR_ARCHIVE)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdBuild_name, "CMD build", Cmd.PACKAGE_DIR)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdInstall_name, "CMD INSTALL", Cmd.PACKAGE_DIR_OR_ARCHIVE)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdRemove_name, "CMD REMOVE", Cmd.PACKAGE_DIR)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdRdconv_name, "CMD Rdconv", Cmd.DOC)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdRd2dvi_name, "CMD Rd2dvi", Cmd.DOC_OR_DIR)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdRd2txt_name, "CMD Rd2txt", Cmd.DOC)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdSd2Rd_name, "CMD Sd2Rd", Cmd.DOC)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdRoxygen_name, "CMD roxygen", Cmd.PACKAGE_DIR)); //$NON-NLS-1$ commands.add(new Cmd(RCmdMessages.RCmd_CmdSweave_name, "CMD Sweave", Cmd.DOC)); //$NON-NLS-1$ fCustomCommand = new Cmd(RCmdMessages.RCmd_CmdOther_name, "", Cmd.CUSTOM); //$NON-NLS-1$ commands.add(fCustomCommand); fCommands = commands.toArray(new Cmd[commands.size()]); resetCommands(); } private void resetCommands() { fCustomCommand.fCommand = "CMD "; //$NON-NLS-1$ } @Override public String getName() { return RCmdMessages.RCmd_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()); Group group; group = new Group(mainComposite, SWT.NONE); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); group.setText(RCmdMessages.RCmd_MainTab_Cmd_label); createCommandControls(group); final Label note = new Label(mainComposite, SWT.WRAP); note.setText(SharedMessages.Note_label + ": " + fArgumentsControl.getNoteText()); //$NON-NLS-1$ note.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, true)); Dialog.applyDialogFont(parent); initBindings(); } private void createCommandControls(final Composite container) { for (final ILaunchConfigurationTab tab : getLaunchConfigurationDialog().getTabs()) { if (tab instanceof REnvTab) { fREnvTab = tab; break; } } fWithHelp = (fREnvTab != null) && (getLaunchConfigurationDialog() instanceof TrayDialog); container.setLayout(LayoutUtil.applyGroupDefaults(new GridLayout(), 3)); final String[] names = new String[fCommands.length]; for (int i = 0; i < fCommands.length; i++) { names[i] = fCommands[i].getName(); } fCmdCombo = new ComboViewer(container, SWT.DROP_DOWN | SWT.READ_ONLY); fCmdCombo.setContentProvider(new ArrayContentProvider()); fCmdCombo.setLabelProvider(new LabelProvider() { @Override public String getText(final Object element) { final Cmd cmd = (Cmd) element; return cmd.getName(); } }); fCmdCombo.setInput(fCommands); fCmdCombo.getCombo().setVisibleItemCount(names.length); fCmdCombo.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); fCmdText = new Text(container, SWT.BORDER | SWT.SINGLE); fCmdText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, fWithHelp ? 1 : 2, 1)); if (fWithHelp) { fHelpButton = new Button(container, SWT.PUSH); fHelpButton.setText(RCmdMessages.RCmd_MainTab_RunHelp_label); fHelpButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { queryHelp(); } }); final GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false); gd.widthHint = LayoutUtil.hintWidth(fHelpButton); fHelpButton.setLayoutData(gd); } LayoutUtil.addSmallFiller(container, false); fArgumentsControl = new InputArgumentsComposite(container); fArgumentsControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); fResourceControl = new ResourceInputComposite(container, ResourceInputComposite.STYLE_LABEL | ResourceInputComposite.STYLE_TEXT, ResourceInputComposite.MODE_FILE | ResourceInputComposite.MODE_OPEN, ""); //$NON-NLS-1$ fResourceControl.setShowInsertVariable(true, new ConstArrayList<VariableFilter>(DialogUtil.EXCLUDE_JAVA_FILTER), null); fResourceControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); } @Override protected void addBindings(final DataBindingContext dbc, final Realm realm) { fCmdValue = new WritableValue(realm, Cmd.class); fArgumentsValue = new WritableValue(realm, String.class); fResourceValue = new WritableValue(realm, String.class); final IObservableValue cmdSelection = ViewersObservables.observeSingleSelection(fCmdCombo); dbc.bindValue(cmdSelection, fCmdValue, null, null); final IValidator cmdValidator = new IValidator() { @Override public IStatus validate(final Object value) { final String s = (String) value; if (s == null || s.trim().isEmpty()) { return ValidationStatus.warning(RCmdMessages.RCmd_MainTab_error_MissingCMD_message); } return ValidationStatus.ok(); } }; dbc.bindValue(SWTObservables.observeText(fCmdText, SWT.Modify), BeansObservables.observeDetailValue(cmdSelection, "command", String.class), //$NON-NLS-1$ new UpdateValueStrategy().setAfterGetValidator(cmdValidator), new UpdateValueStrategy().setBeforeSetValidator(cmdValidator)); dbc.bindValue(SWTObservables.observeText(fArgumentsControl.getTextControl(), SWT.Modify), fArgumentsValue, null, null); fResourceControl.getValidator().setOnLateResolve(IStatus.WARNING); fResourceControl.getValidator().setOnEmpty(IStatus.OK); fResourceControl.getValidator().setIgnoreRelative(true); final Binding resourceBinding = dbc .bindValue( fResourceControl.getObservable(), fResourceValue, new UpdateValueStrategy() .setAfterGetValidator(new SavableErrorValidator(fResourceControl.getValidator())), null); cmdSelection.addValueChangeListener(new IValueChangeListener() { @Override public void handleValueChange(final ValueChangeEvent event) { final Cmd cmd = (Cmd) event.diff.getNewValue(); if (cmd != null) { fCmdText.setEditable(cmd.getType() == Cmd.CUSTOM); String label; int mode = 0; switch (cmd.getType()) { case Cmd.PACKAGE_DIR: label = RCmdMessages.RCmd_Resource_PackageDir_label; mode = ResourceInputComposite.MODE_DIRECTORY; break; case Cmd.PACKAGE_DIR_OR_ARCHIVE: label = RCmdMessages.RCmd_Resource_PackageDirOrArchive_label; mode = ResourceInputComposite.MODE_FILE | ResourceInputComposite.MODE_DIRECTORY; break; case Cmd.DOC: label = RCmdMessages.RCmd_Resource_Doc_label; mode = ResourceInputComposite.MODE_FILE; break; case Cmd.DOC_OR_DIR: label = RCmdMessages.RCmd_Resource_DocOrDir_label; mode = ResourceInputComposite.MODE_FILE | ResourceInputComposite.MODE_DIRECTORY; break; default: // Cmd.CUSTOM: label = RCmdMessages.RCmd_Resource_Other_label; mode = ResourceInputComposite.MODE_FILE | ResourceInputComposite.MODE_DIRECTORY; break; } fResourceControl.setResourceLabel(label); fResourceControl.setMode(mode | ResourceInputComposite.MODE_OPEN); resourceBinding.validateTargetToModel(); } } }); } @Override public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) { configuration.setAttribute(RCmdLaunching.ATTR_R_CMD_COMMAND, fCommands[0].getCommand()); configuration.setAttribute(RCmdLaunching.ATTR_R_CMD_OPTIONS, ""); //$NON-NLS-1$ configuration.setAttribute(RCmdLaunching.ATTR_R_CMD_RESOURCE, "${resource_loc}"); //$NON-NLS-1$ } @Override protected void doInitialize(final ILaunchConfiguration configuration) { resetCommands(); Cmd cmd = null; try { final String command = configuration.getAttribute(RCmdLaunching.ATTR_R_CMD_COMMAND, ""); //$NON-NLS-1$ for (final Cmd candidate : fCommands) { if (candidate.getCommand().equals(command)) { cmd = candidate; break; } } if (cmd == null) { fCustomCommand.setCommand(command); cmd = fCustomCommand; } } catch (final CoreException e) { cmd = fCommands[0]; logReadingError(e); } fCmdValue.setValue(cmd); String options = null; try { options = configuration.getAttribute(RCmdLaunching.ATTR_R_CMD_OPTIONS, ""); //$NON-NLS-1$ } catch (final CoreException e) { options = ""; //$NON-NLS-1$ logReadingError(e); } fArgumentsValue.setValue(options); String resource = null; try { resource = configuration.getAttribute(RCmdLaunching.ATTR_R_CMD_RESOURCE, ""); //$NON-NLS-1$ } catch (final CoreException e) { resource = ""; //$NON-NLS-1$ } fResourceValue.setValue(resource); checkHelp(configuration); } @Override public void activated(final ILaunchConfigurationWorkingCopy workingCopy) { checkHelp(workingCopy); super.activated(workingCopy); } private void checkHelp(final ILaunchConfiguration configuration) { fConfigCache = configuration; if (fWithHelp) { fHelpButton.setEnabled(fREnvTab.isValid(fConfigCache)); } } @Override protected void doSave(final ILaunchConfigurationWorkingCopy configuration) { configuration.setAttribute(RCmdLaunching.ATTR_R_CMD_COMMAND, ((Cmd) fCmdValue.getValue()).getCommand()); configuration.setAttribute(RCmdLaunching.ATTR_R_CMD_OPTIONS, (String) fArgumentsValue.getValue()); configuration.setAttribute(RCmdLaunching.ATTR_R_CMD_RESOURCE, (String) fResourceValue.getValue()); } 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); final String cmd = ((Cmd) fCmdValue.getValue()).getCommand().trim(); if (cmd.length() != 0) { cmdLine.addAll(Arrays.asList(cmd.split(" "))); //$NON-NLS-1$ } String arg1 = null; if (cmdLine.size() > 0) { arg1 = cmdLine.remove(0); } cmdLine.addAll(0, renv.getExecCommand(arg1, EnumSet.of(Exec.CMD))); 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, RCmdMessages.RCmd_MainTab_error_CannotRunHelp_message, e), StatusManager.LOG | StatusManager.SHOW); } catch (final InvocationTargetException e) { StatusManager.getManager() .handle(new Status(IStatus.ERROR, RConsoleUIPlugin.PLUGIN_ID, -1, RCmdMessages.RCmd_MainTab_error_WhileRunningHelp_message, e.getTargetException()), StatusManager.LOG | StatusManager.SHOW); } catch (final InterruptedException e) { } } @Override public void dispose() { if (fWithHelp) { HelpRequestor.closeHelpTray((TrayDialog) getLaunchConfigurationDialog()); } super.dispose(); } }