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 ToolTip


Author: Zafir Anjum

To display multi-line tooltip we extend the JTooltip class. The actual rendering of a tooltip is done by a subclass of ToolTipUI, so we have to create our own subclass that will do the multi-line rendering.

Also, any class derived from JComponent automatically supports JToolTip. However, since we want a component to support our multi-line tooltip, we have to also subclass all components that should support the new tooltip. Given Java's support for anonymous classes, this isn't as cumbersome as it initially sounds.

Here's how we can use the new tooltips.


	button = new JButton( "QWERTY" )
	{
		public JToolTip createToolTip()
		{
			return new JMultiLineToolTip();
		}
	};
	button.setToolTipText("This is a multi-line tooltip\nThis is the second line");

Note that we are creating an anonymous subclass of JButton in which we override only one of the methods - createToolTip(). This causes the component to use the new tooltip rather than the vanilla JToolTip. If you needed a component other than the JButton you would subclass it similarly.

In the above code, we are using multiple lines by using the newline character "\n" within the tooltip text. The JMultiLineToolTip class that we show below also support specification of the tooltip width, and the control will automatically wrap the tooltip text and make it tall enough to fit all the text. You can specify the width in terms of pixels or as number of columns. My understanding of column was that it contains one character (e.i. a char column), however, Swings interpretation seems to be different. You've been warned. To use this feature, you can modify createToolTip() so that it updates the JMultiLineTooltip with the desired width.

Now for the actual code to implement the multiline tooltip. Note that I've created the two classes required in the same file. You may wish to separate them in two separate files.


// JMultiLineToolTip.java
import javax.swing.*;
import javax.swing.plaf.*;

import java.awt.*;
import java.awt.font.*;
import java.awt.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicToolTipUI;
import javax.swing.text.*;


/**
 * @author Zafir Anjum
 */
 

public class JMultiLineToolTip extends JToolTip
{
	private static final String uiClassID = "ToolTipUI";
	
	String tipText;
	JComponent component;
	
	public JMultiLineToolTip() {
	    updateUI();
	}
	
	public void updateUI() {
	    setUI(MultiLineToolTipUI.createUI(this));
	}
	
	public void setColumns(int columns)
	{
		this.columns = columns;
		this.fixedwidth = 0;
	}
	
	public int getColumns()
	{
		return columns;
	}
	
	public void setFixedWidth(int width)
	{
		this.fixedwidth = width;
		this.columns = 0;
	}
	
	public int getFixedWidth()
	{
		return fixedwidth;
	}
	
	protected int columns = 0;
	protected int fixedwidth = 0;
}



class MultiLineToolTipUI extends BasicToolTipUI {
	static MultiLineToolTipUI sharedInstance = new MultiLineToolTipUI();
	Font smallFont; 			     
	static JToolTip tip;
	protected CellRendererPane rendererPane;
	
	private static JTextArea textArea ;
	
	public static ComponentUI createUI(JComponent c) {
	    return sharedInstance;
	}
	
	public MultiLineToolTipUI() {
	    super();
	}
	
	public void installUI(JComponent c) {
	    super.installUI(c);
		tip = (JToolTip)c;
	    rendererPane = new CellRendererPane();
	    c.add(rendererPane);
	}
	
	public void uninstallUI(JComponent c) {
		super.uninstallUI(c);
		
	    c.remove(rendererPane);
	    rendererPane = null;
	}
	
	public void paint(Graphics g, JComponent c) {
	    Dimension size = c.getSize();
	    textArea.setBackground(c.getBackground());
		rendererPane.paintComponent(g, textArea, c, 1, 1,
					    size.width - 1, size.height - 1, true);
	}
	
	public Dimension getPreferredSize(JComponent c) {
		String tipText = ((JToolTip)c).getTipText();
		if (tipText == null)
			return new Dimension(0,0);
		textArea = new JTextArea(tipText );
	    rendererPane.removeAll();
		rendererPane.add(textArea );
		textArea.setWrapStyleWord(true);
		int width = ((JMultiLineToolTip)c).getFixedWidth();
		int columns = ((JMultiLineToolTip)c).getColumns();
		
		if( columns > 0 )
		{
			textArea.setColumns(columns);
			textArea.setSize(0,0);
		textArea.setLineWrap(true);
			textArea.setSize( textArea.getPreferredSize() );
		}
		else if( width > 0 )
		{
		textArea.setLineWrap(true);
			Dimension d = textArea.getPreferredSize();
			d.width = width;
			d.height++;
			textArea.setSize(d);
		}
		else
			textArea.setLineWrap(false);


		Dimension dim = textArea.getPreferredSize();
		
		dim.height += 1;
		dim.width += 1;
		return dim;
	}
	
	public Dimension getMinimumSize(JComponent c) {
	    return getPreferredSize(c);
	}
	
	public Dimension getMaximumSize(JComponent c) {
	    return getPreferredSize(c);
	}
}


Tech Note: We use a CellRendererPane to enable us to use any component to do the actual rendering. The JTextArea comes in handy for our purpose. You'll observe that we create a new JTextArea each time getPreferredSize() is called. Since this function gets called only once each time the ToolTip is displayed, in effect we create a new JTextArea once every time the tooltip is displayed. I tried using a static instance of JTextArea but there are still enough bugs to make this difficult.

It would be more effecient to do the text wrapping and size computation on our own rather than use a JTextArea.

Posted On: 29-Dec-1998

internet.commerce



Acceptable Use Policy

internet.comMediabistrojusttechjobs.comGraphics.com

WebMediaBrands Corporate Info


Advertise | Newsletters | Feedback | Submit News

Legal Notices | Licensing | Permissions | Privacy Policy