diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml index 02d049504778..7c7d27da28ff 100644 --- a/python/src/META-INF/python-core-common.xml +++ b/python/src/META-INF/python-core-common.xml @@ -46,7 +46,7 @@ - + @@ -624,16 +624,14 @@ - - - + @@ -881,10 +879,6 @@ - - - - @@ -892,17 +886,6 @@ - - - com.jetbrains.python.actions.PySciProjectComponent - - - - - com.jetbrains.python.plots.PyPlotToolWindow - - - com.jetbrains.python.testing.VFSTestFrameworkListener diff --git a/python/src/com/jetbrains/python/actions/PySciProjectComponent.java b/python/src/com/jetbrains/python/actions/PySciProjectComponent.java deleted file mode 100644 index 6ce5c5cd3ff5..000000000000 --- a/python/src/com/jetbrains/python/actions/PySciProjectComponent.java +++ /dev/null @@ -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 { - 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; - } -} diff --git a/python/src/com/jetbrains/python/actions/PySciViewAction.java b/python/src/com/jetbrains/python/actions/PySciViewAction.java deleted file mode 100644 index 3b4aa122b865..000000000000 --- a/python/src/com/jetbrains/python/actions/PySciViewAction.java +++ /dev/null @@ -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); - } -} diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form index 0d4c76ee4e78..358bf7e810c1 100644 --- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form +++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form @@ -1,9 +1,9 @@
- + - + @@ -24,12 +24,12 @@ - + - + @@ -52,7 +52,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -125,14 +125,6 @@ - - - - - - - - diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java index a402a58bd88c..c519eda530ce 100644 --- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java +++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java @@ -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()); } diff --git a/python/src/com/jetbrains/python/debugger/containerview/PyDataView.java b/python/src/com/jetbrains/python/debugger/containerview/PyDataView.java index 39a40d5507d3..b7c3a996a86d 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/PyDataView.java +++ b/python/src/com/jetbrains/python/debugger/containerview/PyDataView.java @@ -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"); diff --git a/python/src/com/jetbrains/python/debugger/containerview/PyDataViewDialog.java b/python/src/com/jetbrains/python/debugger/containerview/PyDataViewDialog.java new file mode 100644 index 000000000000..43eba77843a3 --- /dev/null +++ b/python/src/com/jetbrains/python/debugger/containerview/PyDataViewDialog.java @@ -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; + } +} diff --git a/python/src/com/jetbrains/python/debugger/containerview/PyDataViewTabs.java b/python/src/com/jetbrains/python/debugger/containerview/PyDataViewTabs.java index dbf48b678b93..ea2281aaeaf3 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/PyDataViewTabs.java +++ b/python/src/com/jetbrains/python/debugger/containerview/PyDataViewTabs.java @@ -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); } } diff --git a/python/src/com/jetbrains/python/debugger/containerview/PyDataViewToolWindowFactory.java b/python/src/com/jetbrains/python/debugger/containerview/PyDataViewToolWindowFactory.java deleted file mode 100644 index c0581567a040..000000000000 --- a/python/src/com/jetbrains/python/debugger/containerview/PyDataViewToolWindowFactory.java +++ /dev/null @@ -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); - } - } - } -} diff --git a/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java b/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java index 011537ed61b3..71886da63719 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java +++ b/python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java @@ -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 diff --git a/python/src/com/jetbrains/python/inspections/PySciViewAdvertiser.java b/python/src/com/jetbrains/python/inspections/PySciViewAdvertiser.java deleted file mode 100644 index 2c238f03ed19..000000000000 --- a/python/src/com/jetbrains/python/inspections/PySciViewAdvertiser.java +++ /dev/null @@ -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 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." + - "
Would you like to enable Scientific View?
" + - "Yes  No"; - 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; - } - -} diff --git a/python/src/com/jetbrains/python/plots/PyPlotToolWindow.java b/python/src/com/jetbrains/python/plots/PyPlotToolWindow.java deleted file mode 100644 index 286abedec088..000000000000 --- a/python/src/com/jetbrains/python/plots/PyPlotToolWindow.java +++ /dev/null @@ -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() {} - } -} diff --git a/python/src/com/jetbrains/python/plots/PyPlotVirtualFile.java b/python/src/com/jetbrains/python/plots/PyPlotVirtualFile.java deleted file mode 100644 index 387c2a755633..000000000000 --- a/python/src/com/jetbrains/python/plots/PyPlotVirtualFile.java +++ /dev/null @@ -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; - } -} diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineEnvironmentProvider.java b/python/src/com/jetbrains/python/run/PythonCommandLineEnvironmentProvider.java new file mode 100644 index 000000000000..2aa2f95bdbbd --- /dev/null +++ b/python/src/com/jetbrains/python/run/PythonCommandLineEnvironmentProvider.java @@ -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 EP_NAME = + ExtensionPointName.create("Pythonid.pythonCommandLineEnvironmentProvider"); + + void extendEnvironment(@NotNull Project project, @NotNull GeneralCommandLine cmdLine); +} diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java index eee676c67657..0868d6bc330e 100644 --- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java +++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java @@ -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 env, String sdkHome) { @@ -385,10 +384,6 @@ public abstract class PythonCommandLineState extends CommandLineState { Sdk pythonSdk = PythonSdkType.findSdkByPath(config.getSdkHome()); if (pythonSdk != null) { List 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());