KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > gui > swing > SHEditor


1
2 package org.objectweb.jac.aspects.gui.swing;
3
4 import java.awt.Color JavaDoc;
5 import java.awt.Cursor JavaDoc;
6 import java.awt.Dimension JavaDoc;
7 import java.awt.Font JavaDoc;
8 import java.awt.FontMetrics JavaDoc;
9 import java.awt.Graphics JavaDoc;
10 import java.awt.Rectangle JavaDoc;
11 import java.awt.datatransfer.Clipboard JavaDoc;
12 import java.awt.datatransfer.ClipboardOwner JavaDoc;
13 import java.awt.datatransfer.DataFlavor JavaDoc;
14 import java.awt.datatransfer.StringSelection JavaDoc;
15 import java.awt.datatransfer.Transferable JavaDoc;
16 import java.awt.event.FocusEvent JavaDoc;
17 import java.awt.event.FocusListener JavaDoc;
18 import java.awt.event.KeyEvent JavaDoc;
19 import java.awt.event.KeyListener JavaDoc;
20 import java.awt.event.MouseEvent JavaDoc;
21 import java.awt.event.MouseListener JavaDoc;
22 import java.awt.event.MouseMotionListener JavaDoc;
23 import java.awt.event.TextEvent JavaDoc;
24 import java.awt.event.TextListener JavaDoc;
25 import java.io.BufferedInputStream JavaDoc;
26 import java.io.BufferedReader JavaDoc;
27 import java.io.File JavaDoc;
28 import java.io.FileInputStream JavaDoc;
29 import java.io.FileWriter JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.InputStreamReader JavaDoc;
32 import java.io.PrintWriter JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.Vector JavaDoc;
36 import javax.swing.JPanel JavaDoc;
37 import javax.swing.JScrollBar JavaDoc;
38 import javax.swing.JScrollPane JavaDoc;
39 import javax.swing.JViewport JavaDoc;
40 import javax.swing.Scrollable JavaDoc;
41 import javax.swing.SwingConstants JavaDoc;
42 import javax.swing.event.CaretEvent JavaDoc;
43 import javax.swing.event.CaretListener JavaDoc;
44 import org.apache.log4j.Logger;
45 import org.objectweb.jac.util.Strings;
46
47 /**
48  * @author Lars-Erik H. Bergland <a
49 //href="http://www.mycgiserver.com/~hbergla/">www.mycgiserver.com/~hbergla</a>
50 //<a
51 //href="mailto:vagastorm@microsnyft.com">vagastorm@microsnyft.com</a>
52  * @version 1.0
53  *
54  * The CodeEditor is constructed to display java code with syntax
55  * coloring. It was created to be used in the <a
56  * HREF="http://www.mycgiserver.com/~hbergla/SimpleJavaEditor/about.html">SimpleJavaEditor</a>
57  * but it can easily be adjusted so it can be used with any SWING
58  * application that needs to display syntax colored java code. Please
59  * use it in any leagal way you whant, but if you find it usefull tell
60  * me aboute it, along with any wishes you migt have for changes and
61  * I'll see what I can do. */

62
63 public class SHEditor extends JPanel JavaDoc
64     implements KeyListener JavaDoc, MouseListener JavaDoc, MouseMotionListener JavaDoc,
65               Scrollable JavaDoc, ClipboardOwner JavaDoc, FocusListener JavaDoc
66 {
67     static Logger logger = Logger.getLogger("gui.sheditor");
68     static Logger loggerComp = Logger.getLogger("completion");
69     static Logger loggerClip = Logger.getLogger("clipboard");
70
71     private String JavaDoc text = "";
72     private FontMetrics JavaDoc metrics;
73     int lineHeight; // height of line of text
74

75     private int caretPosition = 0;
76     private int selectionStart = 0;
77     private int selectionEnd = 0;
78     /** Whether the selection is some text added by the completion engine */
79     protected boolean isSelectionCompletion = false;
80     
81     /** position of opening char ('(','{' or '[') to highlight */
82     private int openPos = -1;
83     /** position of closing char (')','}' or ']') to highlight */
84     private int closePos = -1;
85    
86     private int lineToMark = -1;
87    
88     private boolean showCaret = true;
89    
90     protected SHEditorConfig conf = new SHEditorConfig();
91     public SHEditorConfig getConfig() {
92         return conf;
93     }
94     public void setConfig(SHEditorConfig conf) {
95         this.conf = conf;
96     }
97     
98     public static final int DEFAULT = 0;
99     public static final int COMMENT = 1;
100     public static final int STRING = 2;
101
102     protected int syntaxUnderCaret;
103     public int getSyntaxUnderCaret() {
104         return syntaxUnderCaret;
105     }
106
107     private int mousePressPos = 0;
108    
109     private Vector JavaDoc doneActions = new Vector JavaDoc();
110     private Vector JavaDoc redoneActions = new Vector JavaDoc();
111    
112     private Rectangle JavaDoc car = new Rectangle JavaDoc(0, 0, 2, 0);
113    
114     boolean changed = false;
115
116     private char separators[] = new char[] {
117         '\n', ' ', '.' , ',', '(', ')', '{', '}', '[', ']', '/', '-', '+', '*',
118         '<', '>', '=', ';', '"', '\'', '&', '|', '!'
119     };
120
121     /**
122      * Sets the characters considered as word separators
123      */

124     public void setWordSeparators(char[] separators) {
125         this.separators = separators;
126     }
127
128     /**
129      * Constructs a empty SHEditor.
130      */

131     public SHEditor()
132     {
133         super();
134       
135         setFont(new Font JavaDoc("MonoSpaced", Font.PLAIN, 12));
136         metrics = getFontMetrics(getFont());
137         setCursor(new Cursor JavaDoc(Cursor.TEXT_CURSOR));
138         addKeyListener(this);
139         addMouseListener(this);
140         addMouseMotionListener(this);
141         addFocusListener(this);
142         if (org.objectweb.jac.core.Jac.getMainJavaVersion().compareTo("1.4")>=0) {
143             setFocusTraversalKeysEnabled(false);
144         }
145         setBackground(Color.white);
146     }
147
148     /**
149      * Constructs a SHEditor where the content is set by a string.
150      * @param txt A String representing initial java file.
151      */

152     public SHEditor(String JavaDoc txt)
153     {
154         this();
155         text = txt;
156     }
157
158     /**
159      * Constructs a SHEditor and reads the content of a file into it.
160      * @param file The initial java file.
161      */

162     public SHEditor(File JavaDoc file)
163     {
164         this();
165         readFromFile(file);
166     }
167
168     Vector JavaDoc caretListeners = new Vector JavaDoc();
169     /**
170      * Adds a caret listener for notification of any changes
171      * to the caret.
172      *
173      * @param listener the listener to be added
174      * @see javax.swing.event.CaretEvent
175      */

176     public void addCaretListener(CaretListener JavaDoc listener) {
177         caretListeners.add(listener);
178     }
179    
180     /**
181      * Removes a caret listener.
182      *
183      * @param listener the listener to be removed
184      * @see javax.swing.event.CaretEvent
185      */

186     public void removeCaretListener(CaretListener JavaDoc listener) {
187         caretListeners.remove(listener);
188     }
189
190     protected void fireCaretUpdate() {
191         CaretEvent JavaDoc e = new MutableCaretEvent(this,caretPosition);
192         for (int i = caretListeners.size()-1; i>=0; i--) {
193             ((CaretListener JavaDoc)textListeners.get(i)).caretUpdate(e);
194         }
195     }
196
197     Vector JavaDoc textListeners = new Vector JavaDoc();
198
199     /**
200      * Adds a text listener for notification of any changes
201      * to the text.
202      *
203      * @param listener the listener to be added
204      * @see javax.swing.event.CaretEvent
205      */

206     public void addTextListener(TextListener JavaDoc listener) {
207         textListeners.add(listener);
208     }
209    
210     /**
211      * Removes a text listener.
212      *
213      * @param listener the listener to be removed
214      * @see javax.swing.event.CaretEvent
215      */

216     public void removeTextListener(TextListener JavaDoc listener) {
217         textListeners.remove(listener);
218     }
219
220     protected void fireTextUpdate() {
221         TextEvent JavaDoc e = new TextEvent JavaDoc(this,TextEvent.TEXT_VALUE_CHANGED);
222         for (int i = textListeners.size()-1; i>=0; i--) {
223             ((TextListener JavaDoc)textListeners.get(i)).textValueChanged(e);
224         }
225     }
226
227     /**
228      * Returns the a String containing the java file.
229      * @return A string containing the content of the current java file.
230      */

231     public String JavaDoc getText()
232     {
233         return text;
234     }
235
236     public void setText(String JavaDoc t) {
237         text=t;
238         fireTextUpdate();
239     }
240
241     /**
242      * Tells wether the caret is at the end of the text
243      */

244     boolean eot() {
245         return caretPosition >= text.length();
246     }
247
248     /**
249      * Tells wether the caret is at the end of the selection
250      */

251     boolean endOfSelection() {
252         return caretPosition == selectionEnd;
253     }
254
255     /**
256      * Tells wether the caret is at the start of the selection
257      */

258     boolean startOfSelection() {
259         return caretPosition == selectionStart;
260     }
261
262     /**
263      * Sets the start of the selection. It ensures that selectionStart<selectionEnd.
264      * @param position new start of selection
265      */

266     public void setSelectionStart(int position) {
267         if (position>selectionEnd) {
268             int oldStart = selectionStart;
269             selectionStart = selectionEnd;
270             selectionEnd = position;
271             repaintChars(selectionStart,position);
272         } else {
273             repaintChars(selectionStart,position);
274             selectionStart = position;
275         }
276     }
277
278     /**
279      * Sets the end of the selection. It ensures that selectionStart<selectionEnd.
280      * @param position new end of selection
281      */

282     public void setSelectionEnd(int position) {
283         if (position<selectionStart) {
284             int oldEnd = selectionEnd;
285             selectionEnd = selectionStart;
286             selectionStart = position;
287             repaintChars(selectionEnd,position);
288         } else {
289             repaintChars(selectionEnd,position);
290             selectionEnd = position;
291         }
292     }
293
294     /**
295      * Sets the selection
296      * @param start position where selection starts
297      * @param end position where selection ends
298      */

299     public void setSelection(int start, int end) {
300         int oldStart = selectionStart;
301         int oldEnd = selectionEnd;
302         if (start<=end) {
303             selectionStart = start;
304             selectionEnd = end;
305         } else {
306             selectionStart = end;
307             selectionEnd = start;
308         }
309         repaintChars(oldStart,oldEnd);
310         repaintChars(selectionStart,selectionEnd);
311     }
312
313     /**
314      * Updates the selection after a backward move
315      * @param select wether the move was a selecting one
316      */

317     void backwardMove(boolean select) {
318         if (select) {
319             if (caretPosition<selectionStart)
320                 setSelectionStart(caretPosition);
321             else
322                 setSelectionEnd(caretPosition);
323         } else {
324             resetSelection();
325         }
326     }
327
328     /**
329      * Updates the selection after a backward move
330      * @param select wether the move was a selecting one
331      */

332     void forwardMove(boolean select) {
333         if (select) {
334             if (caretPosition>selectionEnd)
335                 setSelectionEnd(caretPosition);
336             else
337                 setSelectionStart(caretPosition);
338         } else {
339             resetSelection();
340         }
341     }
342
343     /**
344      * Moves forward n characters
345      * @param n number of characters to move forward
346      * @param select wether to add the text moved over by the caret to
347      * the selection
348      */

349     public void forwardChar(int n, boolean select) {
350         setCaretPosition(caretPosition + n);
351         forwardMove(select);
352         positionVisible();
353     }
354     
355     /**
356      * Moves backward n characters
357      * @param n number of characters to move backward
358      * @param select wether to add the text moved over by the caret to
359      * the selection
360      */

361     public void backwardChar(int n, boolean select) {
362         setCaretPosition(caretPosition - n);
363         backwardMove(select);
364         positionVisible();
365     }
366
367     /**
368      * Moves forward n words
369      * @param n number of words to move forward
370      * @param select wether to add the text moved over by the caret to
371      * the selection
372      */

373     public void forwardWord(int n, boolean select) {
374         boolean endOfSelection = endOfSelection();
375         int newPos = caretPosition;
376         while(!eot() && isDivider(text.charAt(newPos))) {
377             newPos++;
378         }
379         for (; n>0; n--) {
380             while(!eot() && !isDivider(text.charAt(newPos))) {
381                 newPos++;
382             }
383         }
384         setCaretPosition(newPos);
385         forwardMove(select);
386         positionVisible();
387     }
388
389     /**
390      * Moves backward n words
391      * @param n number of words to move backward
392      * @param select wether to add the text moved over by the caret to
393      * the selection
394      */

395     public void backwardWord(int n, boolean select) {
396         int newPos = caretPosition;
397         if (newPos>0) {
398             newPos--;
399         }
400         while (newPos>0 && isDivider(text.charAt(newPos))) {
401             newPos--;
402         }
403         for (; n>0; n--) {
404             while(newPos>0 && !isDivider(text.charAt(newPos))) {
405                 newPos--;
406             }
407         }
408         if (!eot() && newPos>0)
409             newPos++;
410         setCaretPosition(newPos);
411         backwardMove(select);
412         positionVisible();
413     }
414
415     /**
416      * Move to the next line
417      * @param n move to previous line n times
418      * @param select wether to add the text moved over by the caret to
419      * the selection
420      */

421     public void nextLine(int n, boolean select)
422     {
423         boolean moved = false;
424         int newPos = caretPosition;
425         for (; n>0; n--) {
426             int posInLine = getPosInLine(newPos);
427             int nextLineStart = text.indexOf('\n', newPos);
428             if (nextLineStart != -1)
429             {
430                 nextLineStart ++;
431                 int i = 0;
432                 while(i < posInLine && i + nextLineStart < text.length() &&
433                       text.charAt(i + nextLineStart) != '\n')
434                 {
435                     i ++;
436                 }
437                 if ((nextLineStart+i) >newPos)
438                     moved = true;
439                 newPos = nextLineStart + i;
440             }
441         }
442         if (moved) {
443             setCaretPosition(newPos);
444             forwardMove(select);
445         }
446
447         positionVisible();
448     }
449
450     /**
451      * Move to the previous line
452      * @param n move to previous line n times
453      * @param select wether to add the text moved over by the caret to
454      * the selection
455      */

456     public void previousLine(int n, boolean select)
457     {
458         boolean moved = false;
459         int newPos = caretPosition;
460         for (; n>0; n--) {
461             int posInLine = getPosInLine(newPos);
462             int prevLineStart =
463                 text.lastIndexOf('\n', newPos - posInLine - 2) + 1;
464             int i = 0;
465             while(i < posInLine && i + prevLineStart < text.length() &&
466                   text.charAt(i + prevLineStart) != '\n')
467             {
468                 i ++;
469             }
470             if (prevLineStart+i<newPos)
471                 moved = true;
472             newPos = prevLineStart+i;
473         }
474         if (moved) {
475             setCaretPosition(newPos);
476             backwardMove(select);
477         }
478
479         positionVisible();
480     }
481
482     /**
483      * Moves the caret to the beginning of the text.
484      * @param select wether to add the text moved over by the caret to
485      * the selection
486      */

487     public void beginningOfText(boolean select)
488     {
489         setCaretPosition(0);
490         backwardMove(select);
491         positionVisible();
492     }
493
494
495     /**
496      * Moves the caret to the end of the text.
497      * @param select wether to add the text moved over by the caret to
498      * the selection
499      */

500     public void endOfText(boolean select)
501     {
502         setCaretPosition(text.length());
503         backwardMove(select);
504         positionVisible();
505     }
506
507     /**
508      * Moves the caret to the beginning of the current line.
509      * @param select wether to add the text moved over by the caret to
510      * the selection
511      */

512     public void beginningOfLine(boolean select)
513     {
514         int newPos = caretPosition;
515         if (getPosInLine(newPos) <= getWhiteAtLineStart(newPos)) {
516             newPos -= getPosInLine(newPos);
517         } else {
518             newPos -=
519                 getPosInLine(newPos) -
520                 getWhiteAtLineStart(newPos);
521         }
522         setCaretPosition(newPos);
523         backwardMove(select);
524         positionVisible();
525
526     }
527
528     public void realBeginningOfLine(boolean select)
529     {
530         int newPos = caretPosition;
531         if (getPosInLine(newPos) <= getWhiteAtLineStart(newPos)) {
532             newPos -= getPosInLine(newPos);
533         }
534         setCaretPosition(newPos);
535         backwardMove(select);
536         positionVisible();
537     }
538
539     /**
540      * Moves the caret to the end of the current line.
541      * @param select wether to add the text moved over by the caret to
542      * the selection
543      */

544     public void endOfLine(boolean select) {
545         setCaretPosition(caretPosition +
546             getLineWidth(caretPosition) - getPosInLine(caretPosition));
547         forwardMove(select);
548         positionVisible();
549     }
550
551     /**
552      * Sets the caret at the beginning of a line
553      * @param lineNumber number of the line (starts with 1)
554      */

555     public void gotoLine(int lineNumber) {
556         beginningOfText(false);
557         if (lineNumber>1) {
558             nextLine(lineNumber-1,false);
559         }
560     }
561
562     /**
563      * Resets the selection. Sets both its start and end to caretPosition.
564      */

565     void resetSelection() {
566         int oldStart = selectionStart;
567         int oldEnd = selectionEnd;
568         selectionEnd = caretPosition;
569         selectionStart = caretPosition;
570         for (int p=oldStart; p<oldEnd; p++)
571             repaintCharAt(p);
572     }
573    
574     /**
575      * Selects the word around a position
576      */

577     void selectWord(int position) {
578         int oldStart = selectionStart;
579         int oldEnd = selectionEnd;
580
581         selectionEnd = caretPosition;
582         selectionStart = caretPosition;
583         while (selectionEnd<text.length()
584                && Character.isLetterOrDigit(text.charAt(selectionEnd))) {
585             selectionEnd++;
586         }
587         while (selectionStart>=0 && selectionStart<text.length() &&
588                Character.isLetterOrDigit(text.charAt(selectionStart))) {
589             selectionStart--;
590         }
591         if (selectionStart>=0 && selectionStart<text.length() &&
592             !Character.isLetterOrDigit(text.charAt(selectionStart)))
593             selectionStart++;
594
595         for (int p=oldStart; p<oldEnd; p++)
596             repaintCharAt(p);
597     }
598
599     CompletionEngine completionEngine;
600
601     public void setCompletionEngine(CompletionEngine ce) {
602         completionEngine = ce;
603     }
604
605     public CompletionEngine getCompletionEngine() {
606         return completionEngine;
607     }
608
609     void runCompletionEngine(int direction) {
610
611         if (completionEngine!=null) {
612
613             String JavaDoc writtenText = "";
614             int pos;
615             if (selectionStart!=selectionEnd) {
616                 pos = selectionStart;
617             } else {
618                 pos = caretPosition;
619             }
620             int beginWritten = pos;
621             StringBuffer JavaDoc currentProposal = new StringBuffer JavaDoc();
622             // test if the user has already typed something
623
if (pos>0 && !isDivider(text.charAt(pos-1))) {
624                 loggerComp.debug("written word found");
625                 beginWritten--;
626                 // go to the begining of the word
627
while (beginWritten>0 && !isDivider(text.charAt(beginWritten-1))) {
628                     beginWritten--;
629                 }
630                 writtenText = text.substring(beginWritten, pos);
631                 if (selectionStart!=selectionEnd) {
632                     currentProposal.append(writtenText);
633                 }
634             }
635
636             currentProposal.append(text.substring(selectionStart, selectionEnd));
637             int initPosition = caretPosition;
638
639             // removes the current proposal
640
initPosition = selectionStart;
641             remove(selectionStart, selectionEnd - selectionStart);
642             resetSelection();
643             isSelectionCompletion = true;
644
645             String JavaDoc proposedText =
646                 completionEngine.getProposal(
647                     text,beginWritten,writtenText,
648                     currentProposal.toString(),
649                     direction);
650             if (proposedText.length()>0) {
651                 insertString(caretPosition,proposedText.substring(writtenText.length()));
652             }
653
654             setSelectionStart(initPosition);
655             setSelectionEnd(caretPosition);
656
657         }
658     }
659
660     KeyListener JavaDoc toolKeyListener;
661     public void toolDone() {
662         toolKeyListener = null;
663     }
664
665     /**
666      * Key Pressed
667      */

668     public void keyPressed(KeyEvent JavaDoc e)
669     {
670         if (toolKeyListener!=null) {
671             toolKeyListener.keyPressed(e);
672             return;
673         }
674         if (e.isControlDown())
675         {
676             switch (e.getKeyCode()) {
677                 case KeyEvent.VK_C:
678                     copy();
679                     break;
680                 case KeyEvent.VK_V:
681                     paste();
682                     break;
683                 case KeyEvent.VK_X:
684                     cut();
685                     break;
686                 case KeyEvent.VK_Z:
687                     undo();
688                     break;
689                 case KeyEvent.VK_Y:
690                     redo();
691                     break;
692                 case KeyEvent.VK_S:
693                     toolKeyListener = new SearchTool(this,caretPosition);
694                     break;
695                 case KeyEvent.VK_RIGHT:
696                     forwardWord(1, e.isShiftDown());
697                     break;
698                 case KeyEvent.VK_LEFT:
699                     backwardWord(1, e.isShiftDown());
700                     break;
701                 case KeyEvent.VK_HOME:
702                     beginningOfText(e.isShiftDown());
703                     break;
704                 case KeyEvent.VK_END:
705                     endOfText(e.isShiftDown());
706                     break;
707                 case KeyEvent.VK_SPACE:
708                     runCompletionEngine(
709                         e.isShiftDown()?CompletionEngine.BACKWARD:CompletionEngine.FORWARD);
710                     break;
711                 default:
712             }
713         }
714         else if ((e.getModifiers() & KeyEvent.ALT_MASK) > 0)
715         {
716         }
717         else if ((e.getModifiers() & KeyEvent.ALT_GRAPH_MASK) > 0)
718         {
719         }
720         else if (e.isShiftDown())
721         {
722             switch (e.getKeyCode()) {
723                 case KeyEvent.VK_LEFT:
724                     backwardChar(1,e.isShiftDown());
725                     e.consume();
726                     break;
727                 case KeyEvent.VK_RIGHT:
728                     forwardChar(1,e.isShiftDown());
729                     e.consume();
730                     break;
731                 case KeyEvent.VK_UP:
732                     previousLine(1,e.isShiftDown());
733                     e.consume();
734                     break;
735                 case KeyEvent.VK_DOWN:
736                     nextLine(1,e.isShiftDown());
737                     e.consume();
738                     break;
739                 case KeyEvent.VK_HOME:
740                     beginningOfLine(e.isShiftDown());
741                     e.consume();
742                     break;
743                 case KeyEvent.VK_END:
744                     endOfLine(e.isShiftDown());
745                     e.consume();
746                     break;
747                 case KeyEvent.VK_PAGE_UP:
748                     previousLine(15,e.isShiftDown());
749                     e.consume();
750                     break;
751                 case KeyEvent.VK_PAGE_DOWN:
752                     nextLine(15,e.isShiftDown());
753                     e.consume();
754                     break;
755                 case KeyEvent.VK_TAB:
756                     {
757                         if (selectionStart != selectionEnd)
758                         {
759                             int start = selectionStart;
760                             int end = selectionEnd;
761                      
762                             for(int pos = end;
763                                 pos >= start - getPosInLine(start) && pos >= 0;
764                                 pos--)
765                             {
766                                 if (pos == 0 || text.charAt(pos - 1) == '\n')
767                                 {
768                                     for(int i=0;
769                                         i < conf.getTabWidth() && text.charAt(pos) == ' ';
770                                         i++)
771                                     {
772                                         remove(pos, 1);
773                                         end--;
774                                     }
775                                 }
776                             }
777                             setSelection(start,end);
778                         }
779                         else
780                         {
781                         }
782                         e.consume();
783                     }
784                     break;
785                 default:
786             }
787         }
788         else
789         {
790             switch (e.getKeyCode()) {
791                 case KeyEvent.VK_LEFT:
792                     backwardChar(1,e.isShiftDown());
793                     e.consume();
794                     break;
795                 case KeyEvent.VK_RIGHT:
796                     forwardChar(1,e.isShiftDown());
797                     e.consume();
798                     break;
799                 case KeyEvent.VK_UP:
800                     previousLine(1,e.isShiftDown());
801                     e.consume();
802                     break;
803                 case KeyEvent.VK_DOWN:
804                     nextLine(1,e.isShiftDown());
805                     e.consume();
806                     break;
807                 case KeyEvent.VK_TAB:
808                     if (selectionStart == selectionEnd)
809                     {
810                         insertTab(caretPosition);
811                     }
812                     else
813                     {
814                         int start = selectionStart;
815                         int end = selectionEnd;
816                      
817                         for(int pos=end;
818                             pos>=start-getPosInLine(start) && pos>=0;
819                             pos--)
820                         {
821                             if (pos == 0 || text.charAt(pos - 1) == '\n')
822                             {
823                                 end += conf.getTabWidth();
824                                 insertTab(pos);
825                             }
826                         }
827                         setSelection(start,end);
828                     }
829                     e.consume();
830                     break;
831                 case KeyEvent.VK_DELETE:
832                     if (selectionStart == selectionEnd)
833                     {
834                         if (caretPosition < text.length()) {
835                             remove(caretPosition, 1);
836                         }
837                     }
838                     else
839                     {
840                         remove(selectionStart, selectionEnd - selectionStart);
841                     }
842                     resetSelection();
843                     positionVisible();
844                     e.consume();
845                     break;
846                 case KeyEvent.VK_HOME:
847                     beginningOfLine(e.isShiftDown());
848                     e.consume();
849                     break;
850                 case KeyEvent.VK_END:
851                     endOfLine(e.isShiftDown());
852                     e.consume();
853                     break;
854                 case KeyEvent.VK_PAGE_UP:
855                     previousLine(15,e.isShiftDown());
856                     e.consume();
857                     break;
858                 case KeyEvent.VK_PAGE_DOWN:
859                     nextLine(15,e.isShiftDown());
860                     e.consume();
861                     break;
862                 default:
863                     e.consume();
864             }
865         }
866     }
867
868     /**
869      * Key Typed
870      */

871     public void keyTyped(KeyEvent JavaDoc e)
872     {
873         if (toolKeyListener!=null) {
874             toolKeyListener.keyTyped(e);
875             return;
876         }
877         if (e.isControlDown())
878         {
879         }
880         else if ((e.getModifiers() & KeyEvent.ALT_MASK) > 0)
881         {
882         }
883         else
884         {
885             switch (e.getKeyChar()) {
886                 case KeyEvent.VK_TAB:
887                 case KeyEvent.VK_DELETE:
888                     e.consume();
889                     break;
890                 case KeyEvent.VK_BACK_SPACE:
891                     if (selectionStart == selectionEnd && caretPosition > 0)
892                     {
893                         remove(caretPosition - 1, 1);
894                         resetSelection();
895                     }
896                     else
897                     {
898                         remove(selectionStart, selectionEnd - selectionStart);
899                         resetSelection();
900                     }
901                     e.consume();
902                     break;
903                 case KeyEvent.VK_ENTER:
904                     {
905                         if (selectionStart != selectionEnd)
906                             remove(selectionStart, selectionEnd - selectionStart);
907                         insertReturn();
908                         e.consume();
909                     }
910                     break;
911                 case '}':
912                     {
913                         if (selectionStart != selectionEnd)
914                             remove(selectionStart, selectionEnd - selectionStart);
915                         insertCloseCBracket();
916                     }
917                     break;
918                 default:
919                     if (selectionStart != selectionEnd &&
920                         (!isSelectionCompletion || !isAcceptCompletionChar(e.getKeyChar())))
921                         remove(selectionStart, selectionEnd - selectionStart);
922                     isSelectionCompletion = false;
923                     insertChar(e.getKeyChar());
924                     // automatically run completion at the end of words
925
if (!isDivider(e.getKeyChar()) && conf.isAutoComplete() &&
926                         syntaxUnderCaret!=COMMENT && syntaxUnderCaret!=STRING &&
927                         (eot() || isDivider(text.charAt(caretPosition)))) {
928                         runCompletionEngine(CompletionEngine.FORWARD);
929                     } else if (completionEngine!=null &&
930                                completionEngine.isAutomaticCompletionChar(e.getKeyChar()))
931                     {
932                         int i=caretPosition;
933                         completionEngine.runAutomaticCompletion(
934                             this,text,caretPosition,e.getKeyChar());
935                         caretPosition=i;
936                     }
937                     //repaint();
938
positionVisible();
939             }
940         }
941     }
942
943     /**
944      * Wether to accept proposed completion when a char is typed
945      */

946     boolean isAcceptCompletionChar(char c) {
947         return isDivider(c) || c=='.';
948     }
949
950     /**
951      * Inserts a closing curly bracket and takes indentation into
952      * account.
953      */

954     public void insertCloseCBracket() {
955         int white = getWhiteAtLineStart(caretPosition);
956         int lineWidth = getLineWidth(caretPosition);
957         int posInLine = getPosInLine(caretPosition);
958         int neededWhite = 0;
959       
960         int count = 1;
961         int pos = getCaretPosition() - 1;
962       
963         if (pos > 0)
964         {
965             do
966             {
967                 if (text.charAt(pos) == '}')
968                     count ++;
969                 else if (text.charAt(pos) == '{')
970                     count --;
971             
972                 if (count != 0)
973                     pos --;
974             }
975             while (pos > -1 && count > 0);
976         }
977          
978         // array style (={a,b})
979
if (pos==text.length()-1 || text.charAt(pos+1)!='\n') {
980             insertChar('}');
981             return;
982         }
983          
984         // block style
985
while (pos > 0 && text.charAt(pos - 1) != '\n')
986         {
987             neededWhite ++;
988             pos --;
989             if(text.charAt(pos)!=' ') neededWhite=0;
990         }
991       
992         if (white == posInLine && white > neededWhite)
993         {
994             remove(caretPosition - posInLine + neededWhite,
995                    white - neededWhite);
996             insertChar('}');
997         }
998         else if (white == posInLine)
999         {
1000            insertChar('}');
1001        }
1002        else
1003        {
1004            insertChar('\n');
1005            for(int i=0; i<neededWhite; i++)
1006                insertChar(' ');
1007            insertChar('}');
1008        }
1009    }
1010
1011    /**
1012     * Inserts a carriage return and takes indentation into account if
1013     * at the end of a line.
1014     */

1015    public void insertReturn() {
1016        int white = 0;
1017        if (caretPosition==text.length() || text.charAt(caretPosition)=='\n') {
1018            white = getWhiteAtLineStart(selectionStart);
1019            if (selectionStart > 0 && text.charAt(selectionStart - 1) == '{') {
1020                white += 4;
1021            }
1022        } else {
1023            int savedCaret = caretPosition;
1024            int white2 = getWhiteAtLineStart(caretPosition);
1025            realBeginningOfLine(false);
1026            if (caretPosition>0) {
1027                white = getWhiteAtLineStart(caretPosition-1) - white2;
1028                if (savedCaret - caretPosition<=white2)
1029                    white += savedCaret - caretPosition;
1030            }
1031            caretPosition = savedCaret;
1032        }
1033        String JavaDoc ins = "" + '\n';
1034        for(int i=0; i<white; i++) ins += " ";
1035        insertString(caretPosition, ins);
1036    }
1037   
1038    /**
1039     * Inserts a white spaces in the text insted of a tab.
1040     * @param pos The position in the text where the white spaces will be added.
1041     */

1042    void insertTab(int pos)
1043    {
1044        insertString(pos, Strings.newString(' ',conf.getTabWidth()));
1045    }
1046
1047    /**
1048     * Key Released
1049     */

1050    public void keyReleased(KeyEvent JavaDoc e)
1051    {
1052        testOposing();
1053    }
1054
1055    /**
1056     * Used to get the position of a point in a line.
1057     * @param pos the position in text to calculate poition from.
1058     * @return The amount of caracters from the previous \n or start of text to pos
1059     */

1060    int getPosInLine(int pos)
1061    {
1062        int ret = text.lastIndexOf('\n', pos - 1);
1063        ret ++;
1064        ret = pos - ret;
1065        return ret;
1066    }
1067
1068    /**
1069     * Used to get the width of a line.
1070     * @patam A position in the text, that is in the line.
1071     * @return the width of the line where the point is located.
1072     */

1073    int getLineWidth(int pos)
1074    {
1075        int start = 0;
1076        int end = text.indexOf('\n', pos);
1077        if (pos > 0) {
1078            start = text.lastIndexOf('\n',pos-1) + 1;
1079        }
1080      
1081        if (end == -1)
1082            end = text.length();
1083      
1084        return end - start;
1085    }
1086
1087
1088    /**
1089     * Used to get the content of a line.
1090     * @patam A position in the text, that is in the line.
1091     * @return the line's content
1092     */

1093    String JavaDoc getLineText(int pos)
1094    {
1095        int start = 0;
1096        int end = text.indexOf('\n', pos);
1097        if (pos > 0) {
1098            start = text.lastIndexOf('\n', pos-1) + 1;
1099        }
1100      
1101        if (end == -1)
1102            end = text.length();
1103      
1104        return text.substring(start,end);
1105    }
1106
1107    /**
1108     * Returns the number of white spaces at the begining of a line.
1109     * @param pos A position in the line where you whant to find the white spaces.
1110     * @return the number of white spaces at the begining of a line.
1111     */

1112    int getWhiteAtLineStart(int pos)
1113    {
1114        int ret = 0;
1115      
1116        for(int i = pos - getPosInLine(pos);
1117            i >= 0 && i < text.length() && text.charAt(i) == ' ';
1118            i++)
1119        {
1120            ret ++;
1121        }
1122      
1123        return ret;
1124    }
1125
1126    /**
1127     * Inserts a char at caretPosition.
1128     */

1129    void insertChar(char c)
1130    {
1131        changed = true;
1132        doneActions.add(0, new TextAction(TextAction.INSERT, caretPosition, 1, ""));
1133        text = text.substring(0, caretPosition) + c +
1134            text.substring(caretPosition, text.length());
1135        caretPosition ++;
1136        resetSelection();
1137
1138        fireTextUpdate();
1139        repaint();
1140        positionVisible();
1141    }
1142
1143    /**
1144     * Inserts a String s into the text at pos.
1145     * @param pos The position where you whant to insert a String.
1146     * @param str The String you whant to insert into the text.
1147     */

1148    public void insertString(int pos, String JavaDoc str)
1149    {
1150        changed = true;
1151        doneActions.add(0, new TextAction(TextAction.INSERT, pos, str.length(), ""));
1152        text = text.substring(0, pos) + str + text.substring(pos, text.length());
1153        if (caretPosition >= pos)
1154        {
1155            caretPosition += str.length();
1156            resetSelection();
1157        }
1158        fireTextUpdate();
1159        repaint();
1160        positionVisible();
1161    }
1162
1163    /**
1164     * Removes the content of the text from offset to offset + length.
1165     * @param offset Where to start removing text.
1166     * @param length length of the text you whant to remove.
1167     */

1168    public void remove(int offset, int length)
1169    {
1170        changed = true;
1171        if (offset >= 0 && offset + length <= text.length())
1172        {
1173            doneActions.add(
1174                0,
1175                new TextAction(TextAction.REMOVE, offset, length,
1176                               text.substring(offset, offset + length)));
1177         
1178            text = text.substring(0,offset) + text.substring(offset+length,text.length());
1179            if (caretPosition > offset && caretPosition <= offset + length)
1180            {
1181                setCaretPosition(offset);
1182            }
1183            else if (caretPosition > offset)
1184            {
1185                setCaretPosition(caretPosition-length);
1186            }
1187            repaint();
1188            fireTextUpdate();
1189            positionVisible();
1190        }
1191    }
1192
1193    /**
1194     * Tels the SHEditor to undo the last action.
1195     */

1196    public void undo()
1197    {
1198        if (doneActions.size() > 0)
1199        {
1200            changed = true;
1201            TextAction ta = (TextAction)doneActions.remove(0);
1202            try
1203            {
1204                if (ta.action == TextAction.INSERT) {
1205                    redoneActions.add(
1206                        0,
1207                        new TextAction(TextAction.REMOVE,
1208                                       ta.position,
1209                                       ta.length,
1210                                       text.substring(ta.position, ta.position + ta.length)));
1211                    text = text.substring(0, ta.position) +
1212                        text.substring(ta.position + ta.length, text.length());
1213                } else if (ta.action == TextAction.REMOVE) {
1214                    redoneActions.add(
1215                        0,
1216                        new TextAction(TextAction.INSERT, ta.position, ta.length, ""));
1217                    text = text.substring(0, ta.position) + ta.string +
1218                        text.substring(ta.position, text.length());
1219                }
1220                caretPosition = ta.position;
1221            }
1222            catch(Exception JavaDoc e)
1223            {
1224            }
1225            fireTextUpdate();
1226            repaint();
1227        }
1228    }
1229
1230    /**
1231     * Tels the SHEditor to redo the last undone action.
1232     */

1233    public void redo()
1234    {
1235        if (redoneActions.size() > 0)
1236        {
1237            changed = true;
1238            TextAction ta = (TextAction)redoneActions.remove(0);
1239            try
1240            {
1241                if (ta.action == TextAction.INSERT)
1242                {
1243                    doneActions.add(
1244                        0,
1245                        new TextAction(
1246                            TextAction.REMOVE, ta.position, ta.length,
1247                            text.substring(ta.position, ta.position + ta.length)));
1248                    text = text.substring(0, ta.position) +
1249                        text.substring(ta.position + ta.length, text.length());
1250                }
1251                else
1252                {
1253                    doneActions.add(
1254                        0,
1255                        new TextAction(TextAction.INSERT, ta.position, ta.length, ""));
1256                    text = text.substring(0, ta.position) +
1257                        ta.string + text.substring(ta.position, text.length());
1258                }
1259                caretPosition = ta.position;
1260            }
1261            catch(Exception JavaDoc e)
1262            {
1263            }
1264            fireTextUpdate();
1265            repaint();
1266        }
1267    }
1268
1269    /**
1270     * Returns the number of lines to a point.
1271     * @param pos the position to where you whant to count the lines.
1272     * @return The numbers of lines to the pos.
1273     */

1274    int getLine(int pos)
1275    {
1276        int ret = 0;
1277      
1278        int brPos = 0;
1279        boolean done = false;
1280      
1281        while (brPos != -1 && !done)
1282        {
1283            brPos = text.indexOf('\n', brPos);
1284         
1285            if (pos <= brPos)
1286            {
1287                done = true;
1288            }
1289        }
1290        return ret;
1291    }
1292
1293    /**
1294     * Preformes a cut action on the SHEditor.
1295     */

1296    public void cut()
1297    {
1298        if (selectionStart != selectionEnd)
1299        {
1300            try
1301            {
1302                Clipboard JavaDoc clipboard = getToolkit().getSystemClipboard();
1303                String JavaDoc post = text.substring(selectionStart, selectionEnd);
1304                clipboard.setContents(new StringSelection JavaDoc(post), this);
1305                remove(selectionStart,selectionEnd-selectionStart);
1306                resetSelection();
1307                setCaretPosition(selectionStart);
1308                positionVisible();
1309            }
1310            catch(Exception JavaDoc e)
1311            {
1312            }
1313        }
1314    }
1315
1316    /**
1317     * Preformes a copy action on the JJAvaPane.
1318     */

1319    public void copy()
1320    {
1321        if (selectionStart != selectionEnd)
1322        {
1323            try
1324            {
1325                Clipboard JavaDoc clipboard = getToolkit().getSystemClipboard();
1326                String JavaDoc post = text.substring(selectionStart, selectionEnd);
1327                clipboard.setContents(new StringSelection JavaDoc(post), this);
1328            }
1329            catch(Exception JavaDoc e)
1330            {
1331            }
1332        }
1333    }
1334
1335    /**
1336     * Preformes a paste action on the SHEditor.
1337     */

1338    public void paste()
1339    {
1340        loggerClip.debug("paste...");
1341        if (selectionStart != selectionEnd)
1342        {
1343            remove(selectionStart,selectionEnd-selectionStart);
1344            resetSelection();
1345            setCaretPosition(selectionStart);
1346        }
1347        Clipboard JavaDoc clipboard = getToolkit().getSystemClipboard();
1348        Transferable JavaDoc content = clipboard.getContents(this);
1349        if (content != null)
1350        {
1351            try
1352            {
1353                insertString(caretPosition,
1354                             (String JavaDoc)content.getTransferData(DataFlavor.stringFlavor));
1355            }
1356            catch (Exception JavaDoc e)
1357            {
1358                loggerClip.error("error in copying",e);
1359            }
1360        } else {
1361            loggerClip.debug("content is null");
1362        }
1363        fireTextUpdate();
1364    }
1365
1366    /**
1367     * Returns the number of a char in a the text between to positions.
1368     * @param c the char to count.
1369     * @param offset offset where to start looking.
1370     * @param length length the length of the area to search.
1371     */

1372    public int countChar(char c, int offset, int length)
1373    {
1374        int ret = 0;
1375        for (int i=offset; i < offset+length; i++) {
1376            if (text.charAt(i) == c)
1377                ret ++;
1378        }
1379        return c;
1380    }
1381
1382    public void repaint() {
1383        super.repaint();
1384        //logger.debug("repaint",new Exception());
1385
}
1386
1387    int getCharWidth(char c) {
1388        if (Character.isDefined(c))
1389            return metrics.charWidth(c);
1390        else
1391            return 0;
1392    }
1393
1394    /**
1395     * Paints the SHEditor. syntaxUnderCaret is updated.
1396     * @param g the graphics to draw the SHEditor on.
1397     */

1398    public void paintComponent(Graphics JavaDoc g)
1399    {
1400        super.paintComponent(g);
1401
1402        g.setFont(getFont());
1403        lineHeight = metrics.getHeight();
1404
1405        Rectangle JavaDoc rect = getVisibleRect();
1406        logger.debug("SHEditor.paintComponent on "+rect+" / "+g.getClip());
1407        rect = g.getClipBounds();
1408
1409        g.setColor(conf.getBackgroundColor());
1410        g.fillRect(rect.x + getMarginLeft(), rect.y,
1411                   rect.width - getMarginLeft(), rect.height);
1412        g.setColor(new Color JavaDoc(180, 180, 180));
1413        g.fillRect(rect.x, rect.y, getMarginLeft(), rect.height);
1414      
1415        int line = 1;
1416        int pos = 0;
1417        boolean done = false;
1418        boolean ignore = false;
1419
1420        StringBuffer JavaDoc word = new StringBuffer JavaDoc(); // Current word to be displayed
1421

1422        int posXStart = getMarginLeft();
1423        int posX = posXStart;
1424        int maxPosX = posX;
1425        int posY = lineHeight;
1426
1427        // Calculate start line and position
1428
while(posY + lineHeight < rect.y)
1429        {
1430            posY += lineHeight;
1431            if (pos + 1 < text.length()) {
1432                pos = text.indexOf("\n", pos);
1433                pos ++;
1434                line ++;
1435            } else {
1436                break;
1437            }
1438        }
1439
1440        if (text.lastIndexOf("/ *", pos) > text.lastIndexOf("* /", pos))
1441        {
1442            int lastPos = text.lastIndexOf("/*", pos);
1443            int posInLine = getPosInLine(lastPos);
1444            int count = countChar('"', lastPos - posInLine, posInLine);
1445            ignore = (count%2 == 0);
1446        }
1447
1448        syntaxUnderCaret = DEFAULT;
1449        while (pos < text.length())
1450        {
1451            done = false;
1452            g.setColor(conf.getTextColor());
1453         
1454            if (ignore)
1455            {
1456                word.append(text.charAt(pos));
1457                pos ++;
1458      
1459                while (pos < text.length() && !done)
1460                {
1461                    if (text.charAt(pos) == '/' && text.charAt(pos - 1) == '*') {
1462                        done = true;
1463                    }
1464                    word.append(text.charAt(pos));
1465                    pos ++;
1466                }
1467            }
1468            // Double-quoted strings ("blabla")
1469
else if (word.length() == 0 && text.charAt(pos) == '"')
1470            {
1471                int startp = pos;
1472                word.append(text.charAt(pos));
1473                pos ++;
1474            
1475                while (pos < text.length() && !done)
1476                {
1477                    if (text.charAt(pos) == '"') {
1478                        if (text.charAt(pos - 1) != '\\' ||
1479                            text.charAt(pos - 2) == '\\')
1480                        {
1481                            done = true;
1482                        }
1483                    } else if (text.charAt(pos) == '\n') {
1484                        // Quoted Strings are not multiline
1485
done = true;
1486                    }
1487         
1488                    word.append(text.charAt(pos));
1489                    pos ++;
1490                }
1491                if (caretPosition<pos && caretPosition>startp)
1492                    syntaxUnderCaret = STRING;
1493                g.setColor(conf.getStringColor());
1494            }
1495            // Single-quoted strings ('blabla')
1496
else if (word.length() == 0 && text.charAt(pos) == '\'')
1497            {
1498                int startp = pos;
1499                word.append(text.charAt(pos));
1500                pos ++;
1501      
1502                while (pos < text.length() && !done)
1503                {
1504                    if (text.charAt(pos) == '\'') {
1505                        if (text.charAt(pos - 1) != '\\' ||
1506                            text.charAt(pos - 2) == '\\')
1507                        {
1508                            done = true;
1509                        }
1510                    } else if (text.charAt(pos) == '\n') {
1511                        // Quoted Strings are not multiline
1512
done = true;
1513                    }
1514         
1515                    word.append(text.charAt(pos));
1516                    pos ++;
1517                }
1518                if (caretPosition<pos && caretPosition>startp)
1519                    syntaxUnderCaret = STRING;
1520                g.setColor(conf.getStringColor());
1521            }
1522            // Single line comments (// comment blabla)
1523
else if (text.charAt(pos) == '/' &&
1524                     pos < text.length() - 1 &&
1525                     text.charAt(pos + 1) == '/' &&
1526                     (pos == 0 || text.charAt(pos - 1) != '*'))
1527            {
1528                int startp = pos;
1529                word.append(text.charAt(pos));
1530                pos ++;
1531      
1532                while (pos < text.length() && !done)
1533                {
1534                    if (text.charAt(pos) == '\n') {
1535                        done = true;
1536                    }
1537                    word.append(text.charAt(pos));
1538                    pos ++;
1539                }
1540                if (caretPosition<=pos && caretPosition>startp)
1541                    syntaxUnderCaret = COMMENT;
1542                g.setColor(conf.getIgnoreColor());
1543            }
1544            // Multiline comments (/* comment blabla */)
1545
else if (text.charAt(pos) == '/' &&
1546                     pos < text.length() - 1 &&
1547                     text.charAt(pos + 1) == '*' &&
1548                     (pos == 0 || text.charAt(pos - 1) != '/'))
1549            {
1550                int startp = pos;
1551                word.append(text.charAt(pos));
1552                pos ++;
1553      
1554                while (pos < text.length() && !done)
1555                {
1556                    if (text.charAt(pos) == '/' &&
1557                        text.charAt(pos - 1) == '*')
1558                    {
1559                        done = true;
1560                    }
1561                    word.append(text.charAt(pos));
1562                    pos ++;
1563                }
1564                if (caretPosition<pos && caretPosition>startp)
1565                    syntaxUnderCaret = COMMENT;
1566                g.setColor(conf.getIgnoreColor());
1567            }
1568            // Word separator
1569
else if (isDivider(text.charAt(pos)))
1570            {
1571                if (word.length() == 0) {
1572                    word.append(text.charAt(pos));
1573                    pos ++;
1574                }
1575                done = true;
1576            }
1577            // Normal word
1578
else
1579            {
1580                while (pos < text.length() && !done)
1581                {
1582                    if (isDivider(text.charAt(pos))) {
1583                        done = true;
1584                    } else {
1585                        word.append(text.charAt(pos));
1586                        pos ++;
1587                    }
1588                }
1589                if (isKeyword(word.toString())) {
1590                    g.setColor(conf.getKeywordColor());
1591                } else if (isModifier(word.toString())) {
1592                    g.setColor(conf.getModifierColor());
1593                } else if (isType(word.toString())) {
1594                    g.setColor(conf.getTypeColor());
1595                } else {
1596                    g.setColor(conf.getTextColor());
1597                }
1598            }
1599
1600            if (ignore) {
1601                g.setColor(conf.getIgnoreColor());
1602                ignore = false;
1603            } else if (word.toString().equals("{") ||
1604                       word.toString().equals("}")) {
1605                g.setColor(conf.getClampColor());
1606            }
1607
1608            for(int i=0; i<word.length(); i++)
1609            {
1610                char c = word.charAt(i);
1611                int charWidth = getCharWidth(c);
1612
1613                if (posY + lineHeight > rect.y &&
1614                    pos == openPos + 1 || pos == closePos + 1)
1615                {
1616                    // Poink background for openin gor closing chars ('(','[',')',']',...)
1617
Color JavaDoc tmpColor = g.getColor();
1618                    g.setColor(Color.pink);
1619                    if (posX >= rect.x && posX < rect.x + rect.width)
1620                        g.fillRect(posX, posY - metrics.getAscent(),
1621                                   charWidth,
1622                                   metrics.getAscent());
1623                    g.setColor(tmpColor);
1624                }
1625                else if (posY + lineHeight > rect.y &&
1626                         pos - word.length() + i < selectionEnd &&
1627                         pos - word.length() + i >= selectionStart)
1628                {
1629                    // draw background for char
1630
Color JavaDoc tmpColor = g.getColor();
1631                    g.setColor(isSelectionCompletion ?
1632                               conf.getCompletionColor() : conf.getSelectionColor());
1633                    if (posX >= rect.x && posX < rect.x + rect.width)
1634                        g.fillRect(posX, posY - metrics.getAscent(),
1635                                   charWidth,
1636                                   metrics.getAscent());
1637                    g.setColor(tmpColor);
1638                }
1639
1640                if (posY + lineHeight > rect.y &&
1641                    hasFocus() &&
1642                    showCaret &&
1643                    caretPosition == pos - word.length() + i)
1644                {
1645                    car.x = posX;
1646                    car.y = posY - lineHeight;
1647                    car.height = lineHeight;
1648                }
1649                if (c == '\n')
1650                {
1651                    Color JavaDoc tmpColor = g.getColor();
1652                    g.setColor(new Color JavaDoc(180, 180, 180));
1653                    g.fillRect(rect.x, posY - lineHeight,
1654                               getMarginLeft(), lineHeight);
1655                    g.setColor(new Color JavaDoc(200, 0, 0));
1656                    g.drawString(
1657                        "" + line,
1658                        rect.x + (getMarginLeft()-10)
1659                        - metrics.charsWidth(("" + line).toCharArray(),
1660                                             0, ("" + line).length()),
1661                        posY - metrics.getDescent());
1662            
1663                    if (lineToMark == line)
1664                    {
1665                        g.setColor(Color.green);
1666                        g.fillPolygon(
1667                            new int[] { rect.x + 58, rect.x + 63, rect.x + 58 },
1668                            new int[] { posY - (int)(lineHeight / 1.5d),
1669                                        posY - (int)(lineHeight / 3d),
1670                                        posY },
1671                            3);
1672                    }
1673                    g.setColor(tmpColor);
1674            
1675                    posY += lineHeight;
1676                    posX = posXStart;
1677                    line ++;
1678                }
1679                else if (c == '\t')
1680                {
1681                    posX += getCharWidth(' ') * conf.getTabWidth();
1682                }
1683                else if (charWidth > 0 && posY + lineHeight > rect.y)
1684                {
1685                    if ((posX+charWidth) >= rect.x && posX < rect.x + rect.width)
1686                        g.drawString("" + c, posX, posY - metrics.getDescent());
1687                    posX += charWidth;
1688                }
1689            }
1690         
1691            if (posX > maxPosX) {
1692                maxPosX = posX;
1693            }
1694
1695            // If we're out of the viewport, skip until the end
1696
if (posY - lineHeight > rect.y + rect.height)
1697            {
1698                for(int p = pos; p != -1; p = text.indexOf('\n', p + 1))
1699                {
1700                    posY += lineHeight;
1701               
1702                    int width = getPixelTextWidth(getLineText(p));
1703                    if (width > maxPosX) {
1704                        maxPosX = width;
1705                    }
1706                }
1707            
1708                pos = text.length();
1709            }
1710         
1711            word.delete(0, word.length());
1712        }
1713      
1714        if (conf.getShowLineNumbers() &&
1715            (posY - lineHeight <= rect.y + rect.height))
1716        {
1717            g.setColor(conf.getLineNrBgColor());
1718            g.fillRect(rect.x, posY - lineHeight,
1719                       getMarginLeft(), lineHeight);
1720            g.setColor(conf.getLineNrColor());
1721            g.drawString("" + line,
1722                         rect.x + (getMarginLeft()-10)
1723                         - metrics.charsWidth(("" + line).toCharArray(),
1724                                              0, ("" + line).length()),
1725                         posY - metrics.getDescent());
1726         
1727            if (lineToMark == line)
1728            {
1729                g.setColor(Color.green);
1730                g.fillPolygon(
1731                    new int[] { rect.x + 58, rect.x + 63, rect.x + 58 },
1732                    new int[] { posY - (int)(lineHeight / 1.5d),
1733                                posY - (int)(lineHeight / 3d),
1734                                posY },
1735                    3);
1736            }
1737        }
1738      
1739        if (hasFocus() &&
1740            posY - lineHeight <= rect.y + rect.height &&
1741            showCaret && pos == text.length() &&
1742            pos == caretPosition)
1743        {
1744            car.x = posX;
1745            car.y = posY - lineHeight;
1746            car.height = lineHeight;
1747        }
1748
1749        if (hasFocus())
1750            g.setColor(Color.black);
1751        else
1752            g.setColor(Color.gray);
1753        g.fillRect(car.x, car.y, car.width, car.height);
1754      
1755        if (posY + 10 != getSize().height || maxPosX + 10 != getSize().width)
1756        {
1757            setMinimumSize(
1758                new Dimension JavaDoc(
1759                    (maxPosX+10 > getSize().width ? maxPosX+10 : getSize().width),
1760                    posY+10));
1761            setPreferredSize(
1762                new Dimension JavaDoc(maxPosX+10,posY+10));
1763            logger.debug("revalidate");
1764            revalidate();
1765        }
1766    }
1767
1768    /**
1769     * Returns the pixel width of a string
1770     * @param text the string to get the width of
1771     * @return the width in number of pixels the text will have when drawn.
1772     */

1773    protected int getPixelTextWidth(String JavaDoc text) {
1774        int width = 0;
1775        for (int i=0; i<text.length(); i++) {
1776            if (text.charAt(i)==KeyEvent.VK_TAB)
1777                width += getCharWidth(' ') * conf.getTabWidth();
1778            else
1779                width += getCharWidth(text.charAt(i));
1780         
1781        }
1782        return width;
1783    }
1784
1785    /**
1786     * Updates the JJAvaPane (cals paint(Graphics g));
1787     */

1788    public void update(Graphics JavaDoc g)
1789    {
1790        paint(g);
1791    }
1792
1793    /**
1794     * Sets a line as marked, and scrols to that line if needed.
1795     */

1796    public void scrollToLine(int line)
1797    {
1798        lineToMark = line;
1799      
1800        int l = 1;
1801        int pos = 0;
1802        while (l <= line && pos != -1)
1803        {
1804            pos = text.indexOf('\n', pos + 1);
1805            l ++;
1806        }
1807        setCaretPosition(pos);
1808        requestFocus();
1809        //repaint();
1810
positionVisible();
1811    }
1812
1813    /**
1814     * Tests oposing (), [] and {}, and makes sure they are marked if
1815     * the caret is behind one of them.
1816     */

1817    public void testOposing()
1818    {
1819        //unmarkOposing();
1820
if (getCaretPosition() > -1 && getCaretPosition() - 1 < text.length())
1821        {
1822            if (getCaretPosition() > 0)
1823            {
1824                char c = text.charAt(getCaretPosition() - 1);
1825                if (c == '}') {
1826                    testOpening('{','}');
1827                } else if (c == '{') {
1828                    testClosing('{','}');
1829                } else if (c == ')') {
1830                    testOpening('(',')');
1831                } else if (c == '(') {
1832                    testClosing('(',')');
1833                } else if (c == ']') {
1834                    testOpening('[',']');
1835                } else if (c == '[') {
1836                    testClosing('[',']');
1837                } else {
1838                    unmarkOposing();
1839                }
1840            } else {
1841                repaint();
1842            }
1843        }
1844    }
1845
1846    public void testClosing(char opening, char closing) {
1847        if (text.charAt(getCaretPosition() - 1 ) == opening)
1848        {
1849            int oldOpenPos = openPos;
1850            int oldClosePos = closePos;
1851
1852            openPos = getCaretPosition() - 1;
1853         
1854            int count = 1;
1855            int pos = getCaretPosition() - 1;
1856            
1857            while (pos < text.length() - 1 && count > 0) {
1858                pos ++;
1859                if (text.charAt(pos) == opening)
1860                    count ++;
1861                else if (text.charAt(pos) == closing)
1862                    count --;
1863            }
1864            
1865            if (count > 0) {
1866                closePos = -1;
1867                openPos = -1;
1868            } else {
1869                closePos = pos;
1870            }
1871         
1872            repaintCharAt(oldOpenPos);
1873            repaintCharAt(oldClosePos);
1874            repaintCharAt(openPos);
1875            repaintCharAt(closePos);
1876            repaintCharAt(caretPosition);
1877        }
1878    }
1879
1880    public void testOpening(char opening, char closing) {
1881        if (text.charAt(getCaretPosition() - 1) == closing)
1882        {
1883            int oldOpenPos = openPos;
1884            int oldClosePos = closePos;
1885
1886            openPos = getCaretPosition() - 1;
1887            
1888            int count = 0;
1889            int pos = getCaretPosition() - 1;
1890            
1891            if (getCaretPosition() > 0) {
1892                do {
1893                    if (text.charAt(pos) == closing)
1894                        count ++;
1895                    else if (text.charAt(pos) == opening)
1896                        count --;
1897                  
1898                    if (count != 0)
1899                        pos --;
1900                } while (pos > -1 && count > 0);
1901            }
1902
1903            closePos = pos;
1904               
1905            if (closePos == -1)
1906                openPos = -1;
1907            
1908            repaintCharAt(oldOpenPos);
1909            repaintCharAt(oldClosePos);
1910            repaintCharAt(openPos);
1911            repaintCharAt(closePos);
1912            repaintCharAt(caretPosition);
1913        }
1914    }
1915
1916    /**
1917     * Unmarks oposing (), {} or [] given by openPos and closePos.
1918     */

1919    public void unmarkOposing()
1920    {
1921        repaintCharAt(openPos);
1922        repaintCharAt(closePos);
1923        openPos = -1;
1924        closePos = -1;
1925    }
1926
1927    /**
1928     * Makes sure the caret is visible on screen.
1929     */

1930    public void positionVisible()
1931    {
1932        positionVisible(caretPosition);
1933    }
1934
1935    /**
1936     * Makes sure the selection is visible on screen.
1937     */

1938    public void selectionVisible()
1939    {
1940        positionVisible(selectionStart);
1941    }
1942
1943    /**
1944     * Makes sure a position is visible
1945     * @param position the position that must be visible
1946     */

1947    public void positionVisible(int position)
1948    {
1949        // Cast to Object to work around SwingWT inheritance bugs
1950
Object JavaDoc parent = getParent();
1951        if (parent instanceof JViewport JavaDoc)
1952        {
1953            Rectangle JavaDoc rect = getVisibleRect();
1954            Rectangle JavaDoc car = getCaretPos(position);
1955         
1956            try
1957            {
1958                JScrollPane JavaDoc scrollPane = (JScrollPane JavaDoc)((JViewport JavaDoc)parent).getParent();
1959                JScrollBar JavaDoc hs = scrollPane.getHorizontalScrollBar();
1960                JScrollBar JavaDoc vs = scrollPane.getVerticalScrollBar();
1961            
1962                int newX = hs.getValue();
1963                int newY = vs.getValue();
1964         
1965                if (rect.x + rect.width - getMarginLeft() <= car.x)
1966                    newX = car.x + 75 - rect.width;
1967                else if (rect.x > car.x)
1968                    newX = car.x - 10;
1969         
1970                if (rect.y + rect.height <= car.y + car.height)
1971                    newY = car.y + 20 + car.height - rect.height;
1972                else if (rect.y >= car.y)
1973                    newY = car.y - 20;
1974         
1975                if (newX != hs.getValue()) {
1976                    hs.setValue(newX);
1977                }
1978                if (newY != vs.getValue()) {
1979                    vs.setValue(newY);
1980                }
1981            }
1982            catch(Exception JavaDoc e)
1983            {
1984                logger.error("positionVisible "+position, e);
1985            }
1986        }
1987    }
1988   
1989    /**
1990     * Returns a rectangle representation of the caret at a given position.
1991     * @param position position of the caret
1992     * @return a Rectangle representation of the caret.
1993     */

1994    public Rectangle JavaDoc getCaretPos(int position)
1995    {
1996        Rectangle JavaDoc ret = new Rectangle JavaDoc(0, 0, 0 ,0);
1997      
1998        if (metrics != null)
1999        {
2000            int lineStart = 0;
2001            int posY = lineHeight;
2002            int i = 0;
2003            for(; i < text.length() && i < position; i ++)
2004            {
2005                if (text.charAt(i) == '\n')
2006                {
2007                    lineStart = i + 1;
2008                    posY += lineHeight;
2009                }
2010            }
2011         
2012            ret.x = metrics.stringWidth(text.substring(lineStart, i));
2013            ret.y = posY - lineHeight;
2014            ret.height = lineHeight;
2015            ret.width = getCharWidth('m');
2016        }
2017
2018        return ret;
2019    }
2020
2021    /**
2022     * Sets the font of the SHEditor and repaqints it.
2023     * @param font the new font.
2024     */

2025    public void setFont(Font JavaDoc font)
2026    {
2027        super.setFont(font);
2028        repaint();
2029    }
2030
2031    int OFFSET = 35;
2032    protected int getMarginLeft() {
2033        return conf.getShowLineNumbers()?OFFSET:0;
2034    }
2035
2036    /**
2037     * Returns position in the text based on coordinates x and y.
2038     * @param mousePosX the x coordinate of the position in the text.
2039     * @param mousePosY the y coordinate of the position in the text.
2040     * @return the position in the text represented by pint x, y.
2041     */

2042    public int getCharPos(int mousePosX, int mousePosY)
2043    {
2044        if (metrics != null)
2045        {
2046            Rectangle JavaDoc rect = getVisibleRect();
2047      
2048            int pos = 0;
2049            boolean done = false;
2050
2051            String JavaDoc word = "";
2052      
2053            int posXStart = getMarginLeft();
2054            int posX = posXStart;
2055            int posY = lineHeight;
2056         
2057            while (posY + lineHeight < rect.y)
2058            {
2059                posY += lineHeight;
2060                if (pos + 1 < text.length())
2061                {
2062                    pos = text.indexOf('\n', pos);
2063                    pos ++;
2064                }
2065                else
2066                {
2067                    break;
2068                }
2069            }
2070         
2071            if (mousePosY < posY - lineHeight)
2072            {
2073                return -1;
2074            }
2075         
2076            while (pos < text.length())
2077            {
2078                if (text.charAt(pos) == '\n')
2079                {
2080                    if (mousePosX > posX &&
2081                        mousePosY < posY &&
2082                        mousePosY >= posY - lineHeight)
2083                    {
2084                        return pos;
2085                    }
2086                    else if (mousePosX <= posXStart &&
2087                             mousePosY < posY &&
2088                             mousePosY >= posY - lineHeight)
2089                    {
2090                        if (pos + 1 < text.length())
2091                        {
2092                            return pos;
2093                        }
2094                    }
2095                    posY += lineHeight;
2096                    posX = posXStart;
2097               
2098                }
2099                else if (posX < mousePosX &&
2100                         posX + (getCharWidth(text.charAt(pos)) / 2) >= mousePosX &&
2101                         mousePosY < posY &&
2102                         mousePosY >= posY - lineHeight + 2)
2103                {
2104                    return pos;
2105                }
2106                else if (posX < mousePosX &&
2107                         posX + getCharWidth(text.charAt(pos)) >= mousePosX &&
2108                         mousePosY < posY &&
2109                         mousePosY >= posY - lineHeight)
2110                {
2111                    if (pos + 1 < text.length())
2112                    {
2113                        return pos + 1;
2114                    }
2115                    posX += getCharWidth(text.charAt(pos));
2116                }
2117                else if (mousePosX <= posXStart &&
2118                         mousePosY < posY &&
2119                         mousePosY >= posY - lineHeight)
2120                {
2121                    if (pos + 1 < text.length())
2122                    {
2123                        return pos;
2124                    }
2125                    posX += getCharWidth(text.charAt(pos));
2126                }
2127                else
2128                {
2129                    posX += getCharWidth(text.charAt(pos));
2130                }
2131                pos ++;
2132            }
2133        }
2134      
2135        return text.length();
2136    }
2137
2138    /**
2139     * Tests if a character is a divider.
2140     * @param c the char to test.
2141     * @return true if the char is a divider, meaning it might divide
2142     * two java words, returns false othervise. */

2143    public boolean isDivider(char c)
2144    {
2145        for(int i=0; i<separators.length; i++) {
2146            if (c == separators[i])
2147                return true;
2148        }
2149        return false;
2150    }
2151
2152    Set JavaDoc keywords = new HashSet JavaDoc();
2153    /**
2154     * Define some new keywords
2155     * @param addedKeywords the new keywords
2156     */

2157    public void addKeywords(String JavaDoc[] addedKeywords) {
2158        for(int i=0; i<addedKeywords.length; i++) {
2159            keywords.add(addedKeywords[i]);
2160        }
2161    }
2162
2163    /**
2164     * Define some new keywords
2165     * @param addedKeywords the new keywords
2166     */

2167    public void addKeywords(Set JavaDoc addedKeywords) {
2168        keywords.addAll(addedKeywords);
2169    }
2170
2171    public void clearKeywords() {
2172        keywords.clear();
2173    }
2174
2175    /**
2176     * Tells wether a word is keyword or not
2177     */

2178    protected boolean isKeyword(String JavaDoc word) {
2179        return keywords.contains(word);
2180    }
2181
2182    Set JavaDoc modifiers = new HashSet JavaDoc();
2183    /**
2184     * Define some new keywords
2185     * @param addedModifiers the new keywords
2186     */

2187    public void addModifiers(String JavaDoc[] addedModifiers) {
2188        for(int i=0; i<addedModifiers.length; i++) {
2189            modifiers.add(addedModifiers[i]);
2190        }
2191    }
2192    /**
2193     * Tells wether a word is a modifier or not
2194     */

2195    public boolean isModifier(String JavaDoc word) {
2196        return modifiers.contains(word);
2197    }
2198
2199    Set JavaDoc types = new HashSet JavaDoc();
2200    public void addTypes(String JavaDoc[] addedTypes) {
2201        for(int i=0; i<addedTypes.length; i++) {
2202            types.add(addedTypes[i]);
2203        }
2204    }
2205    /**
2206     * Tells wether a word is a type or not
2207     */

2208    public boolean isType(String JavaDoc word) {
2209        if (types.contains(word))
2210            return true;
2211        int index = word.lastIndexOf('.');
2212        if (index!=-1) {
2213            word = word.substring(index+1);
2214        }
2215        return word.length()>1 &&
2216            Character.isUpperCase(word.charAt(0)) &&
2217            Character.isLowerCase(word.charAt(1));
2218    }
2219   
2220    public void setCaretPosition(int caretPosition) {
2221        repaintCharAt(this.caretPosition);
2222        if (caretPosition<0)
2223            caretPosition = 0;
2224        else if (caretPosition>text.length())
2225            caretPosition = text.length();
2226        this.caretPosition = caretPosition;
2227        repaintCharAt(caretPosition);
2228        fireCaretUpdate();
2229    }
2230
2231    protected void repaintCharAt(int pos) {
2232        if (pos!=-1) {
2233            Rectangle JavaDoc rect = getCaretPos(pos);
2234            logger.debug("repaintCharAt "+pos+" -> "+rect);
2235            repaint(rect);
2236        }
2237    }
2238
2239    protected void repaintChars(int start, int end) {
2240        if (start<end)
2241            for (int p=start; p<=end; p++)
2242                repaintCharAt(p);
2243        else
2244            for (int p=end; p<=start; p++)
2245                repaintCharAt(p);
2246    }
2247
2248    /**
2249     * Returns the caretPosition.
2250     * @return the position of the caret in the text.
2251     */

2252    public int getCaretPosition()
2253    {
2254        return caretPosition;
2255    }
2256
2257    /**
2258     * Returns selection start position
2259     * @return the position of the selectionStart in the text.
2260     */

2261    public int getSelectionStart()
2262    {
2263        return selectionStart;
2264    }
2265   
2266    /**
2267     * Returns selection end position.
2268     * @return the position of the selectionEnd in the text.
2269     */

2270    public int getSelectionEnd()
2271    {
2272        return selectionEnd;
2273    }
2274
2275    /**
2276     * Mouse has been pressed.
2277     */

2278    public void mousePressed(MouseEvent JavaDoc e)
2279    {
2280        requestFocus();
2281        int tmp = getCharPos(e.getX(), e.getY());
2282        mousePressPos = tmp;
2283        if (tmp != -1)
2284        {
2285            isSelectionCompletion = false;
2286            if ((e.getModifiers() & MouseEvent.SHIFT_MASK) > 0)
2287            {
2288                if (caretPosition == selectionStart && tmp <= selectionEnd) {
2289                    setCaretPosition(tmp);
2290                    selectionStart = caretPosition;
2291                } else if (caretPosition == selectionStart) {
2292                    selectionStart = selectionEnd;
2293                    setCaretPosition(tmp);
2294                    selectionEnd = caretPosition;
2295                } else if (caretPosition == selectionEnd && tmp >= selectionStart) {
2296                    setCaretPosition(tmp);
2297                    selectionEnd = caretPosition;
2298                } else {
2299                    selectionEnd = selectionStart;
2300                    setCaretPosition(tmp);
2301                    selectionStart = caretPosition;
2302                }
2303            }
2304            else
2305            {
2306                setCaretPosition(tmp);
2307                if (e.getClickCount()==1) {
2308                    selectionEnd = caretPosition;
2309                    selectionStart = caretPosition;
2310                }
2311            }
2312         
2313            repaint();
2314            positionVisible();
2315        }
2316    }
2317
2318    /**
2319     * MouseMoved.
2320     */

2321    public void mouseMoved(MouseEvent JavaDoc e)
2322    {
2323    }
2324
2325    /**
2326     * MouseDragged.
2327     */

2328    public void mouseDragged(MouseEvent JavaDoc e)
2329    {
2330        int tmp = getCharPos(e.getX(), e.getY());
2331        if (mousePressPos != -1) {
2332            if (mousePressPos <= tmp) {
2333                selectionStart = mousePressPos;
2334                selectionEnd = tmp;
2335            } else {
2336                selectionEnd = mousePressPos;
2337                selectionStart = tmp;
2338            }
2339            setCaretPosition(tmp);
2340            repaint();
2341            positionVisible();
2342        } else {
2343            repaint();
2344        }
2345    }
2346
2347    /**
2348     * MouseReleased.
2349     */

2350    public void mouseReleased(MouseEvent JavaDoc e)
2351    {
2352        mousePressPos = -1;
2353        testOposing();
2354    }
2355
2356    /**
2357     * MouseClicked.
2358     */

2359    public void mouseClicked(MouseEvent JavaDoc e)
2360    {
2361        if (e.getClickCount()==2) {
2362            selectWord(caretPosition);
2363        }
2364    }
2365
2366    /**
2367     * MouseEntered.
2368     */

2369    public void mouseEntered(MouseEvent JavaDoc e)
2370    {
2371    }
2372
2373    /**
2374     * MouseExited.
2375     */

2376    public void mouseExited(MouseEvent JavaDoc e)
2377    {
2378    }
2379
2380    protected int minDisplayedLines = 4;
2381    /**
2382     * Gets the minimum number of lines to display
2383     */

2384    public int getMinDisplayedLines() {
2385        return minDisplayedLines;
2386    }
2387    public void setMinDisplayedLines(int n) {
2388        this.minDisplayedLines = n;
2389    }
2390
2391    public Dimension JavaDoc getPreferredScrollableViewportSize()
2392    {
2393        int pos = 0;
2394        int lineStart = 0;
2395        int width = 30;
2396        int height;
2397        int lines = 1;
2398        
2399        while (pos < text.length())
2400        {
2401            if (text.charAt(pos)=='\n' || pos==(text.length()-1)) {
2402                int lineWidth =
2403                    metrics.stringWidth(
2404                        Strings.replace(text.substring(lineStart,pos),
2405                                        "\t",
2406                                        Strings.newString(' ',conf.getTabWidth())))
2407                    + metrics.charWidth('m');
2408                if (lineWidth>width)
2409                    width = lineWidth;
2410                lineStart = pos+1;
2411                lines++;
2412            }
2413            pos++;
2414        }
2415        if (lines<minDisplayedLines)
2416            lines = minDisplayedLines;
2417        height = lines * metrics.getHeight();
2418        return new Dimension JavaDoc(width,height);
2419    }
2420
2421    public int getScrollableUnitIncrement(Rectangle JavaDoc visibleRect, int orientation, int direction)
2422    {
2423        return metrics.getHeight();
2424    }
2425
2426    /**************************************************
2427     * Copied from JTextComponent.
2428     */

2429    public int getScrollableBlockIncrement(Rectangle JavaDoc visibleRect, int orientation, int direction)
2430    {
2431        switch(orientation)
2432        {
2433            case SwingConstants.VERTICAL:
2434                return visibleRect.height;
2435            case SwingConstants.HORIZONTAL:
2436                return visibleRect.width;
2437            default:
2438                throw new IllegalArgumentException JavaDoc("Invalid orientation: " + orientation);
2439        }
2440    }
2441
2442    public boolean getScrollableTracksViewportWidth()
2443    {
2444        // Cast to Object to work around SwingWT inheritance bugs
2445
Object JavaDoc parent = getParent();
2446        return (parent instanceof JViewport JavaDoc) &&
2447            (((JViewport JavaDoc)parent).getWidth() > getPreferredSize().width);
2448    }
2449    public boolean getScrollableTracksViewportHeight()
2450    {
2451        // Cast to Object to work around SwingWT inheritance bugs
2452
Object JavaDoc parent = getParent();
2453        return (parent instanceof JViewport JavaDoc) &&
2454            (((JViewport JavaDoc)parent).getHeight() > getPreferredSize().height);
2455    }
2456
2457    /**********************/
2458   
2459    /**
2460     * Fiered if the SHEditor loses ownership of a Clipboard
2461     */

2462    public void lostOwnership(Clipboard JavaDoc cb, Transferable JavaDoc tr)
2463    {
2464    }
2465
2466    /**
2467     * The SHEditor has lost focus.
2468     */

2469    public void focusLost(FocusEvent JavaDoc e)
2470    {
2471        repaintCharAt(caretPosition);
2472    }
2473
2474    /**
2475     * The SHEditor has gained focus.
2476     */

2477    public void focusGained(FocusEvent JavaDoc e)
2478    {
2479        repaintCharAt(caretPosition);
2480    }
2481
2482    /**
2483     * Reads a file into SHEditor.
2484     * @param f the file to read into the SHEditor.
2485     */

2486    public void readFromFile(File JavaDoc f)
2487    {
2488        try
2489        {
2490            StringBuffer JavaDoc tmp = new StringBuffer JavaDoc();
2491            if (f.exists())
2492            {
2493                BufferedReader JavaDoc in =
2494                    new BufferedReader JavaDoc(
2495                        new InputStreamReader JavaDoc(
2496                            new BufferedInputStream JavaDoc(
2497                                new FileInputStream JavaDoc(f))));
2498            
2499                String JavaDoc read = in.readLine();
2500                boolean first = true;
2501            
2502                while (read != null)
2503                {
2504                    if (!first)
2505                    {
2506                        tmp.append("\n" + read);
2507                    }
2508                    else
2509                    {
2510                        first = false;
2511                        tmp.append(read);
2512                    }
2513                    read = in.readLine();
2514                }
2515                in.close();
2516                text = tmp.toString();
2517            }
2518        }
2519        catch(IOException JavaDoc e)
2520        {
2521            System.out.println("Error: " + e);
2522        }
2523        changed = false;
2524    }
2525
2526    /**
2527     * Saves the file in SHEditor to a file.
2528     * @param f the file where the content of the SHEditor should be saved.
2529     */

2530    public void saveToFile(File JavaDoc f)
2531    {
2532        try
2533        {
2534            PrintWriter JavaDoc out = new PrintWriter JavaDoc(new FileWriter JavaDoc(f));
2535            out.print(text);
2536            out.close();
2537        }
2538        catch(IOException JavaDoc e)
2539        {
2540            System.out.println("Error: " + e);
2541        }
2542        changed = false;
2543    }
2544
2545    /**
2546     * This class is a text action, it is used to undo redo actions..
2547     */

2548    static class TextAction
2549    {
2550        /**
2551         * The action is a remove action.
2552         */

2553        public final static int REMOVE = 0;
2554        /**
2555         * The action is a insert action.
2556         */

2557        public final static int INSERT = 1;
2558      
2559        int action;
2560        int position;
2561        int length;
2562        String JavaDoc string;
2563      
2564        /**
2565         * Constructs a new TextActiont.
2566         * @param a action type REMOVE or INSERT.
2567         * @param p the position of the action.
2568         * @param l the length of the action, only needed by a insert action.
2569         * @param s the string content of the action, only needed by a remove action.
2570         */

2571        TextAction(int a, int p, int l, String JavaDoc s)
2572        {
2573            action = a;
2574            position = p;
2575            length = l;
2576            string = s;
2577        }
2578    }
2579
2580    static class MutableCaretEvent extends CaretEvent JavaDoc {
2581        public MutableCaretEvent(Object JavaDoc source, int caretPosition) {
2582            super(source);
2583            this.caretPosition = caretPosition;
2584        }
2585        int caretPosition;
2586        public int getDot() {
2587            return caretPosition;
2588        }
2589        public int getMark() {
2590            return -1;
2591        }
2592    }
2593}
2594
Popular Tags