MultiLineLabel.java revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* ident "%Z%%M% %I% %E% SMI"
*
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
/* BEGIN JSTYLED */
/**
* MultiLineLabel.java
*
* This example is from the book _Java in a
* Nutshell_ by David Flanagan.
* Written by David Flanagan.
* Copyright (c) 1996 O'Reilly & Associates.
* You may study, use, modify, and distribute
* this example for any purpose.
* This example is provided WITHOUT WARRANTY either
* expressed or implied.
*
* Tilman 05/07/96: added a maxChars parameter to
* specify a maximum line
* length. If any of the lines is longer, it will be cut
* at the last space character before maxChars, until it fits
* into maxChars. Set maxChars to -1 if you don't care.
*
* Van 07/30/96: added the removal of backslash-r
* from the multi-line string
* that might have been added by strings in Windows (which
* expect newlines to be indicated by backslash-r backslash-n)
*
* Van 10/18/96: changed the way lines are tokenized so that multiple
* consequetive newline characters create a blank line(s).
*
* Van 10/21/96: added interfaces to the maxChars variable
*
* @version @(#)MultiLineLabel.java 1.15 97/07/25
*/
/* END JSTYLED */
package sunsoft.jws.visual.rt.awt;
import sunsoft.jws.visual.rt.base.Global;
import java.awt.*;
import java.util.*;
public class MultiLineLabel extends Canvas {
public static final int LEFT = Label.LEFT; // Alignment constants
public static final int CENTER = Label.CENTER;
public static final int RIGHT = Label.RIGHT;
protected String label;
protected Vector lines; // The lines of text to display
protected int num_lines; // The number of lines
protected int maxChars; // maximum width of lines
protected int margin_width; // Left and right margins
protected int margin_height; // Top and bottom margins
protected int line_height; // Total height of the font
protected int line_ascent; // Font height above baseline
protected int[] line_widths; // How wide each line is
protected int max_width; // The width of the widest line
protected int alignment = LEFT; // The alignment of the text.
/**
* This method breaks a specified label up into an array of lines.
* It uses the StringTokenizer utility class.
*/
protected void newLabel(String label) {
if (label == null)
label = /* NOI18N */"";
this.label = label;
lines = new Vector();
int len = label.length();
int startFrom = 0;
while (startFrom != -1 && startFrom < len) {
// determine next line
String line;
int index = label.indexOf(/* NOI18N */"\n", startFrom);
if (index == -1) {
line = label.substring(startFrom);
startFrom = -1;
} else {
line = label.substring(startFrom, index);
startFrom = index + 1;
}
// wrap the words in the line
if ((maxChars == -1) || (line.length() <= maxChars))
lines.addElement(line);
else {
while (line.length() > maxChars) {
int offset = line.lastIndexOf(/* NOI18N */ ' ',
maxChars);
if (offset == -1) {
// didn't get one within maxChars!
offset = line.indexOf(/* NOI18N */ ' ');
if (offset == -1)
break;
}
lines.addElement(line.substring(0, offset));
line = line.substring(offset + 1);
}
lines.addElement(line);
}
}
num_lines = lines.size();
line_widths = new int[num_lines];
}
/**
* This method figures out how the font is, and how wide each
* line of the label is, and how wide the widest line is.
*/
protected void measure() {
/* JSTYLED */
if (this.getFont() == null) return;
FontMetrics fm = this.getFontMetrics(this.getFont());
// If we don't have font metrics yet, just return.
/* JSTYLED */
if (fm == null) return;
line_height = fm.getHeight();
line_ascent = fm.getAscent();
max_width = 0;
for (int i = 0; i < num_lines; i++) {
line_widths[i] = fm.stringWidth(
(String) lines.elementAt(i));
if (line_widths[i] > max_width) max_width = line_widths[i];
}
Dimension d = preferredSize();
setSize(d);
}
// Here are four versions of the constructor.
/**
* Break the label up into separate lines, and save the other info.
*/
public MultiLineLabel(String label, int maxChars,
int margin_width, int margin_height,
int alignment) {
this.maxChars = maxChars;
newLabel(label);
this.margin_width = margin_width;
this.margin_height = margin_height;
this.alignment = alignment;
}
public MultiLineLabel(String label, int maxChars,
int margin_width, int margin_height) {
this(label, maxChars, margin_width, margin_height, LEFT);
}
public MultiLineLabel(String label, int maxChars,
int alignment) {
this(label, maxChars, 10, 10, alignment);
}
public MultiLineLabel(String label, int maxChars) {
this(label, maxChars, 10, 10, LEFT);
}
public MultiLineLabel(String label) {
this(label, -1, 10, 10, LEFT);
}
public MultiLineLabel() {
this(/* NOI18N */"MultiLineLabel");
}
// Methods to set the various attributes of the component
public void setLabel(String label) {
newLabel(label);
measure();
repaint();
}
public String getLabel() {
return label;
}
public void setMaxColumns(int w) {
if (w < 0)
w = -1;
maxChars = w;
newLabel(label);
measure();
repaint();
}
public int getMaxColumns() {
return (maxChars);
}
public void setFont(Font f) {
super.setFont(f);
measure();
repaint();
}
public void setForeground(Color c) {
super.setForeground(c);
repaint();
}
public void setAlignment(int a) { alignment = a; repaint(); }
public void setMarginWidth(int mw) { margin_width = mw; repaint(); }
public void setMarginHeight(int mh) { margin_height = mh;
repaint(); }
public int getAlignment() { return alignment; }
public int getMarginWidth() { return margin_width; }
public int getMarginHeight() { return margin_height; }
/**
* This method is invoked after our Canvas is first created
* but before it can actually be displayed. After we've
* invoked our superclass's addNotify() method, we have font
* metrics and can successfully call measure() to figure out
* how big the label is.
*/
public void addNotify() { super.addNotify(); measure(); }
/**
* This method is called by a layout manager when it wants to
* know how big we'd like to be.
*/
public Dimension preferredSize() {
return new Dimension(max_width + 2*margin_width,
num_lines * line_height + 2*margin_height);
}
/**
* This method is called when the layout manager wants to know
* the bare minimum amount of space we need to get by.
*/
public Dimension minimumSize() {
return new Dimension(max_width, num_lines * line_height);
}
/**
* This method draws the label (applets use the same method).
* Note that it handles the margins and the alignment, but that
* it doesn't have to worry about the color or font--the superclass
* takes care of setting those in the Graphics object we're passed.
*/
public void paint(Graphics g) {
if (Global.isWindows())
g = getGraphics();
int x, y;
Dimension d = this.size();
int mw = Math.max((d.width - max_width)/2, 0);
g.setColor(getForeground());
y = line_ascent + (d.height - num_lines * line_height)/2;
for (int i = 0; i < num_lines; i++, y += line_height) {
switch (alignment) {
case LEFT:
x = mw;
break;
case CENTER:
default:
x = (d.width - line_widths[i])/2;
break;
case RIGHT:
x = d.width - mw - line_widths[i];
break;
}
g.drawString(((String) lines.elementAt(i)).trim(), x, y);
}
}
}