1 /***
2 *
3 */
4 package org.telscenter.pas.ui;
5
6 import java.awt.Dimension;
7 import java.awt.FontMetrics;
8 import java.awt.Graphics;
9 import java.awt.Rectangle;
10 import java.util.StringTokenizer;
11
12 import javax.swing.Icon;
13 import javax.swing.JComponent;
14 import javax.swing.JLabel;
15 import javax.swing.SwingConstants;
16 import javax.swing.SwingUtilities;
17 import javax.swing.plaf.basic.BasicGraphicsUtils;
18 import javax.swing.plaf.basic.BasicLabelUI;
19
20 /***
21 * @author aperritano
22 *
23 */
24 public class MultiLineLabelUI extends BasicLabelUI
25 {
26 static {
27 labelUI = new MultiLineLabelUI();
28 }
29
30 protected String layoutCL(
31 JLabel label,
32 FontMetrics fontMetrics,
33 String text,
34 Icon icon,
35 Rectangle viewR,
36 Rectangle iconR,
37 Rectangle textR)
38 {
39 String s = layoutCompoundLabel(
40 (JComponent) label,
41 fontMetrics,
42 splitStringByLines(text),
43 icon,
44 label.getVerticalAlignment(),
45 label.getHorizontalAlignment(),
46 label.getVerticalTextPosition(),
47 label.getHorizontalTextPosition(),
48 viewR,
49 iconR,
50 textR,
51 label.getIconTextGap());
52
53 if( s.equals("") )
54 return text;
55 return s;
56 }
57
58
59 static final int LEADING = SwingConstants.LEADING;
60 static final int TRAILING = SwingConstants.TRAILING;
61 static final int LEFT = SwingConstants.LEFT;
62 static final int RIGHT = SwingConstants.RIGHT;
63 static final int TOP = SwingConstants.TOP;
64 static final int CENTER = SwingConstants.CENTER;
65
66 /***
67 * Compute and return the location of the icons origin, the
68 * location of origin of the text baseline, and a possibly clipped
69 * version of the compound labels string. Locations are computed
70 * relative to the viewR rectangle.
71 * The JComponents orientation (LEADING/TRAILING) will also be taken
72 * into account and translated into LEFT/RIGHT values accordingly.
73 */
74 public static String layoutCompoundLabel(JComponent c,
75 FontMetrics fm,
76 String[] text,
77 Icon icon,
78 int verticalAlignment,
79 int horizontalAlignment,
80 int verticalTextPosition,
81 int horizontalTextPosition,
82 Rectangle viewR,
83 Rectangle iconR,
84 Rectangle textR,
85 int textIconGap)
86 {
87 boolean orientationIsLeftToRight = true;
88 int hAlign = horizontalAlignment;
89 int hTextPos = horizontalTextPosition;
90
91
92 if (c != null) {
93 if (!(c.getComponentOrientation().isLeftToRight())) {
94 orientationIsLeftToRight = false;
95 }
96 }
97
98
99
100
101 switch (horizontalAlignment) {
102 case LEADING:
103 hAlign = (orientationIsLeftToRight) ? LEFT : RIGHT;
104 break;
105 case TRAILING:
106 hAlign = (orientationIsLeftToRight) ? RIGHT : LEFT;
107 break;
108 }
109
110
111
112 switch (horizontalTextPosition) {
113 case LEADING:
114 hTextPos = (orientationIsLeftToRight) ? LEFT : RIGHT;
115 break;
116 case TRAILING:
117 hTextPos = (orientationIsLeftToRight) ? RIGHT : LEFT;
118 break;
119 }
120
121 return layoutCompoundLabel(fm,
122 text,
123 icon,
124 verticalAlignment,
125 hAlign,
126 verticalTextPosition,
127 hTextPos,
128 viewR,
129 iconR,
130 textR,
131 textIconGap);
132 }
133
134
135 /***
136 * Compute and return the location of the icons origin, the
137 * location of origin of the text baseline, and a possibly clipped
138 * version of the compound labels string. Locations are computed
139 * relative to the viewR rectangle.
140 * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
141 * values in horizontalTextPosition (they will default to RIGHT) and in
142 * horizontalAlignment (they will default to CENTER).
143 * Use the other version of layoutCompoundLabel() instead.
144 */
145 public static String layoutCompoundLabel(
146 FontMetrics fm,
147 String[] text,
148 Icon icon,
149 int verticalAlignment,
150 int horizontalAlignment,
151 int verticalTextPosition,
152 int horizontalTextPosition,
153 Rectangle viewR,
154 Rectangle iconR,
155 Rectangle textR,
156 int textIconGap)
157 {
158
159
160
161 if (icon != null) {
162 iconR.width = icon.getIconWidth();
163 iconR.height = icon.getIconHeight();
164 }
165 else {
166 iconR.width = iconR.height = 0;
167 }
168
169
170
171
172
173
174
175 boolean textIsEmpty = (text == null) || (text.length == 0)
176 || (text.length == 1 && ( (text[0]==null) || text[0].equals("") ));
177
178 String rettext = "";
179 if (textIsEmpty) {
180 textR.width = textR.height = 0;
181 }
182 else {
183 Dimension dim = computeMultiLineDimension( fm, text );
184 textR.width = dim.width;
185 textR.height = dim.height;
186 }
187
188
189
190
191
192
193 int gap = (textIsEmpty || (icon == null)) ? 0 : textIconGap;
194
195 if (!textIsEmpty) {
196
197
198
199
200
201
202 int availTextWidth;
203
204 if (horizontalTextPosition == CENTER) {
205 availTextWidth = viewR.width;
206 }
207 else {
208 availTextWidth = viewR.width - (iconR.width + gap);
209 }
210
211
212 if (textR.width > availTextWidth && text.length == 1) {
213 String clipString = "...";
214 int totalWidth = SwingUtilities.computeStringWidth(fm,clipString);
215 int nChars;
216 for(nChars = 0; nChars < text[0].length(); nChars++) {
217 totalWidth += fm.charWidth(text[0].charAt(nChars));
218 if (totalWidth > availTextWidth) {
219 break;
220 }
221 }
222 rettext = text[0].substring(0, nChars) + clipString;
223 textR.width = SwingUtilities.computeStringWidth(fm,rettext);
224 }
225 }
226
227
228
229
230
231
232 if (verticalTextPosition == TOP) {
233 if (horizontalTextPosition != CENTER) {
234 textR.y = 0;
235 }
236 else {
237 textR.y = -(textR.height + gap);
238 }
239 }
240 else if (verticalTextPosition == CENTER) {
241 textR.y = (iconR.height / 2) - (textR.height / 2);
242 }
243 else {
244 if (horizontalTextPosition != CENTER) {
245 textR.y = iconR.height - textR.height;
246 }
247 else {
248 textR.y = (iconR.height + gap);
249 }
250 }
251
252 if (horizontalTextPosition == LEFT) {
253 textR.x = -(textR.width + gap);
254 }
255 else if (horizontalTextPosition == CENTER) {
256 textR.x = (iconR.width / 2) - (textR.width / 2);
257 }
258 else {
259 textR.x = (iconR.width + gap);
260 }
261
262
263
264
265
266
267
268
269 int labelR_x = Math.min(iconR.x, textR.x);
270 int labelR_width = Math.max(iconR.x + iconR.width,
271 textR.x + textR.width) - labelR_x;
272 int labelR_y = Math.min(iconR.y, textR.y);
273 int labelR_height = Math.max(iconR.y + iconR.height,
274 textR.y + textR.height) - labelR_y;
275
276 int dx, dy;
277
278 if (verticalAlignment == TOP) {
279 dy = viewR.y - labelR_y;
280 }
281 else if (verticalAlignment == CENTER) {
282 dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2));
283 }
284 else {
285 dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
286 }
287
288 if (horizontalAlignment == LEFT) {
289 dx = viewR.x - labelR_x;
290 }
291 else if (horizontalAlignment == RIGHT) {
292 dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
293 }
294 else {
295 dx = (viewR.x + (viewR.width / 2)) -
296 (labelR_x + (labelR_width / 2));
297 }
298
299
300
301
302 textR.x += dx;
303 textR.y += dy;
304
305 iconR.x += dx;
306 iconR.y += dy;
307
308 return rettext;
309 }
310
311 protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY)
312 {
313 int accChar = l.getDisplayedMnemonic();
314 g.setColor(l.getForeground());
315 drawString(g, s, accChar, textX, textY);
316 }
317
318
319 protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY)
320 {
321 int accChar = l.getDisplayedMnemonic();
322 g.setColor(l.getBackground());
323 drawString(g, s, accChar, textX, textY);
324 }
325
326 protected void drawString( Graphics g, String s, int accChar, int textX, int textY )
327 {
328 if( s.indexOf('\n') == -1 )
329 BasicGraphicsUtils.drawString(g, s, accChar, textX, textY);
330 else
331 {
332 String[] strs = splitStringByLines( s );
333 int height = g.getFontMetrics().getHeight();
334
335 BasicGraphicsUtils.drawString(g, strs[0], accChar, textX, textY);
336 for( int i = 1; i < strs.length; i++ )
337 g.drawString( strs[i], textX, textY + (height*i) );
338 }
339 }
340
341 public static Dimension computeMultiLineDimension( FontMetrics fm, String[] strs )
342 {
343 int i, c, width = 0;
344 for(i=0, c=strs.length ; i < c ; i++)
345 width = Math.max( width, SwingUtilities.computeStringWidth(fm,strs[i]) );
346 return new Dimension( width, fm.getHeight() * strs.length );
347 }
348
349
350 protected String str;
351 protected String[] strs;
352
353 public String[] splitStringByLines( String str )
354 {
355 if( str.equals(this.str) )
356 return strs;
357
358 this.str = str;
359
360 int lines = 1;
361 int i, c;
362 for(i=0, c=str.length() ; i < c ; i++) {
363 if( str.charAt(i) == '\n' )
364 lines++;
365 }
366 strs = new String[lines];
367 StringTokenizer st = new StringTokenizer( str, "\n" );
368
369 int line = 0;
370 while( st.hasMoreTokens() )
371 strs[line++] = st.nextToken();
372
373 return strs;
374 }
375 }