| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.debug.ui.launchConfigurations; |
| |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.ui.ILaunchConfigurationTab; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.environment.EnvironmentManager; |
| import org.eclipse.dltk.core.environment.IEnvironment; |
| import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin; |
| import org.eclipse.dltk.debug.ui.messages.ScriptLaunchMessages; |
| import org.eclipse.dltk.internal.debug.ui.interpreters.AbstractInterpreterComboBlock; |
| import org.eclipse.dltk.internal.debug.ui.interpreters.IInterpreterComboBlockContext; |
| import org.eclipse.dltk.internal.debug.ui.interpreters.InterpreterDescriptor; |
| import org.eclipse.dltk.launching.IInterpreterInstall; |
| import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants; |
| import org.eclipse.dltk.launching.ScriptRuntime; |
| import org.eclipse.dltk.ui.DLTKPluginImages; |
| import org.eclipse.dltk.ui.viewsupport.ImageDescriptorRegistry; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Font; |
| 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.Control; |
| |
| /** |
| * A launch configuration tab that displays and edits the Interpreter install |
| * launch configuration attributes. |
| * <p> |
| * This class may be instantiated. This class is not intended to be subclassed. |
| * </p> |
| */ |
| |
| public class InterpreterTab extends CommonScriptLaunchTab { |
| |
| // Interpreter Block |
| protected AbstractInterpreterComboBlock fInterpreterBlock; |
| |
| // Dynamic Interpreter UI widgets |
| protected ILaunchConfigurationTab fDynamicTab; |
| protected Composite fDynamicTabHolder; |
| protected boolean fUseDynamicArea = true; |
| |
| protected ILaunchConfigurationWorkingCopy fWorkingCopy; |
| protected ILaunchConfiguration fLaunchConfiguration; |
| |
| // State |
| protected boolean fIsInitializing = false; |
| |
| private final IMainLaunchConfigurationTab fMainTab; |
| |
| /** |
| * @since 2.0 |
| */ |
| public InterpreterTab(IMainLaunchConfigurationTab mainTab) { |
| this.fMainTab = mainTab; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| protected IMainLaunchConfigurationTab getMainTab() { |
| return fMainTab; |
| } |
| |
| // Selection changed listener (checked InterpreterEnvironment) |
| private IPropertyChangeListener fCheckListener = event -> handleSelectedInterpreterChanged(); |
| |
| // Constants |
| protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| |
| @Override |
| public void dispose() { |
| super.dispose(); |
| registry.dispose(); |
| if (fInterpreterBlock != null) { |
| fInterpreterBlock.removePropertyChangeListener(fCheckListener); |
| } |
| } |
| |
| @Override |
| public void createControl(Composite parent) { |
| Font font = parent.getFont(); |
| |
| Composite topComp = new Composite(parent, SWT.NONE); |
| setControl(topComp); |
| // PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), |
| // IScriptDebugHelpContextIds. |
| // LAUNCH_CONFIGURATION_DIALOG_InterpreterEnvironment_TAB); |
| GridLayout topLayout = new GridLayout(); |
| topLayout.numColumns = 1; |
| topLayout.marginHeight = 0; |
| topLayout.marginWidth = 0; |
| topComp.setLayout(topLayout); |
| GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| topComp.setLayoutData(gd); |
| topComp.setFont(font); |
| |
| fInterpreterBlock = createInterpreterBlock( |
| createInterpreterBlockHost()); |
| if (mainListener == null) { |
| mainListener = new MainListener(); |
| getMainTab().addListener(mainListener); |
| } |
| fInterpreterBlock.setDefaultInterpreterDescriptor( |
| getDefaultInterpreterDescriptor()); |
| fInterpreterBlock.setSpecificInterpreterDescriptor( |
| getSpecificInterpreterDescriptor()); |
| fInterpreterBlock.createControl(topComp); |
| Control control = fInterpreterBlock.getControl(); |
| fInterpreterBlock.addPropertyChangeListener(fCheckListener); |
| gd = new GridData(GridData.FILL_BOTH); |
| control.setLayoutData(gd); |
| |
| Composite dynTabComp = new Composite(topComp, SWT.NONE); |
| dynTabComp.setFont(font); |
| |
| setDynamicTabHolder(dynTabComp); |
| GridLayout tabHolderLayout = new GridLayout(); |
| tabHolderLayout.marginHeight = 0; |
| tabHolderLayout.marginWidth = 0; |
| tabHolderLayout.numColumns = 1; |
| getDynamicTabHolder().setLayout(tabHolderLayout); |
| gd = new GridData(GridData.FILL_BOTH); |
| getDynamicTabHolder().setLayoutData(gd); |
| } |
| |
| private IMainLaunchConfigurationTabListener mainListener = null; |
| |
| private class MainListener implements IMainLaunchConfigurationTabListener { |
| @Override |
| public void projectChanged(IProject project) { |
| refreshInterpreters(); |
| } |
| |
| @Override |
| public void interactiveChanged(boolean state) { |
| } |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| protected void refreshInterpreters() { |
| fInterpreterBlock.refreshInterpreters(); |
| } |
| |
| /** |
| * @return |
| */ |
| private IInterpreterComboBlockContext createInterpreterBlockHost() { |
| return new IInterpreterComboBlockContext() { |
| |
| @Override |
| public int getMode() { |
| return M_LAUNCH_CONFIGURATION; |
| } |
| |
| @Override |
| public IEnvironment getEnvironment() { |
| final IScriptProject project = getScriptProject(); |
| if (project != null) { |
| return EnvironmentManager.getEnvironment(project); |
| } else { |
| return EnvironmentManager.getLocalEnvironment(); |
| } |
| } |
| |
| @Override |
| public String getNatureId() { |
| return fMainTab.getNatureID(); |
| } |
| }; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| protected AbstractInterpreterComboBlock createInterpreterBlock( |
| IInterpreterComboBlockContext context) { |
| return new AbstractInterpreterComboBlock(context); |
| } |
| |
| protected void setDynamicTabHolder(Composite tabHolder) { |
| this.fDynamicTabHolder = tabHolder; |
| } |
| |
| protected Composite getDynamicTabHolder() { |
| return fDynamicTabHolder; |
| } |
| |
| protected void setDynamicTab(ILaunchConfigurationTab tab) { |
| fDynamicTab = tab; |
| } |
| |
| protected ILaunchConfigurationTab getDynamicTab() { |
| return fDynamicTab; |
| } |
| |
| @Override |
| public void setDefaults(ILaunchConfigurationWorkingCopy config) { |
| setLaunchConfigurationWorkingCopy(config); |
| ILaunchConfigurationTab dynamicTab = getDynamicTab(); |
| if (dynamicTab != null) { |
| dynamicTab.setDefaults(config); |
| } |
| } |
| |
| @Override |
| public void initializeFrom(ILaunchConfiguration configuration) { |
| fIsInitializing = true; |
| getControl().setRedraw(false); |
| setLaunchConfiguration(configuration); |
| updateInterpreterFromConfig(configuration); |
| fInterpreterBlock.setDefaultInterpreterDescriptor( |
| getDefaultInterpreterDescriptor()); |
| fInterpreterBlock.refreshInterpreters(); |
| ILaunchConfigurationTab dynamicTab = getDynamicTab(); |
| if (dynamicTab != null) { |
| dynamicTab.initializeFrom(configuration); |
| } |
| getControl().setRedraw(true); |
| fIsInitializing = false; |
| } |
| |
| protected final String getNature() { |
| return fMainTab.getNatureID(); |
| } |
| |
| @Override |
| public void performApply(ILaunchConfigurationWorkingCopy configuration) { |
| configuration.setAttribute( |
| ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE, |
| getNature()); |
| if (fInterpreterBlock.isDefaultInterpreter()) { |
| configuration.setAttribute( |
| ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH, |
| (String) null); |
| } else { |
| IPath containerPath = fInterpreterBlock.getInterpreterPath(); |
| String portablePath = null; |
| if (containerPath != null) { |
| portablePath = containerPath.toPortableString(); |
| } |
| configuration.setAttribute( |
| ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH, |
| portablePath); |
| } |
| |
| // Handle any attributes in the Interpreter-specific area |
| ILaunchConfigurationTab dynamicTab = getDynamicTab(); |
| if (dynamicTab == null) { |
| configuration.setAttribute( |
| ScriptLaunchConfigurationConstants.ATTR_INTERPRETER_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, |
| (Map<String, String>) null); |
| } else { |
| dynamicTab.performApply(configuration); |
| } |
| } |
| |
| @Override |
| public boolean isValid(ILaunchConfiguration config) { |
| |
| setErrorMessage(null); |
| setMessage(null); |
| |
| IStatus status = fInterpreterBlock.getStatus(); |
| if (!status.isOK()) { |
| setErrorMessage(status.getMessage()); |
| return false; |
| } |
| |
| ILaunchConfigurationTab dynamicTab = getDynamicTab(); |
| if (dynamicTab != null) { |
| return dynamicTab.isValid(config); |
| } |
| return true; |
| } |
| |
| @Override |
| public String getName() { |
| return ScriptLaunchMessages.InterpreterTab__Interp_1; |
| } |
| |
| @Override |
| public Image getImage() { |
| return registry.get(DLTKPluginImages.DESC_OBJS_NATIVE_LIB_PATH_ATTRIB); |
| } |
| |
| private final ImageDescriptorRegistry registry = new ImageDescriptorRegistry( |
| false); |
| |
| protected void updateInterpreterFromConfig(ILaunchConfiguration config) { |
| try { |
| String path = config.getAttribute( |
| ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH, |
| (String) null); |
| if (path != null) { |
| fInterpreterBlock.setPath(Path.fromPortableString(path)); |
| return; |
| } |
| } catch (CoreException e) { |
| DLTKDebugUIPlugin.log(e); |
| } |
| fInterpreterBlock.setUseDefaultInterpreter(); |
| } |
| |
| /** |
| * Notification that the user changed the selection in the |
| * InterpreterEnvironment combination box. |
| */ |
| protected void handleSelectedInterpreterChanged() { |
| loadDynamicInterpreterArea(); |
| |
| // always set the newly created area with defaults |
| ILaunchConfigurationWorkingCopy wc = getLaunchConfigurationWorkingCopy(); |
| if (getDynamicTab() == null) { |
| // remove any Interpreter specific arguments from the config |
| if (wc == null) { |
| if (getLaunchConfiguration().isWorkingCopy()) { |
| wc = (ILaunchConfigurationWorkingCopy) getLaunchConfiguration(); |
| } |
| } |
| if (!fIsInitializing) { |
| if (wc != null) { |
| wc.setAttribute( |
| ScriptLaunchConfigurationConstants.ATTR_INTERPRETER_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, |
| (Map<String, String>) null); |
| } |
| } |
| } else { |
| if (wc == null) { |
| try { |
| if (getLaunchConfiguration().isWorkingCopy()) { |
| // get a fresh copy to work on |
| wc = ((ILaunchConfigurationWorkingCopy) getLaunchConfiguration()) |
| .getOriginal().getWorkingCopy(); |
| } else { |
| wc = getLaunchConfiguration().getWorkingCopy(); |
| } |
| } catch (CoreException e) { |
| DLTKDebugUIPlugin.errorDialog( |
| ScriptLaunchMessages.InterpreterTab_Unable_to_initialize_defaults_for_selected_InterpreterEnvironment_1, |
| e); |
| return; |
| } |
| } |
| if (!fIsInitializing) { |
| getDynamicTab().setDefaults(wc); |
| getDynamicTab().initializeFrom(wc); |
| } |
| } |
| |
| updateLaunchConfigurationDialog(); |
| } |
| |
| protected void selectInterpreter(String typeID, String InterpreterName) { |
| if (typeID == null) { |
| fInterpreterBlock.setUseDefaultInterpreter(); |
| } else { |
| fInterpreterBlock.setPath(ScriptRuntime |
| .newInterpreterContainerPath(typeID, InterpreterName)); |
| } |
| } |
| |
| /** |
| * Return the class that implements <code>ILaunchConfigurationTab</code> |
| * that is registered against the install type of the currently selected |
| * Interpreter. |
| */ |
| protected ILaunchConfigurationTab getTabForCurrentInterpreter() { |
| IPath path = fInterpreterBlock.getInterpreterPath(); |
| if (path != null) { |
| IInterpreterInstall Interpreter = fInterpreterBlock |
| .getInterpreter(); |
| if (Interpreter != null) { |
| String InterpreterInstallTypeID = Interpreter |
| .getInterpreterInstallType().getId(); |
| return DLTKDebugUIPlugin.getDefault() |
| .getInterpreterInstallTypePage( |
| InterpreterInstallTypeID); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Show the contributed piece of UI that was registered for the install type |
| * of the currently selected Interpreter. |
| */ |
| protected void loadDynamicInterpreterArea() { |
| |
| // Dispose of any current child widgets in the tab holder area |
| Control[] children = getDynamicTabHolder().getChildren(); |
| for (int i = 0; i < children.length; i++) { |
| children[i].dispose(); |
| } |
| |
| if (isUseDynamicInterpreterArea()) { |
| // Retrieve the dynamic UI for the current InterpreterEnvironment |
| setDynamicTab(getTabForCurrentInterpreter()); |
| if (getDynamicTab() == null) { |
| return; |
| } |
| |
| // Ask the dynamic UI to create its Control |
| getDynamicTab().setLaunchConfigurationDialog( |
| getLaunchConfigurationDialog()); |
| getDynamicTab().createControl(getDynamicTabHolder()); |
| getDynamicTabHolder().layout(); |
| } |
| |
| } |
| |
| protected ILaunchConfigurationWorkingCopy getLaunchConfigurationWorkingCopy() { |
| return fWorkingCopy; |
| } |
| |
| /** |
| * Overridden here so that any error message in the dynamic UI gets |
| * returned. |
| * |
| * @see ILaunchConfigurationTab#getErrorMessage() |
| */ |
| @Override |
| public String getErrorMessage() { |
| ILaunchConfigurationTab tab = getDynamicTab(); |
| if ((super.getErrorMessage() != null) || (tab == null)) { |
| return super.getErrorMessage(); |
| } |
| return tab.getErrorMessage(); |
| } |
| |
| protected void setLaunchConfigurationWorkingCopy( |
| ILaunchConfigurationWorkingCopy workingCopy) { |
| fWorkingCopy = workingCopy; |
| } |
| |
| protected ILaunchConfiguration getLaunchConfiguration() { |
| return fLaunchConfiguration; |
| } |
| |
| protected void setLaunchConfiguration( |
| ILaunchConfiguration launchConfiguration) { |
| fLaunchConfiguration = launchConfiguration; |
| } |
| |
| /** |
| * Sets whether this tab will display the Interpreter specific arguments |
| * area if a InterpreterEnvironment supports Interpreter specific arguments. |
| * |
| * @param visible |
| * whether this tab will display the Interpreter specific |
| * arguments area if a InterpreterEnvironment supports |
| * Interpreter specific arguments |
| */ |
| public void setInterpreterSpecificArgumentsVisible(boolean visible) { |
| fUseDynamicArea = visible; |
| } |
| |
| protected boolean isUseDynamicInterpreterArea() { |
| return fUseDynamicArea; |
| } |
| |
| protected InterpreterDescriptor getDefaultInterpreterDescriptor() { |
| return new InterpreterDescriptor() { |
| |
| @Override |
| public String getDescription() { |
| final IScriptProject project = getScriptProject(); |
| String name = ScriptLaunchMessages.InterpreterTab_7; |
| if (!isValid(project)) { |
| final IInterpreterInstall interpreter = getWorkspaceInterpreter( |
| project); |
| if (interpreter != null) { |
| name = interpreter.getName(); |
| } |
| return NLS.bind(ScriptLaunchMessages.InterpreterTab_8, |
| name); |
| } |
| IInterpreterInstall interpreter = getProjectInterpreter( |
| project); |
| if (interpreter != null) { |
| name = interpreter.getName(); |
| } |
| return NLS.bind(ScriptLaunchMessages.InterpreterTab_9, name); |
| } |
| |
| private boolean isValid(final IScriptProject project) { |
| return project != null && project.getProject().isAccessible(); |
| } |
| |
| private IInterpreterInstall getProjectInterpreter( |
| IScriptProject project) { |
| try { |
| return ScriptRuntime.getInterpreterInstall(project); |
| } catch (CoreException e) { |
| return null; |
| } |
| } |
| |
| private IInterpreterInstall getWorkspaceInterpreter( |
| IScriptProject project) { |
| final IEnvironment environment = EnvironmentManager |
| .getEnvironment(project); |
| return ScriptRuntime.getDefaultInterpreterInstall(getNature(), |
| environment); |
| } |
| |
| @Override |
| public IInterpreterInstall getInterpreter() { |
| final IScriptProject project = getScriptProject(); |
| if (!isValid(project)) { |
| return getWorkspaceInterpreter(project); |
| } else { |
| return getProjectInterpreter(project); |
| } |
| } |
| }; |
| } |
| |
| protected InterpreterDescriptor getSpecificInterpreterDescriptor() { |
| return null; |
| } |
| |
| /** |
| * Returns the Script project associated with the current config being |
| * edited, or <code>null</code> if none. |
| * |
| * @return scriptproject or <code>null</code> |
| */ |
| protected IScriptProject getScriptProject() { |
| return fMainTab.getProject(); |
| } |
| |
| @Override |
| public void activated(ILaunchConfigurationWorkingCopy workingCopy) { |
| // update the default InterpreterEnvironment description, in case it has |
| // changed |
| // based on the selected project |
| fInterpreterBlock.refresh(); |
| } |
| |
| @Override |
| public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) { |
| // do nothing when deactivated |
| } |
| } |