diff --git a/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtmlView.java b/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtmlView.java index d916e2a..dcf9d56 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtmlView.java +++ b/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtmlView.java @@ -29,12 +29,13 @@ package edu.umd.cs.piccolo.nodes; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics2D; -import java.awt.Rectangle; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.plaf.basic.BasicHTML; import javax.swing.text.Position; @@ -44,9 +45,9 @@ import edu.umd.cs.piccolo.util.PPaintContext; /** - * PHtmlView is a Piccolo node for rendering HTML text. It uses a JLabel under the - * hood so you have the same restrictions regarding HTML as you have when using - * standard Swing components (HTML 3.2 + subset of CSS 1.0). + * PHtmlView is a Piccolo node for rendering HTML text. It uses a JLabel under + * the hood so you have the same restrictions regarding HTML as you have when + * using standard Swing components (HTML 3.2 + subset of CSS 1.0). * * @author Chris Malley (cmal...@pixelzoom.com) * @author Sam Reid @@ -57,11 +58,18 @@ /** Default serial version UID. */ private static final long serialVersionUID = 1L; - /** Default font if not otherwise specified in the HTML text, 12 point "SansSerif". */ - // public static final Font DEFAULT_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 12); jdk 1.6+ + /** + * Default font if not otherwise specified in the HTML text, 12 point + * "SansSerif". + */ + // public static final Font DEFAULT_FONT = new Font(Font.SANS_SERIF, + // Font.PLAIN, 12); jdk 1.6+ public static final Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN, 12); - /** Default text color if not otherwise specified in the HTML text, Color.BLACK. */ + /** + * Default text color if not otherwise specified in the HTML text, + * Color.BLACK. + */ public static final Color DEFAULT_TEXT_COLOR = Color.BLACK; /** @@ -93,16 +101,16 @@ public static final int PROPERTY_CODE_TEXT = 1 << 21; /** - * The property name that identifies a change of this node's HTML text color (see - * {@link #getHtml getHTMLColor}). Both old and new value will be set in any - * property change event. + * The property name that identifies a change of this node's HTML text color + * (see {@link #getHtml getHTMLColor}). Both old and new value will be set + * in any property change event. */ public static final String PROPERTY_TEXT_COLOR = "text color"; /** - * The property code that identifies a change of this node's HTML text color (see - * {@link #getHtml getHTMLColor}). Both old and new value will be set in any - * property change event. + * The property code that identifies a change of this node's HTML text color + * (see {@link #getHtml getHTMLColor}). Both old and new value will be set + * in any property change event. */ public static final int PROPERTY_CODE_TEXT_COLOR = 1 << 22; @@ -112,9 +120,6 @@ /** Object that encapsulates the HTML rendering logic. */ private View htmlView; - /** Used to enforce bounds and wrapping on the HTML. */ - private final Rectangle htmlBounds; - /** * Create an empty HTML text node with the default font and text color. */ @@ -123,7 +128,8 @@ } /** - * Create a HTML text node with the specified HTML text and the default font and text color. + * Create a HTML text node with the specified HTML text and the default font + * and text color. * * @param text HTML text for this HTML text node */ @@ -132,8 +138,9 @@ } /** - * Create a HTML text node with the specified HTML text, font, and text color. The font - * and text color are used to render the HTML text if not otherwise specified via CSS. + * Create a HTML text node with the specified HTML text, font, and text + * color. The font and text color are used to render the HTML text if not + * otherwise specified via CSS. * * @param text HTML text for this HTML text node * @param font font for this HTML text node @@ -143,7 +150,6 @@ label = new JLabel(text); label.setFont(font); label.setForeground(textColor); - htmlBounds = new Rectangle(); super.setBounds(0, 0, label.getPreferredSize().getWidth(), label.getPreferredSize().getHeight()); update(); } @@ -168,14 +174,17 @@ */ public void setText(final String text) { final String oldText = label.getText(); + label.setText(text); + update(); firePropertyChange(PROPERTY_CODE_TEXT, PROPERTY_TEXT, oldText, label.getText()); } /** * Return the font for this HTML text node. This font is used to render the - * HTML text if not otherwise specified via CSS. Defaults to {@link #DEFAULT_FONT}. + * HTML text if not otherwise specified via CSS. Defaults to + * {@link #DEFAULT_FONT}. * * @return the font for this HTML text node */ @@ -201,18 +210,20 @@ } /** - * Return the text color for this HTML text node. This text color is used to render the - * HTML text if not otherwise specified via CSS. Defaults to {@link #DEFAULT_TEXT_COLOR}. - * - * @return the text color for this HTML text node - */ + * Return the text color for this HTML text node. This text color is used to + * render the HTML text if not otherwise specified via CSS. Defaults to + * {@link #DEFAULT_TEXT_COLOR}. + * + * @return the text color for this HTML text node + */ public Color getTextColor() { return label.getForeground(); } /** - * Set the text color for this HTML text node to textColor. This text color is - * used to render the HTML text if not otherwise specified via CSS. + * Set the text color for this HTML text node to textColor. + * This text color is used to render the HTML text if not otherwise + * specified via CSS. * *

* This is a bound property. @@ -232,20 +243,39 @@ * updates bounds. */ private void update() { - label.setSize(label.getPreferredSize()); - String htmlContent = label.getText(); if (htmlContent == null) { htmlContent = ""; } htmlView = BasicHTML.createHTMLView(label, htmlContent); + fitHeightToHtmlContent(); - final Rectangle2D bounds = getBounds(); - htmlBounds.setRect(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); repaint(); } + /** + * Resizes the height to be as tall as its rendered html. Takes wrapping + * into account. + * + * TODO: Reuse the JFrame, or find something better. At least it delegates + * to the html renderer. + */ + private void fitHeightToHtmlContent() { + htmlView.setSize((float) getWidth(), 0f); + // float preferredWrapWidth = htmlView.getPreferredSpan(View.X_AXIS); + float preferredWrapHeight = htmlView.getPreferredSpan(View.Y_AXIS); + label.setPreferredSize(new Dimension((int) getWidth(), (int) preferredWrapHeight)); + + JFrame frame = new JFrame(); + frame.getContentPane().add(label); + frame.pack(); + + if (getHeight() != label.getHeight()) { + super.setBounds(getX(), getY(), getWidth(), label.getHeight()); + } + } + /** {@inheritDoc} */ public boolean setBounds(final double x, final double y, final double width, final double height) { final boolean boundsChanged = super.setBounds(x, y, width, height); @@ -264,7 +294,8 @@ * {@inheritDoc} * *

- * The HTML text is painted last, so it will appear on top of any child nodes. + * The HTML text is painted last, so it will appear on top of any child + * nodes. *

*/ protected void paint(final PPaintContext paintContext) { @@ -273,7 +304,7 @@ if (label.getWidth() != 0 && label.getHeight() != 0) { final Graphics2D g2 = paintContext.getGraphics(); - htmlView.paint(g2, htmlBounds); + htmlView.paint(g2, getBounds().getBounds()); } } @@ -283,22 +314,22 @@ * * @param point point in this node's local coordinate system * @return the address specified in the HTML link at the specified point in - * this node's local coordinate system, or null if no such - * HTML link exists + * this node's local coordinate system, or null if no + * such HTML link exists */ public String getLinkAddressAt(final Point2D point) { return getLinkAddressAt(point.getX(), point.getY()); } /** - * Return the address specified in the HTML link at the specified x and y coordinates in - * this node's local coordinate system, if any. + * Return the address specified in the HTML link at the specified x and y + * coordinates in this node's local coordinate system, if any. * * @param x x coordinate in this node's local coordinate system * @param y y coordinate in this node's local coordinate system - * @return the address specified in the HTML link at the specified x and y coordinates in - * this node's local coordinate system, or null if no such - * HTML link exists + * @return the address specified in the HTML link at the specified x and y + * coordinates in this node's local coordinate system, or + * null if no such HTML link exists */ public String getLinkAddressAt(final double x, final double y) { int position = pointToModelIndex(x, y); @@ -339,13 +370,13 @@ } /** - * Return the index into the raw text at the specified x and y coordinates in - * this node's local coordinate system. + * Return the index into the raw text at the specified x and y coordinates + * in this node's local coordinate system. * * @param x x coordinate in this node's local coordinate system * @param y y coordinate in this node's local coordinate system - * @return the index into the raw text at the specified x and y coordinates in - * this node's local coordinate system + * @return the index into the raw text at the specified x and y coordinates + * in this node's local coordinate system */ private int pointToModelIndex(final double x, final double y) { final Position.Bias[] biasReturn = new Position.Bias[1]; @@ -433,7 +464,7 @@ } else { final int startHref = currentPos; - + if (currentPos < tag.length()) { do { currentPos++; diff --git a/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlViewTest.java b/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlViewTest.java index 2f0b7c7..8c2e509 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlViewTest.java +++ b/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlViewTest.java @@ -227,9 +227,8 @@ assertSame(font, html.getFont()); } - public void testPaintFillsBounds() throws IOException { + public void testPaintFillsBounds() { PHtmlView html = new PHtmlView("30. Lorem ipsum dolor sit amet, consectetur adipiscing elit posuere."); - html.setBounds(0, 0, 400, 30); html.setPaint(Color.RED); PCanvas canvas = new PCanvas(); @@ -242,9 +241,8 @@ canvas.paint(g2); assertEquals(Color.red.getRGB(), image.getRGB(0, 0)); - assertEquals(Color.red.getRGB(), image.getRGB(0, 15)); - assertEquals(Color.red.getRGB(), image.getRGB(0, 29)); - assertEquals(Color.red.getRGB(), image.getRGB(399, 0)); + assertEquals(Color.red.getRGB(), image.getRGB(0, 15)); + assertEquals(Color.red.getRGB(), image.getRGB(300, 0)); assertEquals(Color.white.getRGB(), image.getRGB(400, 0)); } }