Preferences: continue to connect SciNotes
[scilab.git] / scilab / modules / scinotes / src / java / org / scilab / modules / scinotes / ScilabEditorPane.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - 2011 - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.scinotes;
14
15 import java.awt.Color;
16 import java.awt.Cursor;
17 import java.awt.Font;
18 import java.awt.Graphics;
19 import java.awt.Point;
20 import java.awt.Rectangle;
21 import java.awt.Shape;
22 import java.awt.event.FocusEvent;
23 import java.awt.event.FocusListener;
24 import java.awt.event.KeyEvent;
25 import java.awt.event.KeyListener;
26 import java.awt.event.MouseEvent;
27 import java.awt.event.MouseListener;
28 import java.awt.event.MouseMotionListener;
29 import java.io.File;
30 import java.util.ArrayList;
31 import java.util.EventObject;
32 import java.util.List;
33 import java.util.UUID;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 import javax.swing.JEditorPane;
38 import javax.swing.JScrollBar;
39 import javax.swing.JScrollPane;
40 import javax.swing.JSplitPane;
41 import javax.swing.SwingUtilities;
42 import javax.swing.UIManager;
43 import javax.swing.event.CaretEvent;
44 import javax.swing.event.CaretListener;
45 import javax.swing.event.EventListenerList;
46 import javax.swing.text.BadLocationException;
47 import javax.swing.text.Caret;
48 import javax.swing.text.DefaultHighlighter;
49 import javax.swing.text.Document;
50 import javax.swing.text.Element;
51 import javax.swing.text.Highlighter;
52 import javax.swing.text.JTextComponent;
53 import javax.swing.text.View;
54
55 import org.scilab.modules.commons.gui.ScilabCaret;
56 import org.scilab.modules.console.utils.ScilabLaTeXViewer;
57 import org.scilab.modules.gui.utils.WebBrowser;
58 import org.scilab.modules.scinotes.actions.CopyAsHTMLAction;
59 import org.scilab.modules.scinotes.actions.OpenSourceFileOnKeywordAction;
60 import org.scilab.modules.scinotes.utils.NavigatorWindow;
61 import org.scilab.modules.scinotes.utils.ScilabScrollPane;
62 import org.scilab.modules.scinotes.utils.SciNotesMessages;
63
64 /**
65  * Class ScilabEditorPane
66  * @author Calixte DENIZET
67  *
68  */
69 public class ScilabEditorPane extends JEditorPane implements Highlighter.HighlightPainter,
70     CaretListener, MouseListener,
71     MouseMotionListener, Cloneable,
72     KeyListener {
73
74     private static final long serialVersionUID = 4322071415211939097L;
75
76     private static final String TIRET = " - ";
77     private static final Cursor HANDCURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
78     private static final Cursor TEXTCURSOR = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
79     private static final DefaultHighlighter.DefaultHighlightPainter HIGHLIGHTER = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
80
81     private static ScilabEditorPane focused;
82
83     private Color highlightColor;
84     private Color highlightContourColor;
85     private boolean highlightEnable;
86     private Object highlightCL;
87     private boolean matchingKeywordsEnable;
88     private boolean matchingOpenersEnable;
89     private boolean overwriteMode;
90     private ScilabLexer lexer;
91     private SciNotes editor;
92     private IndentManager indent;
93     private TabManager tab;
94     private CommentManager com;
95     private HelpOnTypingManager helpOnTyping;
96     private TrailingWhiteManager trailingWhite;
97     private boolean readonly;
98     private boolean binary;
99     private String infoBar = "";
100     private String shortName = "";
101     private String title = "";
102
103     private Point mousePoint;
104
105     private long lastModified;
106
107     /* matchLR matches Left to Right ... */
108     private MatchingBlockManager matchLR;
109     private MatchingBlockManager matchRL;
110
111     private boolean suppressCom = true;
112
113     private SciNotesLineNumberPanel xln;
114     private ScilabEditorPane rightTextPane;
115     private UUID uuid;
116
117     private EditorComponent edComponent;
118
119     private boolean hand;
120     private boolean infoBarChanged;
121     private boolean ctrlHit;
122
123     private Color saveHighlightContourColor;
124     private Color saveHighlightColor;
125     private boolean hasBeenSaved;
126     private boolean saveHighlightEnable;
127
128     private EventListenerList kwListeners = new EventListenerList();
129     private List<Object> highlightedWords = new ArrayList<Object>();
130     private List<Integer> highlightedWordsBegin = new ArrayList<Integer>();
131
132     /**
133      * Constructor
134      * @param editor which uses this pane
135      */
136     public ScilabEditorPane(SciNotes editor) {
137         super();
138         if (focused == null) {
139             focused = this;
140         }
141         this.editor = editor;
142         this.uuid = UUID.randomUUID();
143         edComponent = new EditorComponent(this);
144
145         /*
146           When SciNotes is docked and has two tabs, switching the tabs causes a focus loss.
147           The focus is gave to the other docked component and that generates a toolbar change.
148           The solution is to set FocusCycleRoot to false (set to true by default in JEditorPane).
149         */
150         setFocusCycleRoot(false);
151
152         addCaretListener(this);
153         addMouseMotionListener(this);
154         addMouseListener(this);
155         enableMatchingKeywords(SciNotesOptions.getSciNotesDisplay().highlightKeywords);
156         enableMatchingOpeners(SciNotesOptions.getSciNotesDisplay().highlightBrackets);
157         setFocusable(true);
158         addFocusListener(new FocusListener() {
159             public void focusGained(FocusEvent e) {
160                 updateInfosWhenFocused();
161                 if (ScilabEditorPane.this.editor != null) {
162                     NavigatorWindow nav = ScilabEditorPane.this.editor.getNavigator();
163                     if (nav != null) {
164                         nav.update((ScilabDocument) getDocument());
165                     }
166                 }
167             }
168
169             public void focusLost(FocusEvent e) {
170                 ((ScilabDocument) getDocument()).setFocused(false);
171             }
172         });
173
174         addKeywordListener(new KeywordAdaptater.MouseOverAdaptater() {
175             public void caughtKeyword(KeywordEvent e) {
176                 if (ScilabLexerConstants.isClickable(e.getType())) {
177                     if (ctrlHit) {
178                         setCursor(HANDCURSOR);
179                         hand = true;
180                         try {
181                             String url = ((ScilabDocument) getDocument()).getText(e.getStart(), e.getLength());
182                             if (ScilabLexerConstants.isClickable(e.getType())) {
183                                 String text;
184                                 switch (e.getType()) {
185                                     case ScilabLexerConstants.URL :
186                                         text = SciNotesMessages.OPENURL;
187                                         break;
188                                     case ScilabLexerConstants.MAIL :
189                                         text = SciNotesMessages.MAILTO;
190                                         break;
191                                     case ScilabLexerConstants.MACROS :
192                                         text = SciNotesMessages.OPENSOURCE;
193                                         break;
194                                     case ScilabLexerConstants.MACROINFILE :
195                                         text = SciNotesMessages.SHOWSOURCE;
196                                         break;
197                                     default :
198                                         text = null;
199                                 }
200
201                                 if (text != null && ScilabEditorPane.this.editor != null) {
202                                     ScilabEditorPane.this.editor.getInfoBar().setText(text + url);
203                                     infoBarChanged = true;
204                                 }
205                             }
206                         } catch (BadLocationException ex) { }
207                     } else if (ScilabEditorPane.this.editor != null) {
208                         ScilabEditorPane.this.editor.getInfoBar().setText(SciNotesMessages.CLICKABLE_URL);
209                         infoBarChanged = true;
210                     }
211                 } else {
212                     if (hand) {
213                         setCursor(TEXTCURSOR);
214                         hand = false;
215                     }
216                     if (infoBarChanged && ScilabEditorPane.this.editor != null) {
217                         ScilabEditorPane.this.editor.getInfoBar().setText(infoBar);
218                         infoBarChanged = false;
219                     }
220                     if (ScilabLexerConstants.isLaTeX(e.getType())) {
221                         try {
222                             int start = e.getStart();
223                             int end = start + e.getLength();
224                             String exp = ((ScilabDocument) getDocument()).getText(start, e.getLength());
225                             int height = edComponent.getScrollPane().getHeight() + edComponent.getScrollPane().getVerticalScrollBar().getValue();
226                             ScilabLaTeXViewer.displayExpression(ScilabEditorPane.this, height, exp, start, end);
227                         } catch (BadLocationException ex) { }
228                     } else {
229                         ScilabLaTeXViewer.removeLaTeXViewer(ScilabEditorPane.this);
230                     }
231                 }
232             }
233         });
234
235         addKeywordListener(new KeywordAdaptater.MouseClickedAdaptater() {
236             public void caughtKeyword(KeywordEvent e) {
237                 if (ctrlHit && ScilabLexerConstants.isClickable(e.getType())) {
238                     try {
239                         hand = false;
240                         ctrlHit = false;
241                         infoBarChanged = false;
242                         setCursor(TEXTCURSOR);
243                         if (ScilabEditorPane.this.editor != null) {
244                             ScilabEditorPane.this.editor.getInfoBar().setText(infoBar);
245                         }
246                         String url = ((ScilabDocument) getDocument()).getText(e.getStart(), e.getLength());
247                         if (ScilabLexerConstants.URL == e.getType() || ScilabLexerConstants.MAIL == e.getType()) {
248                             WebBrowser.openUrl(url);
249                         } else if (ScilabLexerConstants.isOpenable(e.getType())) {
250                             OpenSourceFileOnKeywordAction.openSource(ScilabEditorPane.this, url);
251                         }
252                     } catch (BadLocationException ex) { }
253                 }
254             }
255         });
256
257         addKeyListener(this);
258         setTransferHandler(new CopyAsHTMLAction.HTMLTransferHandler());
259     }
260
261     public void enableColorization(boolean b) {
262         View view = ((ScilabDocument) getDocument()).getView();
263         if (view != null) {
264             if (view instanceof ScilabView) {
265                 ((ScilabView) view).enable(b);
266             } else {
267                 ((ScilabPlainView) view).enable(b);
268             }
269         }
270     }
271
272     public void configurationChanged(SciNotesConfiguration.Conf conf) {
273         ((ScilabEditorKit) getEditorKit()).getStylePreferences().configurationChanged(conf);
274
275         if (conf.display) {
276             enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
277             setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
278             enableColorization(SciNotesOptions.getSciNotesDisplay().keywordsColorization);
279
280             boolean kw = SciNotesOptions.getSciNotesDisplay().highlightKeywords;
281             boolean op = SciNotesOptions.getSciNotesDisplay().highlightBrackets;
282
283             if ((kw || op) && (!matchingKeywordsEnable && !matchingOpenersEnable)) {
284                 matchLR = new MatchingBlockManager((ScilabDocument) getDocument(), this, true, getHighlighter());
285                 matchLR.setDefaults();
286                 matchRL = new MatchingBlockManager((ScilabDocument) getDocument(), this, false, getHighlighter());
287                 matchRL.setDefaults();
288                 enableMatchingKeywords(kw);
289                 enableMatchingOpeners(op);
290                 return;
291             }
292
293             if ((kw || op) && (matchingKeywordsEnable || matchingOpenersEnable)) {
294                 matchLR.configurationChanged(conf);
295                 matchRL.configurationChanged(conf);
296                 return;
297             }
298
299             if ((!kw && !op) && (matchingKeywordsEnable || matchingOpenersEnable)) {
300                 matchLR.desactivateMouseOver();
301                 matchLR = null;
302                 matchRL.desactivateMouseOver();
303                 matchRL = null;
304                 return;
305             }
306         }
307     }
308
309     /**
310      * @return the lexer
311      */
312     public ScilabLexer getLexer() {
313         return lexer;
314     }
315
316     /**
317      * {@inheritDoc}
318      * When no split and in wrapped view , this method return true and the consequence is
319      * that there is no horizontal scrollbar.
320      */
321     public boolean getScrollableTracksViewportWidth() {
322         return ((ScilabDocument) getDocument()).getView() instanceof ScilabView && !edComponent.isSplited();
323     }
324
325     /**
326      * @return true if the pane is in OverWrite mode (insert)
327      */
328     public boolean getOverwriteMode() {
329         return this.overwriteMode;
330     }
331
332     /**
333      * @param overwriteMode true if the pane is in OverWrite mode (insert)
334      */
335     public void setOverwriteMode(boolean overwriteMode) {
336         this.overwriteMode = overwriteMode;
337         ((ScilabCaret) getCaret()).setOverwriteMode(overwriteMode);
338     }
339
340     /**
341      * {@inheritDoc}
342      */
343     public void replaceSelection(String content) {
344         if (overwriteMode && getSelectionStart() == getSelectionEnd()) {
345             int pos = getCaretPosition();
346             select(pos, pos + content.length());
347         }
348
349         if (((SciNotesCaret) getCaret()).isEmptySelection()) {
350             super.replaceSelection(content);
351         } else {
352             SciNotesCaret caret = (SciNotesCaret) getCaret();
353             int[][] pos = caret.getSelectedPositions();
354             List<Object> sels = caret.getSelections();
355             int len = content.length();
356             int res = 0;
357             int sres;
358             ScilabDocument doc = (ScilabDocument) getDocument();
359             ((CompoundUndoManager) doc.getUndoManager()).enableOneShot(true);
360             doc.mergeEditsBegin();
361             caret.protectHighlights(true);
362             for (int i = 0; i < pos.length; i++) {
363                 if (sels.get(i) != null) {
364                     sres = pos[i][0] + res;
365                     try {
366                         doc.replace(sres, pos[i][1] - pos[i][0], content, null);
367                     } catch (BadLocationException e) { }
368                     res = sres + len - pos[i][1];
369                     pos[i][0] = sres + len;
370                     pos[i][1] = sres + len;
371                 }
372             }
373             doc.mergeEditsEnd();
374             ((CompoundUndoManager) doc.getUndoManager()).enableOneShot(false);
375             caret.protectHighlights(false);
376             caret.updateHighlights();
377         }
378     }
379
380     /**
381      * Nothing !
382      * @param e the event
383      */
384     public void keyPressed(KeyEvent e) {
385         // Workaround for bug 7238
386         if (e.getKeyLocation() == KeyEvent.KEY_LOCATION_NUMPAD
387                 && e.getKeyCode() == KeyEvent.VK_DELETE
388                 && e.getKeyChar() != KeyEvent.VK_DELETE) {
389             e.setKeyCode(KeyEvent.VK_DECIMAL);
390             ctrlHit = false;
391         } else if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
392             ctrlHit = true;
393         } else {
394             ctrlHit = false;
395         }
396     }
397
398     /**
399      * Nothing !
400      * @param e the event
401      */
402     public void keyReleased(KeyEvent e) {
403         if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
404             ctrlHit = false;
405         }
406     }
407
408     /**
409      * Nothing !
410      * @param e the event
411      */
412     public void keyTyped(KeyEvent e) { }
413
414     /**
415      * @overload #setDocument
416      * @param doc to set
417      */
418     public void setDocument(Document doc) {
419         super.setDocument(doc);
420         if (doc instanceof ScilabDocument) {
421             ((ScilabDocument) doc).getUndoManager().discardAllEdits();
422             initialize((ScilabDocument) doc);
423         }
424     }
425
426     /**
427      * {@inheritDoc}
428      */
429     public void setName(String name) {
430         setNameInSuper(name);
431         setShortNameAndTitle(name);
432         ScilabEditorPane pane = getOtherPaneInSplit();
433         if (pane != null) {
434             // I don't call pane.setName since we will enter in an infinite loop
435             pane.setNameInSuper(name);
436             pane.setShortNameAndTitle(name);
437         }
438     }
439
440     /**
441      * @param name the name
442      */
443     private void setNameInSuper(String name) {
444         super.setName(name);
445     }
446
447     /**
448      * @param name the name
449      */
450     private void setShortNameAndTitle(String name) {
451         if (name != null) {
452             File f = new File(name);
453             setShortName(f.getName());
454             title =  shortName + " (" + f.getAbsolutePath() + ")" + TIRET + SciNotesMessages.SCILAB_EDITOR;
455         }
456     }
457
458     /**
459      * @param title the title
460      */
461     public void setTitle(String title) {
462         this.title = title + TIRET + SciNotesMessages.SCILAB_EDITOR;
463     }
464
465     /**
466      * @return the title
467      */
468     public String getTitle() {
469         return title;
470     }
471
472     /**
473      * @param name the short name
474      */
475     public void setShortName(String name) {
476         this.shortName = name;
477     }
478
479     /**
480      * @return the short name of the file (without the full path)
481      */
482     public String getShortName() {
483         return shortName;
484     }
485
486     /**
487      * Init the pane
488      */
489     public void init() {
490         SwingUtilities.invokeLater(new Runnable() {
491             public void run() {
492                 requestFocus();
493                 setCaretPosition(0);
494             }
495         });
496     }
497
498     /**
499      * Close this pane
500      */
501     public void close() {
502         FocusListener[] l = getFocusListeners();
503         for (int i = 0; i < l.length; i++) {
504             removeFocusListener(l[i]);
505         }
506     }
507
508     /**
509      * Update infos
510      */
511     public void updateInfosWhenFocused() {
512         ScilabDocument doc = (ScilabDocument) getDocument();
513         doc.setFocused(true);
514         SciNotes.setEditor(editor);
515         focused = this;
516         doc.getUndoManager().enableUndoRedoButtons();
517
518         if (editor != null) {
519             if (checkExternalModif()) {
520                 editor.getInfoBar().setText(SciNotesMessages.EXTERNAL_MODIFICATION_INFO);
521             } else {
522                 editor.getInfoBar().setText(getInfoBarText());
523             }
524         }
525     }
526
527     /**
528      * @return true if an external modif occured
529      */
530     public boolean checkExternalModif() {
531         String path = getName();
532         if (path != null) {
533             File f = new File(path);
534             if (f != null && f.exists()) {
535                 return lastModified < f.lastModified();
536             } else {
537                 return true;
538             }
539         }
540         return false;
541     }
542
543     /**
544      * @return the String which must be displayed in the infobar
545      */
546     public String getInfoBarText() {
547         return infoBar;
548     }
549
550     /**
551      * @param text String which must be displayed in the infobar
552      */
553     public void setInfoBarText(String text) {
554         this.infoBar = text;
555         if (editor != null) {
556             editor.getInfoBar().setText(getInfoBarText());
557         }
558     }
559
560     /**
561      * @param readonly true to set Read-Only mode
562      */
563     public void setReadOnly(boolean readonly) {
564         this.readonly = readonly;
565         setEditable(!readonly);
566         setDragEnabled(!readonly);
567         if (readonly) {
568             infoBar = SciNotesMessages.READ_ONLY_MODE;
569         } else {
570             infoBar = "";
571         }
572     }
573
574     /**
575      * @param binary true to set binary mode
576      */
577     public void setBinary(boolean binary) {
578         this.binary = binary;
579         setEditable(!binary);
580         setDragEnabled(!binary);
581         if (binary) {
582             infoBar = SciNotesMessages.BINARY_FILE_MODE;
583             disableAll();
584         } else {
585             infoBar = "";
586         }
587     }
588
589     /**
590      * Copy the props of this textPane to pane
591      * @param pane the pane which receives the same props as this
592      */
593     public void copyProps(ScilabEditorPane pane) {
594         pane.lastModified = lastModified;
595         pane.highlightEnable = highlightEnable;
596         pane.matchingKeywordsEnable = matchingKeywordsEnable;
597         pane.matchingOpenersEnable = matchingOpenersEnable;
598         pane.suppressCom = suppressCom;
599         pane.setName(getName());
600         pane.setShortName(getShortName());
601         pane.setTitle(getTitle().substring(0, getTitle().lastIndexOf(TIRET)));
602         pane.setEditable(isEditable());
603     }
604
605     /**
606      * Get the UUID associated with the editor pane instance.
607      * @return unique identifier
608      */
609     public UUID getUUID() {
610         return uuid;
611     }
612
613     /**
614      * Get the the time where the file associated with this pane
615      * has been modified.
616      * @return the last modified time or 0
617      */
618     public long getLastModified() {
619         return lastModified;
620     }
621
622     /**
623      * Set the last time where the file associated with this pane
624      * has been modified.
625      * @param time the time
626      */
627     public void setLastModified(long time) {
628         this.lastModified = time;
629         ScilabEditorPane pane = getOtherPaneInSplit();
630         if (pane != null) {
631             pane.lastModified = time;
632         }
633     }
634
635     /**
636      * @return the SciNotesLineNumberPanel used with this pane
637      */
638     public SciNotesLineNumberPanel getXln() {
639         return xln;
640     }
641
642     /**
643      * @return the editor
644      */
645     public SciNotes getEditor() {
646         return editor;
647     }
648
649     /**
650      * @param editor to set
651      */
652     public void setEditor(SciNotes editor) {
653         this.editor = editor;
654     }
655
656     /**
657      * Disable all
658      */
659     public void disableAll() {
660         indent = null;
661         tab = null;
662         com = null;
663         trailingWhite = null;
664         enableMatchingKeywords(false);
665         enableMatchingOpeners(false);
666         matchLR.desactivateMouseOver();
667         matchLR = null;
668         matchRL.desactivateMouseOver();
669         matchRL = null;
670     }
671
672     /**
673      * Destroy this component
674      */
675     public void destroy() {
676         FocusListener[] fls = getFocusListeners();
677         for (FocusListener fl : fls) {
678             removeFocusListener(fl);
679         }
680         disableAll();
681     }
682
683     /**
684      * @return the scrollPane or the splitpane associated with this textPane
685      */
686     public EditorComponent getEditorComponent() {
687         return edComponent;
688     }
689
690     /**
691      * @return the scrollPane or the splitpane associated with this textPane
692      */
693     public void setEditorComponent(EditorComponent ed) {
694         this.edComponent = ed;
695     }
696
697     /**
698      * @param split the split used
699      */
700     public void setSplitPane(JSplitPane split) {
701         edComponent.setSplitPane(split);
702     }
703
704     /**
705      * @param split the split used
706      */
707     public JSplitPane getSplitPane() {
708         return edComponent.getSplitPane();
709     }
710
711     /**
712      * Update the title of current tab
713      */
714     public void updateTitle() {
715         if (editor != null) {
716             editor.updateTabTitle();
717         }
718     }
719
720     /**
721      * Scroll the pane to have the line containing pos on the top of the pane
722      * @param pos the position in the document
723      */
724     public void scrollTextToPos(int pos) {
725         scrollTextToPos(pos, true, false);
726     }
727
728     /**
729      * Scroll the pane to have the line containing pos on the top or centered on the pane
730      * @param pos the position in the document
731      * @param setCaret, if true the caret is set at the given position
732      * @param centered, if true the line is centered
733      */
734     public void scrollTextToPos(final int pos, final boolean setCaret, final boolean centered) {
735         SwingUtilities.invokeLater(new Runnable() {
736             public void run() {
737                 try {
738                     if (setCaret) {
739                         setCaretPosition(pos);
740                     }
741                     JScrollBar scrollbar = edComponent.getScrollPane().getVerticalScrollBar();
742                     Rectangle rect = modelToView(pos);
743                     if (centered) {
744                         int value = scrollbar.getValue();
745                         int h = scrollbar.getHeight();
746                         if (rect.y < value || rect.y > value + h) {
747                             scrollbar.setValue(Math.max(0, rect.y - h / 2));
748                         }
749                     } else {
750                         if (rect.y > scrollbar.getMaximum()) {
751                             scrollbar.setMaximum(rect.y);
752                         }
753                         scrollbar.setValue(rect.y);
754                     }
755                 } catch (BadLocationException e) { }
756             }
757         });
758     }
759
760     /**
761      * Scroll the pane to have the line lineNumber on the top of the pane
762      * @param lineNumber the number of the line
763      * @param highlight true to highlight the line
764      */
765     public void scrollTextToLineNumber(int lineNumber, boolean highlight) {
766         scrollTextToLineNumber(lineNumber, highlight, true, false);
767     }
768
769     /**
770      * Scroll the pane to have the line lineNumber on the top or centered on the pane
771      * @param lineNumber the number of the line
772      * @param highlight true to highlight the line
773      * @param setCaret, if true the caret is set at the given line
774      * @param centered, if true the line is centered
775      */
776     public void scrollTextToLineNumber(int lineNumber, final boolean highlight, final boolean setCaret, final boolean centered) {
777         Element root = getDocument().getDefaultRootElement();
778         if (lineNumber >= 1 && lineNumber <= root.getElementCount()) {
779             final int pos = root.getElement(lineNumber - 1).getStartOffset();
780             SwingUtilities.invokeLater(new Runnable() {
781                 public void run() {
782                     scrollTextToPos(pos, setCaret, centered);
783                     if (highlight) {
784                         saveHighlightContourColor = highlightContourColor;
785                         highlightContourColor = null;
786                         saveHighlightColor = highlightColor;
787                         highlightColor = Color.YELLOW;
788                         saveHighlightEnable = highlightEnable;
789                         hasBeenSaved = true;
790                         enableHighlightedLine(false);
791                         enableHighlightedLine(true);
792                     }
793                 }
794             });
795         }
796     }
797
798     /**
799      * Scroll the pane to have the line lineNumber on the top of the pane in whereami mode
800      * The line number is computed regarding the function named funname.
801      * @param lineNumber the number of the line
802      * @param funname the function name
803      * @param highlight true to highlight the line
804      */
805     public void scrollTextToLineNumberInWhereami(int lineNumber, String funname, boolean highlight) {
806         scrollTextToLineNumberInWhereami(lineNumber, funname, highlight, true, false);
807     }
808
809     /**
810      * Scroll the pane to have the line lineNumber on the top of the pane in whereami mode
811      * The line number is computed regarding the function named funname.
812      * @param lineNumber the number of the line
813      * @param funname the function name
814      * @param highlight true to highlight the line
815      * @param setCaret, if true the caret is set at the given line
816      * @param centered, if true the line is centered
817      */
818     public void scrollTextToLineNumberInWhereami(int lineNumber, String funname, boolean highlight, boolean setCaret, boolean centered) {
819         if (funname != null) {
820             Element root = getDocument().getDefaultRootElement();
821             int nlines = root.getElementCount();
822             ScilabDocument.ScilabLeafElement elem;
823             for (int i = 0; i < nlines; i++) {
824                 elem = (ScilabDocument.ScilabLeafElement) root.getElement(i);
825                 if (elem.getFunctionName().equals(funname)) {
826                     lineNumber += i;
827                     break;
828                 }
829             }
830         }
831         scrollTextToLineNumber(lineNumber, highlight, setCaret, centered);
832     }
833
834     /**
835      * @return the width of a white
836      */
837     public int getWhiteWidth() {
838         View view = ((ScilabDocument) getDocument()).getView();
839         if (view != null) {
840             if (view instanceof ScilabView) {
841                 return ((ScilabView) view).getWhiteWidth();
842             } else {
843                 return ((ScilabPlainView) view).getWhiteWidth();
844             }
845         }
846
847         return 0;
848     }
849
850     /**
851      * Set a new font
852      * @param keyword the type of keyword
853      * @param type an int : -2 to reset italic, -1 to reset bold, 1 to set bold and 2 to set italic
854      */
855     public void resetFont(String keyword, int type) {
856         ((ScilabEditorKit) getEditorKit()).getStylePreferences().genFont(keyword, type);
857     }
858
859     /**
860      * Set a new attribute
861      * @param keyword the type of keyword
862      * @param type an int : 0 nothing, 1 underline, 2 stroke, 3 underline and stroke
863      */
864     public void resetAttribute(String keyword, int type) {
865         ((ScilabEditorKit) getEditorKit()).getStylePreferences().genAttribute(keyword, type);
866     }
867
868     /**
869      * Set a new color
870      * @param keyword the kind of the keyword
871      * @param color the color
872      */
873     public void resetColor(String keyword, Color color) {
874         ((ScilabEditorKit) getEditorKit()).getStylePreferences().genColors(keyword, color);
875     }
876
877     /**
878      * Set to true if the comments must be suppressed when the code is executing in the console
879      * @param b boolean
880      */
881     public void suppressCommentsInExecutingCode(boolean b) {
882         suppressCom = b;
883     }
884
885     /**
886      * Execute the code in the console, the code is the selected text if exists
887      * or the text from beginning to actual position of the caret
888      * Comments are removed if suppressCom is set to true
889      * @return the code to be executed in the console.
890      */
891     public String getCodeToExecute() {
892         String selection;
893         int start, end;
894         start = getSelectionStart();
895         end = getSelectionEnd();
896
897         if (((SciNotesCaret) getCaret()).isEmptySelection()) {
898             try {
899                 if (start == end) {
900                     selection = getDocument().getText(0, start);
901                     start = 0;
902                 } else {
903                     selection = getSelectedText();
904                 }
905             } catch (BadLocationException e) {
906                 selection = "";
907             }
908         } else {
909             selection = getSelectedText();
910         }
911
912         if (suppressCom) {
913             StringBuffer buf = new StringBuffer(selection.length());
914             int sstart = start;
915             int tok = lexer.getKeyword(start, false);
916             int len = selection.length();
917             while (start < end) {
918                 int pos = lexer.start + lexer.yychar() + lexer.yylength();
919                 String str = selection.substring(start - sstart, Math.min(pos - sstart, len));
920                 if (!ScilabLexerConstants.isComment(tok) || str.equals("\n")) {
921                     buf.append(str);
922                 }
923                 start = pos;
924                 tok = lexer.getKeyword(start, false);
925             }
926
927             return buf.toString();
928         }
929
930         return selection;
931     }
932
933     /**
934      * Add a new KeywordListener
935      * @param kw a KeywordListener
936      */
937     public void addKeywordListener(KeywordListener kw) {
938         kwListeners.add(KeywordListener.class, kw);
939     }
940
941     /**
942      * Remove a new KeywordListener
943      * @param kw a KeywordListener
944      */
945     public void removeKeywordListener(KeywordListener kw) {
946         kwListeners.remove(KeywordListener.class, kw);
947     }
948
949     /**
950      * @return an array of KeywordListener
951      */
952     public KeywordListener[] getKeywordListeners() {
953         return kwListeners.getListeners(KeywordListener.class);
954     }
955
956     /**
957      * Set a new color for the highlighting
958      * @param c the color, can be null (useful if setHighlightedContourColor is used with a
959      * non-null value)
960      */
961     public void setHighlightedLineColor(Color c) {
962         highlightColor = c;
963     }
964
965     /**
966      * Set a new color for the contour of the highlighting
967      * @param c the color, if null no contour is drawn
968      */
969     public void setHighlightedContourColor(Color c) {
970         highlightContourColor = c;
971     }
972
973     /**
974      * Activate or desactivate the help on typing
975      */
976     public void activateHelpOnTyping() {
977         boolean isActive = HelpOnTypingManager.isActive();
978         if (isActive && helpOnTyping == null) {
979             helpOnTyping = HelpOnTypingManager.getInstance();
980             addKeyListener(helpOnTyping);
981         } else if (!isActive && helpOnTyping != null) {
982             removeKeyListener(helpOnTyping);
983             helpOnTyping = null;
984         }
985     }
986
987     /**
988      * Enable (active true) or disable (active false) the line-highlighting.
989      * @param active true or false
990      */
991     public void enableHighlightedLine(boolean active) {
992         if (active && !highlightEnable) {
993             try {
994                 highlightCL = getHighlighter().addHighlight(0, 0, this);
995             } catch (BadLocationException e) { }
996             highlightEnable = true;
997         }
998
999         if (!active && highlightEnable) {
1000             getHighlighter().removeHighlight(highlightCL);
1001             highlightEnable = false;
1002         }
1003
1004         repaint();
1005     }
1006
1007     /**
1008      * Enable (active true) or disable (active false) the matching keywords.
1009      * @param active true or false
1010      */
1011     public void enableMatchingKeywords(boolean active) {
1012         matchingKeywordsEnable = active;
1013     }
1014
1015     /**
1016      * Enable (active true) or disable (active false) the matching keywords.
1017      * @param active true or false
1018      */
1019     public void enableMatchingOpeners(boolean active) {
1020         matchingOpenersEnable = active;
1021     }
1022
1023     /**
1024      * Get a matching manager
1025      * @param lr true if the LR matcher must be returned
1026      * @return the MatchingBlockManager
1027      */
1028     public MatchingBlockManager getMatchingBlockManager(boolean lr) {
1029         if (lr) {
1030             return matchLR;
1031         } else {
1032             return matchRL;
1033         }
1034     }
1035
1036     /**
1037      * This class listens to the caret event
1038      * @param e event
1039      */
1040     public void caretUpdate(CaretEvent e) {
1041         if (hasBeenSaved) {
1042             removeHighlightForLine();
1043         }
1044
1045         if (hasFocus()) {
1046             String str = getSelectedText();
1047             if (str != null && str.length() != 0) {
1048                 highlightWords(str, true);
1049                 removeHighlightOnPosition(getSelectionStart());
1050             } else {
1051                 removeHighlightedWords();
1052             }
1053         }
1054
1055         if (highlightEnable) {
1056             repaint();
1057         }
1058
1059         int pos = getCaretPosition();
1060
1061         if (matchingKeywordsEnable || matchingOpenersEnable) {
1062             int tok = lexer.getKeyword(pos, false);
1063             matchLR.searchMatchingBlock(false, tok, lexer.start + lexer.yychar());
1064             tok = lexer.getKeyword(pos, true);
1065             matchRL.searchMatchingBlock(false, tok, lexer.start + lexer.yychar() + lexer.yylength());
1066         }
1067
1068         if (!readonly && !binary && editor != null) {
1069             editor.getInfoBar().setText(((ScilabDocument) getDocument()).getCurrentFunction(pos));
1070         }
1071     }
1072
1073     /**
1074      * Used to paint the highlighted line
1075      * @param g graphics to use
1076      * @param p0 start
1077      * @param p1 end
1078      * @param bounds the shape representing the area
1079      * @param c this pane
1080      */
1081     public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
1082         if (highlightEnable) {
1083             try {
1084                 Rectangle r = modelToView(getCaretPosition());
1085                 if (highlightColor != null) {
1086                     g.setColor(highlightColor);
1087                     g.fillRect(0, r.y, getWidth(), r.height);
1088                 }
1089                 if (highlightContourColor != null) {
1090                     g.setColor(highlightContourColor);
1091                     g.drawLine(0, r.y - 1, getWidth(), r.y - 1);
1092                     g.drawLine(0, r.y + r.height, getWidth(), r.y + r.height);
1093                 }
1094
1095             } catch (BadLocationException e) { }
1096         }
1097     }
1098
1099     /**
1100      * @return the current TrailingWhiteManager
1101      */
1102     public TrailingWhiteManager getTrailingWhiteManager() {
1103         return trailingWhite;
1104     }
1105
1106     /**
1107      * @return the current IndentManager
1108      */
1109     public IndentManager getIndentManager() {
1110         return indent;
1111     }
1112
1113     /**
1114      * @return the current TabManager
1115      */
1116     public TabManager getTabManager() {
1117         return tab;
1118     }
1119
1120     /**
1121      * @return the current CommentManager
1122      */
1123     public CommentManager getCommentManager() {
1124         return com;
1125     }
1126
1127     /**
1128      * Get a keyword at a position in the document.
1129      * @param position in the document
1130      * @return the KeywordEvent containing infos about keyword.
1131      */
1132     public KeywordEvent getKeywordEvent(int position) {
1133         int tok = lexer.getKeyword(position, true);
1134         return new KeywordEvent(this, null, tok, lexer.start + lexer.yychar(), lexer.yylength());
1135     }
1136
1137     /**
1138      * Get a keyword at the current position in the document.
1139      * @return the KeywordEvent containing infos about keyword.
1140      */
1141     public KeywordEvent getKeywordEvent() {
1142         return getKeywordEvent(getCaretPosition());
1143     }
1144
1145     /**
1146      * Get a keyword at the current position in the document.
1147      * @param caret if true the position is the current caret position in the doc else
1148      * the position is the mouse pointer position projected in the document.
1149      * @param strict if true the char just after the caret is ignored
1150      * @return the KeywordEvent containing infos about keyword.
1151      */
1152     public KeywordEvent getKeywordEvent(boolean caret, boolean strict) {
1153         int tok;
1154         if (caret) {
1155             tok = lexer.getKeyword(getCaretPosition(), strict);
1156         } else {
1157             tok = lexer.getKeyword(viewToModel(mousePoint), strict);
1158         }
1159         return new KeywordEvent(this, null, tok, lexer.start + lexer.yychar(), lexer.yylength());
1160     }
1161
1162     /**
1163      * Get an helpable keyword at the current position in the document.
1164      * @param caret if true the position is the current caret position in the doc else
1165      * the position is the mouse pointer position projected in the document.
1166      * @return the helpable keyword.
1167      */
1168     public String getHelpableKeyword(boolean caret) {
1169         int tok;
1170         int pos;
1171         if (caret) {
1172             pos = getCaretPosition();
1173         } else {
1174             pos = viewToModel(mousePoint);
1175         }
1176
1177         tok = lexer.getKeyword(pos, true);
1178         if (!ScilabLexerConstants.isHelpable(tok)) {
1179             tok = lexer.getKeyword(pos + 1, true);
1180         }
1181
1182         if (ScilabLexerConstants.isHelpable(tok)) {
1183             try {
1184                 return getDocument().getText(lexer.start + lexer.yychar(), lexer.yylength());
1185             } catch (BadLocationException e) { }
1186         }
1187
1188         return null;
1189     }
1190
1191     /**
1192      * Prevents the different KeywordListener that a MouseEvent occured
1193      * @param position of the mouse
1194      * @param ev the event which occured
1195      * @param type of the event : KeywordListener.ONMOUSECLICKED or KeywordListener.ONMOUSEOVER
1196      */
1197     protected void preventConcernedKeywordListener(int position, EventObject ev, int type) {
1198         KeywordEvent kev = null;
1199         Object[] listeners = kwListeners.getListenerList();
1200         for (int i = listeners.length - 2; i >= 0; i -= 2) {
1201             if (listeners[i] == KeywordListener.class && type == ((KeywordListener) listeners[i + 1]).getType()) {
1202                 if (kev == null) {
1203                     int tok = lexer.getKeyword(position, true);
1204                     kev = new KeywordEvent(this, ev, tok, lexer.start + lexer.yychar(), lexer.yylength());
1205                 }
1206
1207                 ((KeywordListener) listeners[i + 1]).caughtKeyword(kev);
1208             }
1209         }
1210     }
1211
1212     /**
1213      * Implements mouseClicked in MouseListener
1214      * @param e event
1215      */
1216     public void mouseClicked(MouseEvent e) {
1217         preventConcernedKeywordListener(getCaretPosition(), e, KeywordListener.ONMOUSECLICKED);
1218     }
1219
1220     /**
1221      * Implements mouseEntered in MouseListener
1222      * @param e event
1223      */
1224     public void mouseEntered(MouseEvent e) {
1225         this.mousePoint = e.getPoint();
1226     }
1227
1228     /**
1229      * Implements mouseExited in MouseListener
1230      * @param e event
1231      */
1232     public void mouseExited(MouseEvent e) { }
1233
1234     /**
1235      * Implements mousePressed in MouseListener
1236      * @param e event
1237      */
1238     public void mousePressed(MouseEvent e) {
1239         if (hasBeenSaved) {
1240             removeHighlightForLine();
1241         }
1242
1243         removeHighlightedWords();
1244
1245         if (highlightEnable) {
1246             repaint();
1247         }
1248     }
1249
1250     /**
1251      * Implements mouseReleseaed in MouseListener
1252      * @param e event
1253      */
1254     public void mouseReleased(MouseEvent e) { }
1255
1256     /**
1257      * Implements mouseMoved in MouseMotionListener
1258      * @param e event
1259      */
1260     public void mouseMoved(MouseEvent e) {
1261         this.mousePoint = e.getPoint();
1262         preventConcernedKeywordListener(viewToModel(mousePoint), e, KeywordListener.ONMOUSEOVER);
1263     }
1264
1265     /**
1266      * Implements mouseDragged in MouseMotionListener
1267      * @param e event
1268      */
1269     public void mouseDragged(MouseEvent e) {
1270         if (hasBeenSaved) {
1271             removeHighlightForLine();
1272         }
1273
1274         removeHighlightedWords();
1275
1276         if (highlightEnable) {
1277             repaint();
1278         }
1279     }
1280
1281     /**
1282      * @return the current mouse poisition in this pane
1283      */
1284     public Point getMousePoint() {
1285         return mousePoint;
1286     }
1287
1288     /**
1289      * @param pane the EditorPane associated with this EditorPane in a splitted view
1290      */
1291     public void setOtherPaneInSplit(ScilabEditorPane pane) {
1292         if (pane == null) {
1293             rightTextPane.rightTextPane = null;
1294         }
1295         rightTextPane = pane;
1296     }
1297
1298     /**
1299      * @return the EditorPane associated with this EditorPane in a splitted view
1300      */
1301     public ScilabEditorPane getOtherPaneInSplit() {
1302         return rightTextPane;
1303     }
1304
1305     /**
1306      * @return the scrollPane associated with this EditorPane
1307      */
1308     public JScrollPane getScrollPane() {
1309         return edComponent.getScrollPane();
1310     }
1311
1312     /**
1313      * @return the current focused editorPane
1314      */
1315     public static ScilabEditorPane getFocusedPane() {
1316         return focused;
1317     }
1318
1319     /**
1320      * {@inheritDoc}
1321      */
1322     public String toString() {
1323         return shortName;
1324     }
1325
1326     /**
1327      * @return true if something has been copied
1328      */
1329     public boolean copyColumnSelectionInClipBoard() {
1330         return ((SciNotesCaret) getCaret()).copyPositionsInClipboard();
1331     }
1332
1333     /**
1334      * @return true if something has been removed
1335      */
1336     public boolean removeColumnSelection() {
1337         return ((SciNotesCaret) getCaret()).removePositions();
1338     }
1339
1340     /**
1341      * {@inheritDoc}
1342      */
1343     public String getSelectedText() {
1344         String str = ((SciNotesCaret) getCaret()).getSelectedText();
1345         if (str == null) {
1346             return super.getSelectedText();
1347         } else {
1348             return str;
1349         }
1350     }
1351
1352     /**
1353      * @param pos the position int the text
1354      * @return null if no column selection on the same line and an array of
1355      * integer (of size 2) containing the position of the selection
1356      */
1357     public int[] isNearColumnSelection(int pos) {
1358         if (!(getCaret() instanceof SciNotesCaret) || ((SciNotesCaret) getCaret()).isEmptySelection()) {
1359             return null;
1360         }
1361
1362         Element root = getDocument().getDefaultRootElement();
1363         int[][] positions = ((SciNotesCaret) getCaret()).getSelectedPositions();
1364         int line = root.getElementIndex(pos);
1365         int min = root.getElementIndex(positions[0][0]);
1366         int max = root.getElementIndex(positions[positions.length - 1][0]);
1367
1368         if (line >= min && line <= max) {
1369             return positions[line - min];
1370         }
1371
1372         return null;
1373     }
1374
1375     /**
1376      * {@inheritDoc}
1377      */
1378     public void setCaret(Caret c) {
1379         if (!(c instanceof ScilabCaret)) {
1380             final Caret caret = new SciNotesCaret(this);
1381             setCaretColor(getCaretColor());
1382             SwingUtilities.invokeLater(new Runnable() {
1383                 public void run() {
1384                     int blinkRate = 500;
1385                     Object o = UIManager.get("TextComponent.caretBlinkRate");
1386                     if ((o != null) && (o instanceof Integer)) {
1387                         Integer rate = (Integer) o;
1388                         blinkRate = rate.intValue();
1389                     }
1390                     caret.setBlinkRate(blinkRate);
1391                     caret.setVisible(true);
1392                 }
1393             });
1394             super.setCaret(caret);
1395         } else {
1396             super.setCaret(c);
1397         }
1398     }
1399
1400     /**
1401      * {@inheritDoc}
1402      */
1403     public void select(int start, int end) {
1404         removeHighlightOnPosition(start);
1405         int docLength = getDocument().getLength();
1406         if (start > docLength) {
1407             start = docLength;
1408         }
1409         if (end > docLength) {
1410             end = docLength;
1411         }
1412         super.setCaretPosition(start);
1413         super.moveCaretPosition(end);
1414     }
1415
1416     /**
1417      * Remove the highlight putted to show the line (for editor('foo',123))
1418      */
1419     private void removeHighlightForLine() {
1420         highlightContourColor = saveHighlightContourColor;
1421         highlightColor = saveHighlightColor;
1422         enableHighlightedLine(false);
1423         if (saveHighlightEnable) {
1424             enableHighlightedLine(true);
1425         }
1426         hasBeenSaved = false;
1427     }
1428
1429     /**
1430      * Remove the highlight at position start
1431      * @param start the beginning of the highlight
1432      */
1433     public void removeHighlightOnPosition(int start) {
1434         int pos = highlightedWordsBegin.indexOf(start);
1435         if (pos != -1) {
1436             getHighlighter().removeHighlight(highlightedWords.remove(pos));
1437             highlightedWordsBegin.remove(pos);
1438         }
1439     }
1440
1441     /**
1442      * Highlight a word in this textpane.
1443      * @param word the word to highlight
1444      * @param exact if true the search is case sensitive
1445      */
1446     public void highlightWords(String word, boolean exact) {
1447         removeHighlightedWords();
1448         if (word != null && word.length() != 0) {
1449             String text = ((ScilabDocument) getDocument()).getText();
1450             if (!exact) {
1451                 text = text.toLowerCase();
1452                 word = word.toLowerCase();
1453             }
1454
1455             int pos = text.indexOf(word, 0);
1456             int len = word.length();
1457             Highlighter highlighter = getHighlighter();
1458             List<Rectangle> marks = new ArrayList<Rectangle>();
1459             while (pos != -1) {
1460                 try {
1461                     highlightedWords.add(highlighter.addHighlight(pos, pos + len, HIGHLIGHTER));
1462                     highlightedWordsBegin.add(pos);
1463                     Rectangle r = modelToView(pos);
1464                     if (marks.size() == 0 || marks.get(marks.size() - 1).y != r.y) {
1465                         marks.add(r);
1466                     }
1467                 } catch (BadLocationException e) { }
1468                 pos = text.indexOf(word, pos + len);
1469             }
1470             ((ScilabScrollPane) edComponent.getScrollPane()).putMarks(marks);
1471         }
1472     }
1473
1474     /**
1475      * Highlight a word according to a pattern in this textpane.
1476      * @param pattern the pattern to highlight
1477      * @param centered, if true the pane is centered on the first occurence
1478      */
1479     public void highlightWords(Pattern pattern, boolean centered) {
1480         if (pattern != null) {
1481             removeHighlightedWords();
1482             int first = -1;
1483             String text = ((ScilabDocument) getDocument()).getText();
1484             Matcher matcher = pattern.matcher(text);
1485
1486             Highlighter highlighter = getHighlighter();
1487             List<Rectangle> marks = new ArrayList<Rectangle>();
1488             while (matcher.find()) {
1489                 if (first == -1) {
1490                     first = matcher.start();
1491                 }
1492                 try {
1493                     int start = matcher.start();
1494                     highlightedWords.add(highlighter.addHighlight(start, matcher.end(), HIGHLIGHTER));
1495                     highlightedWordsBegin.add(start);
1496                     Rectangle r = modelToView(start);
1497                     if (marks.size() == 0 || marks.get(marks.size() - 1).y != r.y) {
1498                         marks.add(r);
1499                     }
1500                 } catch (BadLocationException e) { }
1501             }
1502
1503             ((ScilabScrollPane) edComponent.getScrollPane()).putMarks(marks);
1504
1505             if (centered && first != -1) {
1506                 scrollTextToPos(first, false, true);
1507             }
1508         }
1509     }
1510
1511     /**
1512      * Remove all the highlighted words
1513      */
1514     public void removeHighlightedWords() {
1515         Highlighter highlighter = getHighlighter();
1516         for (Object obj : highlightedWords) {
1517             highlighter.removeHighlight(obj);
1518         }
1519         highlightedWords.clear();
1520         highlightedWordsBegin.clear();
1521         ((ScilabScrollPane) edComponent.getScrollPane()).removeMarks();
1522     }
1523
1524     /**
1525      * Initialize the pane when the document is loaded
1526      * @param doc used with this pane
1527      */
1528     private void initialize(ScilabDocument doc) {
1529         indent = new IndentManager(doc);
1530         tab = new TabManager(doc, indent);
1531         tab.setDefaultTabulation();
1532         com = new CommentManager(doc);
1533         trailingWhite = new TrailingWhiteManager(doc);
1534
1535         if (matchingKeywordsEnable || matchingOpenersEnable) {
1536             matchLR = new MatchingBlockManager(doc, this, true, getHighlighter());
1537             matchLR.setDefaults();
1538             matchRL = new MatchingBlockManager(doc, this, false, getHighlighter());
1539             matchRL.setDefaults();
1540         }
1541
1542         lexer = doc.createLexer();
1543         xln = new SciNotesLineNumberPanel(this);
1544
1545         /* The order of the next two lines is important: the doc
1546            as listener will be called before xln so the resetTypeWhenBroken
1547            will be called before ! */
1548         doc.addDocumentListener(xln);
1549         doc.addDocumentListener(doc);
1550
1551         edComponent.getScrollPane().setRowHeaderView(xln);
1552         doc.setEditorPane(this);
1553
1554         if (editor != null) {
1555             NavigatorWindow nav = editor.getNavigator();
1556             if (nav != null) {
1557                 nav.addEditorPane(this);
1558             }
1559         }
1560     }
1561 }