1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * ident "%Z%%M% %I% %E% SMI" 24 * 25 * Copyright (c) 2000 by Sun Microsystems, Inc. 26 * All rights reserved. 27 */ 28 29 /* BEGIN JSTYLED */ 30 /** 31 * MultiLineLabel.java 32 * 33 * This example is from the book _Java in a 34 * Nutshell_ by David Flanagan. 35 * Written by David Flanagan. 36 * Copyright (c) 1996 O'Reilly & Associates. 37 * You may study, use, modify, and distribute 38 * this example for any purpose. 39 * This example is provided WITHOUT WARRANTY either 40 * expressed or implied. 41 * 42 * Tilman 05/07/96: added a maxChars parameter to 43 * specify a maximum line 44 * length. If any of the lines is longer, it will be cut 45 * at the last space character before maxChars, until it fits 46 * into maxChars. Set maxChars to -1 if you don't care. 47 * 48 * Van 07/30/96: added the removal of backslash-r 49 * from the multi-line string 50 * that might have been added by strings in Windows (which 51 * expect newlines to be indicated by backslash-r backslash-n) 52 * 53 * Van 10/18/96: changed the way lines are tokenized so that multiple 54 * consequetive newline characters create a blank line(s). 55 * 56 * Van 10/21/96: added interfaces to the maxChars variable 57 * 58 * @version @(#)MultiLineLabel.java 1.15 97/07/25 59 */ 60 /* END JSTYLED */ 61 62 package sunsoft.jws.visual.rt.awt; 63 64 import sunsoft.jws.visual.rt.base.Global; 65 import java.awt.*; 66 import java.util.*; 67 68 public class MultiLineLabel extends Canvas { 69 public static final int LEFT = Label.LEFT; // Alignment constants 70 public static final int CENTER = Label.CENTER; 71 public static final int RIGHT = Label.RIGHT; 72 73 protected String label; 74 protected Vector lines; // The lines of text to display 75 protected int num_lines; // The number of lines 76 protected int maxChars; // maximum width of lines 77 protected int margin_width; // Left and right margins 78 protected int margin_height; // Top and bottom margins 79 protected int line_height; // Total height of the font 80 protected int line_ascent; // Font height above baseline 81 protected int[] line_widths; // How wide each line is 82 protected int max_width; // The width of the widest line 83 protected int alignment = LEFT; // The alignment of the text. 84 85 /** 86 * This method breaks a specified label up into an array of lines. 87 * It uses the StringTokenizer utility class. 88 */ newLabel(String label)89 protected void newLabel(String label) { 90 if (label == null) 91 label = /* NOI18N */""; 92 this.label = label; 93 94 lines = new Vector(); 95 int len = label.length(); 96 int startFrom = 0; 97 while (startFrom != -1 && startFrom < len) { 98 // determine next line 99 String line; 100 int index = label.indexOf(/* NOI18N */"\n", startFrom); 101 if (index == -1) { 102 line = label.substring(startFrom); 103 startFrom = -1; 104 } else { 105 line = label.substring(startFrom, index); 106 startFrom = index + 1; 107 } 108 109 // wrap the words in the line 110 if ((maxChars == -1) || (line.length() <= maxChars)) 111 lines.addElement(line); 112 else { 113 while (line.length() > maxChars) { 114 int offset = line.lastIndexOf(/* NOI18N */ ' ', 115 maxChars); 116 if (offset == -1) { 117 // didn't get one within maxChars! 118 offset = line.indexOf(/* NOI18N */ ' '); 119 if (offset == -1) 120 break; 121 } 122 lines.addElement(line.substring(0, offset)); 123 line = line.substring(offset + 1); 124 } 125 lines.addElement(line); 126 } 127 } 128 num_lines = lines.size(); 129 line_widths = new int[num_lines]; 130 } 131 132 /** 133 * This method figures out how the font is, and how wide each 134 * line of the label is, and how wide the widest line is. 135 */ measure()136 protected void measure() { 137 /* JSTYLED */ 138 if (this.getFont() == null) return; 139 FontMetrics fm = this.getFontMetrics(this.getFont()); 140 // If we don't have font metrics yet, just return. 141 /* JSTYLED */ 142 if (fm == null) return; 143 144 line_height = fm.getHeight(); 145 line_ascent = fm.getAscent(); 146 max_width = 0; 147 for (int i = 0; i < num_lines; i++) { 148 line_widths[i] = fm.stringWidth( 149 (String) lines.elementAt(i)); 150 if (line_widths[i] > max_width) max_width = line_widths[i]; 151 } 152 Dimension d = preferredSize(); 153 setSize(d); 154 } 155 156 // Here are four versions of the constructor. 157 158 /** 159 * Break the label up into separate lines, and save the other info. 160 */ MultiLineLabel(String label, int maxChars, int margin_width, int margin_height, int alignment)161 public MultiLineLabel(String label, int maxChars, 162 int margin_width, int margin_height, 163 int alignment) { 164 this.maxChars = maxChars; 165 newLabel(label); 166 this.margin_width = margin_width; 167 this.margin_height = margin_height; 168 this.alignment = alignment; 169 } MultiLineLabel(String label, int maxChars, int margin_width, int margin_height)170 public MultiLineLabel(String label, int maxChars, 171 int margin_width, int margin_height) { 172 this(label, maxChars, margin_width, margin_height, LEFT); 173 } MultiLineLabel(String label, int maxChars, int alignment)174 public MultiLineLabel(String label, int maxChars, 175 int alignment) { 176 this(label, maxChars, 10, 10, alignment); 177 } MultiLineLabel(String label, int maxChars)178 public MultiLineLabel(String label, int maxChars) { 179 this(label, maxChars, 10, 10, LEFT); 180 } 181 MultiLineLabel(String label)182 public MultiLineLabel(String label) { 183 this(label, -1, 10, 10, LEFT); 184 } 185 MultiLineLabel()186 public MultiLineLabel() { 187 this(/* NOI18N */"MultiLineLabel"); 188 } 189 190 // Methods to set the various attributes of the component setLabel(String label)191 public void setLabel(String label) { 192 newLabel(label); 193 measure(); 194 repaint(); 195 } 196 getLabel()197 public String getLabel() { 198 return label; 199 } 200 setMaxColumns(int w)201 public void setMaxColumns(int w) { 202 if (w < 0) 203 w = -1; 204 maxChars = w; 205 newLabel(label); 206 measure(); 207 repaint(); 208 } 209 getMaxColumns()210 public int getMaxColumns() { 211 return (maxChars); 212 } 213 setFont(Font f)214 public void setFont(Font f) { 215 super.setFont(f); 216 measure(); 217 repaint(); 218 } 219 setForeground(Color c)220 public void setForeground(Color c) { 221 super.setForeground(c); 222 repaint(); 223 } 224 setAlignment(int a)225 public void setAlignment(int a) { alignment = a; repaint(); } setMarginWidth(int mw)226 public void setMarginWidth(int mw) { margin_width = mw; repaint(); } setMarginHeight(int mh)227 public void setMarginHeight(int mh) { margin_height = mh; 228 repaint(); } getAlignment()229 public int getAlignment() { return alignment; } getMarginWidth()230 public int getMarginWidth() { return margin_width; } getMarginHeight()231 public int getMarginHeight() { return margin_height; } 232 233 /** 234 * This method is invoked after our Canvas is first created 235 * but before it can actually be displayed. After we've 236 * invoked our superclass's addNotify() method, we have font 237 * metrics and can successfully call measure() to figure out 238 * how big the label is. 239 */ addNotify()240 public void addNotify() { super.addNotify(); measure(); } 241 242 /** 243 * This method is called by a layout manager when it wants to 244 * know how big we'd like to be. 245 */ preferredSize()246 public Dimension preferredSize() { 247 return new Dimension(max_width + 2*margin_width, 248 num_lines * line_height + 2*margin_height); 249 } 250 251 /** 252 * This method is called when the layout manager wants to know 253 * the bare minimum amount of space we need to get by. 254 */ minimumSize()255 public Dimension minimumSize() { 256 return new Dimension(max_width, num_lines * line_height); 257 } 258 259 /** 260 * This method draws the label (applets use the same method). 261 * Note that it handles the margins and the alignment, but that 262 * it doesn't have to worry about the color or font--the superclass 263 * takes care of setting those in the Graphics object we're passed. 264 */ paint(Graphics g)265 public void paint(Graphics g) { 266 if (Global.isWindows()) 267 g = getGraphics(); 268 int x, y; 269 Dimension d = this.size(); 270 271 int mw = Math.max((d.width - max_width)/2, 0); 272 g.setColor(getForeground()); 273 274 y = line_ascent + (d.height - num_lines * line_height)/2; 275 for (int i = 0; i < num_lines; i++, y += line_height) { 276 switch (alignment) { 277 case LEFT: 278 x = mw; 279 break; 280 case CENTER: 281 default: 282 x = (d.width - line_widths[i])/2; 283 break; 284 case RIGHT: 285 x = d.width - mw - line_widths[i]; 286 break; 287 } 288 g.drawString(((String) lines.elementAt(i)).trim(), x, y); 289 } 290 } 291 } 292