package com.onaro.util.jfc;
import java.io.IOException;
/**
* This class assists in creating text for those Swing JComponents,
* such as JLabel and JButton, that support certain HTML tags. It is
* based on {@link StringBuilder}.
*
* To use this class, create an instance of it and create a chain of method
* calls. End the chain of calls with a call to the {@link #getText} method.
* Use the provided static methods to format text before passing it to the
* {@link #append (CharSequence)} method.
*
* The builder's {@link #toString} method can be used to embed the output of
* one builder in another builder.
*
* Examples:
*
* JLabel label = new JLabel();
* JComponentHtmlBuilder builder = new JComponentHtmlBuilder();
*
* // Display two lines of plain text in the label.
* label.setText (builder.append ("one", "two").getText());
*
* // Add another line of text to the label, this time using a bold font.
* label.setText (builder
* .appendBreak()
* .append (JComponentHtmlBuilder.bold ("three"))
* .getText());
*
* // Display new text, using a red underscored font.
* builder.clear();
* label.setText (builder
* .append (JComponentHtmlBuilder.color (JComponentHtmlBuilder.Color.RED,
* JComponentHtmlBuilder.underscore ("bad news")))
* .getText());
*
* @see How to Use HTML in Swing Components
* for more information about using HTML in Swing components.
*/
public class JComponentHtmlBuilder implements CharSequence, Appendable {
private final StringBuilder builder= new StringBuilder();
/**
* HTML colors supported by {@link JComponentHtmlBuilder}. Only
* the 16 basic VGA names are defined, though the current
* version of HTML defines 130 more names.
*
* The colors are:
*
WHITE
* SILVER
(light gray)
* GRAY
(dark gray)
* BLACK
* RED
(bright red)
* MAROON
(dark red)
* YELLOW
* OLIVE
(brown)
* LIME
(bright green)
* GREEN
(dark green)
* AQUA
(bright cyan)
* TEAL
(dark cyan)
* BLUE
(bright blue)
* NAVY
(dark blue)
* FUCHSIA
(bright magenta)
* PURPLE
(dark magenta)
*
* @see HTML color names
* for samples and more information about these colors.
*/
public enum Color {
WHITE, SILVER, GRAY, BLACK,
RED, MAROON,
YELLOW, OLIVE,
LIME, GREEN,
AQUA, TEAL,
BLUE, NAVY,
FUCHSIA, PURPLE
}
@Override
public int length() {
return builder.length();
}
@Override
public char charAt (int index) {
return builder.charAt (index);
}
@Override
public CharSequence subSequence (int start, int end) {
return builder.subSequence (start, end);
}
/**
* @return HTML fragment without {@code } tag
* @see java.lang.Object#toString()
* @see #getText()
*/
@Override
public String toString() {
return builder.toString();
}
/**
* Appends a character.
* @param character char value
* @return this
* @see StringBuilder#append (char)
*/
@Override
public JComponentHtmlBuilder append (char character) throws IOException {
builder.append (character);
return this;
}
/**
* Appends text with no additional formatting.
* @param text
* @return this
* @see StringBuilder#append (CharSequence)
*/
@Override
public JComponentHtmlBuilder append (CharSequence text) {
builder.append (text);
return this;
}
/**
* Appends zero or more lines of text with breaks (newlines)
* between each line. No other formatting is added to the text.
* @param lines of text. If {@code null}, then {@code "null"}
* (without the quotes) is appended.
* @return this
* @see #append (CharSequence)
*/
public JComponentHtmlBuilder append (CharSequence... lines) {
if (lines == null) {
builder.append ((String)null);
} else {
boolean isFirstLine = true;
for (CharSequence line: lines) {
if (isFirstLine) {
isFirstLine = false;
} else {
appendBreak();
}
builder.append (line);
}
}
return this;
}
/**
* @see StringBuilder#append (CharSequence,int,int)
*/
@Override
public JComponentHtmlBuilder append (CharSequence chars, int start, int end)
throws IOException {
builder.append (chars, start, end);
return this;
}
/**
* Append a break (newline) to the text
* @return this
*/
public JComponentHtmlBuilder appendBreak() {
builder.append ("
"); //$NON-NLS-1$
return this;
}
/**
* Discard all appended text.
* @return this
*/
public JComponentHtmlBuilder clear() {
builder.setLength (0);
return this;
}
/**
* Creates text that will be rendered with a bold version of the current font.
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence bold (Object object) {
return String.format ("%s", object); //$NON-NLS-1$
}
/**
* Creates text that will be rendered with an italic version of the current font.
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence italic (Object object) {
return String.format ("%s", object); //$NON-NLS-1$
}
/**
* Creates text that will be rendered with an underscored version of the current font.
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence underscore (Object object) {
return String.format ("%s", object); //$NON-NLS-1$
}
/**
* Creates text that will be rendered with a large version of the current font.
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence large (Object object) {
return String.format ("%s", object); //$NON-NLS-1$
}
/**
* Creates text that will be rendered with a small version of the current font.
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence small (Object object) {
return String.format ("%s", object); //$NON-NLS-1$
}
/**
* Creates text that will be rendered with the given color.
* @param color one of the {@link Color} enumerators
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence color (Color color, Object object) {
return String.format ("%s", //$NON-NLS-1$
color.toString().toLowerCase(), object);
}
/**
* Creates text that will be rendered with the appearance of a hypertext link
* (typically underscored and bright blue).
* @param object whose text representation will be rendered.
* If object is {@code null}, then {@code "null"} is its representation.
* If object implements {@link java.util.Formattable}, then its
* {@code formatTo} method is invoked. Otherwise, the representation is
* obtained by invoking object's {@code toString} method.
* @return text with HTML tags
*/
public static CharSequence anchor (Object object) {
return String.format ("%s", object); //$NON-NLS-1$
}
/**
* Gets a string containing HTML text that can be
* passed to a JComponent's setText method.
* @return HTML {@link String}
* @see javax.swing.JLabel#setText
* @see javax.swing.AbstractButton#setText
*/
public String getText() {
/*
* Add bracketing tags dynamically (not modifying the builder)
* so the same builder can be used multiple times, with
* additional methods called after getText() is called.
*
* Note no tag necessary in JComponent HTML text.
*/
return String.format ("%s", builder.toString()); //$NON-NLS-1$
}
}