KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > text > wrapped > WrappedContainer


1 package text.wrapped;
2
3 import text.*;
4
5 import java.util.*;
6 import java.awt.*;
7 import rero.util.*;
8
9 public class WrappedContainer
10 {
11    protected int maxSize; // max size window can grow to before I force a wordwrap.
12
protected int minSize; // minimum size window can grow to before I force a wrap.
13

14    protected WrappedContainer next = null;
15    protected WrappedContainer prev = null;
16
17    protected AttributedString text;
18
19    protected AttributedText[] wrapped; // wrapped text.
20

21    public WrappedContainer(String JavaDoc input)
22    {
23       text = AttributedString.CreateAttributedString(input);
24    }
25
26    public WrappedContainer next()
27    {
28       return next;
29    }
30
31    public WrappedContainer previous()
32    {
33       return prev;
34    }
35
36    public boolean hasNext()
37    {
38       return next != null;
39    }
40
41    public boolean hasPrevious()
42    {
43       return prev != null;
44    }
45
46    public void setNext(WrappedContainer n)
47    {
48       next = n;
49    }
50
51    public void setPrevious(WrappedContainer p)
52    {
53       prev = p;
54    }
55
56    /** parameter size is the size of the component we're going to be drawing on **/
57    public void touch(int size)
58    {
59       if (size >= minSize && size <= maxSize)
60       {
61 // System.out.println(size + " >= " + minSize + " && "+size+" <= " + maxSize + " :" + text.getText());
62
return;
63       }
64
65       //
66
// wrap the text...
67
//
68
wrapped = wrap(text, size);
69
70       determineBounds(size);
71    }
72
73    public void reset()
74    {
75       minSize = 1024 * 768;
76       maxSize = 0;
77    }
78
79    protected void determineBounds(int size)
80    {
81       //
82
// determine upper and lower bounds for further wrapping. I don't know how much overhead these
83
// functions will be creating so if its a problem the upper and lower bound optimization may turn
84
// into a heuristic similiar to how I did it before...
85
//
86
minSize = 0;
87       maxSize = Integer.MAX_VALUE;
88
89       AttributedText temp;
90
91       for (int x = 0; x < wrapped.length; x++)
92       {
93           int width = 0;
94
95           temp = wrapped[x];
96           while (temp != null)
97           {
98              width += temp.width;
99              temp = temp.next;
100           }
101
102           if (width > minSize)
103           {
104     // System.out.println("Lower bound tolerance is " + width + " for " + wrapped[x]);
105
minSize = width;
106           }
107       }
108       maxSize = size + 50;
109    }
110
111    /** returns an array of wrapped text, just a note wrapped text is stored in reverse order since drawing happens from the
112        bottom of the component on up. */

113    public AttributedText[] getWrappedText()
114    {
115        return wrapped;
116    }
117
118    /** reconstruct string from attributed text, used by on click mechanism type of deal */
119    public String JavaDoc getText()
120    {
121       return text.getText();
122    }
123
124    /** used by url clicking mechanism... jEAH. */
125    public String JavaDoc getTokenAt(AttributedText lineno, int pixelx)
126    {
127       if (lineno.isIndent())
128       {
129          pixelx -= lineno.width;
130          lineno = lineno.next;
131       }
132       String JavaDoc temp = lineno.getText();
133       TokenizedString tokens = new TokenizedString(temp, " ");
134
135       for (int x = 0; x < (tokens.getTotalTokens() + 1); x++)
136       {
137          if (TextSource.fontMetrics.stringWidth(tokens.getTokenTo(x)) > pixelx)
138          {
139             String JavaDoc rv;
140  
141             if (x > 0) { rv = tokens.getToken(x - 1); }
142             else { rv = tokens.getToken(0); }
143
144             //
145
// is this token self contained in the total string?
146
//
147
if (text.getTokens().isToken(rv))
148             {
149                return rv; // we know that this is a whole complete token.
150
}
151  
152             //
153
// is this token the beginning of another longer token (in which case we want the whole thing)
154
//
155
for (int z = 0; z < text.getTokens().getTotalTokens(); z++)
156             {
157                if (rv.length() < text.getTokens().getToken(z).length())
158                {
159                    if (text.getTokens().getToken(z).substring(0, rv.length()).equals(rv))
160                    {
161                       return text.getTokens().getToken(z);
162                    }
163                }
164             }
165            
166             //
167
// is this token contained within some longer token (again in which case we want the whole thing)
168
//
169
for (int z = 0; z < text.getTokens().getTotalTokens(); z++)
170             {
171                if (rv.length() < text.getTokens().getToken(z).length())
172                {
173                    if (text.getTokens().getToken(z).indexOf(rv) > -1)
174                    {
175                       return text.getTokens().getToken(z);
176                    }
177                }
178             }
179
180             //
181
// I give up...
182
//
183
return rv;
184          }
185       }
186
187       return null;
188    }
189
190    /** used by shift+click mechanism */
191    public AttributedText getAttributedTextAt(AttributedText line, int pixelx)
192    {
193        int width = 0;
194        while (line != null && (width + line.width) < pixelx)
195        {
196           width += line.width;
197           line = line.next;
198        }
199
200        return line;
201    }
202
203    public static AttributedText[] wrap(AttributedString textData, int maxWidth)
204    {
205       TokenizedString tokens = textData.getTokens();
206  
207       LinkedList data = new LinkedList();
208       AttributedText head;
209
210       String JavaDoc text = textData.getText();
211       String JavaDoc current = ""; // the current string we are working with and potentially wordwrapping.
212

213       int tokenNo = 0; // identifier for our current lineno.
214
int start = 0; // index into the "text" of the starting char for this line.
215
int oldlength = 0;
216
217       int indentlen = 0;
218       String JavaDoc indent = ""; // indenting stuff, to be taken into account.
219

220       int totalWidth = 0;
221  
222       while (tokenNo <= tokens.getTotalTokens())
223       {
224          if (totalWidth >= maxWidth)
225          {
226             // the current token has put us over the top, doh!
227
int size = TextSource.fontMetrics.stringWidth(tokens.getToken(tokenNo - 1)) + indentlen;
228
229             if (start == oldlength && size < maxWidth)
230             {
231                //
232
// we're stuck in the current token, need to jiggle things a little bit.
233
//
234

235                oldlength = current.length();
236                tokenNo++;
237
238                current = tokens.getTokenTo(tokenNo);
239                totalWidth = TextSource.fontMetrics.stringWidth(text.substring(start, current.length())) + indentlen;
240             }
241             else if (size >= maxWidth)
242             {
243                //
244
// the current token is larger than a line of text as it is. So we're in
245
// trouble.
246
//
247

248                int y = start + 1;
249                while (y < current.length() && (TextSource.fontMetrics.stringWidth(text.substring(start, y)) + indentlen) < maxWidth)
250                {
251                   y++;
252                }
253                y--;
254
255                // WRAP
256
if (indent.length() > 0)
257                {
258                    head = new AttributedText();
259                    head.text = indent;
260                    head.width = indentlen;
261                    head.next = textData.substring(start, y);
262                    head.setIndent();
263                }
264                else
265                {
266                    head = textData.substring(start, y);
267                }
268                data.add(head);
269
270                // RESET
271
indent = " ";
272                indentlen = TextSource.fontMetrics.stringWidth(" ");
273
274                start = y;
275
276                while (start < text.length() && text.charAt(start) == ' ')
277                {
278                   start++;
279                }
280
281                oldlength = start;
282
283                totalWidth = TextSource.fontMetrics.stringWidth(text.substring(start, current.length())) + indentlen;
284             }
285             else
286             {
287                //
288
// plain jane wrapping case, revert to the last good text position that didn't put us over the top
289
// and add it to the data structure for the return value (the data linked list).
290
//
291

292                 // WRAP
293
if (indent.length() > 0)
294                 {
295                    head = new AttributedText();
296                    head.text = indent;
297                    head.width = indentlen;
298                    head.next = textData.substring(start, oldlength);
299                    head.setIndent();
300                 }
301                 else
302                 {
303                    head = textData.substring(start, oldlength);
304                 }
305                 data.add(head);
306
307                 // RESET
308
indent = " ";
309                 indentlen = TextSource.fontMetrics.stringWidth(" ");
310
311                 start = oldlength;
312
313                 while (start < text.length() && text.charAt(start) == ' ')
314                 {
315                    start++;
316                 }
317
318                 oldlength = start;
319             }
320          }
321          else
322          {
323              //
324
// advance to the next token...
325
//
326

327              oldlength = current.length();
328              tokenNo++;
329
330              current = tokens.getTokenTo(tokenNo);
331              totalWidth = TextSource.fontMetrics.stringWidth(text.substring(start, current.length())) + indentlen;
332          }
333       }
334   
335       //
336
// pick up any left over slop and add it to the data structure...
337
//
338
if (start < text.length())
339       {
340           if (indent.length() > 0)
341           {
342               head = new AttributedText();
343               head.text = indent;
344               head.width = indentlen;
345               head.next = textData.substring(start, oldlength);
346               head.setIndent();
347           }
348           else
349           {
350               head = textData.substring(start, oldlength);
351           }
352           data.add(head);
353       }
354       //
355
// convert the linked list to an array.
356
//
357
AttributedText returnValue[] = new AttributedText[data.size()];
358       int x = data.size() - 1;
359       ListIterator i = data.listIterator();
360       while (i.hasNext())
361       {
362          returnValue[x] = (AttributedText)i.next();
363          x--;
364       }
365
366       return returnValue;
367    }
368 }
369
Popular Tags