light-weight HTML

8 views
Skip to first unread message

Hennin...@googlemail.com

unread,
Nov 10, 2008, 10:19:34 AM11/10/08
to Piccolo2D Users
Hi Piccolo Community,
we are trying to show some light-weight HTML text in Piccolo,
preferably editable (only some simple tags like <b>, <i>, <h1-3>,
<ul>, <li>, <a href>).
I tried to use PStyledText, because I thought it could do that like
JTextPane of Swing, but PStyledText seams to only show very little
HTML properly. (Some tags it does some it doesn't)
I overrode my main paint method and tried to use a normal JTextPane
instead to paint itself to the respective position, but that cuases
the trouble of not being in the right depth or position. (How) can I
influence wther the Swing JTextPane should reside behind in front or
maybe in between piccolo layers?
Does anyone have any other idea or advice how w could do this?
Thanks in a advance

Samuel Robert Reid

unread,
Nov 10, 2008, 12:27:09 PM11/10/08
to piccolo...@googlegroups.com
Here's an HTML node we developed for our project (attached). It
internally uses swing JLabel for rendering the HTML, and therefore
doesn't support all html tags (and as usual with swing, you need to add
your own support for hyperlink listeners, etc). Please let me know if
you have questions or comments about it. Sometime in the future, we may
integrate this into the piccolo-extras package.

Sam Reid

HTMLNode.java

Winston Fassett

unread,
Nov 11, 2008, 10:26:14 PM11/11/08
to Piccolo2D Users
Has anyone done anything similar in .NET? Looks like people usually
just embed a WebBrowser control, but I tried it and it's way too
heavyweight for use as a PNode.

Allain Lalonde

unread,
Nov 12, 2008, 3:14:04 PM11/12/08
to piccolo...@googlegroups.com
You have no idea how happy you just made me :)

Thanks.

2008/11/10 Samuel Robert Reid <Re...@colorado.edu>
/* Copyright 2005, University of Colorado */

/*
 * CVS Info -
 * Filename : $Source$
 * Branch : $Name$
 * Modified by : $Author$
 * Revision : $Revision$
 * Date modified : $Date$
 */

package edu.colorado.phet.common.piccolophet.nodes;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import javax.swing.JLabel;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;

import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.util.PPaintContext;

/**
 * HTMLNode is a Piccolo node for rendering HTML text.
 *
 * @author Chris Malley (cma...@pixelzoom.com)
 * @author Sam Reid
 * @version $Revision$
 */
public class HTMLNode extends PNode {

   //----------------------------------------------------------------------------
   // Class data
   //----------------------------------------------------------------------------

   private static final Font DEFAULT_FONT = new JLabel().getFont();
   private static final Color DEFAULT_HTML_COLOR = Color.BLACK;

   //----------------------------------------------------------------------------
   // Instance data
   //----------------------------------------------------------------------------

   private String html;
   private Font font;
   private Color htmlColor;
   private JLabel htmlLabel;
   private View htmlView;
   private final Rectangle htmlBounds; // BasicHTML$Renderer.paint requires a Rectangle

   //----------------------------------------------------------------------------
   // Constructors
   //----------------------------------------------------------------------------

   public HTMLNode() {
       this( null, DEFAULT_FONT, DEFAULT_HTML_COLOR );
   }

   public HTMLNode( String html ) {
       this( html, DEFAULT_FONT, DEFAULT_HTML_COLOR );
   }

   public HTMLNode( String html, Color htmlColor ) {
       this( html, DEFAULT_FONT, htmlColor );
   }

   public HTMLNode( String html, Font font, Color htmlColor ) {
       this.html = html;
       this.font = font;
       this.htmlColor = htmlColor;
       htmlLabel = new JLabel();
       htmlBounds = new Rectangle();
       update();
   }

   //----------------------------------------------------------------------------
   // Accessors
   //----------------------------------------------------------------------------

   /**
    * Gets the HTML string.
    *
    * @return HTML string
    */
   public String getHTML() {
       return html;
   }

   /**
    * Sets the HMTL string.
    *
    * @param html
    */
   public void setHTML( String html ) {
       if ( ( this.html != null && html == null ) || ( this.html == null && html != null ) || ( !this.html.equals( html ) ) ) {
           this.html = html;
           update();
       }
   }

   /**
    * Gets the font.
    *
    * @return the font
    */
   public Font getFont() {
       return font;
   }

   /**
    * Sets the font.
    *
    * @param font
    */
   public void setFont( Font font ) {
       this.font = font;
       update();
   }

   /**
    * Gets the color used to render the HTML.
    * If you want to get the paint used for the node, use getPaint.
    *
    * @return the color used to render the HTML.
    */
   public Color getHTMLColor() {
       return htmlColor;
   }

   /**
    * Sets the color used to render the HTML.
    * If you want to set the paint used for the node, use setPaint.
    *
    * @param color
    */
   public void setHTMLColor( Color color ) {
       htmlColor = color;
       update();
   }

   //----------------------------------------------------------------------------
   // Update handler
   //----------------------------------------------------------------------------

   /*
   * Updates everything that is involved in rendering the HTML string.
   * This method is called when one the HTML-related properties is modified.
   */

   private void update() {
       htmlLabel.setText( html );
       htmlLabel.setFont( font );
       htmlLabel.setForeground( htmlColor );
       htmlLabel.setSize( htmlLabel.getPreferredSize() );
       htmlView = BasicHTML.createHTMLView( htmlLabel, html == null ? "" : html );
       htmlBounds.setRect( 0, 0, htmlView.getPreferredSpan( View.X_AXIS ), htmlView.getPreferredSpan( View.Y_AXIS ) );
       setBounds( htmlBounds );
       repaint();
   }

   //----------------------------------------------------------------------------
   // PNode overrides
   //----------------------------------------------------------------------------

   /*
   * Paints the node.
   * The HTML string is painted last, so it appears on top of any child nodes.
   *
   * @param paintContext
   */

   protected void paint( PPaintContext paintContext ) {
       super.paint( paintContext );
       if ( htmlLabel.getWidth() == 0 || htmlLabel.getHeight() == 0 ) {
           return;
       }
       Graphics2D g2 = paintContext.getGraphics();
       htmlView.paint( g2, htmlBounds );
   }
}


tchomby

unread,
Mar 11, 2009, 3:13:50 PM3/11/09
to piccolo...@googlegroups.com
I have a need for this also, and the code you posted works, but any
hint on how I might be able to make it wrap text?

Thanks

tchomby

unread,
Mar 12, 2009, 10:39:04 AM3/12/09
to piccolo...@googlegroups.com
On Wed, Mar 11, 2009 at 7:13 PM, tchomby <tch...@googlemail.com> wrote:
> I have a need for this also, and the code you posted works, but any
> hint on how I might be able to make it wrap text?

Figured this out for myself. At first I tried setting the size of the
JLabel used in HTMLNode, but this didn't have any effect. I discovered
instead that it's the bounds set in the call to htmlBounds.setRect in
HTMLNode's update method that matter, the text will be wrapped within
these bounds. The way it's implement, it seems to always set the
bounds to the width of the text if the text is written all on one
line. So I modified the update method a little and added an override
of PNode's setBounds methods so that the user can set the bounds of an
HTMLNode manually and the text will be wrapped within those bounds.

Here's the code I changed, I changed the update method and added the
setBounds methods:

//----------------------------------------------------------------------------
// Update handler
//----------------------------------------------------------------------------

/*
* Updates everything that is involved in rendering the HTML string.
* This method is called when one the HTML-related properties is modified.
*/
private void update() {
htmlLabel.setText(html);
htmlLabel.setFont(font);
htmlLabel.setForeground(htmlColor);
htmlLabel.setSize(htmlLabel.getPreferredSize());
htmlView = BasicHTML.createHTMLView(htmlLabel, html == null ?
"" : html);

htmlBounds.setRect(0, 0, getBounds().getWidth(),
getBounds().getHeight());
repaint();
}

//----------------------------------------------------------------------------
// PNode overrides
//----------------------------------------------------------------------------

@Override
public boolean setBounds(double x, double y, double width, double height) {
boolean boundsChanged = super.setBounds(x,y,width,height);
update();
return boundsChanged;
}

@Override
public boolean setBounds(java.awt.geom.Rectangle2D newBounds) {
boolean boundsChanged = super.setBounds(newBounds);
update();
return boundsChanged;
}

Full new version of the code here: http://gist.github.com/78096

Hennin...@googlemail.com

unread,
Mar 13, 2009, 2:25:02 PM3/13/09
to Piccolo2D Users
Hmm.. thanks for that, but I wonder how you get the actual height of
the wrapped text...
becaue I want a user to set the width of a one lined textfield but if
it wraps text I want it to become two-lined. But i don't know
how tho get the count of wraps or the height.
Has anyone an idea?

thank you
Henning


On Mar 12, 3:39 pm, tchomby <tcho...@googlemail.com> wrote:

tchomby

unread,
Mar 16, 2009, 8:26:15 AM3/16/09
to piccolo...@googlegroups.com
On Fri, Mar 13, 2009 at 11:25:02AM -0700, Hennin...@googlemail.com wrote:
>
> Hmm.. thanks for that, but I wonder how you get the actual height of
> the wrapped text...
> becaue I want a user to set the width of a one lined textfield but if
> it wraps text I want it to become two-lined. But i don't know
> how tho get the count of wraps or the height.
> Has anyone an idea?

You can get the height just by calling getBounds().getHeight() can't you? (A
method inherited from PNode).

I'm not actually sure which class does the text wrapping, but if you wanted a
count of the number of wraps you'd have to get it from that class, and if it
doesn't export that info you might have to modify or extend that class.

Reply all
Reply to author
Forward
0 new messages