From ff9508bc0445929892986498df9d436685f1ee54 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 12 Jul 2017 13:40:51 +0300 Subject: [PATCH] Jupyter notebook: add option to disable markdown rendering --- .../resources/META-INF/ipython-notebook.xml | 2 +- .../org/jetbrains/plugins/ipnb/IpnbUtils.java | 24 ++---- .../ipnb/configuration/IpnbConfigurable.form | 84 +++++++++++-------- .../ipnb/configuration/IpnbConfigurable.java | 64 +++++++++----- .../ipnb/configuration/IpnbSettings.java | 20 ++++- .../ipnb/editor/panels/IpnbFilePanel.java | 53 ++---------- .../ipnb/editor/panels/IpnbMarkdownPanel.java | 4 +- .../editor/panels/code/IpnbHtmlPanel.java | 2 +- .../editor/panels/code/IpnbLatexPanel.java | 2 +- .../ipnb/run/IpnbRunConfiguration.java | 2 +- 10 files changed, 135 insertions(+), 122 deletions(-) diff --git a/python/ipnb/resources/META-INF/ipython-notebook.xml b/python/ipnb/resources/META-INF/ipython-notebook.xml index fabb83369ffe..3f3d6383d60a 100644 --- a/python/ipnb/resources/META-INF/ipython-notebook.xml +++ b/python/ipnb/resources/META-INF/ipython-notebook.xml @@ -10,7 +10,7 @@ + nonDefaultProject="true"/> diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/IpnbUtils.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/IpnbUtils.java index 396664b79be0..0f4c67a551a6 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/IpnbUtils.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/IpnbUtils.java @@ -6,9 +6,9 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.ui.JBColor; import com.intellij.util.TimeoutUtil; -import javafx.application.Platform; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.ipnb.configuration.IpnbSettings; import org.jetbrains.plugins.ipnb.editor.IpnbEditorUtil; import javax.swing.*; @@ -21,10 +21,9 @@ import java.util.concurrent.Future; public class IpnbUtils { private static final Logger LOG = Logger.getInstance(IpnbUtils.class); - private static int hasFx = 0; - public static JComponent createLatexPane(@NotNull final String source, int width) { - final JComponent panel = createHtmlPanel(source, width); + public static JComponent createLatexPane(@NotNull final String source, Project project, int width) { + final JComponent panel = createHtmlPanel(source, project, width); panel.addMouseListener(new MouseAdapter() { @Override @@ -39,21 +38,8 @@ public class IpnbUtils { return panel; } - public static boolean hasFx() { - if (hasFx == 0) { - try { - Platform.setImplicitExit(false); - hasFx = 1; - } - catch (NoClassDefFoundError e) { - hasFx = 2; - } - } - return hasFx == 1; - } - - public static JComponent createHtmlPanel(@NotNull final String source, int width) { - if (hasFx()) { + public static JComponent createHtmlPanel(@NotNull final String source, Project project, int width) { + if (IpnbSettings.getInstance(project).hasFx()) { return IpnbJfxUtils.createHtmlPanel(source, width); } return createNonJfxPanel(source); diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.form b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.form index 84dab598e771..350208f81b77 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.form +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.form @@ -1,6 +1,6 @@
- + @@ -8,47 +8,65 @@ - + - + - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.java index 35edab4b2c55..84ace216c489 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConfigurable.java @@ -1,16 +1,21 @@ package org.jetbrains.plugins.ipnb.configuration; import com.intellij.ide.DataManager; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.ex.Settings; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ClickListener; import com.intellij.ui.UI; import com.intellij.ui.components.JBTextField; +import com.intellij.util.PlatformUtils; import com.intellij.util.ui.UIUtil; import com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.ipnb.editor.IpnbFileEditor; import javax.swing.*; import java.awt.*; @@ -23,11 +28,14 @@ public class IpnbConfigurable implements SearchableConfigurable { private JBTextField myUsernameField; private JLabel myInterpreterSetupLinkLabel; private JPasswordField myPasswordField; + private JPanel myProPanel; + private JCheckBox myMarkdownCheckBox; private final Project myProject; public IpnbConfigurable(@NotNull Project project) { myProject = project; + myProPanel.setVisible(PlatformUtils.isPyCharmPro() || PlatformUtils.isIdeaUltimate()); myInterpreterSetupLinkLabel.setForeground(UI.getColor("link.foreground")); myInterpreterSetupLinkLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); createNavigateToInterpreterSettingsListener().installOn(myInterpreterSetupLinkLabel); @@ -77,39 +85,57 @@ public class IpnbConfigurable implements SearchableConfigurable { public void apply() { final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject); + ipnbSettings.setHasFx(myMarkdownCheckBox.isSelected()); + for (FileEditor editor : FileEditorManager.getInstance(myProject).getAllEditors()) { + if (editor instanceof IpnbFileEditor) { + final VirtualFile file = ((IpnbFileEditor)editor).getVirtualFile(); + FileEditorManager.getInstance(myProject).closeFile(file); + FileEditorManager.getInstance(myProject).openFile(file, false); + } + } + if (myProPanel.isVisible()) { + final String oldUsername = ipnbSettings.getUsername(); + final String oldPassword = ipnbSettings.getPassword(myProject.getLocationHash()); - final String oldUsername = ipnbSettings.getUsername(); - final String oldPassword = ipnbSettings.getPassword(myProject.getLocationHash()); + final String newUsername = getUsername(); + final String newPassword = String.valueOf(myPasswordField.getPassword()); - final String newUsername = getUsername(); - final String newPassword = String.valueOf(myPasswordField.getPassword()); - - if (!oldUsername.equals(newUsername) || !oldPassword.equals(newPassword)) { - IpnbConnectionManager.getInstance(myProject).shutdownKernels(); - ipnbSettings.setUsername(newUsername); - ipnbSettings.setPassword(newPassword, myProject.getLocationHash()); + if (!oldUsername.equals(newUsername) || !oldPassword.equals(newPassword)) { + IpnbConnectionManager.getInstance(myProject).shutdownKernels(); + ipnbSettings.setUsername(newUsername); + ipnbSettings.setPassword(newPassword, myProject.getLocationHash()); + } } } public void reset() { final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject); + final boolean hasFx = ipnbSettings.hasFx(); + myMarkdownCheckBox.setSelected(hasFx); + if (myProPanel.isVisible()) { + final String savedUsername = ipnbSettings.getUsername(); + setInitialText(myUsernameField, savedUsername, DEFAULT_USERNAME_TEXT); - final String savedUsername = ipnbSettings.getUsername(); - setInitialText(myUsernameField, savedUsername, DEFAULT_USERNAME_TEXT); - - final String savedPassword = ipnbSettings.getPassword(myProject.getLocationHash()); - myPasswordField.setText(savedPassword); + final String savedPassword = ipnbSettings.getPassword(myProject.getLocationHash()); + myPasswordField.setText(savedPassword); + } } public boolean isModified() { final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject); - final String oldUsername = ipnbSettings.getUsername(); - final String oldPassword = ipnbSettings.getPassword(myProject.getLocationHash()); + final boolean hasFx = ipnbSettings.hasFx(); + if (hasFx != myMarkdownCheckBox.isSelected()) return true; - final String newPassword = String.valueOf(myPasswordField.getPassword()); - final String newUsername = getUsername(); + if (myProPanel.isVisible()) { + final String oldUsername = ipnbSettings.getUsername(); + final String oldPassword = ipnbSettings.getPassword(myProject.getLocationHash()); - return !oldPassword.equals(newPassword) || !oldUsername.equals(newUsername); + final String newPassword = String.valueOf(myPasswordField.getPassword()); + final String newUsername = getUsername(); + + return !oldPassword.equals(newPassword) || !oldUsername.equals(newUsername); + } + return false; } private String getUsername() { diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbSettings.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbSettings.java index ce6b2aea8584..ae5c86c40e3f 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbSettings.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbSettings.java @@ -8,6 +8,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.annotations.Transient; +import com.sun.javafx.application.PlatformImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,6 +16,7 @@ import org.jetbrains.annotations.Nullable; public class IpnbSettings implements PersistentStateComponent { private static final String IPNB_PASSWORD_KEY = "IPNB_SSH_SETTINGS_PASSWORD_KEY"; private String myUsername; + private boolean hasFx = true; public static IpnbSettings getInstance(@NotNull Project project) { return ServiceManager.getService(project, IpnbSettings.class); @@ -27,7 +29,23 @@ public class IpnbSettings implements PersistentStateComponent { public void setUsername(@Nullable String username) { myUsername = username; } - + + public boolean hasFx() { + if (hasFx) { + try { + PlatformImpl.setImplicitExit(false); + } + catch (NoClassDefFoundError e) { + hasFx = false; + } + } + return hasFx; + } + + public void setHasFx(boolean hasFx) { + this.hasFx = hasFx; + } + @Transient @NotNull public String getPassword(@NotNull String projectPathHash) { diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java index c3954045e747..b33c05895112 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java @@ -1,14 +1,13 @@ package org.jetbrains.plugins.ipnb.editor.panels; import com.google.common.collect.Lists; -import com.intellij.ide.*; +import com.intellij.ide.CopyProvider; +import com.intellij.ide.CutProvider; +import com.intellij.ide.DeleteProvider; +import com.intellij.ide.PasteProvider; import com.intellij.lang.Language; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; @@ -32,12 +31,10 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.ui.JBColor; import com.intellij.ui.KeyStrokeAdapter; import com.intellij.util.Alarm; -import com.intellij.util.PlatformUtils; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.Topic; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.ipnb.IpnbUtils; import org.jetbrains.plugins.ipnb.editor.IpnbEditorUtil; import org.jetbrains.plugins.ipnb.editor.IpnbFileEditor; import org.jetbrains.plugins.ipnb.editor.actions.IpnbToggleLineNumbersAction; @@ -120,9 +117,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D setFocusable(true); }, 10, ModalityState.stateForComponent(this)); myParent.loaded(); - IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { - IdeFocusManager.getGlobalInstance().requestFocus(this, true); - }); + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(this, true)); myBusConnection = ApplicationManager.getApplication().getMessageBus().connect(); myBusConnection.subscribe(ProjectEx.ProjectSaved.TOPIC, new ProjectEx.ProjectSaved() { @@ -189,7 +184,6 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D } private void layoutFile() { - addWarningIfNeeded(); final List cells = myIpnbFile.getCells(); for (IpnbCell cell : cells) { addCellToPanel(cell); @@ -205,35 +199,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D myParent.updateScrollPosition(mySelectedCellPanel); } }); - IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { - IdeFocusManager.getGlobalInstance().requestFocus(this, true); - }); - } - - private void addWarningIfNeeded() { - if (IpnbUtils.hasFx()) return; - final String text; - final String href; - if (PlatformUtils.isPyCharm()) { - href = "https://www.jetbrains.com/pycharm/download/"; - text = "Download PyCharm with bundled JDK for better " + - "Markdown cell rendering"; - } - else { - href = "https://confluence.jetbrains.com/display/PYH/Pycharm+2016.1+Jupyter+Notebook+rendering"; - text = - "Follow instructions " + - "here for better Markdown cell rendering"; - } - final JLabel warning = new JLabel(text, SwingConstants.CENTER); - warning.setForeground(JBColor.RED); - warning.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - BrowserUtil.browse(href); - } - }); - add(warning); + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(this, true)); } private void addCellToPanel(IpnbCell cell) { @@ -665,6 +631,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D } } + @SuppressWarnings("unused") public void selectNextOrPrev(@NotNull IpnbEditablePanel cell) { int index = myIpnbPanels.indexOf(cell); if (index < myIpnbPanels.size() - 1) { @@ -684,9 +651,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D IpnbEditablePanel ipnbPanel = getIpnbPanelByClick(e.getPoint()); if (ipnbPanel != null) { ipnbPanel.setEditing(false); - IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { - IdeFocusManager.getGlobalInstance().requestFocus(this, true); - }); + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(this, true)); setSelectedCell(ipnbPanel, true); } } diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbMarkdownPanel.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbMarkdownPanel.java index 6f98093631cb..9522becfaa6e 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbMarkdownPanel.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbMarkdownPanel.java @@ -36,13 +36,13 @@ public class IpnbMarkdownPanel extends IpnbEditablePanel { @Override protected JComponent createViewPanel() { final int width = myParent.getWidth(); - return IpnbUtils.createLatexPane(StringUtil.join(myCell.getHtmls(), ""), width); + return IpnbUtils.createLatexPane(StringUtil.join(myCell.getHtmls(), ""), myParent.getProject(), width); } } diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/code/IpnbLatexPanel.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/code/IpnbLatexPanel.java index ddecc70018c2..c85052f132eb 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/code/IpnbLatexPanel.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/code/IpnbLatexPanel.java @@ -23,6 +23,6 @@ public class IpnbLatexPanel extends IpnbCodeOutputPanel { @Override protected JComponent createViewPanel() { final int width = myParent.getWidth(); - return IpnbUtils.createLatexPane(StringUtil.join(myCell.getLatex(), ""), width); + return IpnbUtils.createLatexPane(StringUtil.join(myCell.getLatex(), ""), myParent.getProject(), width); } } diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/run/IpnbRunConfiguration.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/run/IpnbRunConfiguration.java index 73da9e58e903..7ca5cf18d454 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/run/IpnbRunConfiguration.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/run/IpnbRunConfiguration.java @@ -91,7 +91,7 @@ public class IpnbRunConfiguration extends AbstractPythonRunConfiguration