Click here to Skip to main content
15,881,139 members
Articles / Programming Languages / Java / Java SE
Article

How to create a wrapping and/or multiline label in AWT.

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
12 Aug 20011 min read 72K   11   2
How to create a wrapping and/or multiline label in AWT

Introduction

VWrappingLabel is based on the Symantec WrappingLabel. Here is a brief blurb taken straight from Daniel Kirkdorffers Visual Cafe Tips, which was the place this code was found originally.

Symantec's WrappingLabel is a very handy component. On top of the ability to automatically wrap label text to fit the width of the component, WrappingLabel can work as a good substitute for the basic Label component in cases where you want to modify foreground or background colors of your label.

A number of people have asked if it is possible for WrappingLabel to take the newline character "\n" into consideration when wrapping to force a newline in certain places. Unfortunately WrappingLabel eats newlines. However in response to the interest, Paul Williams has written another version of WrappingLabel that does handle newlines. I have copies of the source code, compiled class file, and the .desc description file. The key to using this component in Visual Café is to set the text of the label with the setText() method in code, as opposed to setting the text in the Property List window at design time. Visual Café will substitute "\n" with "\\n" otherwise. Paul has also added the nice feature of setting horizontal and vertical alignment of your text via the setHAlignStyle() and setVAlignStyle() methods, or through alternate constructors.

Kudos to Paul Williams formerly of Criterion Inc. I tried to contact you, but it seems your old email address is a dead end. I promise I only made a few minor modifications.

JavaScript
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Dimension;
import java.awt.Label;
import java.util.Vector;
import java.util.Enumeration;

/**
 * VWrappingLabel is based on Symantec's class WrappingLabel; however, this
class
 * can format the text vertically, too.  It also wraps text at newlines
embedded
 * in the label's text.
 *
 * @see symantec.awt.WrappingLabel
 * @author    Paul F. Williams  (mailto:paul@criterioninc.com)
 *          Criterion, Inc.   (http://www.criterioninc.com)
 * @author      Kyle Morris       (mailto:morriskg@nexusfusion.com)
 *
 */


public class VWrappingLabel extends Canvas
{
    //--------------------------------------------------
    // constants
    //--------------------------------------------------

    //--------------------------------------------------
    // class variables
    //--------------------------------------------------


    //--------------------------------------------------
    // member variables
    //--------------------------------------------------
    protected String text;
    protected float m_nHAlign;
    protected float m_nVAlign;
    protected int baseline;
    protected FontMetrics fm;


    //--------------------------------------------------
    // constructors
    //--------------------------------------------------

    public VWrappingLabel()
    {
        this("");
    }

    public VWrappingLabel(String s)
    {
        this(s, Canvas.LEFT_ALIGNMENT, Canvas.CENTER_ALIGNMENT);
    }

    public VWrappingLabel(String s, float nHorizontal, float nVertical)
    {
        setText(s);
        setHAlignStyle(nHorizontal);
        setVAlignStyle(nVertical);
    }


    //--------------------------------------------------
    // accessor members
    //--------------------------------------------------

    public float    getHAlignStyle() { return m_nHAlign; }
    public float    getVAlignStyle() { return m_nVAlign; }
    public String getText()        { return text;      }

    public void setHAlignStyle(float a)
    {
        m_nHAlign = a;
        invalidate();
    }

    public void setVAlignStyle(float a)
    {
        m_nVAlign = a;
        invalidate();
    }

    public void setText(String s)
    {
        text = s;
        repaint();
    }


    //--------------------------------------------------
    // member methods
    //--------------------------------------------------

    public String paramString()
    {
        return "";
    }

    public void paint(Graphics g)
    {
        if (text != null)
        {
            Dimension d;
            int currentY = 0;
            Vector lines;

            // Set up some class variables
            fm = getFontMetrics(getFont());
            baseline = fm.getMaxAscent();

            // Get the maximum height and width of the current control
            d = getSize();

            lines = breakIntoLines (text, d.width);

            //if (m_nVAlign == V_ALIGN_CENTER)
            if (m_nVAlign == Canvas.CENTER_ALIGNMENT)
            {
                int center = (d.height / 2);
                currentY = center - ( (lines.size() / 2) * fm.getHeight() );
            }
            //else if (m_nVAlign == V_ALIGN_BOTTOM)
            else if (m_nVAlign == Canvas.BOTTOM_ALIGNMENT)
            {
                currentY = d.height - ( lines.size() * fm.getHeight() );
            }

            // now we have broken into substrings, print them
            Enumeration elements = lines.elements();
            while (elements.hasMoreElements())
            {
                drawAlignedString(g, 
                  (String)(elements.nextElement()), 
                  0, currentY, d.width);
                currentY += fm.getHeight();
            }

            // We're done with the font metrics...
            fm = null;
        }
    }


    protected Vector breakIntoLines (String s, int width)
    {
        int fromIndex = 0;
        int pos = 0;
        int bestpos;
        String largestString;
        Vector lines = new Vector();

        // while we haven't run past the end of the string...
        while (fromIndex != -1)
        {
            // Automatically skip any spaces at the beginning of the line
            while (fromIndex < text.length() 
                   && text.charAt(fromIndex) == ' ')
            {
                ++fromIndex;
                // If we hit the end of line
                // while skipping spaces, we're done.
                if (fromIndex >= text.length()) break;
            }

            // fromIndex represents the beginning of the line
            pos = fromIndex;
            bestpos = -1;
            largestString = null;

            while (pos >= fromIndex)
            {
                boolean bHardNewline = false;
                int newlinePos = text.indexOf('\n', pos);
                int spacePos   = text.indexOf(' ', pos);

                if (newlinePos != -1 &&    // there is a newline and either
                     ((spacePos == -1) ||  // 1. there is no space, or
                      (spacePos != -1 && 
                        newlinePos < spacePos))) 
                        // 2. the newline is first
                {
                    pos = newlinePos;
                    bHardNewline = true;
                }
                else
                {
                    pos = spacePos;
                    bHardNewline = false;
                }

                // Couldn't find another space?
                if (pos == -1)
                {
                    s = text.substring(fromIndex);
                }
                else
                {
                    s = text.substring(fromIndex, pos);
                }

                // If the string fits, keep track of it.
                if (fm.stringWidth(s) < width)
                {
                    largestString = s;
                    bestpos = pos;

                    // If we've hit the end of the
                    // string or a newline, use it.
                    if (bHardNewline)
                        bestpos++;
                    if (pos == -1 || bHardNewline) break;
                }
                else
                {
                    break;
                }

                ++pos;
            }

            if (largestString == null)
            {
                // Couldn't wrap at a space, so find the largest line
                // that fits and print that.  Note that this will be
                // slightly off -- the width of a string will not necessarily
                // be the sum of the width of its characters, due to kerning.
                int totalWidth = 0;
                int oneCharWidth = 0;

                pos = fromIndex;

                while (pos < text.length())
                {
                    oneCharWidth = fm.charWidth(text.charAt(pos));
                    if ((totalWidth + oneCharWidth) >= width) break;
                    totalWidth += oneCharWidth;
                    ++pos;
                }

                lines.addElement (text.substring(fromIndex, pos));
                fromIndex = pos;
            }
            else
            {
                lines.addElement (largestString);
                fromIndex = bestpos;
            }
           }

           return lines;
       }


    protected void drawAlignedString(Graphics g, 
                   String s, int x, int y, int width)
    {
        int drawx;
        int drawy;

        drawx = x;
        drawy = y + baseline;

        if (m_nHAlign != Canvas.LEFT_ALIGNMENT)
        {
            int sw;

            sw = fm.stringWidth(s);

            if (m_nHAlign == Canvas.CENTER_ALIGNMENT)
            {
                drawx += (width - sw) / 2;
            }
            else if (m_nHAlign == Canvas.RIGHT_ALIGNMENT)
            {
                drawx = drawx + width - sw;
            }
        }

        g.drawString(s, drawx, drawy);
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMy Old Code Pin
PaulWilliams8-Jun-20 3:56
PaulWilliams8-Jun-20 3:56 
GeneralGreat Pin
Member 392808226-Jan-09 1:35
Member 392808226-Jan-09 1:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.