/** * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package org.python.pydev.debug.newconsole.env; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.dialogs.PreferencesUtil; import org.python.pydev.core.IInterpreterInfo; import org.python.pydev.core.IInterpreterManager; import org.python.pydev.core.IPythonNature; import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.NotConfiguredInterpreterException; import org.python.pydev.core.log.Log; import org.python.pydev.debug.model.PyStackFrame; import org.python.pydev.debug.model.PyStackFrameConsole; import org.python.pydev.debug.newconsole.prefs.InteractiveConsolePrefs; import org.python.pydev.editor.PyEdit; import org.python.pydev.plugin.PydevPlugin; import org.python.pydev.plugin.nature.PythonNature; import org.python.pydev.shared_core.structure.Tuple; /** * Helper to choose which kind of jython run will it be. */ final class ChooseProcessTypeDialog extends Dialog { private Button checkboxForCurrentEditor; private Button checkboxPython; private Button checkboxPythonDebug; private Button checkboxJython; private Button checkboxIronpython; private Button checkboxJythonEclipse; private PyEdit activeEditor; private IInterpreterManager interpreterManager; private List<IPythonNature> natures = new ArrayList<IPythonNature>(); private PyStackFrame selectedFrame; private Link link; ChooseProcessTypeDialog(Shell shell, PyEdit activeEditor) { super(shell); this.activeEditor = activeEditor; } @Override protected Control createDialogArea(Composite parent) { Composite area = (Composite) super.createDialogArea(parent); boolean debugButtonCreated = false; if (getSuspendedFrame() != null) { // when debugger is running and valid frame is selected then // displaying debug console as first option createDebugButton(area); debugButtonCreated = true; } checkboxForCurrentEditor = new Button(area, SWT.RADIO); checkboxForCurrentEditor .setToolTipText("Creates a console with the PYTHONPATH used by the current editor (and Jython/Python/IronPython depending on the project type)."); configureEditorButton(); checkboxPython = new Button(area, SWT.RADIO); checkboxPython .setToolTipText("Creates a Python console with the PYTHONPATH containing all the python projects in the workspace."); configureButton(checkboxPython, "Python", PydevPlugin.getPythonInterpreterManager()); checkboxJython = new Button(area, SWT.RADIO); checkboxJython .setToolTipText("Creates a Jython console with the PYTHONPATH containing all the python projects in the workspace."); configureButton(checkboxJython, "Jython", PydevPlugin.getJythonInterpreterManager()); checkboxIronpython = new Button(area, SWT.RADIO); checkboxIronpython .setToolTipText("Creates an IronPython console with the PYTHONPATH containing all the python projects in the workspace."); configureButton(checkboxIronpython, "IronPython", PydevPlugin.getIronpythonInterpreterManager()); checkboxJythonEclipse = new Button(area, SWT.RADIO); checkboxJythonEclipse .setToolTipText("Creates a Jython console using the running Eclipse environment (can potentially halt Eclipse depending on what's done)."); configureButton(checkboxJythonEclipse, "Jython using VM running Eclipse", new JythonEclipseInterpreterManager()); if (!debugButtonCreated) { createDebugButton(area); } link = new Link(area, SWT.LEFT | SWT.WRAP); link.setText("<a>Configure interactive console preferences.</a>\n" + "I.e.: send contents to console on creation,\n" + "connect to variables view, initial commands, etc."); link.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(null, InteractiveConsolePrefs.PREFERENCES_ID, null, null); dialog.open(); } @Override public void widgetDefaultSelected(SelectionEvent e) { } }); return area; } private void createDebugButton(Composite area) { checkboxPythonDebug = new Button(area, SWT.RADIO); checkboxPythonDebug .setToolTipText("Creates a Python debug console associated with the frame selected in the debug view"); configureDebugButton(); } /** * Configures a button related to a given interpreter manager. */ private void configureButton(Button checkBox, String python, IInterpreterManager interpreterManager) { boolean enabled = false; String text; try { if (interpreterManager.getDefaultInterpreterInfo(false) != null) { text = python + " console"; enabled = true; } else { throw new NotConfiguredInterpreterException(); } } catch (MisconfigurationException e) { text = "Unable to create console for " + python + " (interpreter not configured)"; } checkBox.setText(text); checkBox.setEnabled(enabled); } /** * Configures a button related to an editor. * @throws MisconfigurationException */ private void configureEditorButton() { boolean enabled = false; String text; try { if (this.activeEditor != null) { IPythonNature nature = this.activeEditor.getPythonNature(); if (nature != null) { if (nature.getRelatedInterpreterManager().getDefaultInterpreterInfo(false) != null) { text = "Console for currently active editor"; enabled = true; } else { throw new NotConfiguredInterpreterException(); } } else { text = "No python nature configured for the current editor"; } } else { text = "Unable to create console for current editor (no active editor)"; } } catch (MisconfigurationException e) { //expected text = "Unable to create console for current editor (interpreter not configured for the editor)"; } checkboxForCurrentEditor.setText(text); checkboxForCurrentEditor.setEnabled(enabled); } /** * Enable/Disable Pydev debug console radio button * * @param checkBox * @param python * @param interpreterManager */ private void configureDebugButton() { boolean enabled = false; String text = "PyDev Debug Console (Start the debugger and select the valid frame)"; if (getSuspendedFrame() != null) { enabled = true; text = "PyDev Debug Console"; } checkboxPythonDebug.setText(text); checkboxPythonDebug.setEnabled(enabled); } /** * Determine if any frame is selected in the Launch view * * @return */ private PyStackFrame getSuspendedFrame() { IAdaptable context = DebugUITools.getDebugContext(); if (context instanceof PyStackFrame) { if (context instanceof PyStackFrameConsole) { // We already have a real console opened on the Interactive Console, we don't support // opening a special debug console on it return null; } return (PyStackFrame) context; } return null; } /** * Sets the internal pythonpath chosen. */ @Override protected void okPressed() { setSelectedFrame(null); if (checkboxForCurrentEditor.isEnabled() && checkboxForCurrentEditor.getSelection()) { IProject project = this.activeEditor.getProject(); PythonNature nature = PythonNature.getPythonNature(project); natures.add(nature); IInterpreterManager relatedInterpreterManager = nature.getRelatedInterpreterManager(); this.interpreterManager = relatedInterpreterManager; } else if (checkboxPython.isEnabled() && checkboxPython.getSelection()) { this.interpreterManager = PydevPlugin.getPythonInterpreterManager(); } else if (checkboxPythonDebug.isEnabled() && checkboxPythonDebug.getSelection()) { setSelectedFrame(getSuspendedFrame()); this.interpreterManager = PydevPlugin.getPythonInterpreterManager(); } else if (checkboxJython.isEnabled() && checkboxJython.getSelection()) { this.interpreterManager = PydevPlugin.getJythonInterpreterManager(); } else if (checkboxJythonEclipse.isEnabled() && checkboxJythonEclipse.getSelection()) { this.interpreterManager = new JythonEclipseInterpreterManager(); } else if (checkboxIronpython.isEnabled() && checkboxIronpython.getSelection()) { this.interpreterManager = PydevPlugin.getIronpythonInterpreterManager(); } super.okPressed(); } /** * @return the pythonpath/nature to be used or null if not configured (note that the nature can be null) */ public Tuple<Collection<String>, IPythonNature> getPythonpathAndNature(IInterpreterInfo interpreter) { if (this.interpreterManager != null) { if (this.natures.size() == 1) { //chosen for the editor IPythonNature nature = this.natures.get(0); return new Tuple<Collection<String>, IPythonNature>(new ArrayList<String>(nature.getPythonPathNature() .getCompleteProjectPythonPath(interpreter, this.interpreterManager)), nature); } // collect all the python path (no duplicates, hence a set) HashSet<String> pythonpath = new LinkedHashSet<String>(); // Add all the paths in the interpreter (note: it's important that this goes before the // path for the other natures so that if we have something as IPython, the one used will // be the one from the interpreter). pythonpath.addAll(interpreter.getPythonPath()); //we need to get the natures matching the one selected in all the projects. IWorkspace w = ResourcesPlugin.getWorkspace(); for (IProject p : w.getRoot().getProjects()) { PythonNature nature = PythonNature.getPythonNature(p); try { if (nature != null) { if (nature.getRelatedInterpreterManager() == this.interpreterManager) { natures.add(nature); List<String> completeProjectPythonPath = nature.getPythonPathNature() .getCompleteProjectPythonPath(interpreter, this.interpreterManager); if (completeProjectPythonPath != null) { pythonpath.addAll(completeProjectPythonPath); } else { Log.logInfo("Unable to get pythonpath for project: " + nature.getProject() + " (initialization not finished)."); } } } } catch (Exception e) { Log.log(e); } } return new Tuple<Collection<String>, IPythonNature>(pythonpath, null); } return null; } public IInterpreterManager getInterpreterManager() { return this.interpreterManager; } public List<IPythonNature> getNatures() { return natures; } /** * Return the selected frame * * @return */ public PyStackFrame getSelectedFrame() { return selectedFrame; } /** * Set the selectedFrame * * @param selectedFrame */ public void setSelectedFrame(PyStackFrame selectedFrame) { this.selectedFrame = selectedFrame; } }