KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quikj > client > beans > RichTextCanvas


1 /*
2  * RichTextCanvas.java
3  *
4  * Created on November 24, 2002, 1:55 AM
5  */

6
7 package com.quikj.client.beans;
8
9 import java.awt.*;
10 import java.awt.event.*;
11 import java.util.*;
12
13 /**
14  *
15  * @author amit
16  */

17 public class RichTextCanvas extends java.awt.Canvas JavaDoc
18 {
19     /** Creates a new instance of RichTextCanvas */
20     public RichTextCanvas(Scrollbar bar, int rows, int cols)
21     {
22         super();
23         
24         this.bar = bar;
25         
26         setBackgroundColor(DEFAULT_BACKGROUND_COLOR);
27         
28         setForegroundColor(DEFAULT_FOREGROUND_COLOR);
29         
30         defaultRows = rows;
31         defaultColumns = cols;
32         
33         font = DEFAULT_FONT;
34         super.setFont(font);
35         
36         displayList.addElement(new Vector());
37         
38         addComponentListener(new CanvasComponentListener());
39         bar.addAdjustmentListener(new BarListener());
40     }
41     
42     public RichTextCanvas(Scrollbar bar)
43     {
44         this(bar, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLUMNS);
45     }
46     
47     /** Getter for property font.
48      * @return Value of property font.
49      *
50      */

51     public java.awt.Font JavaDoc getFont()
52     {
53         return font;
54     }
55     
56     /** Setter for property font.
57      * @param font New value of property font.
58      *
59      */

60     public void setFont(java.awt.Font JavaDoc font)
61     {
62         this.font = font;
63         super.setFont(font);
64         
65         componentResized();
66     }
67     
68     /** Getter for property forgroundColor.
69      * @return Value of property forgroundColor.
70      *
71      */

72     public java.awt.Color JavaDoc getForegroundColor()
73     {
74         return foregroundColor;
75     }
76     
77     /** Setter for property forgroundColor.
78      * @param forgroundColor New value of property forgroundColor.
79      *
80      */

81     public void setForegroundColor(java.awt.Color JavaDoc foregroundColor)
82     {
83         this.foregroundColor = foregroundColor;
84         
85     }
86     
87     /** Getter for property backgroundColor.
88      * @return Value of property backgroundColor.
89      *
90      */

91     public java.awt.Color JavaDoc getBackgroundColor()
92     {
93         return backgroundColor;
94     }
95     
96     /** Setter for property backgroundColor.
97      * @param backgroundColor New value of property backgroundColor.
98      *
99      */

100     public void setBackgroundColor(java.awt.Color JavaDoc backgroundColor)
101     {
102         this.backgroundColor = backgroundColor;
103         setBackground(backgroundColor);
104     }
105     
106     public Dimension getMinimumSize()
107     {
108         return new Dimension(0, 0);
109     }
110     
111     public Dimension getMaximumSize()
112     {
113         return new Dimension(1000000, 1000000);
114     }
115     
116     public Dimension getPreferredSize()
117     {
118         Graphics g = getGraphics();
119         if (g == null)
120         {
121             return new Dimension(0, 0);
122         }
123         
124         FontMetrics fm = g.getFontMetrics();
125         int font_height = fm.getHeight();
126         int font_width = fm.charWidth('w');
127         
128         return new Dimension(0,
129         font_height * defaultRows);
130     }
131     
132     public void paint(Graphics g)
133     {
134         if (barInitialized == false)
135         {
136             initializeBar();
137         }
138         
139         //System.out.println("In paint() " + displayList.size());
140
FontMetrics fm = g.getFontMetrics();
141         int font_height = fm.getHeight();
142         int x; // x-coordinate
143
int y = font_height; // y-coordinate
144

145         int size = displayList.size();
146         int starting_line = bar.getValue();
147         int ending_line = starting_line + bar.getVisibleAmount();
148         if (ending_line > size) ending_line = size;
149         
150         Rectangle r = getBounds();
151         
152         try
153         {
154             Image img = createImage(r.width, r.height);
155             Graphics og = img.getGraphics();
156             og.setClip(0, 0, r.width, r.height);
157             
158             for (int i = starting_line; i < ending_line; i++, y+=font_height)
159             {
160                 Vector line = (Vector)displayList.elementAt(i);
161                 int num_elements = line.size();
162                 
163                 x = 0; // reset the column to 0
164
int error_count = 0;
165                 for (int j = 0; j < num_elements; j++)
166                 {
167                     try
168                     {
169                         TextAttribute element = (TextAttribute)line.elementAt(j);
170                         
171                         // set the FONT
172
Font my_font = getTextAttributeFont(element);
173                         og.setFont(my_font);
174                         
175                         // set the foreground COLOR
176
og.setColor(getTextAttributeColor(element));
177                         
178                         FontMetrics my_fm = og.getFontMetrics(my_font);
179                         
180                         // finally, draw the string
181
og.drawString(element.getText(), x, y);
182                         x += my_fm.stringWidth(element.getText());
183                         error_count = 0;
184                     }
185                     catch (ArrayIndexOutOfBoundsException JavaDoc ex1)
186                     {
187                         // Old Netscape 4 browser has this weird problem
188
error_count++;
189                         
190                         if (error_count < 3)
191                         {
192                             // sleep for a tiny amount of time (wait for netscape to have the Vector
193
// setup properly)
194
try
195                             {
196                                 Thread.sleep(50);
197                             }
198                             catch (InterruptedException JavaDoc ex2)
199                             {
200                             }
201                             
202                             j--;
203                             continue;
204                         }
205                         else // give up
206
{
207                             error_count = 0;
208                             continue;
209                         }
210                     }
211                 }
212             }
213             
214             g.drawImage(img, 0, 0, null);
215         }
216         catch (Exception JavaDoc ex)
217         {
218             // windows 98 throws unexpected exceptions, just ignore it
219
}
220     }
221     
222     private Font getTextAttributeFont(TextAttribute element)
223     {
224         Font my_font = null;
225         if (element.getStyle() != -1)
226         {
227             // if a style is specified
228
my_font = new Font(font.getName(),
229             element.getStyle(), font.getSize());
230         }
231         else
232         {
233             my_font = font;
234         }
235         
236         return my_font;
237     }
238     
239     private Color getTextAttributeColor(TextAttribute element)
240     {
241         Color my_color = null;
242         if (element.getColor() != null)
243         {
244             my_color = element.getColor();
245         }
246         else
247         {
248             my_color = foregroundColor;
249         }
250         
251         return my_color;
252     }
253     
254     private void addTextToDisplayList(String JavaDoc text,
255     Color color, int style,
256     boolean new_line)
257     {
258         Vector line = null;
259         if (new_line == true)
260         {
261             // add a new element to the vector
262
line = new Vector();
263             displayList.addElement(line);
264         }
265         else
266         {
267             // get the last line
268
line = (Vector)displayList.elementAt(displayList.size() - 1);
269         }
270         
271         TextAttribute element = new TextAttribute(style, color, text);
272         line.addElement(element);
273     }
274     
275     private void addNewLineToTextSegment()
276     {
277         displayList.addElement(new Vector());
278     }
279     
280     private void addTextSegment(String JavaDoc text, Color color, int style)
281     {
282         Vector last_line = (Vector)displayList.elementAt(displayList.size() - 1);
283         
284         // go through the elements of the last line to see where the current x-coordinate is
285
int x = 0;
286         int num_elements = last_line.size();
287         for (int i = 0; i < num_elements; i++)
288         {
289             TextAttribute attr = (TextAttribute)last_line.elementAt(i);
290             Font f = getTextAttributeFont(attr);
291             FontMetrics fm = getGraphics().getFontMetrics(f);
292             x += fm.stringWidth(attr.getText());
293         }
294         
295         //get the screen width
296
int screen_width = getBounds().width;
297         if (screen_width == 0)
298         {
299             return;
300         }
301         
302         int cont_char_width = getGraphics().getFontMetrics(font).charWidth('-');
303         
304         // pre-process the text
305
Vector lines = preProcessText(text);
306         int num_lines = lines.size();
307         
308         boolean new_line = false;
309         for (int i = 0; i < num_lines; i++)
310         {
311 // System.out.println("Line " + i);
312
String JavaDoc line = (String JavaDoc)lines.elementAt(i);
313             int beg_index = 0;
314             int end_index = line.length();
315             
316             if (end_index > 0) // not a blank line
317
{
318                 String JavaDoc line_segment = null;
319                 boolean fits = true;
320                 boolean hyphen = false;
321                 while (beg_index < end_index) // wrap-around loop
322
{
323                     line_segment = line.substring(beg_index, end_index);
324 // System.out.println("Line segment: " + line_segment);
325

326                     TextAttribute tattr = new TextAttribute(style, color, line_segment);
327                     Font f = getTextAttributeFont(tattr);
328                     FontMetrics fm = getGraphics().getFontMetrics(f);
329                     
330                     // check if the segment fits in the current line
331
if ((x + fm.stringWidth(line_segment) + cont_char_width) < screen_width) // fits
332
{
333                         addTextToDisplayList(line_segment, color, style, new_line);
334                         x += fm.stringWidth(line_segment);
335                         
336                         beg_index = end_index;
337                         end_index = line.length();
338                         
339                         // check if it requires a new line
340
if (beg_index <= end_index)
341                         {
342                             // was not fitting below but now it fits,
343
// that means a new line must be added for
344
// wrapping around
345
if (fits == false)
346                             {
347                                 if (hyphen == true)
348                                 {
349                                     addTextToDisplayList("-",
350                                     foregroundColor, Font.PLAIN, false);
351                                     hyphen = false;
352                                     
353                                     addTextToDisplayList(" ", color, style, true);
354                                     x = fm.stringWidth(" ");
355                                     new_line = false;
356                                 }
357                                 else
358                                 {
359                                     x = 0;
360                                     new_line = true;
361                                 }
362                             }
363                         }
364                         
365                         fits = true;
366                     }
367                     else // does not fit
368
{
369                         if (hyphen == false)
370                         {
371                             // for word wrapping, go back to the previous blank space character
372
int saved_index = end_index;
373                             int j = 0;
374                             
375                             for (j = line_segment.length() - 1; j >= 0; j--, end_index--)
376                             {
377                                 if (line_segment.charAt(j) == ' ')
378                                 {
379                                     end_index--;
380                                     break;
381                                 }
382                             }
383                             
384                             if (j < 0) // no blank character found
385
{
386                                 end_index = saved_index;
387                                 hyphen = true;
388                             }
389                         }
390                         
391                         if (hyphen == true)
392                         {
393                             end_index--;
394                         }
395                         
396                         fits = false;
397                     }
398                     
399                 } // wrap-around loop
400

401                 x = 0;
402                 new_line = true;
403                 
404 // if (fits == false)
405
// {
406
// i--;
407
// }
408
}
409             else // a blank line
410
{
411                 addNewLineToTextSegment();
412             }
413         }
414     }
415     
416     private Vector preProcessText(String JavaDoc text)
417     {
418         char[] array = text.toCharArray();
419         Vector v = new Vector();
420         
421         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
422         for (int i = 0; i < array.length; i++)
423         {
424             switch (array[i])
425             {
426                 case '\t':
427                     buf.append("\b\b\b\b\b\b\b\b");
428                     break;
429                     
430                 case '\r':
431                     v.addElement(buf.toString());
432                     buf = new StringBuffer JavaDoc();
433                     
434                     if (i < array.length - 1)
435                     {
436                         if (array[i+1] == '\n')
437                         {
438                             i++;
439                         }
440                     }
441                     break;
442                     
443                 case '\n':
444                     v.addElement(buf.toString());
445                     buf = new StringBuffer JavaDoc();
446                     break;
447                     
448                 default:
449                     buf.append(array[i]);
450                     break;
451             }
452         }
453         
454         v.addElement(buf.toString());
455         return v;
456     }
457     
458     public void clearText()
459     {
460         displayList.removeAllElements();
461         displayList.addElement(new Vector());
462         
463         textList.removeAllElements();
464         
465         Graphics g = getGraphics();
466         if (g != null)
467         {
468             paint(g);
469         }
470     }
471     
472     public void addText(String JavaDoc text, Color color, int style)
473     {
474         //System.out.println("In addText()");
475
// add the element to the text list
476
textList.addElement(new TextAttribute(style, color, text));
477         
478         // add it to the list
479
addTextSegment(text, color, style);
480         
481         // adjust the scroll-bar
482
adjustBar();
483         
484         Graphics g = getGraphics();
485         if (g != null)
486         {
487             paint(g);
488         }
489     }
490     
491     private void componentResized()
492     {
493         displayList = new Vector();
494         displayList.addElement(new Vector());
495         
496         int size = textList.size();
497         for (int i = 0; i < size; i++)
498         {
499             // add it to the list
500
TextAttribute attr = (TextAttribute)textList.elementAt(i);
501             addTextSegment(attr.getText(),
502             attr.getColor(),
503             attr.getStyle());
504         }
505         
506         adjustBar();
507         
508         Graphics g = getGraphics();
509         if (g != null)
510         {
511             paint(g);
512         }
513     }
514     
515     private void initializeBar()
516     {
517         // first calculate the number of lines that can be displayed on the screen
518
int num_lines = getBounds().height / getGraphics().getFontMetrics().getHeight();
519         
520         bar.setValues(0, num_lines, 0, num_lines);
521         bar.setBlockIncrement(num_lines);
522         bar.setUnitIncrement(1);
523         
524         barInitialized = true;
525     }
526     
527     private void adjustBar()
528     {
529         int num_lines = getBounds().height / getGraphics().getFontMetrics().getHeight();
530         int size = displayList.size();
531         
532         // if the number of lines is less than the number of lines that will fit in
533
// the screen, set it to that value
534
int max = size < num_lines ? num_lines : size;
535         bar.setValues(max - num_lines,
536         num_lines,
537         0,
538         max);
539         
540         bar.setBlockIncrement(num_lines);
541         
542     }
543     
544     public String JavaDoc getText()
545     {
546         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
547         
548         int size = textList.size();
549         for (int i = 0; i < size; i++)
550         {
551             TextAttribute attribute = (TextAttribute)textList.elementAt(i);
552             buffer.append(attribute.getText());
553         }
554         
555         return buffer.toString();
556     }
557     
558     class CanvasComponentListener implements ComponentListener
559     {
560         public void componentHidden(ComponentEvent e)
561         {
562         }
563         
564         public void componentMoved(java.awt.event.ComponentEvent JavaDoc componentEvent)
565         {
566         }
567         
568         public void componentResized(java.awt.event.ComponentEvent JavaDoc componentEvent)
569         {
570             //System.out.println("Action Listener: Component resized");
571
RichTextCanvas.this.componentResized();
572         }
573         
574         public void componentShown(java.awt.event.ComponentEvent JavaDoc componentEvent)
575         {
576         }
577     }
578     
579     class BarListener implements AdjustmentListener
580     {
581         public void adjustmentValueChanged(java.awt.event.AdjustmentEvent JavaDoc adjustmentEvent)
582         {
583             paint(getGraphics());
584         }
585     }
586     
587     private static final int DEFAULT_NUM_ROWS = 5;
588     private static final int DEFAULT_NUM_COLUMNS = 60;
589     private static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12);
590     private static final Color DEFAULT_FOREGROUND_COLOR = Color.black;
591     private static final Color DEFAULT_BACKGROUND_COLOR = Color.white;
592     
593     private Font font;
594     private Color foregroundColor;
595     private Color backgroundColor;
596     private int defaultRows;
597     private int defaultColumns;
598     
599     private Vector textList = new Vector();
600     private Vector displayList = new Vector();
601     private Scrollbar bar;
602     private boolean barInitialized = false;
603 }
604
Popular Tags