package uk.ac.rhul.cs.cl1.ui; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.BorderFactory; import javax.swing.CellRendererPane; import javax.swing.JComponent; import javax.swing.JTextArea; import javax.swing.JToolTip; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToolTipUI; /** * Tooltip class that can wrap the tooltip text into multiple lines. * * Based on the JMultiLineToolTip class of Zafir Anjum, see the following URL: * http://www.codeguru.com/java/articles/122.shtml * * @author tamas * */ public class JMultiLineToolTip extends JToolTip { /// The text of the tooltip String text; /// The component to which this tooltip is associated JComponent component; /// The preferred fixed width of the tooltip protected int fixedWidth = 0; public JMultiLineToolTip() { updateUI(); } /** * Returns the preferred fixed width of the tooltip. * * @return the preferred fixed width of the tooltip or zero if * there is no preferred width. */ public int getFixedWidth() { return fixedWidth; } /** * Sets the preferred fixed width of the tooltip. * * @param width the new preferred fixed width or zero if you * don't want to specify a fixed width */ public void setFixedWidth(int width) { this.fixedWidth = width; } public void updateUI() { setUI(MultiLineToolTipUI.createUI(this)); } } /** * UI class corresponding to JMultiLineToolTip. * * Unfortunately I cannot make this class internal to JMultiLineToolTip * because of its static members. Meh. * * @author tamas */ class MultiLineToolTipUI extends BasicToolTipUI { /// Shared instance of this UI class static MultiLineToolTipUI instance = new MultiLineToolTipUI(); /// The border used by the tooltip Border tooltipBorder = new CompoundBorder( BorderFactory.createLineBorder(Color.BLACK, 1), BorderFactory.createEmptyBorder(2, 2, 2, 2) ); JToolTip tip; protected CellRendererPane rendererPane; /// The JTextArea used to render the multi-line tooltip private static JTextArea textArea; /// Returns the shared instance of this UI class public static ComponentUI createUI(JComponent c) { return instance; } /// Installs this UI to the given component public void installUI(JComponent c) { super.installUI(c); tip = (JToolTip)c; rendererPane = new CellRendererPane(); c.add(rendererPane); } /// Uninstalls this UI from the given component public void uninstallUI(JComponent c) { super.uninstallUI(c); c.remove(rendererPane); rendererPane = null; } /// Paints the tooltip on the given component using the given graphics context public void paint(Graphics g, JComponent c) { Dimension size = c.getSize(); textArea.setBackground(c.getBackground()); rendererPane.paintComponent(g, textArea, c, 0, 0, size.width, size.height, true); } /** * Calculates and returns the preferred size of the tooltip */ @Override public Dimension getPreferredSize(JComponent c) { String tipText = ((JToolTip)c).getTipText(); JMultiLineToolTip comp = (JMultiLineToolTip)c; Dimension dim = null; if (tipText == null) return new Dimension(0, 0); textArea = new JTextArea(tipText); textArea.setBorder(tooltipBorder); rendererPane.removeAll(); rendererPane.add(textArea); textArea.setWrapStyleWord(true); int width = comp.getFixedWidth(); if (width > 0) { textArea.setLineWrap(true); dim = textArea.getPreferredSize(); dim.width = width; dim.height++; textArea.setSize(dim); } else textArea.setLineWrap(false); dim = textArea.getPreferredSize(); dim.height++; dim.width++; return dim; } /** * Calculates and returns the minimum size of the tooltip. * * The minimum size is equal to the preferred size. */ @Override public Dimension getMinimumSize(JComponent c) { return getPreferredSize(c); } /** * Calculates and returns the maximum size of the tooltip. * * The maximum size is equal to the preferred size. */ @Override public Dimension getMaximumSize(JComponent c) { return getPreferredSize(c); } }