001: import java.awt.Dimension;
002: import java.awt.Graphics2D;
003: import java.awt.geom.Rectangle2D;
004: import java.io.Serializable;
005: import java.util.StringTokenizer;
006: 
007: import javax.swing.JLabel;
008: 
009: /**
010:    A string that can extend over multiple lines.
011: */
012: public class MultiLineString implements Cloneable, Serializable
013: {
014:    /**
015:       Constructs an empty, centered, normal size multiline
016:       string that is not underlined.
017:    */
018:    public MultiLineString() 
019:    { 
020:       text = ""; 
021:       justification = CENTER;
022:       size = NORMAL;
023:       underlined = false;    
024:    }
025:    /**
026:       Sets the value of the text property.
027:       @param newValue the text of the multiline string
028:    */
029:    public void setText(String newValue) { text = newValue; }
030:    /**
031:       Gets the value of the text property.
032:       @return the text of the multiline string
033:    */
034:    public String getText() { return text; }
035:    /**
036:       Sets the value of the justification property.
037:       @param newValue the justification, one of LEFT, CENTER, 
038:       RIGHT
039:    */
040:    public void setJustification(int newValue) { justification = newValue; }
041:    /**
042:       Gets the value of the justification property.
043:       @return the justification, one of LEFT, CENTER, 
044:       RIGHT
045:    */
046:    public int getJustification() { return justification; }
047:    /**
048:       Gets the value of the underlined property.
049:       @return true if the text is underlined
050:    */
051:    public boolean isUnderlined() { return underlined; }
052:    /**
053:       Sets the value of the underlined property.
054:       @param newValue true to underline the text
055:    */
056:    public void setUnderlined(boolean newValue) { underlined = newValue; }
057:    /**
058:       Sets the value of the size property.
059:       @param newValue the size, one of SMALL, NORMAL, LARGE
060:    */
061:    public void setSize(int newValue) { size = newValue; }
062:    /**
063:       Gets the value of the size property.
064:       @return the size, one of SMALL, NORMAL, LARGE
065:    */
066:    public int getSize() { return size; }
067:    
068:    public String toString()
069:    {
070:       return text.replace('\n', '|');
071:    }
072: 
073:    private void setLabelText()
074:    {
075:       StringBuffer prefix = new StringBuffer();
076:       StringBuffer suffix = new StringBuffer();
077:       StringBuffer htmlText = new StringBuffer();
078:       prefix.append(" ");
079:       suffix.insert(0, " ");
080:       if (underlined) 
081:       {
082:          prefix.append("<u>");
083:          suffix.insert(0, "</u>");
084:       }
085:       if (size == LARGE)
086:       {
087:          prefix.append("<font size=\"+1\">");
088:          suffix.insert(0, "</font>");
089:       }
090:       if (size == SMALL)
091:       {
092:          prefix.append("<font size=\"-1\">");
093:          suffix.insert(0, "</font>");
094:       }
095:       htmlText.append("<html>");
096:       StringTokenizer tokenizer = new StringTokenizer(text, "\n");
097:       boolean first = true;
098:       while (tokenizer.hasMoreTokens())
099:       {
100:          if (first) first = false; else htmlText.append("<br>");
101:          htmlText.append(prefix);
102:          htmlText.append(tokenizer.nextToken());
103:          htmlText.append(suffix);
104:       }      
105:       htmlText.append("</html>");
106:       label.setText(htmlText.toString());
107:       if (justification == LEFT) label.setHorizontalAlignment(JLabel.LEFT);
108:       else if (justification == CENTER) label.setHorizontalAlignment(JLabel.CENTER);
109:       else if (justification == RIGHT) label.setHorizontalAlignment(JLabel.RIGHT);
110:    }
111:    
112:    /**
113:       Gets the bounding rectangle for this multiline string.
114:       @param g2 the graphics context
115:       @return the bounding rectangle (with top left corner (0,0))
116:    */
117:    public Rectangle2D getBounds(Graphics2D g2)
118:    {
119:       if (text.length() == 0) return new Rectangle2D.Double();
120:       setLabelText();
121:       Dimension dim = label.getPreferredSize();       
122:       return new Rectangle2D.Double(0, 0, dim.getWidth(), dim.getHeight());
123:    }
124: 
125:    /**
126:       Draws this multiline string inside a given rectangle
127:       @param g2 the graphics context
128:       @param r the rectangle into which to place this multiline string
129:    */
130:    public void draw(Graphics2D g2, Rectangle2D r)
131:    {
132:       setLabelText();
133:       label.setFont(g2.getFont());
134:       label.setBounds(0, 0, (int) r.getWidth(), (int) r.getHeight());
135:       g2.translate(r.getX(), r.getY());
136:       label.paint(g2);
137:       g2.translate(-r.getX(), -r.getY());        
138:    }
139: 
140:    public Object clone()
141:    {
142:       try
143:       {
144:          return super.clone();
145:       }
146:       catch (CloneNotSupportedException exception)
147:       {
148:          return null;
149:       }
150:    }
151: 
152:    public static final int LEFT = 0;
153:    public static final int CENTER = 1;
154:    public static final int RIGHT = 2;
155:    public static final int LARGE = 3;
156:    public static final int NORMAL = 4;
157:    public static final int SMALL = 5;
158: 
159:    private static final int GAP = 3;
160: 
161:    private String text;
162:    private int justification;
163:    private int size;
164:    private boolean underlined;
165:    
166:    private static JLabel label = new JLabel();
167: }