mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
move scientific mode and SciView toolwindow to pro only
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyAnnotatingVisitor"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyDumbAwareAnnotator"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.inspections.PyCompatibilityInspectionAdvertiser"/>
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.inspections.PySciViewAdvertiser"/>
|
||||
|
||||
<quoteHandler fileType="Python" className="com.jetbrains.python.editor.PythonQuoteHandler"/>
|
||||
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PythonEnterHandler"/>
|
||||
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PyEnterAtIndentHandler" order="first"/>
|
||||
@@ -624,16 +624,14 @@
|
||||
<breadcrumbsInfoProvider implementation="com.jetbrains.python.breadcrumbs.PyBreadcrumbsInfoProvider"/>
|
||||
<highlightVisitor implementation="com.jetbrains.python.highlighting.PyRainbowVisitor"/>
|
||||
|
||||
<toolWindow id="SciView" factoryClass="com.jetbrains.python.debugger.containerview.PyDataViewToolWindowFactory" anchor="right" icon="PythonIcons.Python.DataView"/>
|
||||
<projectService serviceInterface="com.jetbrains.python.debugger.containerview.PyDataView" serviceImplementation="com.jetbrains.python.debugger.containerview.PyDataView"/>
|
||||
<projectService serviceInterface="com.jetbrains.python.plots.PyPlotToolWindow" serviceImplementation="com.jetbrains.python.plots.PyPlotToolWindow"/>
|
||||
|
||||
<createFromTemplateHandler implementation="com.jetbrains.python.packaging.setupPy.PyCreateSetupPyFromTemplateHandler"/>
|
||||
<consoleHistoryModelProvider implementation="com.jetbrains.python.console.PyConsoleHistoryModelProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Pythonid.pythonDocumentationQuickInfoProvider" interface="com.jetbrains.python.documentation.PythonDocumentationQuickInfoProvider"/>
|
||||
<extensionPoint qualifiedName="Pythonid.pythonCommandLineEnvironmentProvider" interface="com.jetbrains.python.run.PythonCommandLineEnvironmentProvider"/>
|
||||
<extensionPoint qualifiedName="Pythonid.importResolver" interface="com.jetbrains.python.psi.impl.PyImportResolver"/>
|
||||
<extensionPoint qualifiedName="Pythonid.magicLiteral" interface="com.jetbrains.python.magicLiteral.PyMagicLiteralExtensionPoint"/>
|
||||
<extensionPoint qualifiedName="Pythonid.unresolvedReferenceSkipper" interface="com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferenceSkipperExtPoint"/>
|
||||
@@ -881,10 +879,6 @@
|
||||
<add-to-group group-id="DebugMainMenu" relative-to-action="ForceRunToCursor" anchor="after"/>
|
||||
<add-to-group group-id="EditorPopupMenuDebug" relative-to-action="ForceRunToCursor" anchor="after"/>
|
||||
</action>
|
||||
|
||||
<action id="PySciView" class="com.jetbrains.python.actions.PySciViewAction">
|
||||
<add-to-group group-id="ViewMenu" anchor="before" relative-to-action="ToggleFullScreenGroup"/>
|
||||
</action>
|
||||
</actions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.spellchecker">
|
||||
@@ -892,17 +886,6 @@
|
||||
<bundledDictionaryProvider implementation="com.jetbrains.python.spellchecker.PythonBundledDictionaryProvider"/>
|
||||
</extensions>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>com.jetbrains.python.actions.PySciProjectComponent</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>com.jetbrains.python.plots.PyPlotToolWindow</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<application-components>
|
||||
<component>
|
||||
<implementation-class>com.jetbrains.python.testing.VFSTestFrameworkListener</implementation-class>
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.actions;
|
||||
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.plots.PyPlotToolWindow;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import static com.intellij.codeInsight.documentation.DocumentationComponent.COLOR_KEY;
|
||||
import static com.jetbrains.python.actions.PySciViewAction.hideDataViewer;
|
||||
import static com.jetbrains.python.actions.PySciViewAction.showDataViewAsToolwindow;
|
||||
import static com.jetbrains.python.debugger.containerview.PyDataView.DATA_VIEWER_ID;
|
||||
|
||||
@State(name = "PySciProjectComponent", storages = @Storage("other.xml"))
|
||||
public class PySciProjectComponent extends AbstractProjectComponent implements PersistentStateComponent<PySciProjectComponent.State> {
|
||||
private State myState = new State();
|
||||
private ServerSocket myServerSocket;
|
||||
private Thread myPlotsThread;
|
||||
private volatile boolean myShouldAccept = true;
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(PySciProjectComponent.class);
|
||||
|
||||
protected PySciProjectComponent(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
public static PySciProjectComponent getInstance(Project project) {
|
||||
return project.getComponent(PySciProjectComponent.class);
|
||||
}
|
||||
|
||||
public void useSciView(boolean useSciView) {
|
||||
myState.PY_SCI_VIEW = useSciView;
|
||||
}
|
||||
|
||||
public void sciViewSuggested(boolean suggested) {
|
||||
myState.PY_SCI_VIEW_SUGGESTED = suggested;
|
||||
}
|
||||
|
||||
public boolean sciViewSuggested() {
|
||||
return myState.PY_SCI_VIEW_SUGGESTED;
|
||||
}
|
||||
|
||||
public boolean useSciView() {
|
||||
return myState.PY_SCI_VIEW;
|
||||
}
|
||||
|
||||
public void matplotlibInToolwindow(boolean inToolwindow) {
|
||||
myState.PY_MATPLOTLIB_IN_TOOLWINDOW = inToolwindow;
|
||||
|
||||
if (inToolwindow) {
|
||||
if (myServerSocket == null) {
|
||||
initializeServerSocket();
|
||||
}
|
||||
if (!useSciView()) {
|
||||
showDataViewAsToolwindow(myProject);
|
||||
}
|
||||
}
|
||||
else if (!useSciView()) {
|
||||
hideDataViewer(myProject);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matplotlibInToolwindow() {
|
||||
return myState.PY_MATPLOTLIB_IN_TOOLWINDOW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectOpened() {
|
||||
final VirtualFile baseDir = myProject.getBaseDir();
|
||||
if (baseDir == null) return;
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
if (myState.PY_SCI_VIEW) {
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(() -> {
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
scheme.setColor(COLOR_KEY, UIUtil.getEditorPaneBackground());
|
||||
|
||||
final PsiDirectory directory = PsiManager.getInstance(myProject).findDirectory(baseDir);
|
||||
if (directory != null) {
|
||||
DocumentationManager.getInstance(myProject).showJavaDocInfo(directory, directory);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (matplotlibInToolwindow()) {
|
||||
initializeServerSocket();
|
||||
|
||||
if (!useSciView()) {
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(() -> showDataViewAsToolwindow(myProject));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeServerSocket() {
|
||||
try {
|
||||
myServerSocket = new ServerSocket(0);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Failed to initialize server socket for python plots " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
myPlotsThread = new Thread(()->{
|
||||
while (myShouldAccept) {
|
||||
processConnection();
|
||||
}
|
||||
}, "Python plots client");
|
||||
myPlotsThread.setDaemon(true);
|
||||
myPlotsThread.start();
|
||||
}
|
||||
|
||||
private void processConnection() {
|
||||
try {
|
||||
final Socket socket = myServerSocket.accept();
|
||||
try {
|
||||
final InputStream stream = socket.getInputStream();
|
||||
final DataInputStream inputStream = new DataInputStream(stream);
|
||||
try {
|
||||
final int width = inputStream.readInt();
|
||||
final int count = inputStream.readInt();
|
||||
final byte[] raw = new byte[count];
|
||||
inputStream.readFully(raw);
|
||||
|
||||
PyPlotToolWindow.getInstance(myProject).onMessage(width, raw);
|
||||
ToolWindow window = ToolWindowManager.getInstance(myProject).getToolWindow(DATA_VIEWER_ID);
|
||||
if (window == null) {
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
window.show(null);
|
||||
final Content plotsTab = window.getContentManager().getContent(1);
|
||||
if (plotsTab != null) {
|
||||
window.getContentManager().setSelectedContent(plotsTab);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (!socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (myServerSocket == null) {
|
||||
myShouldAccept = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopMatplotlibCommunication() {
|
||||
if (myServerSocket != null && !myServerSocket.isClosed()) {
|
||||
try {
|
||||
myServerSocket.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
myShouldAccept = false;
|
||||
myServerSocket = null;
|
||||
try {
|
||||
if (myPlotsThread != null) {
|
||||
myPlotsThread.join();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return myServerSocket != null ? myServerSocket.getLocalPort() : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
stopMatplotlibCommunication();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PySciProjectComponent.State getState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(PySciProjectComponent.State state) {
|
||||
myState.PY_SCI_VIEW = state.PY_SCI_VIEW;
|
||||
myState.PY_SCI_VIEW_SUGGESTED = state.PY_SCI_VIEW_SUGGESTED;
|
||||
myState.PY_MATPLOTLIB_IN_TOOLWINDOW = state.PY_MATPLOTLIB_IN_TOOLWINDOW;
|
||||
}
|
||||
|
||||
public static class State {
|
||||
public boolean PY_SCI_VIEW = false;
|
||||
public boolean PY_SCI_VIEW_SUGGESTED = false;
|
||||
public boolean PY_MATPLOTLIB_IN_TOOLWINDOW = true;
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.actions;
|
||||
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager;
|
||||
import com.intellij.execution.RunManager;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.options.FontSize;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.ToolWindowType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.console.PythonConsoleToolWindow;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.run.PythonConfigurationType;
|
||||
import com.jetbrains.python.run.PythonRunConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import static com.intellij.codeInsight.documentation.DocumentationComponent.COLOR_KEY;
|
||||
import static com.intellij.codeInsight.documentation.DocumentationComponent.QUICK_DOC_FONT_SIZE_PROPERTY;
|
||||
import static com.jetbrains.python.debugger.containerview.PyDataView.DATA_VIEWER_ID;
|
||||
|
||||
public class PySciViewAction extends ToggleAction implements DumbAware {
|
||||
private static final String TEXT_SCI_VIEW = "Scientific Mode";
|
||||
|
||||
private boolean wasConsoleVisible = false;
|
||||
|
||||
public static final String ACTION_ID = "PySciView";
|
||||
private Color myDocumentationBackgroundColor = EditorColorsManager.getInstance().getGlobalScheme().getColor(COLOR_KEY);
|
||||
|
||||
public PySciViewAction() {
|
||||
super(TEXT_SCI_VIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return e.getProject() != null && PySciProjectComponent.getInstance(e.getProject()).useSciView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
final Project project = e.getProject();
|
||||
if (project == null) return;
|
||||
PySciProjectComponent.getInstance(project).useSciView(state);
|
||||
|
||||
final PsiElement element = getPsiElement(e, project);
|
||||
|
||||
if (state) {
|
||||
showConsoleToolwindow(project);
|
||||
showDocumentationToolwindow(project, element);
|
||||
showDataViewAsToolwindow(project);
|
||||
showCommandLineInRunConfiguration(project, true);
|
||||
renderExternalDocumentation(element, true);
|
||||
}
|
||||
else {
|
||||
hideConsoleToolwindow(project);
|
||||
restoreDocumentationPopup(project);
|
||||
hideDataViewer(project);
|
||||
showCommandLineInRunConfiguration(project, false);
|
||||
renderExternalDocumentation(element, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderExternalDocumentation(PsiElement element, boolean render) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(element);
|
||||
if (module != null) {
|
||||
PyDocumentationSettings.getInstance(module).setRenderExternalDocumentation(render);
|
||||
}
|
||||
}
|
||||
|
||||
private static void showCommandLineInRunConfiguration(Project project, boolean show) {
|
||||
final RunnerAndConfigurationSettings template =
|
||||
RunManager.getInstance(project).getConfigurationTemplate(PythonConfigurationType.getInstance().getFactory());
|
||||
final RunConfiguration configuration = template.getConfiguration();
|
||||
if (configuration instanceof PythonRunConfiguration) {
|
||||
((PythonRunConfiguration)configuration).setShowCommandLineAfterwards(show);
|
||||
}
|
||||
}
|
||||
|
||||
private void showConsoleToolwindow(@NotNull final Project project) {
|
||||
final PythonConsoleToolWindow pythonConsoleToolWindow = PythonConsoleToolWindow.getInstance(project);
|
||||
if (pythonConsoleToolWindow == null) return;
|
||||
final ToolWindow consoleToolWindow = pythonConsoleToolWindow.getToolWindow();
|
||||
if (consoleToolWindow == null) return;
|
||||
wasConsoleVisible = consoleToolWindow.isVisible();
|
||||
consoleToolWindow.show(null);
|
||||
}
|
||||
|
||||
private void hideConsoleToolwindow(@NotNull final Project project) {
|
||||
if (!wasConsoleVisible) {
|
||||
final PythonConsoleToolWindow pythonConsoleToolWindow = PythonConsoleToolWindow.getInstance(project);
|
||||
if (pythonConsoleToolWindow != null) {
|
||||
final ToolWindow consoleToolWindow = pythonConsoleToolWindow.getToolWindow();
|
||||
if (consoleToolWindow != null) {
|
||||
consoleToolWindow.hide(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showDocumentationToolwindow(Project project, PsiElement element) {
|
||||
final String showInToolWindowProperty = DocumentationManager.getInstance(project).getShowInToolWindowProperty();
|
||||
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
myDocumentationBackgroundColor = scheme.getColor(COLOR_KEY);
|
||||
scheme.setColor(COLOR_KEY, UIUtil.getEditorPaneBackground());
|
||||
|
||||
PropertiesComponent.getInstance().setValue(showInToolWindowProperty, true);
|
||||
PropertiesComponent.getInstance().setValue(DocumentationManager.getInstance(project).getAutoUpdateEnabledProperty(), true);
|
||||
|
||||
if (element != null) {
|
||||
DocumentationManager.getInstance(project).showJavaDocInfo(element, element);
|
||||
}
|
||||
setDocFontSize();
|
||||
}
|
||||
|
||||
private static void setDocFontSize() {
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
final int editorFontSize = scheme.getEditorFontSize();
|
||||
final FontSize[] values = FontSize.values();
|
||||
FontSize fontSize = FontSize.MEDIUM;
|
||||
for (FontSize value : values) {
|
||||
if (value.getSize() > editorFontSize) {
|
||||
break;
|
||||
}
|
||||
fontSize = value;
|
||||
}
|
||||
|
||||
PropertiesComponent.getInstance().setValue(QUICK_DOC_FONT_SIZE_PROPERTY, String.valueOf(fontSize.toString()));
|
||||
}
|
||||
|
||||
private void restoreDocumentationPopup(Project project) {
|
||||
PropertiesComponent.getInstance().setValue(DocumentationManager.getInstance(project).getAutoUpdateEnabledProperty(), false);
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
scheme.setColor(COLOR_KEY, myDocumentationBackgroundColor);
|
||||
|
||||
final ToolWindow window = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.DOCUMENTATION);
|
||||
if (window != null) {
|
||||
DocumentationManager.getInstance(project).restorePopupBehavior();
|
||||
final JBPopup hint = DocumentationManager.getInstance(project).getDocInfoHint();
|
||||
if (hint != null) {
|
||||
hint.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void showDataViewAsToolwindow(@NotNull final Project project) {
|
||||
ToolWindow dataViewToolWindow = ToolWindowManager.getInstance(project).getToolWindow(DATA_VIEWER_ID);
|
||||
if (dataViewToolWindow != null) {
|
||||
dataViewToolWindow.setType(ToolWindowType.DOCKED, null);
|
||||
dataViewToolWindow.setAutoHide(false);
|
||||
dataViewToolWindow.setShowStripeButton(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void hideDataViewer(Project project) {
|
||||
final ToolWindow dataViewer = ToolWindowManager.getInstance(project).getToolWindow(DATA_VIEWER_ID);
|
||||
if (dataViewer != null) {
|
||||
dataViewer.setType(ToolWindowType.FLOATING, null);
|
||||
dataViewer.setAutoHide(true);
|
||||
dataViewer.setShowStripeButton(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiElement getPsiElement(AnActionEvent e, Project project) {
|
||||
PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(e.getDataContext());
|
||||
if (element == null) {
|
||||
element = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
|
||||
}
|
||||
if (element == null) {
|
||||
element = PsiManager.getInstance(project).findDirectory(project.getBaseDir());
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
super.update(e);
|
||||
final Project project = e.getProject();
|
||||
final Presentation presentation = e.getPresentation();
|
||||
presentation.setEnabledAndVisible(project != null);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.configuration.PyIntegratedToolsConfigurable">
|
||||
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="8" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="657" height="304"/>
|
||||
<xy x="20" y="20" width="657" height="275"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -24,12 +24,12 @@
|
||||
</component>
|
||||
<vspacer id="fc19e">
|
||||
<constraints>
|
||||
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<grid id="728f8" binding="myErrorPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="7" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -52,7 +52,7 @@
|
||||
<grid id="e7a5f" binding="myDocStringsPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -95,7 +95,7 @@
|
||||
<grid id="9f040" binding="myRestPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -125,14 +125,6 @@
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="5432b" class="javax.swing.JCheckBox" binding="myShowPlots">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Show plots in toolwindow"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -41,7 +41,6 @@ import com.intellij.util.FileContentUtilCore;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.ReSTService;
|
||||
import com.jetbrains.python.actions.PySciProjectComponent;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
|
||||
import com.jetbrains.python.packaging.PyPackageManagerUI;
|
||||
@@ -79,7 +78,6 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
|
||||
private JPanel myDocStringsPanel;
|
||||
private JPanel myRestPanel;
|
||||
private JCheckBox renderExternal;
|
||||
private JCheckBox myShowPlots;
|
||||
|
||||
public PyIntegratedToolsConfigurable(@NotNull Module module) {
|
||||
myModule = module;
|
||||
@@ -102,7 +100,6 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
|
||||
txtIsRst.setSelected(service.txtIsRst());
|
||||
analyzeDoctest.setSelected(myDocumentationSettings.isAnalyzeDoctest());
|
||||
renderExternal.setSelected(myDocumentationSettings.isRenderExternalDocumentation());
|
||||
myShowPlots.setSelected(PySciProjectComponent.getInstance(myProject).matplotlibInToolwindow());
|
||||
myRequirementsPathField.addBrowseFolderListener("Choose path to the package requirements file:", null, myProject,
|
||||
FileChooserDescriptorFactory.createSingleLocalFileDescriptor());
|
||||
myRequirementsPathField.setText(getRequirementsPath());
|
||||
@@ -214,9 +211,6 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
|
||||
if (renderExternal.isSelected() != myDocumentationSettings.isRenderExternalDocumentation()) {
|
||||
return true;
|
||||
}
|
||||
if (myShowPlots.isSelected() != PySciProjectComponent.getInstance(myProject).matplotlibInToolwindow()) {
|
||||
return true;
|
||||
}
|
||||
if (!ReSTService.getInstance(myModule).getWorkdir().equals(myWorkDir.getText())) {
|
||||
return true;
|
||||
}
|
||||
@@ -246,7 +240,6 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
|
||||
}
|
||||
myModel.apply();
|
||||
myDocumentationSettings.setRenderExternalDocumentation(renderExternal.isSelected());
|
||||
PySciProjectComponent.getInstance(myProject).matplotlibInToolwindow(myShowPlots.isSelected());
|
||||
myDocumentationSettings.setFormat((DocStringFormat)myDocstringFormatComboBox.getSelectedItem());
|
||||
final ReSTService reSTService = ReSTService.getInstance(myModule);
|
||||
reSTService.setWorkdir(myWorkDir.getText());
|
||||
@@ -284,7 +277,6 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
|
||||
txtIsRst.setSelected(ReSTService.getInstance(myModule).txtIsRst());
|
||||
analyzeDoctest.setSelected(myDocumentationSettings.isAnalyzeDoctest());
|
||||
renderExternal.setSelected(myDocumentationSettings.isRenderExternalDocumentation());
|
||||
myShowPlots.setSelected(PySciProjectComponent.getInstance(myProject).matplotlibInToolwindow());
|
||||
myRequirementsPathField.setText(getRequirementsPath());
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,19 @@ public class PyDataView implements DumbAware {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public void show(@NotNull PyDebugValue value) {
|
||||
public void show(@NotNull PyDebugValue value, boolean inToolwindow) {
|
||||
if (inToolwindow) {
|
||||
showInToolwindow(value);
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
final PyDataViewDialog dialog = new PyDataViewDialog(myProject, value);
|
||||
dialog.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void showInToolwindow(@NotNull PyDebugValue value) {
|
||||
ToolWindow window = ToolWindowManager.getInstance(myProject).getToolWindow(DATA_VIEWER_ID);
|
||||
if (window == null) {
|
||||
LOG.error("Tool window '" + DATA_VIEWER_ID + "' is not found");
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.debugger.containerview;
|
||||
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.jetbrains.python.debugger.PyDebugValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class PyDataViewDialog extends DialogWrapper {
|
||||
private final JPanel myMainPanel;
|
||||
|
||||
PyDataViewDialog(@NotNull Project project, @NotNull final PyDebugValue value) {
|
||||
super(project, false);
|
||||
setModal(false);
|
||||
setCancelButtonText("Close");
|
||||
setCrossClosesWindow(true);
|
||||
myMainPanel = new JPanel(new VerticalFlowLayout());
|
||||
final PyDataViewerPanel panel = new PyDataViewerPanel(project, value.getFrameAccessor());
|
||||
panel.apply(value);
|
||||
myMainPanel.add(panel);
|
||||
panel.setBorder(BorderFactory.createLineBorder(JBColor.GRAY));
|
||||
final JBCheckBox colored = new JBCheckBox("Colored cells");
|
||||
final JBCheckBox resize = new JBCheckBox("Resize Automatically");
|
||||
resize.setSelected(PropertiesComponent.getInstance(project).getBoolean(PyDataView.AUTO_RESIZE, true));
|
||||
colored.setSelected(PropertiesComponent.getInstance(project).getBoolean(PyDataView.COLORED_BY_DEFAULT, true));
|
||||
colored.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
panel.setColored(colored.isSelected());
|
||||
panel.updateUI();
|
||||
}
|
||||
});
|
||||
resize.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
panel.resize(resize.isSelected());
|
||||
panel.updateUI();
|
||||
}
|
||||
});
|
||||
myMainPanel.add(colored);
|
||||
myMainPanel.add(resize);
|
||||
setTitle(value.getFullName());
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected Action[] createActions() {
|
||||
return new Action[]{getCancelAction()};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myMainPanel;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.awt.*;
|
||||
|
||||
class PyDataViewTabs extends JBRunnerTabs {
|
||||
|
||||
public static final String EMPTY_TEXT = "Run debugger to view available data ";
|
||||
private static final String HELP_ID = "reference.toolWindows.PyDataView";
|
||||
|
||||
public PyDataViewTabs(@NotNull Project project) {
|
||||
@@ -40,7 +40,7 @@ class PyDataViewTabs extends JBRunnerTabs {
|
||||
super.paintComponent(g);
|
||||
if (isEmptyVisible()) {
|
||||
UISettings.setupAntialiasing(g);
|
||||
UIUtil.drawCenteredString((Graphics2D)g, g.getClipBounds(), PyDataViewToolWindowFactory.EMPTY_TEXT);
|
||||
UIUtil.drawCenteredString((Graphics2D)g, g.getClipBounds(), EMPTY_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.debugger.containerview;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.RunContentManager;
|
||||
import com.intellij.execution.ui.RunContentWithExecutorListener;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowFactory;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.ex.ToolWindowEx;
|
||||
import com.intellij.ui.content.ContentManagerAdapter;
|
||||
import com.intellij.ui.content.ContentManagerEvent;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.xdebugger.XDebugProcess;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import com.intellij.xdebugger.XDebuggerManagerListener;
|
||||
import com.jetbrains.python.console.PythonConsoleToolWindowFactory;
|
||||
import com.jetbrains.python.debugger.PyDebugProcess;
|
||||
import com.jetbrains.python.plots.PyPlotToolWindow;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PyDataViewToolWindowFactory implements ToolWindowFactory {
|
||||
public static final String EMPTY_TEXT = "Run debugger to view available data ";
|
||||
private static final Logger LOG = Logger.getInstance(PyDataViewToolWindowFactory.class);
|
||||
|
||||
@Override
|
||||
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
initializeDataTab(project, toolWindow);
|
||||
PyPlotToolWindow.getInstance(project).init(toolWindow);
|
||||
}
|
||||
|
||||
private static void initializeDataTab(@NotNull Project project, @NotNull ToolWindow toolWindow) {
|
||||
PyDataView.getInstance(project).init(toolWindow);
|
||||
final MessageBusConnection connection = project.getMessageBus().connect(project);
|
||||
connection.subscribe(XDebuggerManager.TOPIC, new ChangeContentXDebuggerManagerListener(project));
|
||||
|
||||
connection.subscribe(RunContentManager.TOPIC, new RunContentWithExecutorListener() {
|
||||
@Override
|
||||
public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
|
||||
if (!(executor instanceof DefaultDebugExecutor)) {
|
||||
return;
|
||||
}
|
||||
if (descriptor == null) {
|
||||
return;
|
||||
}
|
||||
ProcessHandler handler = descriptor.getProcessHandler();
|
||||
if (handler == null) {
|
||||
return;
|
||||
}
|
||||
PyDataView.getInstance(project).updateTabs(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
addPythonConsoleListener(project);
|
||||
PyDataViewToggleAction autoResizeAction = new PyDataViewToggleAction("Resize Automatically", PyDataView.AUTO_RESIZE) {
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
super.setSelected(e, state);
|
||||
PyDataView.getInstance(project).changeAutoResize(state);
|
||||
}
|
||||
};
|
||||
DefaultActionGroup group = new DefaultActionGroup(new PyDataViewToggleAction("Colored by Default", PyDataView.COLORED_BY_DEFAULT),
|
||||
autoResizeAction);
|
||||
((ToolWindowEx)toolWindow).setAdditionalGearActions(group);
|
||||
}
|
||||
|
||||
private static void addPythonConsoleListener(@NotNull Project project) {
|
||||
final ToolWindow pythonConsole = ToolWindowManager.getInstance(project).getToolWindow(PythonConsoleToolWindowFactory.Companion.getID());
|
||||
if (pythonConsole == null) {
|
||||
return;
|
||||
}
|
||||
pythonConsole.getContentManager().addContentManagerListener(new ContentManagerAdapter() {
|
||||
@Override
|
||||
public void contentRemoved(ContentManagerEvent event) {
|
||||
PyDataView.getInstance(project).closeDisconnectedFromConsoleTabs();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class PyDataViewToggleAction extends ToggleAction {
|
||||
private final String myPropertyKey;
|
||||
|
||||
public PyDataViewToggleAction(String text, String propertyKey) {
|
||||
super(text);
|
||||
myPropertyKey = propertyKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return PropertiesComponent.getInstance(e.getProject()).getBoolean(myPropertyKey, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
PropertiesComponent.getInstance(e.getProject()).setValue(myPropertyKey, state, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChangeContentXDebuggerManagerListener implements XDebuggerManagerListener {
|
||||
private final Project myProject;
|
||||
|
||||
public ChangeContentXDebuggerManagerListener(Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processStarted(@NotNull XDebugProcess debugProcess) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processStopped(@NotNull XDebugProcess debugProcess) {
|
||||
if (debugProcess instanceof PyDebugProcess) {
|
||||
PyDataView.getInstance(myProject).closeTabs(frameAccessor -> frameAccessor instanceof PyDebugProcess && frameAccessor == debugProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -18,6 +18,7 @@ package com.jetbrains.python.debugger.containerview;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
@@ -43,7 +44,7 @@ public class PyViewNumericContainerAction extends XDebuggerTreeActionBase {
|
||||
}
|
||||
|
||||
public static void showNumericViewer(Project project, PyDebugValue debugValue) {
|
||||
PyDataView.getInstance(project).show(debugValue);
|
||||
PyDataView.getInstance(project).show(debugValue, PlatformUtils.isPyCharmPro());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.notification.NotificationDisplayType;
|
||||
import com.intellij.notification.NotificationGroup;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.jetbrains.python.actions.PySciProjectComponent;
|
||||
import com.jetbrains.python.actions.PySciViewAction;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyImportElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.jetbrains.python.actions.PySciViewAction.ACTION_ID;
|
||||
|
||||
public class PySciViewAdvertiser implements Annotator {
|
||||
|
||||
private static final NotificationGroup BALLOON_NOTIFICATIONS = new NotificationGroup("Python Scientific View Advertiser",
|
||||
NotificationDisplayType.STICKY_BALLOON, false);
|
||||
private static final Key<Boolean> BALLOON_SHOWING = Key.create("showingSciViewAdvertiserBalloon");
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if (element instanceof PyFile) {
|
||||
final PyFile pyFile = (PyFile)element;
|
||||
final Project project = element.getProject();
|
||||
|
||||
if (PySciProjectComponent.getInstance(project).sciViewSuggested()) {
|
||||
return;
|
||||
}
|
||||
final VirtualFile vFile = pyFile.getVirtualFile();
|
||||
if (vFile != null && FileIndexFacade.getInstance(project).isInLibraryClasses(vFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Boolean showingFlag = project.getUserData(BALLOON_SHOWING);
|
||||
if (showingFlag != null && showingFlag.booleanValue()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (containsNumpyImports(pyFile)) {
|
||||
showInspectionAdvertisement(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void showInspectionAdvertisement(@NotNull Project project) {
|
||||
final String msg = "Your source code imports the 'numpy' package." +
|
||||
"<br/>Would you like to enable Scientific View?<br/>" +
|
||||
"<a href=\"#yes\">Yes</a> <a href=\"#no\">No</a>";
|
||||
showSingletonNotification(project, msg, NotificationType.INFORMATION, (notification, event) -> {
|
||||
final boolean enabled = "#yes".equals(event.getDescription());
|
||||
PySciProjectComponent.getInstance(project).sciViewSuggested(true);
|
||||
if (enabled) {
|
||||
final AnAction action = ActionManager.getInstance().getAction(ACTION_ID);
|
||||
if (action instanceof PySciViewAction) {
|
||||
PySciProjectComponent.getInstance(project).sciViewSuggested();
|
||||
final AnActionEvent anActionEvent = AnActionEvent.createFromDataContext(
|
||||
ActionPlaces.UNKNOWN, null, DataManager.getInstance().getDataContextFromFocus().getResult());
|
||||
((PySciViewAction)action).setSelected(anActionEvent, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void showSingletonNotification(@NotNull Project project,
|
||||
@NotNull String htmlContent,
|
||||
@NotNull NotificationType type,
|
||||
@NotNull NotificationListener listener) {
|
||||
project.putUserData(BALLOON_SHOWING, true);
|
||||
BALLOON_NOTIFICATIONS.createNotification("Scientific View", htmlContent, type, (notification, event) -> {
|
||||
try {
|
||||
listener.hyperlinkUpdate(notification, event);
|
||||
}
|
||||
finally {
|
||||
notification.expire();
|
||||
}
|
||||
}).notify(project);
|
||||
}
|
||||
|
||||
private static boolean containsNumpyImports(@NotNull PyFile file) {
|
||||
for (PyImportElement importTarget : file.getImportTargets()) {
|
||||
final QualifiedName qName = importTarget.getImportedQName();
|
||||
if (qName != null && qName.matches("numpy")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.jetbrains.python.plots;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.fileChooser.FileSaverDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileSaverDialog;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorProvider;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorTabbedContainer;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFileWrapper;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.testFramework.BinaryLightVirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.ui.docking.DockContainer;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import com.intellij.ui.docking.DockableContent;
|
||||
import com.intellij.ui.docking.DragSession;
|
||||
import com.intellij.ui.tabs.JBTabsPosition;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.impl.DefaultEditorTabsPainter;
|
||||
import com.intellij.ui.tabs.impl.JBEditorTabs;
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl;
|
||||
import com.intellij.ui.tabs.impl.TabLabel;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class PyPlotToolWindow extends JPanel implements DumbAware {
|
||||
public static final String PLOT_DEFAULT_NAME = "myplot";
|
||||
public static final String PLOT_FORMAT = "png";
|
||||
private final static int ourPreviewSize = 80;
|
||||
|
||||
private final JBEditorTabs myTabs;
|
||||
private final Project myProject;
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(PyPlotToolWindow.class);
|
||||
private MyDockContainer myDockContainer;
|
||||
|
||||
public PyPlotToolWindow(final Project project) {
|
||||
super(new BorderLayout());
|
||||
myProject = project;
|
||||
myTabs = new MyTabs(myProject);
|
||||
myTabs.setTabsPosition(JBTabsPosition.right);
|
||||
myTabs.setPopupGroup(new DefaultActionGroup(new SaveAsFileAction()), ActionPlaces.UNKNOWN, true);
|
||||
myTabs.setTabDraggingEnabled(true);
|
||||
add(myTabs);
|
||||
}
|
||||
|
||||
public void onMessage(int width, byte[] raw) {
|
||||
final PyPlotVirtualFile plotVirtualFile = new PyPlotVirtualFile(width, raw);
|
||||
final TabInfo info = createTabInfo(plotVirtualFile);
|
||||
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
myTabs.addTab(info);
|
||||
myTabs.select(info, true);
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TabInfo createTabInfo(@NotNull final PyPlotVirtualFile plotVirtualFile) {
|
||||
final JPanel panel = new MyPlotPanel(plotVirtualFile);
|
||||
final TabInfo info = new TabInfo(panel);
|
||||
info.setTabColor(UIUtil.getPanelBackground());
|
||||
final BufferedImage image = plotVirtualFile.getImage();
|
||||
final Image after = image.getScaledInstance(JBUI.scale(64), JBUI.scale(48), Image.SCALE_SMOOTH);
|
||||
info.setIcon(new ImageIcon(after));
|
||||
info.setText(" ");
|
||||
info.setTabLabelActions(new DefaultActionGroup(new ClosePlotAction(info)), ActionPlaces.UNKNOWN);
|
||||
info.setDragOutDelegate(new MyDragOutDelegate());
|
||||
return info;
|
||||
}
|
||||
|
||||
public void init(ToolWindow toolWindow) {
|
||||
final ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
|
||||
Content content = contentFactory.createContent(this, "Plots", false);
|
||||
content.setCloseable(false);
|
||||
toolWindow.getContentManager().addContent(content);
|
||||
|
||||
if (myDockContainer == null) {
|
||||
myDockContainer = new MyDockContainer(toolWindow);
|
||||
Disposer.register(myProject, myDockContainer);
|
||||
DockManager.getInstance(myProject).register(myDockContainer);
|
||||
}
|
||||
}
|
||||
|
||||
public static PyPlotToolWindow getInstance(@NotNull final Project project) {
|
||||
return ServiceManager.getService(project, PyPlotToolWindow.class);
|
||||
}
|
||||
|
||||
private static class MyTabs extends JBEditorTabs {
|
||||
public MyTabs(Project project) {
|
||||
super(project, ActionManager.getInstance(), IdeFocusManager.findInstance(), project);
|
||||
myDefaultPainter = new DefaultEditorTabsPainter(this) {
|
||||
@Override
|
||||
public Color getBackgroundColor() {
|
||||
return JBColor.LIGHT_GRAY;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TabLabel createTabLabel(TabInfo info) {
|
||||
return new MyTabLabel(this, info);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyTabLabel extends TabLabel {
|
||||
public MyTabLabel(JBTabsImpl tabs, TabInfo info) {
|
||||
super(tabs, info);
|
||||
final JComponent label = getLabelComponent();
|
||||
if (label instanceof SimpleColoredComponent) {
|
||||
((SimpleColoredComponent)label).setIconOnTheRight(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(JBUI.scale(ourPreviewSize + 20), JBUI.scale(ourPreviewSize));
|
||||
}
|
||||
}
|
||||
|
||||
private class ClosePlotAction extends AnAction {
|
||||
private final TabInfo myInfo;
|
||||
|
||||
public ClosePlotAction(TabInfo info) {
|
||||
super("Close Plot", "Close selected plot", AllIcons.Actions.Close);
|
||||
myInfo = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myTabs.removeTab(myInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private class SaveAsFileAction extends AnAction {
|
||||
public SaveAsFileAction() {
|
||||
super("Save as File");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
TabInfo info = myTabs.getSelectedInfo();
|
||||
final Project project = e.getProject();
|
||||
if (info != null && project != null) {
|
||||
final MyPlotPanel component = (MyPlotPanel)info.getComponent();
|
||||
final BinaryLightVirtualFile virtualFile = component.getVirtualFile();
|
||||
|
||||
FileSaverDescriptor descriptor = new FileSaverDescriptor("Select File to Save Plot", "", PLOT_FORMAT);
|
||||
final FileSaverDialog chooser = FileChooserFactory.getInstance().createSaveFileDialog(descriptor, project);
|
||||
|
||||
final VirtualFileWrapper fileWrapper = chooser.save(project.getBaseDir(), PLOT_DEFAULT_NAME);
|
||||
try {
|
||||
if (fileWrapper != null) {
|
||||
final File ioFile = fileWrapper.getFile();
|
||||
Files.write(Paths.get(ioFile.getPath()), virtualFile.getContent());
|
||||
}
|
||||
}
|
||||
catch (IOException e1) {
|
||||
LOG.warn("Failed to save image " + e1.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyPlotPanel extends JPanel {
|
||||
private final PyPlotVirtualFile myVirtualFile;
|
||||
|
||||
public MyPlotPanel(PyPlotVirtualFile virtualFile) {
|
||||
super(new BorderLayout());
|
||||
myVirtualFile = virtualFile;
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
//ImageFileEditorProvider#EDITOR_TYPE_ID
|
||||
final FileEditorProvider provider = FileEditorProviderManager.getInstance().getProvider("images");
|
||||
if (provider != null) {
|
||||
final FileEditor editor = provider.createEditor(myProject, myVirtualFile);
|
||||
Disposer.register(myProject, editor);
|
||||
add(editor.getComponent());
|
||||
}
|
||||
});
|
||||
|
||||
setBackground(UIUtil.getEditorPaneBackground());
|
||||
}
|
||||
|
||||
public BinaryLightVirtualFile getVirtualFile() {
|
||||
return myVirtualFile;
|
||||
}
|
||||
}
|
||||
|
||||
class MyDragOutDelegate implements TabInfo.DragOutDelegate {
|
||||
private DragSession mySession;
|
||||
|
||||
@Override
|
||||
public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) {
|
||||
final TabInfo previousSelection = info.getPreviousSelection();
|
||||
final Image img = JBTabsImpl.getComponentImage(info);
|
||||
info.setHidden(true);
|
||||
if (previousSelection != null) {
|
||||
myTabs.select(previousSelection, true);
|
||||
}
|
||||
|
||||
Presentation presentation = new Presentation(info.getText());
|
||||
presentation.setIcon(info.getIcon());
|
||||
final MyPlotPanel component = (MyPlotPanel)info.getComponent();
|
||||
final BinaryLightVirtualFile file = component.getVirtualFile();
|
||||
mySession = getDockManager().createDragSession(mouseEvent, new EditorTabbedContainer.DockableEditor(myProject, img, file, presentation,
|
||||
info.getComponent().getPreferredSize(), false));
|
||||
|
||||
}
|
||||
|
||||
private DockManager getDockManager() {
|
||||
return DockManager.getInstance(myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDragOut(MouseEvent event, TabInfo source) {
|
||||
mySession.process(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOutFinished(MouseEvent event, TabInfo source) {
|
||||
myTabs.removeTab(source);
|
||||
mySession.process(event);
|
||||
mySession = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOutCancelled(TabInfo source) {
|
||||
source.setHidden(false);
|
||||
if (mySession != null) {
|
||||
mySession.cancel();
|
||||
}
|
||||
mySession = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class MyDockContainer implements DockContainer {
|
||||
private final ToolWindow myToolWindow;
|
||||
|
||||
public MyDockContainer(ToolWindow toolWindow) {
|
||||
myToolWindow = toolWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeRectangle getAcceptArea() {
|
||||
return new RelativeRectangle(myToolWindow.getComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeRectangle getAcceptAreaFallback() {
|
||||
return getAcceptArea();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ContentResponse getContentResponse(@NotNull DockableContent content, RelativePoint point) {
|
||||
return content.getKey() instanceof PyPlotVirtualFile ? ContentResponse.ACCEPT_MOVE : ContentResponse.DENY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getContainerComponent() {
|
||||
return myToolWindow.getComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(@NotNull DockableContent content, RelativePoint dropTarget) {
|
||||
final Object key = content.getKey();
|
||||
if (key instanceof PyPlotVirtualFile) {
|
||||
final TabInfo info = createTabInfo((PyPlotVirtualFile)key);
|
||||
myTabs.addTab(info);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeAll() {}
|
||||
|
||||
@Override
|
||||
public void addListener(Listener listener, Disposable parent) {}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Image startDropOver(@NotNull DockableContent content, RelativePoint point) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Image processDropOver(@NotNull DockableContent content, RelativePoint point) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetDropOver(@NotNull DockableContent content) {}
|
||||
|
||||
@Override
|
||||
public boolean isDisposeWhenEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {}
|
||||
|
||||
@Override
|
||||
public void showNotify() {}
|
||||
|
||||
@Override
|
||||
public void hideNotify() {}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.jetbrains.python.plots;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.testFramework.BinaryLightVirtualFile;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PyPlotVirtualFile extends BinaryLightVirtualFile {
|
||||
private static final Logger LOG = Logger.getInstance(PyPlotToolWindow.class);
|
||||
private BufferedImage myImage;
|
||||
|
||||
public PyPlotVirtualFile(int width, byte[] raw) {
|
||||
super(PyPlotToolWindow.PLOT_DEFAULT_NAME + "." + PyPlotToolWindow.PLOT_FORMAT);
|
||||
|
||||
int height = raw.length / 3 / width;
|
||||
final DataBuffer buffer = new DataBufferByte(raw, raw.length);
|
||||
final SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 3, width * 3,
|
||||
new int[]{0, 1, 2});
|
||||
final Raster raster = Raster.createRaster(sampleModel, buffer, null);
|
||||
myImage = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
if (SystemInfo.isMac && UIUtil.isRetina()) {
|
||||
myImage = myImage.getSubimage(0, 0, width / 2, height / 2);
|
||||
}
|
||||
myImage.setData(raster);
|
||||
byte[] bytes = imageToByteArray(myImage);
|
||||
if (bytes == null) return;
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
try {
|
||||
setBinaryContent(bytes);
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
return myImage;
|
||||
}
|
||||
|
||||
public static byte[] imageToByteArray(BufferedImage image) {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
try {
|
||||
ImageIO.write(image, PyPlotToolWindow.PLOT_FORMAT, stream);
|
||||
stream.flush();
|
||||
byte[] imageInByte = stream.toByteArray();
|
||||
stream.close();
|
||||
return imageInByte;
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("Failed to convert image to byte array " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.run;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface PythonCommandLineEnvironmentProvider {
|
||||
ExtensionPointName<PythonCommandLineEnvironmentProvider> EP_NAME =
|
||||
ExtensionPointName.create("Pythonid.pythonCommandLineEnvironmentProvider");
|
||||
|
||||
void extendEnvironment(@NotNull Project project, @NotNull GeneralCommandLine cmdLine);
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.facet.Facet;
|
||||
import com.intellij.facet.FacetManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
@@ -54,7 +55,6 @@ import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
|
||||
import com.intellij.remote.RemoteProcessControl;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.actions.PySciProjectComponent;
|
||||
import com.jetbrains.python.console.PyDebugConsoleBuilder;
|
||||
import com.jetbrains.python.debugger.PyDebugRunner;
|
||||
import com.jetbrains.python.debugger.PyDebuggerOptionsProvider;
|
||||
@@ -325,10 +325,6 @@ public abstract class PythonCommandLineState extends CommandLineState {
|
||||
if (myConfig.getEnvs() != null) {
|
||||
env.putAll(myConfig.getEnvs());
|
||||
}
|
||||
if (PySciProjectComponent.getInstance(project).matplotlibInToolwindow() &&
|
||||
PySciProjectComponent.getInstance(project).getPort() != -1) {
|
||||
env.put("PYCHARM_MATPLOTLIB_PORT", String.valueOf(PySciProjectComponent.getInstance(project).getPort()));
|
||||
}
|
||||
addCommonEnvironmentVariables(getInterpreterPath(project, myConfig), env);
|
||||
|
||||
setupVirtualEnvVariables(myConfig, env, myConfig.getSdkHome());
|
||||
@@ -337,8 +333,11 @@ public abstract class PythonCommandLineState extends CommandLineState {
|
||||
commandLine.getEnvironment().putAll(env);
|
||||
commandLine.withParentEnvironmentType(myConfig.isPassParentEnvs() ? ParentEnvironmentType.CONSOLE : ParentEnvironmentType.NONE);
|
||||
|
||||
|
||||
buildPythonPath(project, commandLine, myConfig, isDebug);
|
||||
|
||||
for (PythonCommandLineEnvironmentProvider envProvider : Extensions.getExtensions(PythonCommandLineEnvironmentProvider.EP_NAME)) {
|
||||
envProvider.extendEnvironment(project, commandLine);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setupVirtualEnvVariables(PythonRunParams myConfig, Map<String, String> env, String sdkHome) {
|
||||
@@ -385,10 +384,6 @@ public abstract class PythonCommandLineState extends CommandLineState {
|
||||
Sdk pythonSdk = PythonSdkType.findSdkByPath(config.getSdkHome());
|
||||
if (pythonSdk != null) {
|
||||
List<String> pathList = Lists.newArrayList();
|
||||
if (PySciProjectComponent.getInstance(project).matplotlibInToolwindow() &&
|
||||
PySciProjectComponent.getInstance(project).getPort() != -1) {
|
||||
pathList.add(PythonHelpersLocator.getHelperPath("pycharm_matplotlib_backend"));
|
||||
}
|
||||
pathList.addAll(getAddedPaths(pythonSdk));
|
||||
pathList.addAll(collectPythonPath(project, config, isDebug));
|
||||
initPythonPath(commandLine, config.isPassParentEnvs(), pathList, config.getSdkHome());
|
||||
|
||||
Reference in New Issue
Block a user