Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/memoire/bu/BuAutoStyledDocument.java


1   /**
2    * @modification $Date: 2002/12/16 18:56:24 $
3    * @statut       unstable
4    * @file         BuAutoStyledDocument.java
5    * @version      0.36
6    * @author       Guillaume Desnoix
7    * @email        guillaume@desnoix.com
8    * @license      GNU General Public License 2 (GPL2)
9    * @copyright    1998-2001 Guillaume Desnoix
10   */
11  
12  package com.memoire.bu;
13  
14  import com.memoire.bu.*;
15  import com.memoire.dnd.*;
16  import com.memoire.fu.*;
17  import com.memoire.re.*;
18  
19  
20  import java.awt.*;
21  import java.io.*;
22  import java.util.*;
23  
24  import javax.swing.*;
25  import javax.swing.text.*;
26  
27  /**
28   * A auto-colorized document (using regular expressions).
29   */
30  public class BuAutoStyledDocument
31      extends DefaultStyledDocument
32  {
33    public static final String KEYWORD ="KEYWORD";
34    public static final String MODIFIER="MODIFIER";
35    public static final String TYPE    ="TYPE";
36    public static final String SPECIAL ="SPECIAL";
37    public static final String OPERATOR="OPERATOR";
38    public static final String BLOCK   ="BLOCK";
39    public static final String NUMBER  ="NUMBER";
40    public static final String COMMENT ="COMMENT";
41    public static final String PRAGMA  ="PRAGMA";
42    public static final String STRING  ="STRING";
43  
44    /*
45     * A faire: n'utiliser regexp que qd c'est necessaire.
46     * TYPE:STYLE
47     * boolean: replace is different than find if
48     * indexes are not the same.
49     */
50  
51    public static final byte IS_KEYWORD         =1;
52    public static final byte IS_SIMPLE_STRING   =2;
53    public static final byte IS_SIMPLE_CHAR     =3;
54    public static final byte IS_ONELINE_REGEXP  =4;
55    public static final byte IS_MULTILINE_REGEXP=5;
56  
57    private class Key
58    {
59      public String  match;
60      public String  replace;
61      public String  style;
62      public byte    type;
63      public RE      regexp_match;
64      public RE      regexp_replace;
65  
66      Key(String _match,String _replace, String _style, byte _type)
67      {
68        match  =_match;
69        replace=_replace;
70        style  =_style;
71        type   =_type;
72  
73        /*
74    if(  (type==IS_ONELINE_REGEXP)
75     ||(type==IS_MULTILINE_REGEXP))
76        */
77        {
78    try
79    {
80      regexp_match=new RE(match,RE.REG_MULTILINE,
81              RESyntax.RE_SYNTAX_PERL5);
82      regexp_replace=new RE(replace,RE.REG_MULTILINE,
83          RESyntax.RE_SYNTAX_PERL5);
84  
85      while(keys_.contains(this))
86        keys_.removeElement(this);
87  
88      keys_.addElement(this);
89    }
90    catch(REException ex)
91    {
92      System.err.println("Bad regular exception\n  "+match+"\n  "+replace);
93    }
94        }
95      }
96  
97      public boolean equals(Object _ok)
98      {
99        boolean r=false;
100 
101       if(_ok instanceof Key)
102       {
103   Key k=(Key)_ok;
104   r=(match.equals(k.match)&&replace.equals(k.replace));
105       }
106 
107       return r;
108     }
109   }
110 
111   public Key createKey(String _match,String _replace,String _style)
112     { return new Key(_match,_replace,_style,IS_MULTILINE_REGEXP); }
113 
114   public Key createKey(String _match,String _style)
115     { return createKey(_match,_match,_style); }
116 
117   public Key createKeyword(String _word,String _style)
118   {
119     return createKey("(^|[^a-zA-Z0-9_])"+_word+"($|[^a-zA-Z0-9_])",
120          _word,_style);
121   }
122 
123   public Key createKeyword(String _word)
124   {
125     return createKeyword(_word,KEYWORD);
126   }
127 
128   private Vector keys_;
129 
130   public BuAutoStyledDocument(String _text)
131   {
132     this(_text,null);
133   }
134 
135   public BuAutoStyledDocument(String _text, String _syntax)
136   {
137     this();
138     if(_syntax!=null) setSyntax(_syntax);
139     try { insertString(0,_text,null); }
140     catch(BadLocationException ex) { ex.printStackTrace(); }
141   }
142 
143   public BuAutoStyledDocument()
144   {
145     super(new StyleContext());
146     ta_  =null;
147     keys_=new Vector();
148 
149     createStyle(KEYWORD ,null                ,true ,false);
150     createStyle(TYPE    ,new Color(0,128,  0),false,false);
151     createStyle(MODIFIER,new Color(0,128,128),false,false);
152     createStyle(SPECIAL ,new Color(128,128,0),false,true );
153     createStyle(OPERATOR,new Color(192, 96,0),true ,false);
154     createStyle(BLOCK   ,Color.red           ,false,false);
155     createStyle(NUMBER  ,Color.blue          ,false,false);
156     createStyle(COMMENT ,new Color(64,64,160),false,true );
157     createStyle(PRAGMA  ,new Color(160,0,160),false,true );
158     createStyle(STRING  ,Color.magenta       ,false,false);
159 
160 //      createKey("(^|[^a-zA-Z0-9_.])[0-9]*\\.[0-9]*[df]?($|[^a-zA-Z0-9_.])",
161 //               "[0-9]*\\.[0-9]*[df]?",
162 //          NUMBER);
163 //      createKey("(^|[^a-zA-Z0-9_])[0-9][0-9]*[l]?($|[^a-zA-Z0-9_])",
164 //          "[0-9][0-9]*[l]?",
165 //          NUMBER);
166 //      createKeyword("hello");
167 //      createKeyword("world");
168 //      createKeyword("this" );
169 //      createKeyword("super");
170 //      createKey("\\{"           ,BLOCK);
171 //      createKey("\\}"           ,BLOCK);
172 //      createKey("\\("           ,BLOCK);
173 //      createKey("\\)"           ,BLOCK);
174 //      createKey("\"[^\"]*\""    ,STRING);
175 //      createKey("\'[^\']*\'"    ,STRING);
176 //      createKey("/\\*[^/*]*\\*/",COMMENT);
177 //      createKey("//.*$"         ,COMMENT);
178 
179     setColorized(true);
180   }
181 
182   public Style createStyle(String _name,Color _fg,
183          boolean _bold,boolean _italic)
184   {
185     Style style=((StyleContext)getAttributeContext()).addStyle(_name,null);
186     if(_fg!=null) style.addAttribute(StyleConstants.Foreground,_fg);
187     if(_bold    ) style.addAttribute(StyleConstants.Bold      ,Boolean.TRUE);
188     if(_italic  ) style.addAttribute(StyleConstants.Italic    ,Boolean.TRUE);
189     return style;
190   }
191 
192   public void loadSyntax(String _language)
193        throws IOException
194   {
195     LineNumberReader lnr=new LineNumberReader
196       (new InputStreamReader
197        (getClass().getResourceAsStream(_language+"Syntax.txt")));
198 
199     String l;
200     while(true)
201     {
202       l=lnr.readLine();
203       if(l==null) return;
204       if("".equals(l)) continue;
205 
206       if("INHERIT".equals(l))
207       {
208   String f=lnr.readLine();
209   System.err.println("load parent syntax: "+f);
210   loadSyntax(f);
211       }
212       if("KEY".equals(l))
213       {
214   String m=lnr.readLine();
215   String r=lnr.readLine();
216   String s=lnr.readLine();
217   createKey(m,r,s);
218       }
219       if(  "OPERATOR".equals(l)
220    ||"BLOCK"   .equals(l)
221    ||"STRING"  .equals(l)
222    ||"COMMENT" .equals(l))
223       {
224   String s=l;
225   while(true)
226   {
227     l=lnr.readLine();
228     if(l==null) return;
229     if("".equals(l)) break;
230     createKey(l,s);
231   }
232       }
233       else
234       {
235   String s=l;
236   while(true)
237   {
238     l=lnr.readLine();
239     if(l==null) return;
240     if("".equals(l)) break;
241     createKeyword(l,s);
242   }
243       }
244     }
245   }
246 
247   private BuTextPane ta_;
248 
249   public BuTextPane getTextPane()
250     { return ta_; }
251 
252   public void setTextPane(BuTextPane _ta)
253   {
254     ta_=_ta;
255     if(ta_!=null) ta_.repaint(0);
256   }
257 
258   private boolean colorized_=false;
259   public boolean isColorized() { return colorized_; }
260   public void setColorized(boolean _b) { colorized_=_b; }
261 
262   private String syntax_;
263   public String getSyntax() { return syntax_; }
264   public void setSyntax(String _syntax)
265   {
266     //System.err.println("set-syntax: "+_syntax);
267 
268     if((_syntax==null)||(!_syntax.equals(syntax_)))
269     {
270       syntax_=_syntax;
271 
272       keys_.removeAllElements();
273       try { loadSyntax(syntax_); }
274       catch(Exception ex)
275       {
276   System.err.println("syntax '"+_syntax+"' not available.");
277   //ex.printStackTrace();
278       }
279 
280       if(isColorized()) colorize();
281       else              uncolorize();
282     }
283   }
284 
285   private int getLineCount()
286   {
287     return getDefaultRootElement().getElementCount();
288   }
289   
290   private int getLineStartOffset(int _offset)
291   {
292     return getParagraphElement(_offset).getStartOffset();
293   }
294 
295   private int getLineEndOffset(int _offset)
296   {
297     return getParagraphElement(_offset).getEndOffset();
298   }
299 
300   /*
301   private int getLineStartOffset(int _offset)
302   {
303     int r=0;
304     try 
305     {
306       int n=getLineCount()-1;
307       int p=getLength();
308       while((p>=_offset)&&(n>=0))
309       {
310   p=getDefaultRootElement().getElement(n).getStartOffset();
311   n--;
312       }
313       r=p;
314     }
315     catch(Exception ex) { System.err.println(ex); }
316     // System.err.println("Start="+r);
317     return r;
318   }
319   */
320 
321   /*
322   private int getLineEndOffset(int _offset)
323   {
324     int r=getLength();
325     try
326     {
327       int nmax=getLineCount()-1;
328       int p=0;
329       int n=0;
330       while((p<_offset)&&(n<=nmax))
331       {
332   p=getDefaultRootElement().getElement(n).getEndOffset();
333   n++;
334       }
335       r=p;
336     }
337     catch(Exception ex) { System.err.println(ex); }
338     // System.err.println("End  ="+r);
339     return r;
340   }
341   */
342 
343   /*
344   public void setText(String _string)
345   {
346     try
347     {
348       super.remove(0,getLength());
349       super.insertString(0,_string,null);
350       // colorize();
351     }
352     catch(Exception ex) { }
353   }
354   */
355 
356   public void insertString(int _offset, String _string, AttributeSet _attr)
357        throws BadLocationException
358   {
359     if(_string!=null)
360     {
361       // replace tabs ?
362       //_string=BuPrinter.replace(_string,"\t","        ");
363       super.insertString(_offset,_string,_attr);
364 
365       if(_string.length()<120)
366       {
367   if(_string.indexOf('\n')>=0)
368     colorize(_offset,_string.length());
369       }
370 
371       if(_string.length()==1)
372   if((ta_!=null)&&(ta_.getDocument()==this))
373   {
374     try
375     {
376       Rectangle r=ta_.modelToView(ta_.getCaretPosition());
377       r.x=Math.max(0,r.x-10);
378       r.y=Math.max(0,r.y-10);
379       r.width =20;
380       r.height=20;
381       ta_.scrollRectToVisible(r);
382     }
383     catch(Exception ex) { }
384   }
385     }
386   }
387 
388   /*
389   public Dimension computePreferredSize()
390   {
391     Style fs=getStyle(StyleContext.DEFAULT_STYLE);
392     FontMetrics fm=ta_.getFontMetrics
393       (new Font(StyleConstants.getFontFamily(fs),
394     Font.PLAIN,
395     StyleConstants.getFontSize(fs)));
396     
397     int n=getDefaultRootElement().getElementCount();
398     int c=0;
399     for(int i=0;i<n;i++)
400     {
401       int start=getLineStartOffset(i);
402       int end  =getLineEndOffset(i);
403       c=Math.max(c,end-start+1);
404     }
405     int w=fm.stringWidth("m")*c;
406     int h=fm.getHeight()*n;
407 
408     return new Dimension(w,h);
409   }
410   */
411 
412   public void uncolorize()
413   {
414     try
415     {
416       String text=getText(0,getLength());
417       super.remove(0,getLength());
418       super.insertString(0,text,null);
419     }
420     catch(BadLocationException ex) { }
421   }
422 
423   public void colorize()
424   {
425     if(!colorized_) return;
426     __colorize(0,getLength());
427   }
428 
429   public void colorize(final int _start, final int _len)
430   {
431     if(!colorized_) return;
432 
433     //try
434     {
435       int start=getLineStartOffset(_start);
436       int end  =getLineEndOffset  (_start+_len);
437       //System.err.println("start="+start+",offset="+_start+",end="+end);
438       //try { System.err.println(getText(start,Math.max(0,end-start-1))); }
439       //catch(BadLocationException ex) { }
440       __colorize(start,Math.max(0,end-start-1));
441     }
442     //catch(BadLocationException ex)
443     //  { System.err.println("BAD LOC"); }
444 
445     /*
446     try
447     {
448       int start=getLineStartOffset(_start);
449       int len  =getText(start,80).indexOf('\n');
450       if((len<0)||(len<_len+_start-start)) len=_len+_start-start;
451       // System.err.println("start="+start+",offset="+_start+",len="+len);
452       // System.err.println(getText(start,len));
453       __colorize(start,len);
454     }
455     catch(BadLocationException ex) { }
456     */
457   }
458 
459   public void colorize(BuCommonInterface _app)
460   {
461     Colorizer t=new Colorizer(_app);
462     t.setPriority(Thread.MIN_PRIORITY);
463     t.start();
464   }
465 
466   class Colorizer extends BuTask
467   {
468     private BuCommonInterface app_;
469 
470     public Colorizer(BuCommonInterface _app)
471     {
472       super();
473       app_=_app;
474 
475       setName(BuResource.BU.getString("Coloration"));
476       if(app_!=null) setTaskView(app_.getMainPanel().getTaskView());
477     }
478 
479     public void start()
480     {
481       super.start();
482     }
483 
484     public void run()
485     {
486       boolean editable=false;
487 
488       // System.err.println("TA="+ta_);
489       setProgression(2);
490 
491       if(ta_!=null)
492       {
493   editable=ta_.isEditable();
494   ta_.setEditable(false);
495   ta_.setDocument(new BuAutoStyledDocument(ta_.getText()));
496   BuAutoStyledDocument.this.removeDocumentListener(ta_);
497   BuAutoStyledDocument.this.removeUndoableEditListener(ta_);
498       }
499 
500       boolean colorized=isColorized();
501       setColorized(true);
502       setProgression(5);
503 
504       try { __colorize(0,getLength()); }
505       catch(Exception ex) { }
506 
507       setColorized(colorized);
508       
509       if(ta_!=null)
510       {
511   setProgression(97);
512   ta_.setDocument(BuAutoStyledDocument.this);
513   BuAutoStyledDocument.this.addDocumentListener(ta_);
514   BuAutoStyledDocument.this.addUndoableEditListener(ta_);
515   ta_.setEditable(editable);
516       }
517 
518       setProgression(100);
519       super.run();
520     }
521   }
522 
523   private void __colorize(int _start, int _len)
524        // throws BadLocationException
525   {
526     String text;
527 
528     try { text=getText(_start,_len); }
529     catch(BadLocationException ex) { return; }
530 
531     int pos=0;
532     if(ta_!=null) pos=ta_.getCaretPosition();
533 
534     //System.err.println("Colorize ["+_start+","+(_start+_len)+"]");
535     //System.err.println("Text="+text);
536 
537     try
538     {
539       super.remove(_start,_len);
540       super.insertString(_start,text,null);
541     }
542     catch(BadLocationException ex)
543     {
544       System.err.println("BuAutoStyledDocument: bad location 1");
545       return;
546     }
547     
548     int l=keys_.size();
549     for(int i=0;i<l;i++)
550     {
551       Thread t=Thread.currentThread();
552       if(t instanceof Colorizer)
553   ((Colorizer)t).setProgression(5+90*i/l);
554 
555       // System.err.print("\r"+(100*i/keys_.size())+"%");
556       
557       Key key=(Key)keys_.elementAt(i);
558       try
559       {
560   if(key.regexp_match==null)
561   {
562     System.err.println("Bad regular expression: "+key.match);
563     break;
564   }
565 
566   if(key.regexp_replace==null)
567   {
568     System.err.println("Bad regular expression: "+key.replace);
569     break;
570   }
571 
572   REMatch mm;
573   int     p=0;
574   int     q=0;
575 
576   while((mm=key.regexp_match.getMatch(text,p))!=null)
577   {
578     String oldtext=text.substring(mm.getStartIndex(),
579           mm.getEndIndex  ());
580 
581     REMatch mr=key.regexp_replace.getMatch(oldtext);
582 
583     /*
584     q++;
585     if(q==500)
586     {
587       System.err.println("MAYBE LOOP : AUTOSTYLED");
588       System.err.println
589         ("ERROR COLORIZE: MATCH "+key.match);
590       System.err.println
591         ("              : REPL. "+key.replace);
592       System.err.println
593         ("              : "+oldtext);
594       break;
595     }
596     */
597 
598     if(mr==null)
599     {
600       System.err.println("MR=NULL : AUTOSTYLED");
601       System.err.println
602         ("ERROR COLORIZE: MATCH "+key.match);
603       System.err.println
604         ("              : REPL. "+key.replace);
605       System.err.println
606         ("              : "+oldtext);
607       break;
608     }
609 
610     String newtext=oldtext.substring(mr.getStartIndex(),
611              mr.getEndIndex  ());
612 
613     /*
614     if(oldtext.equals(newtext))
615     {
616       System.err.println("SAMETEXT : AUTOSTYLED");
617       System.err.println
618         ("ERROR COLORIZE: MATCH "+key.match);
619       System.err.println
620         ("              : REPL. "+key.replace);
621       System.err.println
622         ("              : "+oldtext);
623       break;
624     }
625     */
626 
627     int si=_start+mm.getStartIndex()+mr.getStartIndex();
628     int ei=_start+mm.getStartIndex()+mr.getEndIndex  ();
629 
630     super.remove(si,ei-si);
631     super.insertString(si,newtext,getStyle(key.style));
632 
633     p=mm.getStartIndex()+mr.getStartIndex()+newtext.length();
634   }
635       }
636       catch(BadLocationException ex)
637   { System.err.println("BuAutoStyledDocument: bad location 2"); }
638       catch(Error ex)
639   { System.err.println(""+ex); }
640     }
641 
642     if(ta_!=null)
643     {
644       ta_.setCaretPosition(pos);
645       ta_.repaint(0);
646     }
647   }
648 
649   public void remove(int _start, int _len)
650        throws BadLocationException
651   {
652     super.remove(_start,_len);
653     colorize(_start,0);
654   }
655 }
656