fixed ipython notebook cell resize.

Now we use vertical flow layout instead of grid bag layout. Editable cells are self contained so we have invisible prompt labels in them.
This commit is contained in:
Ekaterina Tuzova
2014-10-29 17:31:47 +03:00
parent a681e95474
commit 941efb724a
7 changed files with 94 additions and 186 deletions
@@ -11,7 +11,6 @@ import net.sourceforge.jeuclid.context.LayoutContextImpl;
import net.sourceforge.jeuclid.context.Parameter;
import net.sourceforge.jeuclid.converter.Converter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.ipnb.editor.panels.IpnbFilePanel;
import org.jetbrains.plugins.ipnb.editor.panels.IpnbTexPackageDefinitions;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
@@ -26,8 +25,6 @@ import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.event.HierarchyBoundsAdapter;
import java.awt.event.HierarchyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
@@ -72,7 +69,7 @@ public class IpnbUtils {
return ourMarkdownProcessor.markdown(StringUtil.join(lines, "\n"));
}
public static void addLatexToPanel(@NotNull final String source, @NotNull final JPanel panel) {
public static JEditorPane createLatexPane(@NotNull final String source) {
final JEditorPane editorPane = new JEditorPane();
editorPane.setContentType(new HTMLEditorKit().getContentType());
editorPane.setEditorKit(new HTMLEditorKit());
@@ -87,43 +84,20 @@ public class IpnbUtils {
editorPane.setEditable(false);
final String html = convertToHtml(source, editorPane);
editorPane.setText("<html><body>" + html + "</body></html>");
editorPane.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final MouseEvent parentEvent = SwingUtilities.convertMouseEvent(editorPane, e, panel);
panel.dispatchEvent(parentEvent);
final Container parent = editorPane.getParent();
final MouseEvent parentEvent = SwingUtilities.convertMouseEvent(editorPane, e, parent);
parent.dispatchEvent(parentEvent);
}
});
editorPane.addHyperlinkListener(new BrowserHyperlinkListener());
//TODO: jump to the section (see User Interface#Utilities)
editorPane.addHierarchyBoundsListener(new IpnbHierarchyBoundsAdapter(editorPane));
panel.add(editorPane);
}
public static class IpnbHierarchyBoundsAdapter extends HierarchyBoundsAdapter {
private final JComponent myComponent;
public IpnbHierarchyBoundsAdapter(@NotNull final JComponent component) {
myComponent = component;
}
@Override
public void ancestorResized(HierarchyEvent e) {
final Component component = e.getChanged();
if (component instanceof IpnbFilePanel) {
final int width = component.getWidth();
if (width > 0) {
myComponent.setPreferredSize(new Dimension(width - 300, myComponent.getPreferredSize().height));
myComponent.revalidate();
myComponent.repaint();
}
}
}
return editorPane;
}
private static String convertToHtml(@NotNull final String source, @NotNull final JEditorPane editorPane) {
@@ -6,14 +6,17 @@ import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.ipnb.IpnbUtils;
import org.jetbrains.plugins.ipnb.editor.IpnbEditorUtil;
import org.jetbrains.plugins.ipnb.format.cells.IpnbEditableCell;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public abstract class IpnbEditablePanel<T extends JComponent, K extends IpnbEditableCell> extends IpnbPanel<T, K> {
private static final Logger LOG = Logger.getInstance(IpnbEditablePanel.class);
@@ -32,6 +35,28 @@ public abstract class IpnbEditablePanel<T extends JComponent, K extends IpnbEdit
protected void initPanel() {
addViewPanel();
addEditablePanel();
}
private void addEditablePanel() {
myEditablePanel = createEditablePanel();
final JPanel panel = new JPanel(new GridBagLayout());
final GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
panel.setName(EDITABLE_PANEL);
panel.setBackground(IpnbEditorUtil.getBackground());
addPromptPanel(panel, null, IpnbEditorUtil.PromptType.None, myEditablePanel, c);
add(panel, EDITABLE_PANEL);
}
private void addViewPanel() {
myViewPanel = createViewPanel();
myViewPanel.addMouseListener(new MouseAdapter() {
@Override
@@ -45,12 +70,36 @@ public abstract class IpnbEditablePanel<T extends JComponent, K extends IpnbEdit
}
});
myViewPanel.setName(VIEW_PANEL);
add(myViewPanel, VIEW_PANEL);
myEditablePanel = createEditablePanel();
myEditablePanel.setName(EDITABLE_PANEL);
add(myEditablePanel, EDITABLE_PANEL);
final JPanel panel = new JPanel(new GridBagLayout());
final GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
addPromptPanel(panel, null, IpnbEditorUtil.PromptType.None, myViewPanel, c);
panel.setBackground(IpnbEditorUtil.getBackground());
add(panel, VIEW_PANEL);
}
public void addPromptPanel(@NotNull final JComponent parent, Integer promptNumber,
@NotNull final IpnbEditorUtil.PromptType promptType,
@NotNull final JComponent component, @NotNull final GridBagConstraints c) {
c.gridx = 0;
c.weightx = 0;
c.anchor = GridBagConstraints.NORTHWEST;
final JComponent promptComponent = IpnbEditorUtil.createPromptComponent(promptNumber, promptType);
c.insets = new Insets(2,2,2,5);
parent.add(promptComponent, c);
c.gridx = 1;
c.weightx = 1;
c.insets = new Insets(2,2,2,2);
c.anchor = GridBagConstraints.CENTER;
parent.add(component, c);
}
public void switchToEditing() {
setEditing(true);
@@ -84,24 +133,6 @@ public abstract class IpnbEditablePanel<T extends JComponent, K extends IpnbEdit
private JTextArea createEditablePanel() {
final JTextArea textArea = new JTextArea(getRawCellText());
addHierarchyBoundsListener(new IpnbUtils.IpnbHierarchyBoundsAdapter(this));
textArea.addHierarchyBoundsListener(new IpnbUtils.IpnbHierarchyBoundsAdapter(textArea));
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
final int height = Math.max(textArea.getFontMetrics(getFont()).getHeight() * getLineCount(textArea),
myViewPanel.getPreferredSize().height);
setPreferredSize(new Dimension(textArea.getWidth(), height));
final Container parent = getParent();
if (parent instanceof IpnbFilePanel) {
IpnbFilePanel filePanel = (IpnbFilePanel)parent;
filePanel.revalidate();
filePanel.repaint();
}
}
});
textArea.setLineWrap(true);
textArea.setEditable(true);
textArea.setBorder(BorderFactory.createLineBorder(JBColor.lightGray));
@@ -123,16 +154,6 @@ public abstract class IpnbEditablePanel<T extends JComponent, K extends IpnbEdit
textArea.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
final int height = textArea.getFontMetrics(getFont()).getHeight() * getLineCount(textArea);
final Dimension preferredSize = myViewPanel.getPreferredSize();
setPreferredSize(new Dimension(preferredSize.width, Math.max(height, preferredSize.height)));
textArea.setPreferredSize(new Dimension(textArea.getWidth(), height));
textArea.revalidate();
textArea.repaint();
revalidate();
repaint();
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
setEditing(false);
final Container parent = getParent();
@@ -6,6 +6,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.UIUtil;
@@ -29,9 +30,6 @@ import java.util.ArrayList;
import java.util.List;
public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
public static final int INSET_Y = 10;
public static final int INSET_X = 5;
private IpnbFile myIpnbFile;
private Project myProject;
@@ -48,7 +46,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
public IpnbFilePanel(@NotNull final Project project, @NotNull final IpnbFileEditor parent, @NotNull final VirtualFile vFile,
@NotNull final IpnbFileEditor.CellSelectionListener listener) {
super(new GridBagLayout());
super(new VerticalFlowLayout(VerticalFlowLayout.TOP, 100, 5, true, false));
myProject = project;
myParent = parent;
myListener = listener;
@@ -87,24 +85,9 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
}
private void layoutFile() {
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 2;
c.insets = new Insets(INSET_Y, INSET_X, 0, 0);
c.gridy = 1;
c.gridwidth = 1;
final JPanel panel = new JPanel();
panel.setPreferredSize(IpnbEditorUtil.PROMPT_SIZE);
panel.setBackground(getBackground());
panel.setOpaque(false);
add(panel, c);
final List<IpnbCell> cells = myIpnbFile.getCells();
for (IpnbCell cell : cells) {
c.gridy = addCellToPanel(cell, c);
addCellToPanel(cell);
}
if (myInitialSelection >= 0 && myIpnbPanels.size() > myInitialSelection) {
@@ -112,31 +95,27 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
setSelectedCell(toSelect);
myParent.getScrollPane().getViewport().setViewPosition(new Point(0, myInitialPosition));
}
c.weighty = 1;
add(createEmptyPanel(), c);
add(createEmptyPanel());
}
private int addCellToPanel(IpnbCell cell, GridBagConstraints c) {
private void addCellToPanel(IpnbCell cell) {
IpnbEditablePanel panel;
if (cell instanceof IpnbCodeCell) {
panel = new IpnbCodePanel(myProject, myParent, (IpnbCodeCell)cell);
c.gridwidth = 2;
c.gridx = 0;
add(panel, c);
add(panel);
myIpnbPanels.add(panel);
}
else if (cell instanceof IpnbMarkdownCell) {
panel = new IpnbMarkdownPanel((IpnbMarkdownCell)cell);
addComponent(c, panel);
addComponent(panel);
}
else if (cell instanceof IpnbHeadingCell) {
panel = new IpnbHeadingPanel((IpnbHeadingCell)cell);
addComponent(c, panel);
addComponent(panel);
}
else {
throw new UnsupportedOperationException(cell.getClass().toString());
}
return c.gridy + 1;
}
public void createAndAddCell(boolean below) {
@@ -148,13 +127,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
}
private void addCell(@NotNull final IpnbEditablePanel panel, boolean below) {
final GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
c.insets = new Insets(INSET_Y, INSET_X, 0, 0);
removeAll();
final IpnbEditablePanel selectedCell = getSelectedCell();
int index = myIpnbPanels.indexOf(selectedCell);
if (below) {
@@ -164,28 +137,10 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
myIpnbFile.addCell(cell, index);
myIpnbPanels.add(index, panel);
final JPanel promptPanel = new JPanel();
promptPanel.setPreferredSize(new Dimension(IpnbEditorUtil.PROMPT_SIZE.width, 1));
promptPanel.setBackground(getBackground());
promptPanel.setOpaque(false);
add(promptPanel, c);
c.gridy += 1;
for (IpnbPanel comp : myIpnbPanels) {
c.gridwidth = 1;
c.gridx = 1;
if (comp instanceof IpnbCodePanel) {
c.gridwidth = 2;
c.gridx = 0;
add(comp, c);
}
else {
add(comp, c);
}
c.gridy += 1;
add(comp);
}
c.weighty = 1;
add(createEmptyPanel(), c);
add(createEmptyPanel());
setSelectedCell(panel);
requestFocus();
@@ -255,26 +210,17 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
}
public void replaceComponent(@NotNull final IpnbEditablePanel from, @NotNull final IpnbCell cell) {
final GridBagConstraints c = ((GridBagLayout)getLayout()).getConstraints(from);
removeAll();
final int index = myIpnbPanels.indexOf(from);
IpnbEditablePanel panel;
if (cell instanceof IpnbCodeCell) {
panel = new IpnbCodePanel(myProject, myParent, (IpnbCodeCell)cell);
c.gridwidth = 2;
c.gridx = 0;
add(panel, c);
}
else if (cell instanceof IpnbMarkdownCell) {
panel = new IpnbMarkdownPanel((IpnbMarkdownCell)cell);
c.gridwidth = 1;
c.gridx = 1;
add(panel, c);
}
else if (cell instanceof IpnbHeadingCell) {
panel = new IpnbHeadingPanel((IpnbHeadingCell)cell);
c.gridwidth = 1;
c.gridx = 1;
add(panel, c);
}
else {
throw new UnsupportedOperationException(cell.getClass().toString());
@@ -283,6 +229,11 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
myIpnbPanels.remove(index);
myIpnbPanels.add(index, panel);
}
for (IpnbPanel comp : myIpnbPanels) {
add(comp);
}
add(createEmptyPanel());
if (from instanceof IpnbCodePanel) {
panel.switchToEditing();
}
@@ -292,11 +243,8 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
repaint();
}
private void addComponent(@NotNull final GridBagConstraints c, @NotNull final IpnbEditablePanel comp) {
c.gridwidth = 1;
c.gridx = 1;
add(comp, c);
private void addComponent(@NotNull final IpnbEditablePanel comp) {
add(comp);
myIpnbPanels.add(comp);
}
@@ -376,14 +324,8 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider {
super.paintComponent(g);
if (mySelectedCell != null) {
g.setColor(mySelectedCell.isEditing() ? JBColor.GREEN : JBColor.GRAY);
if (mySelectedCell instanceof IpnbCodePanel) {
g.drawRoundRect(mySelectedCell.getX() - 50, mySelectedCell.getTop() - 1,
g.drawRoundRect(mySelectedCell.getX() - 50, mySelectedCell.getTop() - 1,
mySelectedCell.getWidth() + 145 - IpnbEditorUtil.PROMPT_SIZE.width, mySelectedCell.getHeight() + 2, 5, 5);
}
else {
g.drawRoundRect(mySelectedCell.getX() - IpnbEditorUtil.PROMPT_SIZE.width - 55, mySelectedCell.getTop() - 1,
mySelectedCell.getWidth() + 150, mySelectedCell.getHeight() + 2, 5, 5);
}
}
}
@@ -1,15 +1,12 @@
package org.jetbrains.plugins.ipnb.editor.panels;
import com.intellij.openapi.ui.VerticalFlowLayout;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.ipnb.IpnbUtils;
import org.jetbrains.plugins.ipnb.editor.IpnbEditorUtil;
import org.jetbrains.plugins.ipnb.format.cells.IpnbMarkdownCell;
import javax.swing.*;
import java.awt.*;
public class IpnbMarkdownPanel extends IpnbEditablePanel<JPanel, IpnbMarkdownCell> {
public class IpnbMarkdownPanel extends IpnbEditablePanel<JEditorPane, IpnbMarkdownCell> {
public IpnbMarkdownPanel(@NotNull final IpnbMarkdownCell cell) {
super(cell);
@@ -22,23 +19,13 @@ public class IpnbMarkdownPanel extends IpnbEditablePanel<JPanel, IpnbMarkdownCel
}
@Override
protected JPanel createViewPanel() {
final JPanel panel = new JPanel(new VerticalFlowLayout(FlowLayout.LEFT, false, true));
updatePanel(panel);
panel.setBackground(IpnbEditorUtil.getBackground());
panel.setOpaque(true);
return panel;
protected JEditorPane createViewPanel() {
return IpnbUtils.createLatexPane(myCell.getSourceAsString());
}
private void updatePanel(@NotNull final JPanel panel) {
panel.removeAll();
IpnbUtils.addLatexToPanel(myCell.getSourceAsString(), panel);
}
@Override
public void updateCellView() {
updatePanel(myViewPanel);
myViewPanel = IpnbUtils.createLatexPane(myCell.getSourceAsString());
}
@SuppressWarnings("CloneDoesntCallSuperClone")
@@ -50,20 +50,10 @@ public class IpnbCodePanel extends IpnbEditablePanel<JComponent, IpnbCodeCell> {
public void addPromptPanel(@NotNull final JComponent parent, Integer promptNumber,
@NotNull final IpnbEditorUtil.PromptType promptType,
@NotNull final IpnbPanel component, @NotNull final GridBagConstraints c) {
c.gridx = 0;
c.weightx = 0;
c.anchor = GridBagConstraints.NORTHWEST;
final JComponent promptComponent = IpnbEditorUtil.createPromptComponent(promptNumber, promptType);
c.insets = new Insets(2,2,2,5);
parent.add(promptComponent, c);
c.gridx = 1;
c.weightx = 1;
c.insets = new Insets(2,2,2,2);
c.anchor = GridBagConstraints.CENTER;
parent.add(component, c);
myOutputPanels.add(component);
@NotNull final JComponent component, @NotNull final GridBagConstraints c) {
super.addPromptPanel(parent, promptNumber, promptType, component, c);
if (component instanceof IpnbPanel)
myOutputPanels.add((IpnbPanel)component);
}
@Override
@@ -83,7 +83,7 @@ public class IpnbCodeSourcePanel extends IpnbPanel<JComponent, IpnbCodeCell> imp
final int keyCode = e.getKeyCode();
final Container parent = myParent.getParent();
final int height = myEditor.getLineHeight() * Math.max(myEditor.getDocument().getLineCount(), 1) + 5;
final int height = myEditor.getLineHeight() * Math.max(myEditor.getDocument().getLineCount(), 1) + 10;
contentComponent.setPreferredSize(new Dimension(parent.getWidth() - 300, height));
panel.setPreferredSize(new Dimension(parent.getWidth() - 300, height));
myParent.revalidate();
@@ -131,7 +131,7 @@ public class IpnbCodeSourcePanel extends IpnbPanel<JComponent, IpnbCodeCell> imp
public void hierarchyChanged(HierarchyEvent e) {
final Container parent = myParent.getParent();
if (parent != null) {
final int height = myEditor.getLineHeight() * Math.max(myEditor.getDocument().getLineCount(), 1) + 5;
final int height = myEditor.getLineHeight() * Math.max(myEditor.getDocument().getLineCount(), 1) + 10;
contentComponent.setPreferredSize(new Dimension(parent.getWidth() - 300, height));
panel.setPreferredSize(new Dimension(parent.getWidth() - 300, height));
}
@@ -143,7 +143,7 @@ public class IpnbCodeSourcePanel extends IpnbPanel<JComponent, IpnbCodeCell> imp
final Container parent = myParent.getParent();
final Component component = e.getChanged();
if (parent != null && component instanceof IpnbFilePanel) {
final int height = myEditor.getLineHeight() * Math.max(myEditor.getDocument().getLineCount(), 1) + 5;
final int height = myEditor.getLineHeight() * Math.max(myEditor.getDocument().getLineCount(), 1) + 10;
contentComponent.setPreferredSize(new Dimension(parent.getWidth() - 300, height));
panel.setPreferredSize(new Dimension(parent.getWidth() - 300, height));
panel.revalidate();
@@ -8,22 +8,16 @@ import org.jetbrains.plugins.ipnb.editor.IpnbEditorUtil;
import org.jetbrains.plugins.ipnb.format.cells.output.IpnbLatexOutputCell;
import javax.swing.*;
import java.awt.*;
public class IpnbLatexPanel extends IpnbCodeOutputPanel<IpnbLatexOutputCell> {
public IpnbLatexPanel(@NotNull final IpnbLatexOutputCell cell) {
super(cell);
setLayout(new VerticalFlowLayout(FlowLayout.LEFT));
setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP));
setBackground(IpnbEditorUtil.getBackground());
}
@Override
protected JComponent createViewPanel() {
final JPanel panel = new JPanel();
IpnbUtils.addLatexToPanel(StringUtil.join(myCell.getLatex()), panel);
setBackground(IpnbEditorUtil.getBackground());
panel.setBackground(IpnbEditorUtil.getBackground());
panel.setOpaque(true);
setOpaque(true);
return panel;
return IpnbUtils.createLatexPane(StringUtil.join(myCell.getLatex()));
}
}