package bluej.utility;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
| A label which supports multiple lines of text, and which wraps text if
| it is too long (longer than the label width). An arbitrary wrapping width
| can also be specified.
|
| @author Davin McCall
|
public class MultiWrapLabel
extends JComponent{
private static String lineSep = System.getProperty("line.separator");
private String text;
private int wrapWidth;
| Create an empty MultiWrapLabel.
|
public MultiWrapLabel()
{
text = "";
wrapWidth = -1;
}
| Create a MultiWrapLabel to display the given text.
|
public MultiWrapLabel(String text)
{
this.text = text;
wrapWidth = -1;
}
| Set the text which this MultiWrapLabel should display.
|
public void setText(String text)
{
this.text = text;
invalidate();
}
| Set the desired wrap width for this MultiWrapLabel. This also determines
| the preferred width of the label. Text will be wrapped at the given width,
| unless the width of the label is less than the given width, in which case
| text will be wrapped at the width of the label instead.
|
| Specify -1 to indicate there is no preferred wrap width. In this case the
| preferred width of the label will be the length of the longest line of text
| in the label, and text will always wrap at the width of the label.
|
| @param wrapWidth The desired wrapping width, or -1 for no specific width.
|
public void setWrapWidth(int wrapWidth)
{
this.wrapWidth = wrapWidth;
}
| (non-Javadoc)
| @see java.awt.Component#getMaximumSize()
|
@Override
public Dimension getMaximumSize()
{
if (isMaximumSizeSet()) {
return super.getMaximumSize();
}
else {
return getPreferredSize();
}
}
| (non-Javadoc)
| @see java.awt.Component#getMinimumSize()
|
@Override
public Dimension getMinimumSize()
{
if (isMinimumSizeSet()) {
return super.getMinimumSize();
}
else {
return getPreferredSize();
}
}
| (non-Javadoc)
| @see java.awt.Component#getPreferredSize()
|
@Override
public Dimension getPreferredSize()
{
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
else if (wrapWidth != -1) {
return getPreferredSizeWrapped();
}
else {
double height = 0f;
double width = 0f;
FontMetrics metrics = getFontMetrics(getFont());
int npos = 0;
while (npos < text.length()){
int end = text.indexOf(lineSep, npos);
if (end == -1) {
end = text.length();
}
String line = text.substring(npos, end);
Rectangle2D lineRect = metrics.getStringBounds(line, getGraphics());
if (lineRect.getWidth() > width) {
width = lineRect.getWidth();
}
height += lineRect.getHeight();
npos = end + lineSep.length();
}
return new Dimension((int) width + 1, (int) height);
}
}
| Get the preferred size, given that a particular wrapping width is desired.
|
private Dimension getPreferredSizeWrapped()
{
Graphics ng = getGraphics();
int myWidth = wrapWidth;
FontMetrics metrics = getFontMetrics(getFont());
int npos = 0;
int currentY = 0;
while (npos < text.length()){
int end = text.indexOf(lineSep, npos);
if (end == -1) {
end = text.length();
}
String line = text.substring(npos, end);
Rectangle2D lineRect = metrics.getStringBounds(line, ng);
int lineAmount;
int lineHeight = (int) lineRect.getHeight();
if (lineRect.getWidth() > myWidth) {
int lbound = 0;
int hbound = line.length();
int lboundw = 0;
int hboundw = (int) lineRect.getWidth();
while (hbound - lbound > 1){
int middle = lbound + (hbound - lbound) * (hboundw - lboundw) / (myWidth - lboundw);
if (middle <= lbound) {
middle = lbound + 1;
}
if (middle >= hbound) {
middle = hbound - 1;
}
lineRect = metrics.getStringBounds(line, 0, middle, ng);
int middlew = (int) lineRect.getWidth();
if (middlew > myWidth) {
hbound = middle;
hboundw = middlew;
}
else {
lbound = middle;
lboundw = middlew;
lineHeight = (int) lineRect.getHeight();
}
}
lineAmount = lbound;
int priorSpace = line.indexOf(' ', 1);
while (priorSpace != -1 && priorSpace <= lbound){
lineAmount = priorSpace - 1;
priorSpace = line.indexOf(' ', priorSpace + 1);
}
if (lineAmount <= 0) {
lineAmount = 1;
}
}
else {
lineAmount = line.length();
}
currentY += lineHeight;
if (lineAmount < line.length()) {
npos += lineAmount;
if (text.charAt(npos) == ' ') {
npos++;
}
}
else {
npos = end + lineSep.length();
}
}
return new Dimension(wrapWidth, currentY);
}
| (non-Javadoc)
| @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
|
@Override
protected void paintComponent(Graphics g)
{
Graphics ng = g.create();
ng.setPaintMode();
int myWidth = getWidth();
if (isOpaque()) {
ng.setColor(getBackground());
ng.fillRect(0, 0, myWidth, getHeight());
}
if (wrapWidth != -1 && wrapWidth < myWidth) {
myWidth = wrapWidth;
}
ng.setFont(getFont());
FontMetrics metrics = getFontMetrics(getFont());
int npos = 0;
int currentX = 0;
int currentY = 0;
while (npos < text.length()){
int end = text.indexOf(lineSep, npos);
if (end == -1) {
end = text.length();
}
String line = text.substring(npos, end);
Rectangle2D lineRect = metrics.getStringBounds(line, ng);
int lineAmount;
int lineHeight = (int) lineRect.getHeight();
if (lineRect.getWidth() > myWidth) {
int lbound = 0;
int hbound = line.length();
int lboundw = 0;
int hboundw = (int) lineRect.getWidth();
while (hbound - lbound > 1){
int middle = lbound + (hbound - lbound) * (hboundw - lboundw) / (myWidth - lboundw);
if (middle <= lbound) {
middle = lbound + 1;
}
if (middle >= hbound) {
middle = hbound - 1;
}
lineRect = metrics.getStringBounds(line, 0, middle, ng);
int middlew = (int) lineRect.getWidth();
if (middlew > myWidth) {
hbound = middle;
hboundw = middlew;
}
else {
lbound = middle;
lboundw = middlew;
lineHeight = (int) lineRect.getHeight();
}
}
lineAmount = lbound;
int priorSpace = line.indexOf(' ', 1);
while (priorSpace != -1 && priorSpace <= lbound){
lineAmount = priorSpace;
priorSpace = line.indexOf(' ', priorSpace + 1);
}
if (lineAmount == 0) {
lineAmount = 1;
}
}
else {
lineAmount = line.length();
}
float ascent = metrics.getLineMetrics(line, 0, lineAmount, ng).getAscent();
ng.drawString(line.substring(0, lineAmount), currentX, (int)(currentY + ascent));
currentY += lineHeight;
if (lineAmount < line.length()) {
npos += lineAmount;
if (text.charAt(npos) == ' ') {
npos++;
}
}
else {
npos = end + lineSep.length();
}
}
}
}
top,
use,
map,
class MultiWrapLabel
. MultiWrapLabel
. MultiWrapLabel
. setText
. setWrapWidth
. getMaximumSize
. getMinimumSize
. getPreferredSize
. getPreferredSizeWrapped
. paintComponent
385 neLoCode
+ 24 LoComm