KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > chart2d > TextArea


1 /**
2  * Chart2D, a java library for drawing two dimensional charts.
3  * Copyright (C) 2001 Jason J. Simas
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * The author of this library may be contacted at:
19  * E-mail: jjsimas@users.sourceforge.net
20  * Street Address: J J Simas, 887 Tico Road, Ojai, CA 93023-3555 USA
21  */

22
23
24 package net.sourceforge.chart2d;
25
26
27 import java.awt.*;
28 import java.util.*;
29 import java.awt.font.*;
30 import java.awt.geom.*;
31 import java.text.*;
32
33
34 /**
35  * A customizable text label. This label has built-int bordering, spacing
36  * between borders and text, text rotation, line breaking, auto justification
37  * within the borders, growing and shrinking, and auto locating. Much of this
38  * functionality is provided by its super classes.<br>
39  * Note: Does not support null values. Pass empty strings instead.
40  */

41 final class TextArea extends FontArea {
42
43
44   private String JavaDoc text;
45   private Vector textLayouts;
46   private boolean rotateLeft;
47   private int textJustification;
48   private boolean needsUpdate;
49
50
51   /**
52    * Creates a new text area with the following default values:
53    * setText ("");<br>
54    * setRotateLeft (false);<br>
55    * setTextJustification (CENTER);<br>
56    * resetTextAreaModel (true);<br>
57    */

58   TextArea () {
59
60     setText ("");
61     setRotateLeft (false);
62     setTextJustification (CENTER);
63     resetTextAreaModel (true);
64     needsUpdate = true;
65   }
66
67
68   /**
69    * Changes the text of this label.
70    * @param t The new text.
71    */

72   final void setText (String JavaDoc t) {
73
74     needsUpdate = true;
75     text = t;
76   }
77
78
79   /**
80    * Adjusts the rotation of the text within the label. If not rotated, text
81    * runs from left to right, top to bottom of the are. If rotate, text runs
82    * from bottom to top, left to right. The text is rotated -90 degree. Even
83    * when rotate, the location or origin of this label is always the top left
84    * corner of it, however, the text's actual origin is near the bottom left
85    * corner.
86    * @param r If true, then adjusts settings so that text is rotated.
87    */

88   final void setRotateLeft (boolean r) {
89
90     needsUpdate = true;
91     rotateLeft = r;
92   }
93
94
95   /**
96    * Specifies whether text will be (in the case text is not rotated) left,
97    * right, or center justified respective to the space within the bordered
98    * area. In the case text is rotated, then bottom, top or center
99    * justification is available. This only adjusts the horizontal
100    * justification, or in the case of rotated text, the vertical justification.
101    * @param which Which justification for the text. Possible values, if not
102    * rotated: LEFT, RIGHT, CENTER; if rotated: BOTTOM, TOP, CENTER. Also,
103    * if you prefer and when rotated, LEFT and RIGHT may be used to mean BOTTOM
104    * and TOP respectively; this program translates them into BOTTOM and TOP for
105    * you.
106    */

107   final void setTextJustification (int which) {
108
109     needsUpdate = true;
110     if (which == TOP) textJustification = RIGHT;
111     else if (which == BOTTOM) textJustification = LEFT;
112     else textJustification = which;
113   }
114
115
116   /**
117    * Returns the text of this label.
118    * @return The label's text.
119    */

120   final String JavaDoc getText() {
121
122     return text;
123   }
124
125
126   /**
127    * Returns whether this text is rotated left 90 degrees.
128    * @return If rotated, then true.
129    */

130   final boolean getRotateLeft () {
131
132     return rotateLeft;
133   }
134
135
136   /**
137    * Indicates whether some property of this class has changed.
138    * @return True if some property has changed.
139    */

140   final boolean getTextAreaNeedsUpdate() {
141
142     return (needsUpdate || getFontAreaNeedsUpdate());
143   }
144
145
146   /**
147    * Updates all the variables of all this parent's classes, then all the
148    * variables of this class.
149    * @param g2D The graphics context under which to make calculations.
150    */

151   final void updateTextArea (Graphics2D g2D) {
152
153     if (getTextAreaNeedsUpdate()) {
154       updateFontArea ();
155       update (g2D);
156     }
157     needsUpdate = false;
158   }
159
160
161   /**
162    * Resets the model for this class. The model is used for shrinking and
163    * growing of its components based on the maximum size of this class. If this
164    * method is called, then the next time the maximum size is set, this classes
165    * model maximum size will be made equal to the new maximum size. Effectively
166    * what this does is ensure that whenever this objects maximum size is equal
167    * to the one given, then all of the components will take on their default
168    * model sizes. Note: This is only useful when auto model max sizing is
169    * disabled.
170    * @param reset True causes the max model size to be set upon the next max
171    * sizing.
172    */

173   final void resetTextAreaModel (boolean reset) {
174
175     needsUpdate = true;
176     resetFontAreaModel (reset);
177   }
178
179
180   /**
181    * Paints all of the components of this class. First all the variables are
182    * updated. Then all the components are painted.
183    * @param g2D The graphics context for calculations and painting.
184    */

185   final void paintComponent (Graphics2D g2D) {
186
187     updateTextArea (g2D);
188     super.paintComponent (g2D);
189
190     Color oldColor = g2D.getColor();
191     g2D.setColor (getFontColor());
192
193     int delta = 0;
194     int count = textLayouts.size();
195     for (int i = 0; i < count; ++i) {
196
197       TextLayout layout = (TextLayout)textLayouts.get(i);
198       Shape shape = layout.getOutline(new AffineTransform());
199       int ascent = (int)Math.abs (shape.getBounds(). y);
200       int descent = shape.getBounds().height - ascent;
201       int height = ascent + descent;
202       int leading = (int)layout.getLeading();
203
204       if (!rotateLeft) {
205
206         int clipHeight = delta + height > getSpaceSize(MIN).height ?
207           getSpaceSize(MIN).height - delta : height;
208         Rectangle rect = new Rectangle
209           (getSpaceSizeLocation (MIN).x, getSpaceSizeLocation (MIN).y + delta,
210             getSpaceSize(MIN).width, clipHeight);
211         g2D.clip (rect);
212         int translateX;
213         if (textJustification == LEFT) {
214           translateX =
215             getSpaceSizeLocation (MIN).x - shape.getBounds().x;
216         }
217         else if (textJustification == RIGHT) {
218           translateX = getSpaceSizeLocation (MIN).x + getSpaceSize (MIN).width -
219             shape.getBounds().width - shape.getBounds().x;
220         }
221         else {
222           translateX = getSpaceSizeLocation (MIN).x +
223           (getSpaceSize (MIN).width - shape.getBounds().width) / 2 -
224             shape.getBounds().x;
225         }
226         int translateY = getSpaceSizeLocation (MIN).y + delta + ascent;
227         g2D.translate (translateX, translateY);
228         g2D.fill (shape);
229
230         g2D.setClip (null);
231         g2D.translate (-translateX, -translateY);
232         delta = delta + height + leading;
233       }
234       else {
235
236         int clipHeight = delta + height > getSpaceSize(MIN).width ?
237           getSpaceSize(MIN).width - delta : height;
238         Rectangle rect = new Rectangle
239           (getSpaceSizeLocation (MIN).x + delta, getSpaceSizeLocation (MIN).y,
240             clipHeight, getSpaceSize(MIN).height);
241         g2D.clip (rect);
242         int translateX = getSpaceSizeLocation (MIN).x + delta + ascent;
243         int translateY;
244         if (textJustification == LEFT) {
245           translateY = getSpaceSizeLocation (MIN).y + getSpaceSize(MIN).height +
246             shape.getBounds().x;
247         }
248         else if (textJustification == RIGHT) {
249           translateY = getSpaceSizeLocation (MIN).y + shape.getBounds().width +
250             shape.getBounds().x;
251         }
252         else {
253           translateY = getSpaceSizeLocation (MIN).y +
254             (getSpaceSize (MIN).height + shape.getBounds().width) / 2
255             + shape.getBounds().x;
256         }
257         g2D.translate (translateX, translateY);
258         g2D.rotate(Math.toRadians(-90d));
259         g2D.fill (shape);
260
261         g2D.setClip (null);
262         g2D.rotate (Math.toRadians(90d));
263         g2D.translate (-translateX, -translateY);
264         delta = delta + height + leading;
265       }
266     }
267
268     g2D.setColor (oldColor);
269   }
270
271
272   private void update (Graphics2D g2D) {
273
274     int greatestAdvance = 0;
275     int lineBreaksMeasurement = 0;
276     int leading = 0;
277     textLayouts = new Vector (0, 1);
278     if (text.length() > 0) {
279       int wrapping =
280         !rotateLeft ? getSpaceSize (MAX).width : getSpaceSize (MAX).height;
281       int mockWrapping = wrapping;
282       boolean fits = true;
283       AttributedString attributedString =
284         new AttributedString (text, getFont().getAttributes());
285       AttributedCharacterIterator attributedCharacterIterator =
286         attributedString.getIterator();
287       FontRenderContext fontRenderContext = g2D.getFontRenderContext();
288       for(;;) {
289         LineBreakMeasurer measurer = new LineBreakMeasurer
290           (attributedCharacterIterator, fontRenderContext);
291         textLayouts = new Vector (0, 1);
292         greatestAdvance = 0;
293         lineBreaksMeasurement = 0;
294         for (TextLayout layout = measurer.nextLayout (mockWrapping);
295           layout != null;
296           layout = measurer.nextLayout(mockWrapping)) {
297           textLayouts.add (layout);
298           Shape shape = layout.getOutline(new AffineTransform());
299           int width = shape.getBounds().width;
300           greatestAdvance = greatestAdvance < width ? width : greatestAdvance;
301           int ascent = (int)Math.abs (shape.getBounds().y);
302           int descent = shape.getBounds().height - ascent;
303           int height = ascent + descent;
304           leading = (int)layout.getLeading();
305           lineBreaksMeasurement = lineBreaksMeasurement + height + leading;
306
307         }
308         lineBreaksMeasurement -= leading;
309
310         if (lineBreaksMeasurement >
311           (!rotateLeft ? getSpaceSize (MAX).height : getSpaceSize (MAX).width))
312           {
313           fits = false;
314           greatestAdvance = 0;
315           lineBreaksMeasurement = 0;
316           textLayouts = new Vector(0,1);
317           break;
318         }
319         else if (greatestAdvance > wrapping) {
320           mockWrapping = mockWrapping - (greatestAdvance - mockWrapping);
321           if (mockWrapping <= 0) {
322             fits = false;
323             greatestAdvance = 0;
324             lineBreaksMeasurement = 0;
325             textLayouts = new Vector(0,1);
326             break;
327           }
328           //else loop again
329
}
330         else break; //it fits
331
}
332     }
333
334     if (!getAutoSize (MIN)) {
335       if (!rotateLeft) {
336         setSpaceSize (MIN,
337           new Dimension (greatestAdvance, lineBreaksMeasurement));
338       }
339       else {
340         setSpaceSize (MIN,
341           new Dimension (lineBreaksMeasurement, greatestAdvance));
342       }
343       updateFontArea();
344     }
345   }
346 }
Popular Tags