EarthWeb
Developer.com
Site
windows 2000
visual c++
java
visual basic
javascripts
recommend it
 
Book
thinking in java
 
Interact
forum
guest book
jobs
jokes
what's new

share code
 
Resource
add resource
modify resource
new resource
 

[Internet Jobs]
-----
Java by E-mail:

Get the weekly e-mail highlights on Java!
-----

-

Multi-line JLabel


Author: Zafir Anjum

Use multi-line text in a JLabel.

image

To enable multi-line in a JLabel we have to specify our own LabelUI class that will render the multiple lines. Although the code shown
below seems quite long, most of it is actually Swing code being reused.


import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

import javax.swing.plaf.basic.*;

public class Main
{
	public static void main(String[] args)
	{
		JFrame frame = new JFrame("Main");
		frame.addWindowListener( new WindowAdapter() {
			public void windowClosing(WindowEvent e)
			{
				Window win = e.getWindow();
				win.setVisible(false);
				win.dispose();
				System.exit(0);
			}
		} );
		
		frame.getContentPane().setLayout( new FlowLayout() );

		ImageIcon icon = new ImageIcon( "dukeWave.gif" ) ;
		JLabel l = new JLabel( "This is the first line\nThis the second", icon, SwingConstants.LEFT );
		l.setUI( new MultiLineLabelUI() );
		l.setBorder( new EtchedBorder() );
		frame.getContentPane().add( l );

		l = new JLabel( "This \nlabel \nhas \none \nword \non \neach \nline.", icon, SwingConstants.LEFT );
		l.setHorizontalTextPosition( SwingConstants.LEFT );
		l.setUI( new MultiLineLabelUI() );
		l.setBorder( new EtchedBorder() );
		frame.getContentPane().add( l );
		frame.getContentPane().add( new JButton( "Button" ) );
		frame.pack();
		frame.show();
		
		
	}
}



class MultiLineLabelUI extends BasicLabelUI
{
	static {
		labelUI = new MultiLineLabelUI();
	}
	
    protected String layoutCL(
        JLabel label,                  
        FontMetrics fontMetrics, 
        String text, 
        Icon icon, 
        Rectangle viewR, 
        Rectangle iconR, 
        Rectangle textR)
    {
        String s = layoutCompoundLabel(
            (JComponent) label,
            fontMetrics,
            splitStringByLines(text),
            icon,
            label.getVerticalAlignment(),
            label.getHorizontalAlignment(),
            label.getVerticalTextPosition(),
            label.getHorizontalTextPosition(),
            viewR,
            iconR,
            textR,
            label.getIconTextGap());
    	
    	if( s.equals("") )
    		return text;
    	return s;
    }
	
	
	static final int LEADING = SwingConstants.LEADING;
	static final int TRAILING = SwingConstants.TRAILING;
	static final int LEFT = SwingConstants.LEFT;
	static final int RIGHT = SwingConstants.RIGHT;
	static final int TOP = SwingConstants.TOP;
	static final int CENTER = SwingConstants.CENTER;

	/**
     * Compute and return the location of the icons origin, the
     * location of origin of the text baseline, and a possibly clipped
     * version of the compound labels string.  Locations are computed
     * relative to the viewR rectangle.
     * The JComponents orientation (LEADING/TRAILING) will also be taken
     * into account and translated into LEFT/RIGHT values accordingly.
     */
    public static String layoutCompoundLabel(JComponent c,
                                             FontMetrics fm,
                                             String[] text,
                                             Icon icon,
                                             int verticalAlignment,
                                             int horizontalAlignment,
                                             int verticalTextPosition,
                                             int horizontalTextPosition,
                                             Rectangle viewR,
                                             Rectangle iconR,
                                             Rectangle textR,
                                             int textIconGap)
    {
        boolean orientationIsLeftToRight = true;
        int     hAlign = horizontalAlignment;
        int     hTextPos = horizontalTextPosition;

        
        if (c != null) {
            if (!(c.getComponentOrientation().isLeftToRight())) {
                orientationIsLeftToRight = false;
            }
        }
        

        // Translate LEADING/TRAILING values in horizontalAlignment
        // to LEFT/RIGHT values depending on the components orientation
        switch (horizontalAlignment) {
        case LEADING: 
            hAlign = (orientationIsLeftToRight) ? LEFT : RIGHT;
            break;
        case TRAILING: 
            hAlign = (orientationIsLeftToRight) ? RIGHT : LEFT;
            break;
        }

        // Translate LEADING/TRAILING values in horizontalTextPosition
        // to LEFT/RIGHT values depending on the components orientation
        switch (horizontalTextPosition) {
        case LEADING: 
            hTextPos = (orientationIsLeftToRight) ? LEFT : RIGHT;
            break;
        case TRAILING: 
            hTextPos = (orientationIsLeftToRight) ? RIGHT : LEFT;
            break;
        }

        return layoutCompoundLabel(fm,
                                   text,
                                   icon,
                                   verticalAlignment,
                                   hAlign,
                                   verticalTextPosition,
                                   hTextPos,
                                   viewR,
                                   iconR,
                                   textR,
                                   textIconGap);
    }


    /**
     * Compute and return the location of the icons origin, the
     * location of origin of the text baseline, and a possibly clipped
     * version of the compound labels string.  Locations are computed
     * relative to the viewR rectangle.
     * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
     * values in horizontalTextPosition (they will default to RIGHT) and in
     * horizontalAlignment (they will default to CENTER).
     * Use the other version of layoutCompoundLabel() instead.
     */
    public static String layoutCompoundLabel(
        FontMetrics fm,
        String[] text,
        Icon icon,
        int verticalAlignment,
        int horizontalAlignment,
        int verticalTextPosition,
        int horizontalTextPosition,
        Rectangle viewR,
        Rectangle iconR,
        Rectangle textR,
        int textIconGap)
    {
        /* Initialize the icon bounds rectangle iconR.
         */

        if (icon != null) {
            iconR.width = icon.getIconWidth();
            iconR.height = icon.getIconHeight();
        }
        else {
            iconR.width = iconR.height = 0;
        }

        /* Initialize the text bounds rectangle textR.  If a null
         * or and empty String was specified we substitute "" here
         * and use 0,0,0,0 for textR.
         */

        // Fix for textIsEmpty sent by Paulo Santos
        boolean textIsEmpty = (text == null) || (text.length == 0)
			|| (text.length == 1 && ( (text[0]==null) || text[0].equals("") ));

    	String rettext = "";
        if (textIsEmpty) {
            textR.width = textR.height = 0;
        }
        else {
        	Dimension dim = computeMultiLineDimension( fm, text );
            textR.width = dim.width;
            textR.height = dim.height;
        }

        /* Unless both text and icon are non-null, we effectively ignore
         * the value of textIconGap.  The code that follows uses the
         * value of gap instead of textIconGap.
         */

        int gap = (textIsEmpty || (icon == null)) ? 0 : textIconGap;

        if (!textIsEmpty) {

            /* If the label text string is too wide to fit within the available
             * space "..." and as many characters as will fit will be
             * displayed instead.
             */

            int availTextWidth;

            if (horizontalTextPosition == CENTER) {
                availTextWidth = viewR.width;
            }
            else {
                availTextWidth = viewR.width - (iconR.width + gap);
            }


            if (textR.width > availTextWidth && text.length == 1) {
                String clipString = "...";
                int totalWidth = SwingUtilities.computeStringWidth(fm,clipString);
                int nChars;
                for(nChars = 0; nChars < text[0].length(); nChars++) {
                    totalWidth += fm.charWidth(text[0].charAt(nChars));
                    if (totalWidth > availTextWidth) {
                        break;
                    }
                }
                rettext = text[0].substring(0, nChars) + clipString;
                textR.width = SwingUtilities.computeStringWidth(fm,rettext);
            }
        }


        /* Compute textR.x,y given the verticalTextPosition and
         * horizontalTextPosition properties
         */

        if (verticalTextPosition == TOP) {
            if (horizontalTextPosition != CENTER) {
                textR.y = 0;
            }
            else {
                textR.y = -(textR.height + gap);
            }
        }
        else if (verticalTextPosition == CENTER) {
            textR.y = (iconR.height / 2) - (textR.height / 2);
        }
        else { // (verticalTextPosition == BOTTOM)
            if (horizontalTextPosition != CENTER) {
                textR.y = iconR.height - textR.height;
            }
            else {
                textR.y = (iconR.height + gap);
            }
        }

        if (horizontalTextPosition == LEFT) {
            textR.x = -(textR.width + gap);
        }
        else if (horizontalTextPosition == CENTER) {
            textR.x = (iconR.width / 2) - (textR.width / 2);
        }
        else { // (horizontalTextPosition == RIGHT)
            textR.x = (iconR.width + gap);
        }

        /* labelR is the rectangle that contains iconR and textR.
         * Move it to its proper position given the labelAlignment
         * properties.
         *
         * To avoid actually allocating a Rectangle, Rectangle.union
         * has been inlined below.
         */
        int labelR_x = Math.min(iconR.x, textR.x);
        int labelR_width = Math.max(iconR.x + iconR.width,
                                    textR.x + textR.width) - labelR_x;
        int labelR_y = Math.min(iconR.y, textR.y);
        int labelR_height = Math.max(iconR.y + iconR.height,
                                     textR.y + textR.height) - labelR_y;

        int dx, dy;

        if (verticalAlignment == TOP) {
            dy = viewR.y - labelR_y;
        }
        else if (verticalAlignment == CENTER) {
            dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2));
        }
        else { // (verticalAlignment == BOTTOM)
            dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
        }

        if (horizontalAlignment == LEFT) {
            dx = viewR.x - labelR_x;
        }
        else if (horizontalAlignment == RIGHT) {
            dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
        }
        else { // (horizontalAlignment == CENTER)
            dx = (viewR.x + (viewR.width / 2)) -
                 (labelR_x + (labelR_width / 2));
        }

        /* Translate textR and glypyR by dx,dy.
         */

        textR.x += dx;
        textR.y += dy;

        iconR.x += dx;
        iconR.y += dy;

        return rettext;
    }
	
    protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY)
    {
        int accChar = l.getDisplayedMnemonic();
        g.setColor(l.getForeground());
        drawString(g, s, accChar, textX, textY);
    }


    protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY)
    {
		int accChar = l.getDisplayedMnemonic();
		g.setColor(l.getBackground());
    	drawString(g, s, accChar, textX, textY);
    }
	
	protected void drawString( Graphics g, String s, int accChar, int textX, int textY )
	{
    	if( s.indexOf('\n') == -1 )
			BasicGraphicsUtils.drawString(g, s, accChar, textX, textY);
    	else
    	{
    		String[] strs = splitStringByLines( s );
    		int height = g.getFontMetrics().getHeight();
    		// Only the first line can have the accel char
    		BasicGraphicsUtils.drawString(g, strs[0], accChar, textX, textY);
    		for( int i = 1; i < strs.length; i++ )
    			g.drawString( strs[i], textX, textY + (height*i) );
    	}
	}
	
	public static Dimension computeMultiLineDimension( FontMetrics fm, String[] strs )
	{
		int i, c, width = 0;
        for(i=0, c=strs.length ; i < c ; i++)
        	width = Math.max( width, SwingUtilities.computeStringWidth(fm,strs[i]) );
		return new Dimension( width, fm.getHeight() * strs.length );
	}
	
	
	protected String str;
	protected String[] strs;
	
	public String[] splitStringByLines( String str )
	{
		if( str.equals(this.str) )
			return strs;
		
		this.str = str;
		
		int lines = 1;
		int i, c;
        for(i=0, c=str.length() ; i < c ; i++) {
            if( str.charAt(i) == '\n' )
            	lines++;
        }
		strs = new String[lines];
		StringTokenizer st = new StringTokenizer( str, "\n" );
		
		int line = 0;
		while( st.hasMoreTokens() )
			strs[line++] = st.nextToken();
			
		return strs;
	}
}



Posted On: 28-Jul-1999

internet.commerce
Partner With Us
Web Hosting Directory
Computer Deals
Televisions
Imprinted Promotions
Promote Your Website
KVM over IP
Promos and Premiums
Phone Cards
Ram Memory
Desktop Computers
PDA Phones & Cases
Online Education
Laptops
Promotional Products



Acceptable Use Policy

JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Web Hosting | Newsletters | Tech Jobs | Shopping | E-mail Offers