Desktop: Add a button in dockbar to get the help about the component
[scilab.git] / scilab / modules / scinotes / src / java / org / scilab / modules / scinotes / SciNotes.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  * Copyright (C) 2010 - 2011 - Calixte DENIZET
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 package org.scilab.modules.scinotes;
15
16 import java.awt.Color;
17 import java.awt.Component;
18 import java.io.BufferedWriter;
19 import java.io.File;
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.io.OutputStreamWriter;
23 import java.io.StringReader;
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.UUID;
33
34 import javax.swing.BorderFactory;
35 import javax.swing.ImageIcon;
36 import javax.swing.JFileChooser;
37 import javax.swing.JFrame;
38 import javax.swing.JOptionPane;
39 import javax.swing.JSplitPane;
40 import javax.swing.KeyStroke;
41 import javax.swing.SwingUtilities;
42 import javax.swing.event.ChangeEvent;
43 import javax.swing.event.ChangeListener;
44 import javax.swing.text.BadLocationException;
45 import javax.swing.text.EditorKit;
46 import javax.swing.text.View;
47 import javax.swing.undo.UndoManager;
48
49 import org.apache.commons.logging.LogFactory;
50 import org.flexdock.docking.event.DockingEvent;
51 import org.scilab.modules.core.Scilab;
52 import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser;
53 import org.scilab.modules.gui.bridge.tab.SwingScilabTab;
54 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
55 import org.scilab.modules.gui.filechooser.Juigetfile;
56 import org.scilab.modules.gui.filechooser.ScilabFileChooser;
57 import org.scilab.modules.gui.menubar.MenuBar;
58 import org.scilab.modules.gui.messagebox.MessageBox;
59 import org.scilab.modules.gui.messagebox.ScilabMessageBox;
60 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
61 import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption;
62 import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType;
63 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
64 import org.scilab.modules.gui.pushbutton.PushButton;
65 import org.scilab.modules.gui.tab.SimpleTab;
66 import org.scilab.modules.gui.tab.Tab;
67 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
68 import org.scilab.modules.gui.textbox.TextBox;
69 import org.scilab.modules.gui.toolbar.ToolBar;
70 import org.scilab.modules.gui.utils.ClosingOperationsManager;
71 import org.scilab.modules.gui.utils.ConfigManager;
72 import org.scilab.modules.gui.utils.Position;
73 import org.scilab.modules.gui.utils.SciFileFilter;
74 import org.scilab.modules.gui.utils.Size;
75 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
76 import org.scilab.modules.gui.window.ScilabWindow;
77 import org.scilab.modules.gui.window.Window;
78 import org.scilab.modules.scinotes.actions.ConfigTabulationsAction;
79 import org.scilab.modules.scinotes.actions.EncodingAction;
80 import org.scilab.modules.scinotes.actions.EndOfLineAction;
81 import org.scilab.modules.scinotes.actions.ExitAction;
82 import org.scilab.modules.scinotes.actions.FindAction;
83 import org.scilab.modules.scinotes.actions.IncrementalSearchAction;
84 import org.scilab.modules.scinotes.actions.InsertOverwriteAction;
85 import org.scilab.modules.scinotes.actions.LineBeautifierAction;
86 import org.scilab.modules.scinotes.actions.OpenSourceFileOnKeywordAction;
87 import org.scilab.modules.scinotes.actions.RecentFileAction;
88 import org.scilab.modules.scinotes.actions.RestoreOpenedFilesAction;
89 import org.scilab.modules.scinotes.actions.SciNotesCompletionAction;
90 import org.scilab.modules.scinotes.actions.SearchWordInFilesAction;
91 import org.scilab.modules.scinotes.actions.SetColorsAction;
92 import org.scilab.modules.scinotes.tabfactory.CodeNavigatorTab;
93 import org.scilab.modules.scinotes.tabfactory.SciNotesTab;
94 import org.scilab.modules.scinotes.tabfactory.SciNotesTabFactory;
95 import org.scilab.modules.scinotes.tabfactory.SearchInFilesTab;
96 import org.scilab.modules.scinotes.utils.ConfigSciNotesManager;
97 import org.scilab.modules.scinotes.utils.DropFilesListener;
98 import org.scilab.modules.scinotes.utils.NavigatorWindow;
99 import org.scilab.modules.scinotes.utils.SaveFile;
100 import org.scilab.modules.scinotes.utils.SciNotesContents;
101 import org.scilab.modules.scinotes.utils.SciNotesMessages;
102 import org.scilab.modules.scinotes.utils.ScilabTabbedPane;
103 import org.scilab.modules.scinotes.utils.SearchFile;
104
105 /**
106  * Main SciNotes class.
107  * @author Bruno JOFRET
108  * @author Calixte DENIZET
109  */
110 public class SciNotes extends SwingScilabTab implements Tab {
111
112     private static final long serialVersionUID = -6410183357490518676L;
113
114     private static final String SCINOTES = "SciNotes";
115     private static final String SCI_EXTENSION = ".sci";
116     private static final String SCE_EXTENSION = ".sce";
117     private static final String TST_EXTENSION = ".tst";
118     private static final String QUIT_EXTENSION = ".quit";
119     private static final String DEM_EXTENSION = ".dem";
120     private static final String START_EXTENSION = ".start";
121     private static final String ALL_TST_FILES = "*.tst";
122     private static final String ALL_QUIT_FILES = "*.quit";
123     private static final String ALL_START_FILES = "*.start";
124     private static final String ALL_SCI_FILES = "*.sci";
125     private static final String ALL_SCE_FILES = "*.sce";
126     private static final String ALL_DEM_FILES = "*.dem";
127     private static final String ALL_SCX_FILES = "*.sc*";
128     private static final String ALL_SCILAB = "all";
129     private static final String ALL_FILES = "*.*";
130     private static final String DOT = ".";
131
132     private static final String DEFAULTACTIONPATH = "org.scilab.modules.scinotes.actions";
133
134     private static List<SciNotes> scinotesList = new ArrayList<SciNotes>();
135     private static SciNotes editor;
136
137     private Window parentWindow;
138     private final UUID uuid;
139
140     private ScilabTabbedPane tabPane;
141     private final SciNotesContents contentPane;
142     private NavigatorWindow navigator;
143     private SearchFile searchInFiles;
144
145     private int numberOfUntitled;
146     private EditorKit editorKit;
147
148     private PushButton undoButton;
149     private PushButton redoButton;
150
151     private boolean protectOpenFileList;
152     private boolean restored;
153
154     private final List<Integer> tabList = new ArrayList<Integer>();
155     private final List<Integer> closedTabList = new ArrayList<Integer>();
156
157     static {
158         ConfigSciNotesManager.createUserCopy();
159         ScilabTabFactory.getInstance().addTabFactory(SciNotesTabFactory.getInstance());
160         Scilab.registerInitialHook(new Runnable() {
161                 @Override
162                 public void run() {
163                     updateSciNotes();
164                 }
165             });
166     }
167
168     /**
169      * Create SciNotes instance
170      */
171     public SciNotes(String uuid) {
172         super(SCINOTES, uuid);
173         setAssociatedXMLIDForHelp("scinotes");
174         this.uuid = UUID.fromString(uuid);
175         editor = this;
176         scinotesList.add(this);
177         numberOfUntitled = 0;
178         editorKit = new ScilabEditorKit(!ConfigSciNotesManager.getHorizontalWrap());
179         protectOpenFileList = false;
180         contentPane = new SciNotesContents(this);
181         tabPane = contentPane.getScilabTabbedPane();
182         tabPane.addChangeListener(new ChangeListener() {
183                 @Override
184                 public void stateChanged(ChangeEvent e) {
185                     if (getTextPane() != null) {
186                         //updateUI();
187                         getTextPane().updateInfosWhenFocused();
188                         getTextPane().requestFocus();
189                         getTextPane().highlightWords(IncrementalSearchAction.getWord(SciNotes.this), IncrementalSearchAction.getExact(SciNotes.this));
190
191                         // Update encoding menu
192                         EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
193
194                         // Update End Of Line  menu
195                         EndOfLineAction.updateEolMenu((ScilabDocument) getTextPane().getDocument());
196                         setTitle(getTextPane().getTitle());
197                     }
198                 }
199             });
200         this.setContentPane(contentPane);
201     }
202
203     /**
204      * Default constructor
205      */
206     public SciNotes() {
207         this(UUID.randomUUID().toString());
208     }
209
210     /**
211      * Get an opened editor from its uuid
212      * @param uuid the uuid
213      * @return the corresponding editor
214      */
215     public static SciNotes getEditorFromUUID(String uuid) {
216         for (SciNotes ed : scinotesList) {
217             if (ed.getPersistentId().equals(uuid)) {
218                 return ed;
219             }
220         }
221
222         return null;
223     }
224
225     public void setParentWindow() {
226         this.parentWindow = ScilabWindow.createWindow();
227         setWindowIcon("accessories-text-editor");
228         SwingScilabWindow window = (SwingScilabWindow) parentWindow.getAsSimpleWindow();
229         Position pos = ConfigSciNotesManager.getMainWindowPosition();
230         window.setLocation(pos.getX(), pos.getY());
231         Size size = ConfigSciNotesManager.getMainWindowSize();
232         window.setSize(size.getWidth(), size.getHeight());
233     }
234
235     /**
236      * {@inheritDoc}
237      */
238     @Override
239     public void setTitle(String title) {
240         super.setTitle(title);
241         SwingScilabWindow window = (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, tabPane);
242         if (window != null) {
243             window.setTitle(title);
244         }
245     }
246
247     public void insertBottomComponent(Component c) {
248         contentPane.insertBottomComponent(c);
249     }
250
251     /**
252      * @return the SwingScilabWindow containing this editor
253      */
254     public SwingScilabWindow getSwingParentWindow() {
255         return (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this);
256     }
257
258     /**
259      * {@inheritDoc}
260      */
261     @Override
262     public void undockingComplete(DockingEvent evt) {
263         super.undockingComplete(evt);
264         if (navigator != null) {
265             navigator.addToolBar(null);
266         }
267         if (searchInFiles != null) {
268             searchInFiles.addToolBar(null);
269         }
270     }
271
272     /**
273      * {@inheritDoc}
274      */
275     @Override
276     public void dockingComplete(DockingEvent evt) {
277         super.dockingComplete(evt);
278         if (navigator != null) {
279             navigator.changeToolBar();
280         }
281         if (searchInFiles != null) {
282             searchInFiles.changeToolBar();
283         }
284     }
285
286     /**
287      * Add a code navigator
288      */
289     public void addNavigator() {
290         if (navigator == null) {
291             String navUUID = ConfigSciNotesManager.getCodeNavigatorStateForEditor(getPersistentId());
292             boolean success = WindowsConfigurationManager.restoreUUID(navUUID);
293             if (!success) {
294                 navigator = CodeNavigatorTab.getCodeNavigatorInstance(this, null);
295                 navigator.setParentWindow();
296             }
297             int count = getTabPane().getTabCount();
298             for (int i = 0; i < count; i++) {
299                 navigator.addEditorPane(getTextPane(i));
300             }
301         }
302     }
303
304     /**
305      * Add a code navigator
306      */
307     public void addNavigator(NavigatorWindow navigator) {
308         this.navigator = navigator;
309     }
310
311     /**
312      * Remove the navigator
313      */
314     public void removeNavigator() {
315         navigator = null;
316     }
317
318     /**
319      * @return the navigator associated with this editor
320      */
321     public NavigatorWindow getNavigator() {
322         return navigator;
323     }
324
325     /**
326      * Add a Search in files
327      */
328     public void addSearchInFiles() {
329         if (searchInFiles == null) {
330             String sfUUID = ConfigSciNotesManager.getSearchInFilesStateForEditor(getPersistentId());
331             boolean success = WindowsConfigurationManager.restoreUUID(sfUUID);
332             if (!success) {
333                 searchInFiles = SearchInFilesTab.getSearchInFilesTabInstance(this, null);
334                 searchInFiles.setParentWindow();
335             }
336         }
337     }
338
339     /**
340      * Add a Search In Files
341      */
342     public void addSearchInFiles(SearchFile sf) {
343         this.searchInFiles = sf;
344     }
345
346     /**
347      * Remove Search in Files
348      */
349     public void removeSearchInFiles() {
350         searchInFiles = null;
351     }
352
353     /**
354      * @return the Search In Files associated with this editor
355      */
356     public SearchFile getSearchInFiles() {
357         return searchInFiles;
358     }
359
360     /**
361      * Update the editor
362      */
363     public static void updateSciNotes() {
364         ScilabLexer.update();
365         for (SciNotes editor : scinotesList) {
366             if (editor.getTextPane() != null) {
367                 editor.getTextPane().repaint();
368             }
369         }
370     }
371
372     /**
373      * Launch SciNotes with an empty file
374      *
375      * This method *must not* be called on the EDT thread.
376      */
377     public static void scinotes() {
378         ScilabLexer.update();
379         try {
380             SwingUtilities.invokeAndWait(new Runnable() {
381
382                     @Override
383                     public void run() {
384                         launchSciNotes();
385                         // Open an empty file if no tabs were opened at launch.
386                         if (editor.getTabPane().getTabCount() == 0)  {
387                             editor.openFile(null, 0, null);
388                         }
389                     }
390                 });
391         } catch (InterruptedException e) {
392             LogFactory.getLog(SciNotes.class).error(e);
393             throw new RuntimeException(e);
394         } catch (InvocationTargetException e) {
395             LogFactory.getLog(SciNotes.class).error(e);
396             e.printStackTrace();
397             throw new RuntimeException(e);
398         }
399     }
400
401     /**
402      * Launch SciNotes with a file name to open.
403      * @param filePath the name of the file to open
404      *
405      * This method *must not* be called on the EDT thread.
406      */
407     public static void scinotes(final String filePath) {
408         ScilabLexer.update();
409         try {
410             SwingUtilities.invokeAndWait(new Runnable() {
411
412                     @Override
413                     public void run() {
414                         launchSciNotes();
415                         editor.openFile(filePath, 0, null);
416                     }
417                 });
418         } catch (InterruptedException e) {
419             LogFactory.getLog(SciNotes.class).error(e);
420             throw new RuntimeException(e);
421         } catch (InvocationTargetException e) {
422             e.printStackTrace();
423             LogFactory.getLog(SciNotes.class).error(e);
424             throw new RuntimeException(e);
425         }
426     }
427
428     /**
429      * Launch SciNotes with a file name to open and a line to highlight.
430      * @param filePath the name of the file to open
431      * @param lineNumber the line to highlight
432      *
433      * This method *must not* be called on the EDT thread.
434      */
435     public static void scinotes(final String filePath, final int lineNumber, final String functionName) {
436         ScilabLexer.update();
437         try {
438             SwingUtilities.invokeAndWait(new Runnable() {
439
440                     @Override
441                     public void run() {
442                         launchSciNotes();
443                         editor.openFile(filePath, lineNumber, functionName);
444                     }
445                 });
446         } catch (InterruptedException e) {
447             LogFactory.getLog(SciNotes.class).error(e);
448             throw new RuntimeException(e);
449         } catch (InvocationTargetException e) {
450             e.printStackTrace();
451             LogFactory.getLog(SciNotes.class).error(e);
452             throw new RuntimeException(e);
453         }
454     }
455
456     /**
457      * Launch SciNotes with a file name to open and a line to highlight.
458      * @param filePath the name of the file to open
459      * @param option such as 'readonly'
460      *
461      * This method *must not* be called on the EDT thread.
462      */
463     public static void scinotes(final String filePath, final String option) {
464         ScilabLexer.update();
465         try {
466             SwingUtilities.invokeAndWait(new Runnable() {
467
468                     @Override
469                     public void run() {
470                         launchSciNotes();
471                         editor.openFile(filePath, 0, option);
472                     }
473                 });
474         } catch (InterruptedException e) {
475             LogFactory.getLog(SciNotes.class).error(e);
476             throw new RuntimeException(e);
477         } catch (InvocationTargetException e) {
478             e.printStackTrace();
479             LogFactory.getLog(SciNotes.class).error(e);
480             throw new RuntimeException(e);
481         }
482     }
483
484     /**
485      * Launch SciNotes with a provided text (from the help for example).
486      * @param text the text which should be modified
487      */
488     public static void scinotesWithText(String text) {
489         ScilabLexer.update();
490         launchSciNotes();
491         ScilabEditorPane theTextPane;
492         if (editor.getTabPane().getTabCount() != 0) {
493             String name = editor.getTextPane(0).getName();
494             if (name == null) {
495                 theTextPane = editor.getTextPane(0);
496             } else {
497                 theTextPane = editor.addEmptyTab();
498             }
499         } else {
500             theTextPane = editor.addEmptyTab();
501         }
502
503         ScilabDocument styleDocument = (ScilabDocument) theTextPane.getDocument();
504         try {
505             editor.getEditorKit().read(new StringReader(text), styleDocument, theTextPane.getCaretPosition());
506         } catch (IOException e) {
507             System.err.println(SciNotesMessages.ERROR_WITH_STRING);
508         } catch (BadLocationException e) {
509             System.err.println(SciNotesMessages.ERROR_WITH_STRING);
510         }
511     }
512
513     /**
514      * Clone the current tab and if b is true close the tab
515      * @param ed the editor where the tab is
516      * @param b a boolean
517      */
518     public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b) {
519         ScilabDocument cdoc = (ScilabDocument) ed.getTextPane().getDocument();
520         String title = ed.getTabPane().getScilabTitleAt(ed.getTabPane().getSelectedIndex());
521         ScilabEditorPane currentSep = ed.getTextPane();
522         String winTitle = ed.getTitle();
523
524         if (b) {
525             ed.closeTabAtWithoutConfirmation(ed.getTabPane().getSelectedIndex());
526             if (ed.getTabPane().getTabCount() == 0) {
527                 ClosingOperationsManager.startClosingOperationWithoutSave((SwingScilabTab) ed);
528                 ConfigSciNotesManager.removeEditorUUID(ed.uuid.toString());
529             }
530         }
531
532         editor = null;
533
534         scinotesWithText(cdoc.getText());
535         ScilabEditorPane sep = editor.getTextPane();
536
537         if (currentSep.getName() != null) {
538             editor.getTabPane().setTitleAt(0, title);
539             editor.setTitle(winTitle);
540         }
541
542         currentSep.copyProps(sep);
543         ScilabDocument sdoc = (ScilabDocument) sep.getDocument();
544         sdoc.setContentModified(cdoc.isContentModified());
545         sdoc.getUndoManager().discardAllEdits();
546         sep.setCaretPosition(0);
547         editor.enableUndoButton(false);
548         editor.enableRedoButton(false);
549         ConfigSciNotesManager.saveToOpenFiles(sep.getName(), editor, editor.getTextPane());
550     }
551
552     /**
553      * Clone the current tab and if b is true close the tab
554      * @param ed the editor where the tab is
555      * @param b a boolean
556      */
557     public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b, int x, int y) {
558         cloneAndCloseCurrentTab(ed, b);
559         editor.getSwingParentWindow().setLocation(x, y);
560     }
561
562     /**
563      * Execute after when the restoration is finished
564      */
565     @Override
566     public void endedRestoration() {
567         if (!SwingUtilities.isEventDispatchThread()) {
568             try {
569                 SwingUtilities.invokeAndWait(new Runnable() {
570
571                         @Override
572                         public void run() {
573                             restorePreviousSession();
574                         }
575                     });
576             } catch (InterruptedException e) {
577                 LogFactory.getLog(SciNotes.class).error(e);
578                 throw new RuntimeException(e);
579             } catch (InvocationTargetException e) {
580                 LogFactory.getLog(SciNotes.class).error(e);
581                 throw new RuntimeException(e);
582             }
583         } else {
584             restorePreviousSession();
585         }
586     }
587
588     /**
589      * Restore the previous session
590      */
591     public void restorePreviousSession() {
592         restored = true;
593         if (!ConfigSciNotesManager.getRestoreOpenedFiles() || ConfigSciNotesManager.countExistingOpenFiles(getUUID()) ==  0)  {
594             if (getTabPane().getTabCount() != 1 || getTextPane(0).getName() != null) {
595                 openFile(null, 0, null);
596             }
597             setWindowIcon("accessories-text-editor");
598             WindowsConfigurationManager.restorationFinished(this);
599
600             return;
601         }
602
603         SwingUtilities.invokeLater(new Runnable() {
604                 @Override
605                 public void run() {
606                     RestoreOpenedFilesAction.displayDialog((JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, SciNotes.this), getUUID().toString());
607                     List<File> list = RestoreOpenedFilesAction.getSelectedFiles();
608
609                     if (list != null && list.size() != 0) {
610                         for (File f : list) {
611                             openFile(f.getPath(), 0, null);
612                         }
613                     } else {
614                         if (getTabPane().getTabCount() == 0 || getTextPane(0).getName() == null) {
615                             openFile(null, 0, null);
616                         }
617                     }
618
619                     setWindowIcon("accessories-text-editor");
620
621                     if (navigator != null) {
622                         navigator.updateTree();
623                     }
624
625                     WindowsConfigurationManager.restorationFinished(SciNotes.this);
626                 }
627             });
628     }
629
630     /**
631      * Create SciNotes instance
632      * @return the instance
633      */
634     public static void launchSciNotes() {
635         if (editor == null) {
636             List<String> uuids = ConfigSciNotesManager.getEditorsUUID();
637             boolean success = false;
638             if (!uuids.isEmpty()) {
639                 for (String uuid : uuids) {
640                     boolean exists = false;
641                     for (SciNotes ed : scinotesList) {
642                         if (ed.uuid.toString().equals(uuid)) {
643                             exists = true;
644                             break;
645                         }
646                     }
647                     if (!exists) {
648                         success = WindowsConfigurationManager.restoreUUID(uuid);
649                         break;
650                     }
651                 }
652             }
653             if (!success) {
654                 editor = SciNotesTab.getEditorInstance(null);
655                 editor.setParentWindow();
656                 ConfigSciNotesManager.saveEditorUUID(editor.getPersistentId());
657                 SciNotesGUI.init(editor.getParentWindow(), editor, SCINOTES);
658             }
659         }
660
661         if (!editor.restored) {
662             editor.restorePreviousSession();
663         }
664     }
665
666     /**
667      * Open a file.
668      *
669      * This method *must* be called on the EDT thread.
670      *
671      * @param filePath the file path (may be null)
672      * @param lineNumber the line number (use 0 for unspecified)
673      * @param option the options (may be null)
674      */
675     public void openFile(String filePath, int lineNumber, String option) {
676         if (!SwingUtilities.isEventDispatchThread()) {
677             throw new RuntimeException("called outside the EDT thread.");
678         }
679
680         if (filePath == null) {
681             addEmptyTab();
682             return;
683         }
684
685         File f = fileToCanonicalFile(new File(filePath));
686         if (!f.getParentFile().exists()) {
687             JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.OPEN_ERROR);
688             addEmptyTab();
689             return;
690         }
691
692         if (f.isDirectory()) { /* Bug 5131 */
693             ConfigManager.saveLastOpenedDirectory(f.getPath());
694             addEmptyTab();
695             return;
696         }
697
698         readFileAndWait(f);
699         if (option == null || option.length() == 0 || "readonly".equals(option.toLowerCase())) {
700             getTextPane().scrollTextToLineNumber(lineNumber, true);
701         } else {
702             getTextPane().scrollTextToLineNumberInWhereami(lineNumber, option, true);
703         }
704         if ((option != null && "readonly".equals(option.toLowerCase()))) {
705             getTextPane().setReadOnly(true);
706             getInfoBar().setText(getTextPane().getInfoBarText());
707             ConfigSciNotesManager.removeFromOpenFiles(this, getTextPane());
708         } else {
709             ConfigSciNotesManager.saveToRecentOpenedFiles(filePath);
710             RecentFileAction.updateRecentOpenedFilesMenu(this);
711         }
712     }
713
714     /**
715      * Close SciNotes instance including all tabs.
716      */
717     public void closeSciNotes() {
718         for (int i = 0; i < getTabPane().getTabCount(); i++) {
719             ScilabEditorPane textPaneAt = getTextPane(i);
720             textPaneAt.destroy();
721         }
722
723         FindAction.close();
724         IncrementalSearchAction.close(this);
725         SetColorsAction.closeSetColorsWindow();
726         OpenSourceFileOnKeywordAction.closeOpenSourceWindow();
727         ConfigTabulationsAction.closeConfTabWindow();
728         SearchWordInFilesAction.closeWindow();
729
730         /*setProtectOpenFileList(true);
731           while (getTabPane().getTabCount() > 0) {
732           closeTabAt(0, true);
733           }
734           setProtectOpenFileList(false);*/
735
736         scinotesList.remove(this);
737         editor = null;
738         ConfigSciNotesManager.resetDocument();
739     }
740
741     public boolean canClose() {
742         int numberOfTab = getTabPane().getTabCount();
743         setProtectOpenFileList(true);
744
745         for (int i = 0; i < numberOfTab; i++) {
746             boolean ans = checkToCloseTabAt(i);
747             if (!ans) {
748                 setProtectOpenFileList(false);
749                 return false;
750             }
751         }
752         setProtectOpenFileList(false);
753
754         return true;
755     }
756
757     public String askForClosing() {
758         int numberOfTab = getTabPane().getTabCount();
759         boolean isContentModified = false;
760         for (int i = 0; i < getTabPane().getTabCount(); i++) {
761             ScilabEditorPane textPaneAt = getTextPane(i);
762             if (((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
763                 isContentModified = true;
764                 break;
765             }
766         }
767
768         if (isContentModified) {
769             return "SciNotes";
770         }
771
772         return null;
773     }
774
775
776     public static void closeEditor(SciNotes ed) {
777         if (scinotesList.size() > 1) {
778             ClosingOperationsManager.startClosingOperationWithoutSave((SwingScilabTab) ed);
779         } else {
780             ClosingOperationsManager.startClosingOperation((SwingScilabTab) ed);
781         }
782     }
783
784     /**
785      * Close a tab using its index.
786      * @param indexTab the index of the tab
787      * @return if the tab has been really closed
788      */
789     public boolean closeTabAtWithoutConfirmation(int indexTab) {
790         return closeTabAt(indexTab, false, false);
791     }
792
793     /**
794      * Close a tab using its index.
795      * @param indexTab the index of the tab
796      * @return if the tab has been really closed
797      */
798     public boolean closeTabAt(int indexTab) {
799         return closeTabAt(indexTab, false, true);
800     }
801
802     /**
803      * Close a tab using its index.
804      * @param indexTab the index of the tab
805      * @param scilabClose if true, save dialog confirmation cannot be canceled
806      * @return if the tab has been really closed
807      */
808     public boolean closeTabAt(int indexTab, boolean scilabClose, boolean confirmation) {
809         ScilabEditorPane textPaneAt = getTextPane(indexTab);
810
811         /* Test for modification added after bug 5103 fix: do not ask the user for an Untitled not-modified file saving when closing SciNotes */
812         if (confirmation && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
813             if (!save(indexTab, false, scilabClose)) {
814                 return false;
815             }
816         }
817
818         textPaneAt.close();
819
820         if (textPaneAt.getName() == null) {
821             String closedTabName = tabPane.getScilabTitleAt(indexTab);
822             String closedTabNameIndex = closedTabName.substring(closedTabName.length() - 1, closedTabName.length());
823             tabList.remove(Integer.valueOf(closedTabNameIndex));
824             closedTabList.add(Integer.valueOf(closedTabNameIndex));
825         }
826
827         // correction for bug 5404, closing the last tabPane generate an exception
828         // that's why we need to remove ChangeListeners before closing
829         if ((indexTab == 0) && (getTabPane().getTabCount() == 1)) {
830             for (int i = 0; i < tabPane.getChangeListeners().length; i++) {
831                 tabPane.removeChangeListener(tabPane.getChangeListeners()[i]);
832             }
833         }
834
835         // Remove the filename associated with the tab from the list of open files.
836         if (!protectOpenFileList) {
837             ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt);
838         }
839
840         if (navigator != null) {
841             navigator.removePane(textPaneAt);
842         }
843
844         textPaneAt.close();
845         tabPane.remove(indexTab);
846
847         textPaneAt = getTextPane();
848         if (textPaneAt != null) {
849             if (navigator != null) {
850                 navigator.update((ScilabDocument) textPaneAt.getDocument());
851             }
852         }
853         return true;
854     }
855
856     public boolean checkToCloseTabAt(int index) {
857         ScilabEditorPane textPaneAt = getTextPane(index);
858
859         /* Test for modification added after bug 5103 fix: do not ask the user for an Untitled not-modified file saving when closing SciNotes */
860         if (((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
861             if (!save(index, false, false)) {
862                 return false;
863             }
864         }
865
866         return true;
867     }
868
869     /**
870      * Set or unset protection of the currently open file list.
871      * Call before closing tabs if the tabs should be restored when scinotes restarts.
872      * @param protect Enables protection of the open file list if true.
873      */
874     public void setProtectOpenFileList(boolean protect) {
875         protectOpenFileList = protect;
876     }
877
878     /**
879      * Determines if this editor is the only editor instance.
880      * @return true if this is the last editor instance.
881      */
882     public boolean isOnlyInstance() {
883         if (scinotesList.size() > 1) {
884             return false;
885         }
886
887         return true;
888     }
889
890     /**
891      * @return the list of the different openened editors
892      */
893     public static List<SciNotes> getSciNotesList() {
894         return scinotesList;
895     }
896
897     /**
898      * Save a file.
899      * @param indexTab the textPane index containing the file contents
900      * @return execution status
901      */
902     public boolean save(int indexTab) {
903         return save(indexTab, false, false);
904     }
905
906     /**
907      * Save a file.
908      * @param indexTab the textPane index containing the file contents
909      * @param force : force save without confirmation dialog ( SaveAction )
910      * @return execution status
911      */
912     public boolean save(int indexTab, boolean force) {
913         return save(indexTab, force, false);
914     }
915
916     /**
917      * Save a file.
918      * @param indexTab the textPane index containing the file contents
919      * @param force : force save without confirmation dialog ( SaveAction )
920      * @param scilabClose : if true, save dialog confirmation cannot be canceled
921      * @return execution status
922      */
923     public boolean save(int indexTab, boolean force, boolean scilabClose) {
924         ScilabEditorPane textPaneAt = getTextPane(indexTab);
925         getTabPane().setSelectedIndex(indexTab);
926
927         //if the file ( empty, new or loaded ) is not modified, exit save process and return true
928         if (!textPaneAt.checkExternalModif() && !((ScilabDocument) textPaneAt.getDocument()).isContentModified()
929             && (textPaneAt.getName() != null)) { /* Bug 5103 fix */
930             return true;
931         }
932
933         if (!force) {
934             AnswerOption answer;
935             if (scilabClose) {
936                 answer = ScilabModalDialog.show(this, getTabPane().getScilabTitleAt(indexTab) + SciNotesMessages.MODIFIED,
937                                                 SciNotesMessages.SCILAB_EDITOR, IconType.QUESTION_ICON, ButtonType.YES_NO);
938             } else {
939                 answer = ScilabModalDialog.show(this, getTabPane().getScilabTitleAt(indexTab) + SciNotesMessages.MODIFIED,
940                                                 SciNotesMessages.SCILAB_EDITOR, IconType.QUESTION_ICON, ButtonType.YES_NO_CANCEL);
941             }
942
943             switch (answer) {
944             case YES_OPTION : //Yes, continue
945                 break;
946             case NO_OPTION ://No, exit and returns true
947                 return true;
948             case CANCEL_OPTION : //Cancel, exit and return false
949                 return false;
950             default:
951                 break;
952             }
953         }
954
955         String fileToSave = textPaneAt.getName();
956         if (fileToSave == null) {
957             //need a filename, call chooseFileToSave
958             fileToSave = chooseFileToSave(SciNotesMessages.SAVE);
959         } else {
960             //check if the file has been modified by external software
961             fileToSave = checkExternalModification(fileToSave);
962         }
963
964         if (fileToSave == null || fileToSave.length() == 0) {
965             return true; /* Bug 5189: The user cancels ==> do not want an error message */
966         }
967
968         File newSavedFile = new File(fileToSave);
969
970         if (!SaveFile.doSave(textPaneAt, indexTab, newSavedFile, editorKit)) {
971             return false;
972         }
973
974         ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument();
975         styledDocument.setContentModified(false);
976
977         textPaneAt.setLastModified(newSavedFile.lastModified());
978
979         if (textPaneAt.getName() == null) {
980             String name = getTabPane().getScilabTitleAt(indexTab);
981             String index = name.substring(name.length() - 1, name.length());
982             tabList.remove(Integer.valueOf(index));
983             closedTabList.add(Integer.valueOf(index));
984         }
985
986         textPaneAt.setName(fileToSave);
987         getTabPane().setTitleAt(indexTab , newSavedFile.getName());
988
989         setTitle(textPaneAt.getTitle());
990         ConfigSciNotesManager.saveToOpenFiles(fileToSave, this, textPaneAt);
991
992         return true;
993     }
994
995     /**
996      * Overwrite the file at a given index.
997      * @param indexTab the textPane index containing the file contents
998      * @return execution status
999      */
1000     public boolean overwrite(int indexTab) {
1001         ScilabEditorPane textPaneAt = getTextPane(indexTab);
1002         String fileToSave = textPaneAt.getName();
1003         if (fileToSave == null) {
1004             return true;
1005         }
1006
1007         File newSavedFile = new File(fileToSave);
1008         if (!newSavedFile.exists()) {
1009             return true;
1010         }
1011
1012         if (!SaveFile.doSave(textPaneAt, indexTab, newSavedFile, editorKit)) {
1013             return false;
1014         }
1015
1016         ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument();
1017         styledDocument.setContentModified(false);
1018
1019         getTabPane().setTitleAt(getTabPane().getSelectedIndex() , newSavedFile.getName());
1020
1021         // Get current file path for Execute file into Scilab
1022         getTextPane().setLastModified(newSavedFile.lastModified());
1023
1024         textPaneAt.setName(fileToSave);
1025         setTitle(textPaneAt.getTitle());
1026
1027         return true;
1028     }
1029
1030     /**
1031      * Check for external modification. If it is the case, propose
1032      * to select a new file name.
1033      * @param filename The name of the file
1034      * @return the filename where to save
1035      */
1036     public String checkExternalModification(String filename) {
1037         File newSavedFile = new File(filename);
1038         if (newSavedFile.lastModified() > getTextPane().getLastModified()) {
1039             if (ScilabModalDialog.show(this, String.format(SciNotesMessages.EXTERNAL_MODIFICATION, newSavedFile.getPath()),
1040                                        SciNotesMessages.REPLACE_FILE_TITLE, IconType.QUESTION_ICON,
1041                                        ButtonType.YES_NO) == AnswerOption.NO_OPTION) {
1042                 return chooseFileToSave(SciNotesMessages.SAVE);
1043             }
1044         }
1045         return filename;
1046     }
1047
1048     /**
1049      * Return through a file selector the name of the selected
1050      * file.
1051      * @param title the title for JFileChooser
1052      * @return the file picked up by the user
1053      */
1054     public String chooseFileToSave(String title) {
1055         return chooseFileToSave(title, null);
1056     }
1057
1058     /**
1059      * Return through a file selector the name of the selected
1060      * file.
1061      * @param title the title for JFileChooser
1062      * @param path the path where to open the filechooser
1063      * @return the file picked up by the user
1064      */
1065     public String chooseFileToSave(String title, String path) {
1066         String extension = new String();
1067
1068         String initialDirectoryPath = path;
1069         if (initialDirectoryPath == null) {
1070             initialDirectoryPath = getTextPane().getName();
1071         }
1072         if (initialDirectoryPath == null) {
1073             initialDirectoryPath =  ConfigManager.getLastOpenedDirectory();
1074         }
1075
1076         SciFileFilter sceFilter = new SciFileFilter(ALL_SCE_FILES, null, 0);
1077         SciFileFilter sciFilter = new SciFileFilter(ALL_SCI_FILES, null, 1);
1078         SciFileFilter scxFilter = new SciFileFilter(ALL_SCX_FILES, null, 2);
1079         SciFileFilter tstFilter = new SciFileFilter(ALL_TST_FILES, null, 3);
1080         SciFileFilter startFilter = new SciFileFilter(ALL_START_FILES, null, 4);
1081         SciFileFilter quitFilter = new SciFileFilter(ALL_QUIT_FILES, null, 5);
1082         SciFileFilter demFilter = new SciFileFilter(ALL_DEM_FILES, null, 6);
1083         SciFileFilter allFilter = new SciFileFilter(ALL_FILES, null, 7);
1084         SciFileFilter allScilabFilter = new SciFileFilter(ALL_SCILAB, null, 8);
1085
1086         SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser());
1087
1088         fileChooser.setInitialDirectory(ConfigManager.getLastOpenedDirectory());
1089         fileChooser.setAcceptAllFileFilterUsed(false);
1090         fileChooser.setInitialDirectory(initialDirectoryPath);
1091         fileChooser.setUiDialogType(Juigetfile.SAVE_DIALOG);
1092
1093         // order is also important here
1094         fileChooser.addChoosableFileFilter(sceFilter);
1095         fileChooser.addChoosableFileFilter(sciFilter);
1096         fileChooser.addChoosableFileFilter(scxFilter);
1097         fileChooser.addChoosableFileFilter(tstFilter);
1098         fileChooser.addChoosableFileFilter(startFilter);
1099         fileChooser.addChoosableFileFilter(quitFilter);
1100         fileChooser.addChoosableFileFilter(demFilter);
1101         fileChooser.addChoosableFileFilter(allFilter);
1102         fileChooser.addChoosableFileFilter(allScilabFilter);
1103
1104         //select default file type
1105         fileChooser.setFileFilter(sceFilter);
1106         fileChooser.setTitle(title);
1107
1108         String name = getTextPane().getName();
1109         if (name == null) {
1110             name = ((ScilabDocument) getTextPane().getDocument()).getFirstFunctionName();
1111             if (name != null) {
1112                 name += SCI_EXTENSION;
1113             }
1114         }
1115
1116         if (name != null) {
1117             fileChooser.setSelectedFile(new File(name));
1118         }
1119
1120         int retval = fileChooser.showSaveDialog(this);
1121
1122         if (retval == JFileChooser.APPROVE_OPTION) {
1123             File f = fileToCanonicalFile(fileChooser.getSelectedFile());
1124             initialDirectoryPath = f.getPath();
1125             if (f.exists()) {
1126                 if (ScilabModalDialog.show(this, SciNotesMessages.REPLACE_FILE_TITLE,
1127                                            SciNotesMessages.FILE_ALREADY_EXIST, IconType.QUESTION_ICON,
1128                                            ButtonType.YES_NO) == AnswerOption.NO_OPTION) {
1129                     return chooseFileToSave(SciNotesMessages.SAVE);
1130                 }
1131             }
1132
1133             /*we test if the file has already a scilab extension*/
1134             boolean hasNoExtension = true;
1135
1136             // if the file name is like this : any character , a dot , then 2,3or 4 characters, then
1137             // we consider the file has already an extension
1138             // we previously only check for .sci and .sce extension, but what if the user open a txt file
1139             String fileName = f.getName();
1140             if (fileName.lastIndexOf(DOT) != -1) {
1141                 if (fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() >= 2
1142                     && fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() <= 4) {
1143                     hasNoExtension = false;
1144                 }
1145             }
1146
1147             /*if no extension , we add it */
1148             if (hasNoExtension) {
1149                 if (fileChooser.getFileFilter() == sciFilter) {
1150                     extension = SCI_EXTENSION;
1151                 } else if (fileChooser.getFileFilter() == sceFilter) {
1152                     extension = SCE_EXTENSION;
1153                 } else if (fileChooser.getFileFilter() == scxFilter) {
1154                     extension = SCE_EXTENSION;
1155                 } else if (fileChooser.getFileFilter() == tstFilter) {
1156                     extension = TST_EXTENSION;
1157                 } else if (fileChooser.getFileFilter() == startFilter) {
1158                     extension = START_EXTENSION;
1159                 } else if (fileChooser.getFileFilter() == quitFilter) {
1160                     extension = QUIT_EXTENSION;
1161                 } else if (fileChooser.getFileFilter() == demFilter) {
1162                     extension = DEM_EXTENSION;
1163                 } else {
1164                     extension = "";
1165                 }
1166                 return f.getPath() + extension;
1167             }
1168
1169             if (initialDirectoryPath != null) {
1170                 ConfigManager.saveLastOpenedDirectory(initialDirectoryPath);
1171             }
1172
1173             return f.getPath();
1174         } else if (retval == JFileChooser.CANCEL_OPTION) {
1175             return "";
1176         }
1177
1178         return null;
1179     }
1180
1181     /**
1182      * Save a file.
1183      * @param path the initial path where the filechooser will be open
1184      * @return execution status
1185      */
1186     public boolean saveAs(String path) {
1187         String filename = chooseFileToSave(SciNotesMessages.SAVE_AS, path);
1188         if (filename == null || filename.length() == 0) {
1189             return true;
1190         }
1191
1192         File f = new File(filename);
1193         ScilabDocument styledDocument = (ScilabDocument) getTextPane().getDocument();
1194
1195         if (!SaveFile.doSave(getTextPane(), getTabPane().getSelectedIndex(), f, editorKit)) {
1196             return false;
1197         }
1198
1199         if (getTextPane().getName() == null) {
1200             String name = getTabPane().getScilabTitleAt(getTabPane().getSelectedIndex());
1201             String index = name.substring(name.length() - 1, name.length());
1202             tabList.remove(Integer.valueOf(index));
1203             closedTabList.add(Integer.valueOf(index));
1204         }
1205
1206         ConfigManager.saveLastOpenedDirectory(f.getPath());
1207         ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
1208         ConfigSciNotesManager.renameOpenFilesItem(f.getPath(), this, getTextPane());
1209         getTextPane().setName(f.getPath());
1210         getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
1211         setTitle(getTextPane().getTitle());
1212
1213         RecentFileAction.updateRecentOpenedFilesMenu(this);
1214
1215         if (navigator != null) {
1216             navigator.update(styledDocument);
1217         }
1218
1219         styledDocument.setContentModified(false);
1220         getTextPane().setLastModified(f.lastModified());
1221         getTextPane().setReadOnly(false);
1222         getInfoBar().setText(getTextPane().getInfoBarText());
1223
1224         return true;
1225     }
1226
1227     /**
1228      * Create a new tab in SciNotes.
1229      * @param title the title of the tab
1230      * @return the text component inside the tab
1231      */
1232     public ScilabEditorPane addTab(String title) {
1233         return addTab(title, Integer.MAX_VALUE);
1234     }
1235
1236     /**
1237      * Create a new tab in SciNotes.
1238      * @param title the title of the tab
1239      * @param index the index where to put the new tab
1240      * @return the text component inside the tab
1241      */
1242     public ScilabEditorPane addTab(String title, int index) {
1243         ScilabEditorPane sep = new ScilabEditorPane(this);
1244         initPane(sep);
1245         int ind = Math.min(Math.max(0, index), tabPane.getTabCount());
1246         tabPane.insertTab(title, null, sep.getEditorComponent(), "", ind);
1247         tabPane.setSelectedIndex(ind);
1248         initInputMap(sep);
1249         updateTabTitle();
1250         getInfoBar().setText(sep.getInfoBarText());
1251         repaint();
1252         sep.init();
1253         return sep;
1254     }
1255
1256     /**
1257      * Init a pane
1258      * @param pane the pane to init
1259      */
1260     public void initPane(ScilabEditorPane pane) {
1261         initPane(pane, !ConfigSciNotesManager.getHorizontalWrap());
1262     }
1263
1264     /**
1265      * Init the EditorPane.
1266      * @param pane the EditorPane
1267      * @param plain true for a plain view or false for a wrapped view
1268      */
1269     public void initPane(ScilabEditorPane pane, boolean plain) {
1270         setHighlight(pane);
1271         pane.setEditorKit(new ScilabEditorKit(plain));
1272
1273         // Panel of line number for the text pane
1274         pane.getXln().setWhereamiLineNumbering(ConfigSciNotesManager.getLineNumberingState());
1275         activateHelpOnTyping(pane);
1276
1277         pane.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
1278         pane.setFont(ConfigSciNotesManager.getFont());
1279
1280         pane.setBackground(ConfigSciNotesManager.getSciNotesBackgroundColor());
1281         pane.setCaretColor(ConfigSciNotesManager.getSciNotesForegroundColor());
1282
1283         pane.setFocusable(true);
1284         pane.setRequestFocusEnabled(true);
1285         pane.setDragEnabled(true); /* Bug 5497 */
1286
1287         DropFilesListener dndTarget = new DropFilesListener(pane);
1288
1289         pane.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(this));
1290     }
1291
1292     /**
1293      * Init the EditorPane with the InputMap found in ConfigSciNotesManager
1294      * @param pane the EditorPane
1295      */
1296     public void initInputMap(ScilabEditorPane pane) {
1297         setKeyStrokeAction(pane, this);
1298         LineBeautifierAction.putInInputMap(pane);
1299         InsertOverwriteAction.putInInputMap(pane);
1300     }
1301
1302     /**
1303      * Split the EditorPane
1304      * @param vertical true for a vertical split
1305      */
1306     public void splitTab(boolean vertical) {
1307         ScilabEditorPane pane = getTextPane();
1308         Component bottom = pane.getEditorComponent().getBottom();
1309         int state = pane.getXln().getState();
1310         ScilabEditorPane leftPane = new ScilabEditorPane(editor);
1311         ScilabEditorPane rightPane = new ScilabEditorPane(editor);
1312         if (navigator != null) {
1313             navigator.changePaneOnSplit(pane, leftPane);
1314         }
1315         initPane(leftPane, true);
1316         initPane(rightPane, true);
1317         leftPane.setOtherPaneInSplit(rightPane);
1318         rightPane.setOtherPaneInSplit(leftPane);
1319         pane.copyProps(leftPane);
1320         pane.copyProps(rightPane);
1321         ScilabDocument doc = (ScilabDocument) pane.getDocument();
1322         leftPane.setDocument(doc);
1323         rightPane.setDocument(doc);
1324         leftPane.setCaretPosition(0);
1325         rightPane.setCaretPosition(0);
1326         JSplitPane split;
1327         if (vertical) {
1328             split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
1329         } else {
1330             split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
1331         }
1332         leftPane.getXln().setWhereamiLineNumbering(state);
1333         rightPane.getXln().setWhereamiLineNumbering(state);
1334         split.setLeftComponent(leftPane.getScrollPane());
1335         split.setRightComponent(rightPane.getScrollPane());
1336         split.setResizeWeight(0.5);
1337         rightPane.setEditorComponent(leftPane.getEditorComponent());
1338         leftPane.setSplitPane(split);
1339         rightPane.setSplitPane(split);
1340
1341         activateHelpOnTyping(leftPane);
1342         activateHelpOnTyping(rightPane);
1343         initInputMap(leftPane);
1344         initInputMap(rightPane);
1345         if (doc.getBinary()) {
1346             leftPane.setBinary(true);
1347             rightPane.setBinary(true);
1348         }
1349         getInfoBar().setText(leftPane.getInfoBarText());
1350         updateTabTitle();
1351         tabPane.setComponentAt(tabPane.getSelectedIndex(), leftPane.getEditorComponent());
1352         leftPane.getEditorComponent().insertBottomComponent(bottom);
1353         leftPane.requestFocus();
1354     }
1355
1356     /**
1357      * Remove a split
1358      */
1359     public void removeSplit() {
1360         if (((EditorComponent) tabPane.getSelectedComponent()).isSplited()) {
1361             ScilabEditorPane pane = new ScilabEditorPane(editor);
1362             ScilabEditorPane textpane = getTextPane();
1363             Component bottom = textpane.getEditorComponent().getBottom();
1364             if (navigator != null) {
1365                 navigator.changePaneOnSplit(textpane, pane);
1366             }
1367             initPane(pane);
1368             textpane.setOtherPaneInSplit(null);
1369             textpane.copyProps(pane);
1370             ScilabDocument doc = (ScilabDocument) textpane.getDocument();
1371             pane.setDocument(doc);
1372             pane.setCaretPosition(0);
1373             activateHelpOnTyping(pane);
1374             tabPane.setComponentAt(tabPane.getSelectedIndex(), pane.getEditorComponent());
1375             initInputMap(pane);
1376             if (doc.getBinary()) {
1377                 pane.setBinary(true);
1378             }
1379             getInfoBar().setText(pane.getInfoBarText());
1380             updateTabTitle();
1381             pane.getEditorComponent().insertBottomComponent(bottom);
1382             pane.requestFocus();
1383         }
1384     }
1385
1386     /**
1387      * Create an empty tab inside SciNotes.
1388      * @return the text component inside the tab
1389      */
1390     public ScilabEditorPane addEmptyTab() {
1391         ScilabEditorPane sep;
1392         int n = getNumberForEmptyTab();
1393         sep = addTab(SciNotesMessages.UNTITLED + n);
1394         sep.setShortName(SciNotesMessages.UNTITLED + n);
1395         sep.setTitle(SciNotesMessages.UNTITLED + n);
1396         setTitle(sep.getTitle());
1397
1398         return sep;
1399     }
1400
1401     /**
1402      * Get an integer used for untitled document
1403      */
1404     public int getNumberForEmptyTab() {
1405         if (closedTabList.size() > 0) {
1406             Integer n = Collections.min(closedTabList);
1407             closedTabList.remove(n);
1408             return n.intValue();
1409         } else {
1410             numberOfUntitled++;
1411             tabList.add(Integer.valueOf(numberOfUntitled));
1412             return numberOfUntitled;
1413         }
1414     }
1415
1416     /**
1417      * Add or remove '*' prefix in current tab tile according to isContentModified().
1418      */
1419     public void updateTabTitle() {
1420         StringBuffer newTitle = new StringBuffer();
1421         ScilabEditorPane currentTextPane = getTextPane();
1422         if (((ScilabDocument) currentTextPane.getDocument()).isContentModified()) {
1423             newTitle.append('*');
1424         }
1425
1426         String textPaneName = currentTextPane.getName();
1427         try {
1428             File f = new File(textPaneName);
1429             newTitle.append(f.getName());
1430         } catch (NullPointerException e) { // not a file name, no path prefix to remove, but maybe a '*'
1431             textPaneName = getTabPane().getScilabTitleAt(getTabPane().getSelectedIndex());
1432             if (textPaneName.charAt(0) == '*') {
1433                 newTitle.append(textPaneName.substring(1, textPaneName.length()));
1434             } else {
1435                 newTitle.append(textPaneName);
1436             }
1437         }
1438         getTabPane().setTitleAt(getTabPane().getSelectedIndex(), newTitle.toString());
1439     }
1440
1441     /**
1442      * @param button the UndoButton used in this editor
1443      */
1444     public void setUndoButton(PushButton button) {
1445         undoButton = button;
1446         enableUndoButton(false);
1447     }
1448
1449     /**
1450      * @param b true to enable the button
1451      */
1452     public void enableUndoButton(boolean b) {
1453         if (undoButton != null) {
1454             undoButton.setEnabled(b);
1455         }
1456     }
1457
1458     /**
1459      * Undo last modification.
1460      */
1461     public void undo() {
1462         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1463         synchronized (doc) {
1464             doc.getUndoManager().undo();
1465         }
1466     }
1467
1468     /**
1469      * @param button the RedoButton used in this editor
1470      */
1471     public void setRedoButton(PushButton button) {
1472         redoButton = button;
1473         enableRedoButton(false);
1474     }
1475
1476     /**
1477      * @param b true to enable the button
1478      */
1479     public void enableRedoButton(boolean b) {
1480         if (redoButton != null) {
1481             redoButton.setEnabled(b);
1482         }
1483     }
1484
1485     /**
1486      * Redo last modification.
1487      */
1488     public void redo() {
1489         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1490         synchronized (doc) {
1491             doc.getUndoManager().redo();
1492         }
1493     }
1494
1495     /**
1496      * Reload a file inside SciNotes.
1497      * @param index the index
1498      */
1499     public void reload(int index) {
1500         ScilabEditorPane textPaneAt = getTextPane(index);
1501         if (textPaneAt.getName() != null) {
1502             if ((index == 0) && (getTabPane().getTabCount() == 1)) {
1503                 for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1504                     tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1505                 }
1506             }
1507             ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt);
1508             tabPane.remove(index);
1509             File f = new File(textPaneAt.getName());
1510             if (f.exists()) {
1511                 loadFile(f, index);
1512             } else {
1513                 createNewFile(f);
1514             }
1515         }
1516     }
1517
1518     /**
1519      * Load a file inside SciNotes.
1520      * @param f the file to open
1521      */
1522     public void readFile(File f) {
1523         /** Is this file already opened */
1524         boolean alreadyOpened = false;
1525         for (int i = 0; i < tabPane.getTabCount(); i++) {
1526             ScilabEditorPane textPaneAt = getTextPane(i);
1527             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1528                 /* File is already opnened */
1529                 tabPane.setSelectedIndex(i);
1530                 alreadyOpened = true;
1531                 break;
1532             }
1533         }
1534
1535         if (!alreadyOpened) {
1536             if (f.exists()) {
1537                 loadFile(f);
1538             } else {
1539                 createNewFile(f);
1540             }
1541         }
1542     }
1543
1544     /**
1545      * Load a file inside SciNotes.
1546      * @param file the file to open
1547      */
1548     public void readFileAndWait(File file) {
1549         /** Is this file already opened */
1550         File f = file;
1551         boolean alreadyOpened = false;
1552         int index = -1;
1553         for (int i = 0; i < tabPane.getTabCount(); i++) {
1554             ScilabEditorPane textPaneAt = getTextPane(i);
1555             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1556                 /* File is already opened */
1557                 tabPane.setSelectedIndex(i);
1558                 if (f.lastModified() > textPaneAt.getLastModified()) {
1559
1560                     /*
1561                      * Create a new messagebox to know what the user wants to do
1562                      * if the file has been modified outside SciNotes
1563                      */
1564                     MessageBox messageBox = ScilabMessageBox.createMessageBox();
1565                     messageBox.setTitle(SciNotesMessages.REPLACE_FILE_TITLE);
1566                     messageBox.setMessage(String.format(SciNotesMessages.EXTERNAL_MODIFICATION, textPaneAt.getName()));
1567
1568                     String[] labels = new String[]{SciNotesMessages.RELOAD, SciNotesMessages.OVERWRITE, SciNotesMessages.IGNORE};
1569                     messageBox.setButtonsLabels(labels);
1570
1571                     messageBox.setIcon("question"); // Question icon
1572
1573                     messageBox.setParentForLocation(this); // Centered on SciNotes main window
1574
1575                     messageBox.displayAndWait(); // Waits for a user action
1576
1577                     switch (messageBox.getSelectedButton()) {
1578                     case 1: // Reload
1579                         if ((i == 0) && (getTabPane().getTabCount() == 1)) {
1580                             for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1581                                 tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1582                             }
1583                         }
1584                         tabPane.remove(i);
1585                         f = new File(textPaneAt.getName());
1586                         index = i;
1587                         break;
1588                     case 2: // Overwrite 2
1589                         overwrite(i);
1590                         alreadyOpened = true;
1591                         break;
1592                     default: // Ignore
1593                         alreadyOpened = true;
1594                     }
1595                 } else {
1596                     alreadyOpened = true;
1597                 }
1598                 break;
1599             }
1600         }
1601
1602         if (!alreadyOpened) {
1603             if (f.exists()) {
1604                 loadFile(f, index);
1605             } else {
1606                 createNewFile(f);
1607             }
1608         }
1609     }
1610
1611     /**
1612      * Get current text component. If the window is splitted, then
1613      * return the focused text component.
1614      * @return the text component
1615      */
1616     public ScilabEditorPane getTextPane() {
1617         try {
1618             EditorComponent c = (EditorComponent) tabPane.getSelectedComponent();
1619             return c.getEditorPane();
1620         } catch (NullPointerException e) {
1621             return null;
1622         } catch (ArrayIndexOutOfBoundsException e) {
1623             return null;
1624         }
1625     }
1626
1627     /**
1628      * Get text component at index.
1629      * @param index the index of the textpane
1630      * @return the text component
1631      */
1632     public ScilabEditorPane getTextPane(int index) {
1633         try {
1634             EditorComponent c = (EditorComponent) tabPane.getComponentAt(index);
1635             return c.getEditorPane();
1636         } catch (NullPointerException e) {
1637             return null;
1638         } catch (ArrayIndexOutOfBoundsException e) {
1639             return null;
1640         }
1641     }
1642
1643     /**
1644      * Enable the whereami-line numbering
1645      * @param state int
1646      */
1647     public static void setWhereamiLineNumbering(int state) {
1648         for (SciNotes ed : scinotesList) {
1649             int n = ed.getTabPane().getTabCount();
1650             for (int i = 0; i < n; i++) {
1651                 ScilabEditorPane sep = ed.getTextPane(i);
1652                 sep.getXln().setWhereamiLineNumbering(state);
1653                 if (sep.getOtherPaneInSplit() != null) {
1654                     sep.getOtherPaneInSplit().getXln().setWhereamiLineNumbering(state);
1655                 }
1656             }
1657             ed.repaint();
1658         }
1659     }
1660
1661     /**
1662      * Auto-indent mode management
1663      * @param b true to activate auto-indent mode
1664      */
1665     public static void setAutoIndent(boolean b) {
1666         for (SciNotes ed : scinotesList) {
1667             int n = ed.getTabPane().getTabCount();
1668             for (int i = 0; i < n; i++) {
1669                 ScilabEditorPane sep = ed.getTextPane(i);
1670                 ((ScilabDocument) sep.getDocument()).setAutoIndent(b);
1671                 if (sep.getOtherPaneInSplit() != null) {
1672                     ((ScilabDocument) sep.getOtherPaneInSplit().getDocument()).setAutoIndent(b);
1673                 }
1674             }
1675         }
1676     }
1677
1678     /**
1679      * Auto-indent mode management
1680      * @param b true to activate auto-indent mode
1681      */
1682     public static void setSuppressComments(boolean b) {
1683         for (SciNotes ed : scinotesList) {
1684             int n = ed.getTabPane().getTabCount();
1685             for (int i = 0; i < n; i++) {
1686                 ScilabEditorPane sep = ed.getTextPane(i);
1687                 sep.suppressCommentsInExecutingCode(b);
1688                 if (sep.getOtherPaneInSplit() != null) {
1689                     sep.getOtherPaneInSplit().suppressCommentsInExecutingCode(b);
1690                 }
1691             }
1692         }
1693     }
1694
1695     /**
1696      * Horizontal Wrap mode management
1697      * @param b true to activate horizontal wrapping mode
1698      */
1699     public static void setHorizontalWrap(boolean b) {
1700         for (SciNotes ed : scinotesList) {
1701             int n = ed.getTabPane().getTabCount();
1702             for (int i = 0; i < n; i++) {
1703                 ScilabEditorPane sep = ed.getTextPane(i);
1704                 if (sep.getOtherPaneInSplit() == null) {
1705                     ScilabEditorPane pane = new ScilabEditorPane(editor);
1706                     ed.initPane(pane, !b);
1707                     sep.copyProps(pane);
1708                     pane.setDocument(sep.getDocument());
1709                     pane.setCaretPosition(sep.getCaretPosition());
1710                     pane.getXln().setWhereamiLineNumbering(ConfigSciNotesManager.getLineNumberingState());
1711                     ed.tabPane.setComponentAt(i, pane.getEditorComponent());
1712                     ed.activateHelpOnTyping(pane);
1713                     ed.initInputMap(pane);
1714                     if (((ScilabDocument) sep.getDocument()).getBinary()) {
1715                         pane.setBinary(true);
1716                     }
1717                     ed.getInfoBar().setText(pane.getInfoBarText());
1718                 }
1719             }
1720         }
1721     }
1722
1723     /**
1724      * Enable the highlighted line in this editor
1725      * @param b boolean
1726      */
1727     public static void enableHighlightedLine(boolean b) {
1728         for (SciNotes ed : scinotesList) {
1729             int n = ed.getTabPane().getTabCount();
1730             for (int i = 0; i < n; i++) {
1731                 ScilabEditorPane sep = ed.getTextPane(i);
1732                 sep.enableHighlightedLine(b);
1733                 if (sep.getOtherPaneInSplit() != null) {
1734                     sep.getOtherPaneInSplit().enableHighlightedLine(b);
1735                 }
1736             }
1737         }
1738     }
1739
1740     /**
1741      * Enable the help on typing in the current textPane
1742      * @param pane the pane
1743      */
1744     public static void activateHelpOnTyping(ScilabEditorPane pane) {
1745         pane.activateHelpOnTyping();
1746     }
1747
1748     /**
1749      * Enable the help on typing in this editor
1750      */
1751     public static void activateHelpOnTyping() {
1752         for (SciNotes ed : scinotesList) {
1753             int n = ed.getTabPane().getTabCount();
1754             for (int i = 0; i < n; i++) {
1755                 ScilabEditorPane sep = ed.getTextPane(i);
1756                 sep.activateHelpOnTyping();
1757                 if (sep.getOtherPaneInSplit() != null) {
1758                     sep.getOtherPaneInSplit().activateHelpOnTyping();
1759                 }
1760             }
1761         }
1762     }
1763
1764     /**
1765      * Set the color of the highlighted line in this editor
1766      * @param c Color
1767      */
1768     public static void setDefaultTabulation(TabManager.Tabulation tab) {
1769         for (SciNotes ed : scinotesList) {
1770             int n = ed.getTabPane().getTabCount();
1771             for (int i = 0; i < n; i++) {
1772                 ScilabEditorPane sep = ed.getTextPane(i);
1773                 sep.getTabManager().setTabulation(tab);
1774                 View view = ((ScilabDocument) sep.getDocument()).getView();
1775                 if (view != null) {
1776                     if (view instanceof ScilabView) {
1777                         ((ScilabView) view).setTabRepresentation(tab);
1778                         ((ScilabView) view).reinitialize();
1779                     } else {
1780                         ((ScilabPlainView) view).setTabRepresentation(tab);
1781                         ((ScilabPlainView) view).reinitialize();
1782                     }
1783                 }
1784             }
1785         }
1786     }
1787
1788     /**
1789      * Set the color of the highlighted line in this editor
1790      * @param c Color
1791      */
1792     public static void setHighlightedLineColor(Color c) {
1793         for (SciNotes ed : scinotesList) {
1794             int n = ed.getTabPane().getTabCount();
1795             for (int i = 0; i < n; i++) {
1796                 ScilabEditorPane sep = ed.getTextPane(i);
1797                 sep.setHighlightedLineColor(c);
1798                 if (sep.getOtherPaneInSplit() != null) {
1799                     sep.getOtherPaneInSplit().setHighlightedLineColor(c);
1800                 }
1801             }
1802         }
1803     }
1804
1805     /**
1806      * Set the color of the contour of the highlighted line in this editor
1807      * @param c Color
1808      */
1809     public static void setHighlightedContourColor(Color c) {
1810         for (SciNotes ed : scinotesList) {
1811             int n = ed.getTabPane().getTabCount();
1812             for (int i = 0; i < n; i++) {
1813                 ScilabEditorPane sep = ed.getTextPane(i);
1814                 sep.setHighlightedContourColor(c);
1815                 if (sep.getOtherPaneInSplit() != null) {
1816                     sep.getOtherPaneInSplit().setHighlightedContourColor(c);
1817                 }
1818             }
1819         }
1820     }
1821
1822     /**
1823      * Set the highlighted line in this textPane
1824      * @param sep ScilabEditorPane
1825      */
1826     public static void setHighlight(ScilabEditorPane sep) {
1827         sep.enableHighlightedLine(ConfigSciNotesManager.getHighlightState());
1828         Color[] arr = ConfigSciNotesManager.getHighlightColors();
1829         sep.setHighlightedLineColor(arr[0]);
1830         sep.setHighlightedContourColor(arr[1]);
1831     }
1832
1833     /**
1834      * Get SciNotes as a Tab.
1835      * @return SciNotes instance
1836      * @see org.scilab.modules.gui.tab.Tab#getAsSimpleTab()
1837      */
1838     @Override
1839     public SimpleTab getAsSimpleTab() {
1840         return this;
1841     }
1842
1843     /**
1844      * Get SciNotes parent Window.
1845      * @return parent Window
1846      * @see org.scilab.modules.gui.tab.Tab#getParentWindow()
1847      */
1848     @Override
1849     public Window getParentWindow() {
1850         return parentWindow;
1851     }
1852
1853     /**
1854      * Get the UUID associated with the editor instance.
1855      * @return unique identifier
1856      */
1857     public UUID getUUID() {
1858         return uuid;
1859     }
1860
1861     /**
1862      * Add a status bar to SciNotes.
1863      * @param infoBarToAdd the status bar to be added
1864      * @see org.scilab.modules.gui.uielement.UIElement#addInfoBar(org.scilab.modules.gui.textbox.TextBox)
1865      */
1866     @Override
1867     public void addInfoBar(TextBox infoBarToAdd) {
1868         setInfoBar(infoBarToAdd);
1869     }
1870
1871     /**
1872      * Add a menu bar to SciNotes.
1873      * @param menuBarToAdd the menu bar to be added
1874      * @see org.scilab.modules.gui.uielement.UIElement#addMenuBar(org.scilab.modules.gui.menubar.MenuBar)
1875      */
1876     @Override
1877     public void addMenuBar(MenuBar menuBarToAdd) {
1878         setMenuBar(menuBarToAdd);
1879     }
1880
1881     /**
1882      * Add a tool bar to SciNotes.
1883      * @param toolBarToAdd the tool bar to be added
1884      * @see org.scilab.modules.gui.uielement.UIElement#addToolBar(org.scilab.modules.gui.toolbar.ToolBar)
1885      */
1886     @Override
1887     public void addToolBar(ToolBar toolBarToAdd) {
1888         setToolBar(toolBarToAdd);
1889     }
1890
1891     /**
1892      * Get SciNotes main ScilabTabbedPane.
1893      * @return SciNotes main ScilabTabbedPane
1894      */
1895     public ScilabTabbedPane getTabPane() {
1896         return tabPane;
1897     }
1898
1899     /**
1900      * Set SciNotes main ScilabTabbedPane.
1901      * @param tabPane SciNotes main ScilabTabbedPane
1902      */
1903     public void setTabPane(ScilabTabbedPane tabPane) {
1904         this.tabPane = tabPane;
1905     }
1906
1907     /**
1908      * Load a file and add it at the end
1909      * @param f the file to load
1910      */
1911     public void loadFile(File f) {
1912         loadFile(f, -1);
1913     }
1914
1915     /**
1916      * Load a file and add it at the index
1917      * @param f the file to load
1918      * @param index the index where to put the file
1919      */
1920     public void loadFile(File f, int index) {
1921         ScilabDocument styleDocument = null;
1922         ScilabEditorPane theTextPane;
1923
1924         // File exist
1925         if (f.exists()) {
1926             if (!f.canRead()) {
1927                 ScilabModalDialog.show(this, SciNotesMessages.NOTREADABLE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON);
1928                 if (getTabPane().getTabCount() == 0) {
1929                     addEmptyTab();
1930                 }
1931                 return;
1932             }
1933
1934             getInfoBar().setText(SciNotesMessages.LOADING);
1935
1936             if (index != -1) {
1937                 theTextPane = addTab(f.getName(), index);
1938             } else {
1939                 theTextPane = addTab(f.getName());
1940             }
1941             styleDocument = (ScilabDocument) theTextPane.getDocument();
1942             styleDocument.disableUndoManager();
1943             theTextPane.setLastModified(f.lastModified());
1944
1945             try {
1946                 styleDocument.setUpdater(false);
1947                 boolean indentMode = styleDocument.getAutoIndent();
1948                 styleDocument.setAutoIndent(false);
1949                 try {
1950                     ((ScilabEditorKit) editorKit).read(this, f, styleDocument, 0);
1951                 } catch (BadLocationException e) {
1952                     e.printStackTrace();
1953                 }
1954                 styleDocument.setAutoIndent(indentMode);
1955                 styleDocument.setUpdater(true);
1956             } catch (IOException ioex) {
1957                 ioex.printStackTrace();
1958             }
1959
1960             theTextPane.setName(f.getAbsolutePath());
1961             getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
1962             setTitle(theTextPane.getTitle());
1963             styleDocument.setContentModified(false);
1964             styleDocument.enableUndoManager();
1965
1966             if (styleDocument.getBinary()) {
1967                 theTextPane.setBinary(true);
1968             }
1969
1970             if (!f.canWrite()) {
1971                 getTextPane().setReadOnly(true);
1972                 JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.READONLY);
1973             }
1974
1975             getInfoBar().setText(theTextPane.getInfoBarText());
1976
1977             EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
1978
1979             ConfigManager.saveLastOpenedDirectory(f.getPath());
1980             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
1981             ConfigSciNotesManager.saveToOpenFiles(f.getPath(), this, getTextPane());
1982
1983             // Empty the undo Manager
1984             UndoManager undo = ((ScilabDocument) getTextPane().getDocument()).getUndoManager();
1985             undo.discardAllEdits();
1986
1987             if (getTabPane().getTabCount() == 2) {
1988                 ScilabEditorPane pane = getTextPane(0);
1989                 if (pane.getName() == null && !((ScilabDocument) pane.getDocument()).isContentModified()) {
1990                     closeTabAt(0);
1991                 }
1992             }
1993         }
1994     }
1995
1996     /**
1997      * Creates a file if it doesn't exist
1998      * @param f the file to create
1999      */
2000     public void createNewFile(File f) {
2001         ScilabEditorPane theTextPane = addEmptyTab();
2002         ScilabDocument styleDocument = null;
2003         int choice = JOptionPane.showConfirmDialog(SciNotes.this,
2004                                                    String.format(SciNotesMessages.FILE_DOESNT_EXIST, f.getName()),
2005                                                    SCINOTES,
2006                                                    JOptionPane.YES_NO_OPTION);
2007         if (choice == 0) { //OK
2008             styleDocument = (ScilabDocument) theTextPane.getDocument();
2009             styleDocument.disableUndoManager();
2010
2011             BufferedWriter bw = null;
2012             OutputStreamWriter osw = null;
2013             FileOutputStream fos = null;
2014
2015             try {
2016                 fos = new FileOutputStream(f);
2017                 osw = new OutputStreamWriter(fos, styleDocument.getEncoding());
2018                 bw = new BufferedWriter(osw);
2019                 editorKit.write(bw, styleDocument, 0, styleDocument.getLength());
2020                 bw.flush();
2021             } catch (IOException e) {
2022                 System.err.println(e);
2023             } catch (BadLocationException e) {
2024                 System.err.println(e);
2025             } finally {
2026                 try {
2027                     if (fos != null) {
2028                         fos.close();
2029                     }
2030                     if (osw != null) {
2031                         osw.close();
2032                     }
2033                     if (bw != null) {
2034                         bw.close();
2035                     }
2036                 } catch (IOException e) {
2037                     System.err.println(e);
2038                 }
2039             }
2040
2041             ConfigManager.saveLastOpenedDirectory(f.getPath());
2042             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
2043             ConfigSciNotesManager.saveToOpenFiles(theTextPane.getName(), this, theTextPane);
2044
2045             theTextPane.setName(f.getPath());
2046             getTabPane().setTitleAt(getTabPane().getSelectedIndex() , f.getName());
2047             setTitle(theTextPane.getTitle());
2048             RecentFileAction.updateRecentOpenedFilesMenu(this);
2049
2050             styleDocument.setContentModified(false);
2051             styleDocument.enableUndoManager();
2052             theTextPane.setLastModified(f.lastModified());
2053         }
2054
2055         getInfoBar().setText("");
2056     }
2057
2058     /**
2059      * EditorKit Getter
2060      * @return EditorKit
2061      */
2062     public EditorKit getEditorKit() {
2063         return editorKit;
2064     }
2065
2066     /**
2067      * @param scinotes the focused editor
2068      */
2069     public static void setEditor(SciNotes scinotes) {
2070         editor = scinotes;
2071     }
2072
2073     /**
2074      * @return the focused editor
2075      */
2076     public static SciNotes getEditor() {
2077         return editor;
2078     }
2079
2080     /**
2081      * EditorKit Setter
2082      * @param editorKit EditorKit
2083      */
2084     public void setEditorKit(EditorKit editorKit) {
2085         this.editorKit = editorKit;
2086     }
2087
2088     /**
2089      * Close scinotes from scilab.
2090      *
2091      * This method can be called outside the EDT thread.
2092      */
2093     public static void closeSciNotesFromScilab() {
2094         try {
2095             SwingUtilities.invokeAndWait(new Runnable() {
2096
2097                     @Override
2098                     public void run() {
2099                         SciNotes[] arr = scinotesList.toArray(new SciNotes[0]);
2100                         for (int i = 0; i < arr.length; i++) {
2101                             arr[i].setProtectOpenFileList(true);
2102                             ExitAction.doExit(arr[i]);
2103                         }
2104                         scinotesList.clear();
2105                     }
2106                 });
2107         } catch (InterruptedException e) {
2108             LogFactory.getLog(SciNotes.class).error(e);
2109         } catch (InvocationTargetException e) {
2110             LogFactory.getLog(SciNotes.class).error(e);
2111         }
2112     }
2113
2114     /**
2115      * @param f the file
2116      * @return the canonical file if possible
2117      */
2118     public static File fileToCanonicalFile(File f) {
2119         /* Fix bug 5648 */
2120         try {
2121             return f.getCanonicalFile();
2122         } catch (IOException e) {
2123             return f;
2124         }
2125     }
2126
2127     /**
2128      * Set the shortcuts in the pane relatively to the file keysConfiguration.xml
2129      * @param sep the textpane
2130      * @param ed the SciNotes editor
2131      */
2132     private static void setKeyStrokeAction(ScilabEditorPane sep, SciNotes ed) {
2133         Map<String, KeyStroke> map = new HashMap<String, KeyStroke>();
2134         ConfigSciNotesManager.addMapActionNameKeys(map);
2135
2136         ClassLoader loader = ClassLoader.getSystemClassLoader();
2137         Iterator<String> iter = map.keySet().iterator();
2138         while (iter.hasNext()) {
2139             String action = iter.next();
2140             if (!action.equals("SciNotesCompletionAction")) {
2141                 String className;
2142                 if (action.lastIndexOf(DOT) != -1)  {
2143                     className = action;
2144                 } else {
2145                     className = DEFAULTACTIONPATH + DOT + action;
2146                 }
2147                 try {
2148                     Class clazz = loader.loadClass(className);
2149                     Constructor constructor = clazz.getConstructor(new Class[]{String.class, SciNotes.class});
2150                     Object act = constructor.newInstance(new Object[]{"", ed});
2151                     sep.getInputMap().put(map.get(action), act);
2152                 } catch (ClassNotFoundException e) {
2153                     System.err.println("No action: " + className);
2154                 } catch (InstantiationException e) {
2155                     System.err.println("Problem to instantiate in action: " + className);
2156                 } catch (NoSuchMethodException e) {
2157                     System.err.println("No valid constructor in action: " + className);
2158                 } catch (IllegalAccessException e) {
2159                     System.err.println("The constructor must be public: " + className);
2160                 } catch (InvocationTargetException e) {
2161                     System.err.println("The constructor in " + className + " threw an exception :");
2162                     e.printStackTrace();
2163                 }
2164             } else {
2165                 sep.getInputMap().put(map.get(action), new SciNotesCompletionAction(sep, ed));
2166             }
2167         }
2168     }
2169 }