/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2000 Blacksmith, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.ui.swing.components; import java.awt.Component; import java.awt.Dimension; import javax.swing.JList; import javax.swing.JViewport; import javax.swing.ListCellRenderer; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * A list cell renderer that wraps its text to subsequent lines depending on the * length of text string and the width of the parent list. * * This renderer depends on listening to the parent list's viewport and fixing * the list's width to match the viewport's size. * * @author michael@mpowers.net * @author $Author: cgruber $ * @date $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $ * @revision $Revision: 904 $ */ public class LineWrappingRenderer extends MultiLineLabel implements ListCellRenderer, ChangeListener { protected static Border noFocusBorder; protected JList list; protected JViewport viewport; protected int preferredWidth; /** * Required constructor. The renderer keeps a reference to the list in which it * is used and its viewport. This list is the only list that may use this * renderer. The renderer will use the current size of the list to determine * where lines will initially break. * * @param containerList The list that will be using this renderer. */ public LineWrappingRenderer(JList containerList) { super(); setLineWrap(true); noFocusBorder = new EmptyBorder(1, 1, 1, 1); list = containerList; preferredWidth = 400; if (list.getParent() instanceof JViewport) { viewport = (JViewport) list.getParent(); viewport.addChangeListener(this); int newWidth = viewport.getExtentSize().width; if (newWidth > 0) preferredWidth = newWidth; } else { // should function adequately in absence of a viewport // System.err.println( "LineWrappingRenderer.init: list.getParent = " + // list.getParent() ); } } /** * Returns the preferred size of the label, with width constrained to the * current width. * * @return the size */ public Dimension getPreferredSize() { int width = getWidth(); if (width != preferredWidth) { // if component has not yet been placed within the list if (width < list.getWidth() / 2) width = list.getWidth(); preferredWidth = width; } return new Dimension(preferredWidth, super.getPreferredSize().height); } /** * Returns this component with the width set to the width of the specified * JList. * * @return this component. */ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { // System.out.println( "LineWrappingRenderer.getListCellRendererComponent:" ); if (list != this.list) { System.err.println("LineWrappingRenderer.getListCellRendererComponent: " + "warning: the list using the renderer is not the list specified in the constructor."); } if (isSelected) { setBackground(this.list.getSelectionBackground()); setForeground(this.list.getSelectionForeground()); } else { setBackground(this.list.getBackground()); setForeground(this.list.getForeground()); } setText((value == null) ? "" : value.toString()); setEnabled(this.list.isEnabled()); setFont(this.list.getFont()); setBorder((cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder); return this; } /** * Overridden to respond to viewport changes. */ public void stateChanged(ChangeEvent e) { int newWidth = viewport.getExtentSize().width; if (newWidth > 0) preferredWidth = newWidth; // set fixed width on list list.setFixedCellWidth(preferredWidth); setSize(preferredWidth, super.getSize().height); } }