Refactorization of the management of the actions in menus, button, shortcuts
[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 - 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.awt.Dimension;
19 import java.awt.Point;
20 import java.awt.event.ActionEvent;
21 import java.io.BufferedReader;
22 import java.io.BufferedWriter;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileNotFoundException;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.OutputStreamWriter;
30 import java.io.StringReader;
31 import java.io.UnsupportedEncodingException;
32 import java.lang.reflect.InvocationTargetException;
33 import java.lang.reflect.Constructor;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Iterator;
40
41 import javax.swing.BorderFactory;
42 import javax.swing.JFileChooser;
43 import javax.swing.JOptionPane;
44 import javax.swing.JScrollPane;
45 import javax.swing.JSplitPane;
46 import javax.swing.JTabbedPane;
47 import javax.swing.KeyStroke;
48 import javax.swing.SwingUtilities;
49 import javax.swing.event.ChangeEvent;
50 import javax.swing.event.ChangeListener;
51 import javax.swing.text.BadLocationException;
52 import javax.swing.text.ChangedCharSetException;
53 import javax.swing.text.EditorKit;
54 import javax.swing.undo.UndoManager;
55
56 import org.apache.commons.logging.LogFactory;
57 import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser;
58 import org.scilab.modules.gui.bridge.tab.SwingScilabTab;
59 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
60 import org.scilab.modules.gui.events.callback.CallBack;
61 import org.scilab.modules.gui.filechooser.Juigetfile;
62 import org.scilab.modules.gui.filechooser.ScilabFileChooser;
63 import org.scilab.modules.gui.menubar.MenuBar;
64 import org.scilab.modules.gui.messagebox.MessageBox;
65 import org.scilab.modules.gui.messagebox.ScilabMessageBox;
66 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
67 import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption;
68 import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType;
69 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
70 import org.scilab.modules.gui.pushbutton.PushButton;
71 import org.scilab.modules.gui.tab.SimpleTab;
72 import org.scilab.modules.gui.tab.Tab;
73 import org.scilab.modules.gui.textbox.TextBox;
74 import org.scilab.modules.gui.toolbar.ToolBar;
75 import org.scilab.modules.gui.utils.ConfigManager;
76 import org.scilab.modules.gui.utils.Position;
77 import org.scilab.modules.gui.utils.SciFileFilter;
78 import org.scilab.modules.gui.utils.Size;
79 import org.scilab.modules.gui.window.ScilabWindow;
80 import org.scilab.modules.gui.window.Window;
81 import org.scilab.modules.scinotes.actions.ExitAction;
82 import org.scilab.modules.scinotes.actions.FindAction;
83 import org.scilab.modules.scinotes.actions.SetColorsAction;
84 import org.scilab.modules.scinotes.actions.LineBeautifierAction;
85 import org.scilab.modules.scinotes.actions.RecentFileAction;
86 import org.scilab.modules.scinotes.actions.SciNotesCompletionAction;
87 import org.scilab.modules.scinotes.actions.EncodingAction;
88 import org.scilab.modules.scinotes.actions.EndOfLineAction;
89 import org.scilab.modules.scinotes.utils.ConfigSciNotesManager;
90 import org.scilab.modules.scinotes.utils.DropFilesListener;
91 import org.scilab.modules.scinotes.utils.SaveFile;
92 import org.scilab.modules.scinotes.utils.SciNotesMessages;
93
94 /**
95  * Main SciNotes class.
96  * @author Bruno JOFRET
97  * @author Calixte DENIZET
98  */
99 public class SciNotes extends SwingScilabTab implements Tab {
100
101     private static final long serialVersionUID = -6410183357490518676L;
102
103     private static final String SCINOTES = "SciNotes";
104     private static final String SCI_EXTENSION = ".sci";
105     private static final String SCE_EXTENSION = ".sce";
106     private static final String TST_EXTENSION = ".tst";
107     private static final String QUIT_EXTENSION = ".quit";
108     private static final String START_EXTENSION = ".start";
109     private static final String ALL_TST_FILES = "*.tst";
110     private static final String ALL_QUIT_FILES = "*.quit";
111     private static final String ALL_START_FILES = "*.start";
112     private static final String ALL_SCI_FILES = "*.sci";
113     private static final String ALL_SCE_FILES = "*.sce";
114     private static final String ALL_SCX_FILES = "*.sc*";
115     private static final String ALL_SCILAB = "all";
116     private static final String ALL_FILES = "*.*";
117     private static final String TIRET = " - ";
118     private static final String DOT = ".";
119
120     private static final String DEFAULTACTIONPATH = "org.scilab.modules.scinotes.actions";
121
122     private static final int ZERO = 0;
123     private static final int ONE = 1;
124     private static final int TWO = 2;
125     private static final int THREE = 3;
126     private static final int FOUR = 4;
127
128     private static List<SciNotes> scinotesList = new ArrayList();
129     private static SciNotes editor;
130
131     private final Window parentWindow;
132
133     private JTabbedPane tabPane;
134     private ScilabEditorPane textPane;
135     private JScrollPane scrollingText;
136     private int numberOfUntitled;
137     private EditorKit editorKit;
138     private Object synchro = new Object();
139     private FindAction find;
140
141     private PushButton undoButton;
142     private PushButton redoButton;
143
144     private boolean highlight;
145     private Color highlightColor;
146     private Color highlightContourColor;
147
148     private boolean helpOnTyping;
149
150     private int whereami;
151
152     private List<Integer> tabList = new ArrayList();
153     private List<Integer> closedTabList = new ArrayList();
154
155     private String fileFullPath = "";
156
157     private File fileToEncode;
158
159     /**
160      * Create SciNotes instance inside parent Window
161      * @param parentWindow the parent Window
162      */
163     public SciNotes(Window parentWindow) {
164         super(SCINOTES);
165         scinotesList.add(this);
166         this.parentWindow = parentWindow;
167         numberOfUntitled = 0;
168         editorKit = new ScilabEditorKit();
169         setDefaultHighlight();
170         setDefaultHelpOnTyping();
171         SwingScilabWindow window = (SwingScilabWindow) parentWindow.getAsSimpleWindow();
172         Position pos = ConfigSciNotesManager.getMainWindowPosition();
173         window.setLocation(pos.getX(), pos.getY());
174         Size size = ConfigSciNotesManager.getMainWindowSize();
175         window.setSize(size.getWidth(), size.getHeight());
176         tabPane = new JTabbedPane();
177         tabPane.addChangeListener(new ChangeListener() {
178                 public void stateChanged(ChangeEvent e) {
179                     String path = new String("");
180                     if (getTextPane() != null) {
181                         if (getTextPane().getName() != null) {
182                             path  =  " (" + getTextPane().getName() + ")";
183                         }
184                         updateUI();
185                         getTextPane().updateInfosWhenFocused();
186
187                         // Update encoding menu
188                         EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
189
190                         // Update End Of Line  menu
191                         EndOfLineAction.updateEolMenu((ScilabDocument) getTextPane().getDocument());
192                         setTitle(tabPane.getTitleAt(tabPane.getSelectedIndex()) + path + TIRET + SciNotesMessages.SCILAB_EDITOR);
193                     }
194                 }
195             });
196         this.setContentPane(tabPane);
197     }
198
199     /**
200      * {@inheritDoc}
201      */
202     public void setTitle(String title) {
203         super.setTitle(title);
204         final SwingScilabWindow window = (SwingScilabWindow) SwingUtilities
205             .getAncestorOfClass(SwingScilabWindow.class, tabPane);
206         if (window != null) {
207             window.setTitle(title);
208         }
209     }
210
211     /**
212      * Launch SciNotes from command line.
213      * @param args command line args
214      */
215     public static void main(String[] args) {
216         scinotes();
217     }
218
219     /**
220      * Launch SciNotes with an empty file
221      *
222      * This method *must not* be called on the EDT thread.
223      */
224     public static void scinotes() {
225         try {
226             SwingUtilities.invokeAndWait(new Runnable() {
227
228                     @Override
229                     public void run() {
230                         launchSciNotes().openFile(null, 0, null);
231                     }
232                 });
233         } catch (InterruptedException e) {
234             LogFactory.getLog(SciNotes.class).error(e);
235             throw new RuntimeException(e);
236         } catch (InvocationTargetException e) {
237             LogFactory.getLog(SciNotes.class).error(e);
238             e.printStackTrace();
239             throw new RuntimeException(e);
240         }
241     }
242
243     /**
244      * Launch SciNotes with a file name to open.
245      * @param filePath the name of the file to open
246      *
247      * This method *must not* be called on the EDT thread.
248      */
249     public static void scinotes(final String filePath) {
250         try {
251             SwingUtilities.invokeAndWait(new Runnable() {
252
253                     @Override
254                     public void run() {
255                         launchSciNotes().openFile(filePath, 0, null);
256                     }
257                 });
258         } catch (InterruptedException e) {
259             LogFactory.getLog(SciNotes.class).error(e);
260             throw new RuntimeException(e);
261         } catch (InvocationTargetException e) {
262             LogFactory.getLog(SciNotes.class).error(e);
263             throw new RuntimeException(e);
264         }
265     }
266
267     /**
268      * Launch SciNotes with a file name to open and a line to highlight.
269      * @param filePath the name of the file to open
270      * @param lineNumber the line to highlight
271      *
272      * This method *must not* be called on the EDT thread.
273      */
274     public static void scinotes(final String filePath, final int lineNumber) {
275         try {
276             SwingUtilities.invokeAndWait(new Runnable() {
277
278                     @Override
279                     public void run() {
280                         launchSciNotes().openFile(filePath, lineNumber, null);
281                     }
282                 });
283         } catch (InterruptedException e) {
284             LogFactory.getLog(SciNotes.class).error(e);
285             throw new RuntimeException(e);
286         } catch (InvocationTargetException e) {
287             LogFactory.getLog(SciNotes.class).error(e);
288             throw new RuntimeException(e);
289         }
290     }
291
292     /**
293      * Launch SciNotes with a file name to open and a line to highlight.
294      * @param filePath the name of the file to open
295      * @param option such as 'readonly'
296      *
297      * This method *must not* be called on the EDT thread.
298      */
299     public static void scinotes(final String filePath, final String option) {
300         try {
301             SwingUtilities.invokeAndWait(new Runnable() {
302
303                     @Override
304                     public void run() {
305                         launchSciNotes().openFile(filePath, 0, option);
306                     }
307                 });
308         } catch (InterruptedException e) {
309             LogFactory.getLog(SciNotes.class).error(e);
310             throw new RuntimeException(e);
311         } catch (InvocationTargetException e) {
312             LogFactory.getLog(SciNotes.class).error(e);
313             throw new RuntimeException(e);
314         }
315     }
316
317     /**
318      * Launch SciNotes with a provided text (from the help for example).
319      * @param text the text which should be modified
320      */
321     public static void scinotesWithText(String text) {
322         SciNotes editorInstance = launchSciNotes();
323         ScilabEditorPane theTextPane = editorInstance.addEmptyTab();
324         ScilabDocument styleDocument = (ScilabDocument) theTextPane.getDocument();
325         try {
326             editorInstance.getEditorKit().read(new StringReader(text), styleDocument, 0);
327         } catch (IOException e) {
328             System.err.println(SciNotesMessages.ERROR_WITH_STRING);
329         } catch (BadLocationException e) {
330             System.err.println(SciNotesMessages.ERROR_WITH_STRING);
331         }
332     }
333
334     /**
335      * Clone the current tab and if b is true close the tab
336      * @param ed the editor where the tab is
337      * @param b a boolean
338      */
339     public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b) {
340         ScilabDocument cdoc = (ScilabDocument) ed.getTextPane().getDocument();
341         String title = ed.getTabPane().getTitleAt(ed.getTabPane().getSelectedIndex());
342         ScilabEditorPane currentSep = ed.getTextPane();
343         String winTitle = ed.getTitle();
344
345         if (b) {
346             ed.closeTabAt(ed.getTabPane().getSelectedIndex());
347             if (ed.getTabPane().getTabCount() == 0) {
348                 ed.addEmptyTab();
349             }
350         }
351
352         editor = null;
353         scinotesWithText(cdoc.getText());
354         editor.getTabPane().setTitleAt(0, title);
355         currentSep.copyProps(editor.getTextPane());
356         editor.setTitle(winTitle);
357         ScilabDocument sdoc = (ScilabDocument) editor.getTextPane().getDocument();
358         sdoc.setContentModified(cdoc.isContentModified());
359         sdoc.getUndoManager().discardAllEdits();
360         editor.getTextPane().setCaretPosition(0);
361         editor.enableUndoButton(false);
362         editor.enableRedoButton(false);
363     }
364
365     /**
366      * Create SciNotes instance
367      * @return the instance
368      */
369     public static SciNotes launchSciNotes() {
370         if (editor == null) {
371             editor = createEditor();
372         }
373         return editor;
374     }
375
376     /**
377      * Open a file.
378      *
379      * This method *must* be called on the EDT thread.
380      *
381      * @param filePath the file path (may be null)
382      * @param lineNumber the line number (use 0 for unspecified)
383      * @param option the options (may be null)
384      */
385     public void openFile(String filePath, int lineNumber, String option) {
386         if (!SwingUtilities.isEventDispatchThread()) {
387             throw new RuntimeException("called outside the EDT thread.");
388         }
389
390         if (filePath == null) {
391             addEmptyTab();
392             return;
393         }
394
395         File f = fileToCanonicalFile(new File(filePath));
396         if (f.isDirectory()) { /* Bug 5131 */
397             ConfigManager.saveLastOpenedDirectory(f.getPath());
398             addEmptyTab();
399             return;
400         }
401
402         ConfigSciNotesManager.saveToRecentOpenedFiles(filePath);
403         RecentFileAction.updateRecentOpenedFilesMenu(this);
404         readFileAndWait(f);
405         getTextPane().scrollTextToLineNumber(lineNumber);
406         if (option != null && "readonly".equals(option.toLowerCase())) {
407             getTextPane().setReadOnly(true);
408             getInfoBar().setText(getTextPane().getInfoBarText());
409         }
410     }
411
412     /**
413      * Close SciNotes instance including all tabs.
414      */
415     public void closeSciNotes() {
416         if (find != null) {
417             find.closeFindReplaceWindow();
418         }
419         SetColorsAction.closeSetColorsWindow();
420         while (getTabPane().getComponentCount() > 0) {
421             closeTabAt(0, true);
422         }
423         scinotesList.remove(this);
424         editor = null;
425         SwingScilabWindow window = (SwingScilabWindow) parentWindow.getAsSimpleWindow();
426         Point p = window.getLocation();
427         ConfigSciNotesManager.saveMainWindowPosition(new Position(p.x, p.y));
428         Dimension d = window.getSize();
429         ConfigSciNotesManager.saveMainWindowSize(new Size(d.width, d.height));
430     }
431
432     /**
433      * Create SciNotes instance.
434      * @return the instance
435      */
436     private static SciNotes createEditor() {
437         ConfigSciNotesManager.createUserCopy();
438         Window mainWindow = ScilabWindow.createWindow();
439
440         final SciNotes editorInstance = new SciNotes(mainWindow);
441
442         SciNotesGUI.init(mainWindow, editorInstance, SCINOTES);
443         editorInstance.setCallback(new CallBack(SciNotesMessages.DEFAULT + SciNotesMessages.DOTS) {
444                 /**
445                  * serialVersionUID
446                  */
447                 private static final long serialVersionUID = -4121140054209319523L;
448
449                 /**
450                  * Action callback on Exit menu
451                  */
452                 public void callBack() {
453                     SwingUtilities.invokeLater(new Runnable() {
454                             public void run() {
455                                 if (editorInstance.getTabPane().getTabCount() != 1) {
456                                     if (ScilabModalDialog.show(editorInstance,
457                                                                SciNotesMessages.EXIT_CONFIRM, SciNotesMessages.EXIT,
458                                                                IconType.WARNING_ICON, ButtonType.YES_NO) == AnswerOption.YES_OPTION) {
459                                         ExitAction.doExit(editorInstance);
460                                     }
461                                 } else {
462                                     ExitAction.doExit(editorInstance);
463                                 }
464                             }
465                         });
466                 }
467
468                 /**
469                  * actionPerformed
470                  * @param e ActionEvent
471                  */
472                 public void actionPerformed(ActionEvent e) {
473                     callBack();
474                 }
475             });
476
477         return editorInstance;
478     }
479
480     /**
481      * Close a tab using its index.
482      * @param indexTab the index of the tab
483      * @return if the tab has been really closed
484      */
485     public boolean closeTabAt(int indexTab) {
486         return closeTabAt(indexTab, false);
487     }
488
489     /**
490      * Close a tab using its index.
491      * @param indexTab the index of the tab
492      * @param scilabClose if true, save dialog confirmation cannot be canceled
493      * @return if the tab has been really closed
494      */
495     public boolean closeTabAt(int indexTab, boolean scilabClose) {
496         ScilabEditorPane textPaneAt = getTextPane(indexTab);
497
498         /* Test for modification added after bug 5103 fix: do not ask the user for an Untitled not-modified file saving when closing SciNotes */
499         if (((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
500             if (!save(indexTab, false, scilabClose)) {
501                 return false;
502             }
503         }
504
505         if (textPaneAt.getName() == null) {
506             String closedTabName = tabPane.getTitleAt(indexTab);
507             String closedTabNameIndex = closedTabName.substring(closedTabName.length() - 1, closedTabName.length());
508             tabList.remove(Integer.valueOf(closedTabNameIndex));
509             closedTabList.add(Integer.valueOf(closedTabNameIndex));
510         }
511
512         // correction for bug 5404, closing the last tabPane generate an exception
513         // that's why we need to remove ChangeListeners before closing
514         if ((indexTab == 0) && (getTabPane().getTabCount() == 1)) {
515             for (int i = 0; i < tabPane.getChangeListeners().length; i++) {
516                 tabPane.removeChangeListener(tabPane.getChangeListeners()[i]);
517             }
518         }
519
520         textPaneAt.close();
521         tabPane.remove(indexTab);
522         return true;
523
524     }
525
526     /**
527      * Save a file.
528      * @param indexTab the textPane index containing the file contents
529      * @return execution status
530      */
531     public boolean save(int indexTab) {
532         return save(indexTab, false, false);
533     }
534
535     /**
536      * Save a file.
537      * @param indexTab the textPane index containing the file contents
538      * @param force : force save without confirmation dialog ( SaveAction )
539      * @return execution status
540      */
541     public boolean save(int indexTab, boolean force) {
542         return save(indexTab, force, false);
543     }
544
545     /**
546      * Save a file.
547      * @param indexTab the textPane index containing the file contents
548      * @param force : force save without confirmation dialog ( SaveAction )
549      * @param scilabClose : if true, save dialog confirmation cannot be canceled
550      * @return execution status
551      */
552     public boolean save(int indexTab, boolean force, boolean scilabClose) {
553         ScilabEditorPane textPaneAt = getTextPane(indexTab);
554         //if the file ( empty, new or loaded ) is not modified, exit save process and return true
555         if (!textPaneAt.checkExternalModif() && !((ScilabDocument) textPaneAt.getDocument()).isContentModified()
556             && (textPaneAt.getName() != null)) { /* Bug 5103 fix */
557             return true;
558         }
559
560         if (!force) {
561             AnswerOption answer;
562             if (scilabClose) {
563                 answer = ScilabModalDialog.show(this, getTabPane().getTitleAt(indexTab) + SciNotesMessages.MODIFIED,
564                                                 SciNotesMessages.SCILAB_EDITOR, IconType.QUESTION_ICON, ButtonType.YES_NO);
565             } else {
566                 answer = ScilabModalDialog.show(this, getTabPane().getTitleAt(indexTab) + SciNotesMessages.MODIFIED,
567                                                 SciNotesMessages.SCILAB_EDITOR, IconType.QUESTION_ICON, ButtonType.YES_NO_CANCEL);
568             }
569
570             switch (answer) {
571             case YES_OPTION : //Yes, continue
572                 break;
573             case NO_OPTION ://No, exit and returns true
574                 return true;
575             case CANCEL_OPTION : //Cancel, exit and return false
576                 return false;
577             default:
578                 break;
579             }
580         }
581
582         String fileToSave = textPaneAt.getName();
583         if (fileToSave == null) {
584             //need a filename, call chooseFileToSave
585             fileToSave = chooseFileToSave(SciNotesMessages.SAVE);
586         } else {
587             //check if the file has been modified by external software
588             fileToSave = checkExternalModification(fileToSave);
589         }
590
591         if (fileToSave == null) {
592             return true; /* Bug 5189: The user cancels ==> do not want an error message */
593         }
594
595         File newSavedFile = new File(fileToSave);
596
597         if (!SaveFile.doSave(textPaneAt, newSavedFile, editorKit)) {
598             return false;
599         }
600
601         ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument();
602         styledDocument.setContentModified(false);
603
604         getTabPane().setTitleAt(getTabPane().getSelectedIndex() , newSavedFile.getName());
605         setTitle(newSavedFile.getPath() + TIRET + SciNotesMessages.SCILAB_EDITOR);
606
607         // Get current file path for Execute file into Scilab
608         fileFullPath = newSavedFile.getAbsolutePath();
609         getTextPane().setLastModified(newSavedFile.lastModified());
610
611         textPaneAt.setName(fileToSave);
612         return true;
613     }
614
615     /**
616      * Overwrite the file at a given index.
617      * @param indexTab the textPane index containing the file contents
618      * @return execution status
619      */
620     public boolean overwrite(int indexTab) {
621         ScilabEditorPane textPaneAt = getTextPane(indexTab);
622         String fileToSave = textPaneAt.getName();
623         if (fileToSave == null) {
624             return true;
625         }
626
627         File newSavedFile = new File(fileToSave);
628         if (!newSavedFile.exists()) {
629             return true;
630         }
631
632         if (!SaveFile.doSave(textPaneAt, newSavedFile, editorKit)) {
633             return false;
634         }
635
636         ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument();
637         styledDocument.setContentModified(false);
638
639         getTabPane().setTitleAt(getTabPane().getSelectedIndex() , newSavedFile.getName());
640         setTitle(newSavedFile.getPath() + TIRET + SciNotesMessages.SCILAB_EDITOR);
641
642         // Get current file path for Execute file into Scilab
643         fileFullPath = newSavedFile.getAbsolutePath();
644         getTextPane().setLastModified(newSavedFile.lastModified());
645
646         textPaneAt.setName(fileToSave);
647         return true;
648     }
649
650     /**
651      * Check for external modification. If it is the case, propose
652      * to select a new file name.
653      * @param filename The name of the file
654      * @return the filename where to save
655      */
656     public String checkExternalModification(String filename) {
657         File newSavedFile = new File(filename);
658         if (newSavedFile.lastModified() > getTextPane().getLastModified()) {
659             if (ScilabModalDialog.show(this, String.format(SciNotesMessages.EXTERNAL_MODIFICATION, newSavedFile.getPath()),
660                                        SciNotesMessages.REPLACE_FILE_TITLE, IconType.QUESTION_ICON,
661                                        ButtonType.YES_NO) == AnswerOption.NO_OPTION) {
662                 return chooseFileToSave(SciNotesMessages.SAVE);
663             }
664         }
665         return filename;
666     }
667
668     /**
669      * Return through a file selector the name of the selected
670      * file.
671      * @param title the title for JFileChooser
672      * @return the file picked up by the user
673      */
674     public String chooseFileToSave(String title) {
675         String extension = new String();
676
677         String initialDirectoryPath = getTextPane().getName();
678         if (initialDirectoryPath == null) {
679             initialDirectoryPath =  ConfigManager.getLastOpenedDirectory();
680         }
681
682         SciFileFilter sceFilter = new SciFileFilter(ALL_SCE_FILES, null, 0);
683         SciFileFilter sciFilter = new SciFileFilter(ALL_SCI_FILES, null, 1);
684         SciFileFilter scxFilter = new SciFileFilter(ALL_SCX_FILES, null, 2);
685         SciFileFilter tstFilter = new SciFileFilter(ALL_TST_FILES, null, 3);
686         SciFileFilter startFilter = new SciFileFilter(ALL_START_FILES, null, 4);
687         SciFileFilter quitFilter = new SciFileFilter(ALL_QUIT_FILES, null, 5);
688         SciFileFilter allFilter = new SciFileFilter(ALL_FILES, null, 6);
689         SciFileFilter allScilabFilter = new SciFileFilter(ALL_SCILAB, null, 7);
690
691         SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser());
692
693         fileChooser.setInitialDirectory(ConfigManager.getLastOpenedDirectory());
694         fileChooser.setAcceptAllFileFilterUsed(false);
695         fileChooser.setInitialDirectory(initialDirectoryPath);
696         fileChooser.setUiDialogType(Juigetfile.SAVE_DIALOG);
697
698         // order is also important here
699         fileChooser.addChoosableFileFilter(sceFilter);
700         fileChooser.addChoosableFileFilter(sciFilter);
701         fileChooser.addChoosableFileFilter(scxFilter);
702         fileChooser.addChoosableFileFilter(tstFilter);
703         fileChooser.addChoosableFileFilter(startFilter);
704         fileChooser.addChoosableFileFilter(quitFilter);
705         fileChooser.addChoosableFileFilter(allFilter);
706         fileChooser.addChoosableFileFilter(allScilabFilter);
707
708         //select default file type
709         fileChooser.setFileFilter(sceFilter);
710         fileChooser.setTitle(title);
711
712         String name = ((ScilabDocument) getTextPane().getDocument()).getFirstFunctionName();
713         if (name != null) {
714             fileChooser.setSelectedFile(new File(name + SCI_EXTENSION));
715         }
716
717         int retval = fileChooser.showSaveDialog(this);
718
719         if (retval == JFileChooser.APPROVE_OPTION) {
720             File f = fileToCanonicalFile(fileChooser.getSelectedFile());
721             initialDirectoryPath = f.getPath();
722             if (f.exists()) {
723                 if (ScilabModalDialog.show(this, SciNotesMessages.REPLACE_FILE_TITLE,
724                                            SciNotesMessages.FILE_ALREADY_EXIST, IconType.QUESTION_ICON,
725                                            ButtonType.YES_NO) == AnswerOption.NO_OPTION) {
726                     return chooseFileToSave(SciNotesMessages.SAVE);
727                 }
728             }
729
730             /*we test if the file has already a scilab extension*/
731             boolean hasNoExtension = true;
732
733             // if the file name is like this : any character , a dot , then 2,3or 4 characters, then
734             // we consider the file has already an extension
735             // we previously only check for .sci and .sce extension, but what if the user open a txt file
736             String fileName = f.getName();
737             if (fileName.lastIndexOf(DOT) != -1) {
738                 if (fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() >= 2
739                     && fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() <= 4) {
740                     hasNoExtension = false;
741                 }
742             }
743
744             /*if no extension , we add it */
745             if (hasNoExtension) {
746
747                 if (fileChooser.getFileFilter() == sciFilter) {
748                     extension = SCI_EXTENSION;
749                 } else if (fileChooser.getFileFilter() == sceFilter) {
750                     extension = SCE_EXTENSION;
751                 } else if (fileChooser.getFileFilter() == scxFilter) {
752                     extension = SCE_EXTENSION;
753                 } else if (fileChooser.getFileFilter() == tstFilter) {
754                     extension = TST_EXTENSION;
755                 } else if (fileChooser.getFileFilter() == startFilter) {
756                     extension = START_EXTENSION;
757                 } else if (fileChooser.getFileFilter() == quitFilter) {
758                     extension = QUIT_EXTENSION;
759                 } else {
760                     extension = "";
761                 }
762                 return f.getPath() + extension;
763             }
764             return f.getPath();
765         } else if (retval == JFileChooser.CANCEL_OPTION) {
766             return "";
767         }
768
769         return null;
770     }
771
772     /**
773      * Save a file.
774      * @return execution status
775      */
776     public boolean saveAs() {
777         boolean isSuccess = false;
778         String filename = chooseFileToSave(SciNotesMessages.SAVE_AS);
779         if (filename == null) {
780             return false;
781         } else if (filename.length() == 0) {
782             return true;
783         }
784
785         File f = new File(filename);
786         ScilabDocument styledDocument = (ScilabDocument) getTextPane().getDocument();
787
788         if (!SaveFile.doSave(getTextPane(), f, editorKit)) {
789             return false;
790         }
791
792         ConfigManager.saveLastOpenedDirectory(f.getPath());
793         ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
794         getTextPane().setName(f.getPath());
795         getTabPane().setTitleAt(getTabPane().getSelectedIndex() , f.getName());
796         setTitle(f.getPath() + TIRET + SciNotesMessages.SCILAB_EDITOR);
797         RecentFileAction.updateRecentOpenedFilesMenu(this);
798
799         styledDocument.setContentModified(false);
800         getTextPane().setLastModified(f.lastModified());
801         isSuccess = true;
802
803         // Get current file path for Execute file into Scilab
804         fileFullPath = f.getAbsolutePath();
805
806         return isSuccess;
807     }
808
809     /**
810      * Create a new tab in SciNotes.
811      * @param title the title of the tab
812      * @return the text component inside the tab
813      */
814     public ScilabEditorPane addTab(String title) {
815         return addTab(title, Integer.MAX_VALUE);
816     }
817
818     /**
819      * Create a new tab in SciNotes.
820      * @param title the title of the tab
821      * @param index the index where to put the new tab
822      * @return the text component inside the tab
823      */
824     public ScilabEditorPane addTab(String title, int index) {
825         ScilabEditorPane sep = new ScilabEditorPane(this);
826         initPane(sep);
827         int ind = Math.min(Math.max(0, index), tabPane.getTabCount());
828         tabPane.insertTab(title, null, sep.getParentComponent(), "", ind);
829         tabPane.setSelectedIndex(ind);
830         setContentPane(tabPane);
831         initInputMap(sep);
832         setTitle(title + TIRET + SciNotesMessages.SCILAB_EDITOR);
833         updateTabTitle();
834         getInfoBar().setText(sep.getInfoBarText());
835         repaint();
836         sep.init();
837         return sep;
838     }
839
840     /**
841      * Init a pane
842      * @param pane the pane to init
843      */
844     public void initPane(ScilabEditorPane pane) {
845         initPane(pane, false);
846     }
847
848     /**
849      * Init the EditorPane.
850      * @param pane the EditorPane
851      * @param plain true for a plain view or false for a wrapped view
852      */
853     public void initPane(ScilabEditorPane pane, boolean plain) {
854         setHighlight(pane);
855         pane.setEditorKit(new ScilabEditorKit(plain));
856
857         // Panel of line number for the text pane
858         pane.getXln().setWhereamiLineNumbering(ConfigSciNotesManager.getLineNumberingState());
859         setHelpOnTyping(pane);
860
861         pane.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
862         pane.setFont(ConfigSciNotesManager.getFont());
863
864         pane.setBackground(ConfigSciNotesManager.getSciNotesBackgroundColor());
865         pane.setCaretColor(ConfigSciNotesManager.getSciNotesForegroundColor());
866
867         pane.setFocusable(true);
868         pane.setRequestFocusEnabled(true);
869         pane.setDragEnabled(true); /* Bug 5497 */
870
871         DropFilesListener dndTarget = new DropFilesListener(pane);
872
873         pane.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(this));
874     }
875
876     /**
877      * Init the EditorPane with the InputMap found in ConfigSciNotesManager
878      * @param pane the EditorPane
879      */
880     public void initInputMap(ScilabEditorPane pane) {
881         setKeyStrokeAction(pane, this);
882         LineBeautifierAction.putInInputMap(pane);
883     }
884
885     /**
886      * Split the EditorPane
887      * @param vertical true for a vertical split
888      */
889     public void splitTab(boolean vertical) {
890         ScilabEditorPane pane = getTextPane();
891         ScilabEditorPane leftPane = new ScilabEditorPane(editor);
892         ScilabEditorPane rightPane = new ScilabEditorPane(editor);
893         initPane(leftPane, true);
894         initPane(rightPane, true);
895         leftPane.setOtherPaneInSplit(rightPane);
896         rightPane.setOtherPaneInSplit(leftPane);
897         pane.copyProps(leftPane);
898         pane.copyProps(rightPane);
899         ScilabDocument doc = (ScilabDocument) pane.getDocument();
900         leftPane.setDocument(doc);
901         rightPane.setDocument(doc);
902         leftPane.setCaretPosition(0);
903         rightPane.setCaretPosition(0);
904         JSplitPane split;
905         if (vertical) {
906             split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
907         } else {
908             split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
909         }
910         tabPane.setComponentAt(tabPane.getSelectedIndex(), split);
911         split.setLeftComponent(leftPane.getScrollPane());
912         split.setRightComponent(rightPane.getScrollPane());
913         split.setResizeWeight(0.5);
914         setContentPane(tabPane);
915         setHelpOnTyping(leftPane);
916         setHelpOnTyping(rightPane);
917         initInputMap(leftPane);
918         initInputMap(rightPane);
919         if (doc.getBinary()) {
920             leftPane.setBinary(true);
921             rightPane.setBinary(true);
922         }
923         getInfoBar().setText(leftPane.getInfoBarText());
924         updateTabTitle();
925     }
926
927     /**
928      * Remove a split
929      */
930     public void removeSplit() {
931         if (tabPane.getSelectedComponent() instanceof JSplitPane) {
932             ScilabEditorPane pane = new ScilabEditorPane(editor);
933             ScilabEditorPane textpane = getTextPane();
934             initPane(pane);
935             textpane.setOtherPaneInSplit(null);
936             textpane.copyProps(pane);
937             ScilabDocument doc = (ScilabDocument) textpane.getDocument();
938             pane.setDocument(doc);
939             pane.setCaretPosition(0);
940             setHelpOnTyping(pane);
941             tabPane.setComponentAt(tabPane.getSelectedIndex(), pane.getScrollPane());
942             setContentPane(tabPane);
943             initInputMap(pane);
944             if (doc.getBinary()) {
945                 pane.setBinary(true);
946             }
947             getInfoBar().setText(pane.getInfoBarText());
948             updateTabTitle();
949         }
950     }
951
952     /**
953      * Create an empty tab inside SciNotes.
954      * @return the text component inside the tab
955      */
956     public ScilabEditorPane addEmptyTab() {
957         if (closedTabList.size() > 0) {
958             Object obj = Collections.min(closedTabList);
959             closedTabList.remove(Integer.valueOf(obj.toString()));
960             return addTab(SciNotesMessages.UNTITLED + obj.toString());
961
962         } else {
963             numberOfUntitled++;
964             tabList.add(Integer.valueOf(numberOfUntitled));
965             return addTab(SciNotesMessages.UNTITLED + numberOfUntitled);
966         }
967     }
968
969     /**
970      * Add or remove '*' prefix in current tab tile according to isContentModified().
971      */
972     public void updateTabTitle() {
973         StringBuffer newTitle = new StringBuffer();
974         ScilabEditorPane currentTextPane = getTextPane();
975         if (((ScilabDocument) currentTextPane.getDocument()).isContentModified()) {
976             newTitle.append('*');
977         }
978
979         String textPaneName = currentTextPane.getName();
980         try {
981             File f = new File(textPaneName);
982             newTitle.append(f.getName());
983         } catch (NullPointerException e) { // not a file name, no path prefix to remove, but maybe a '*'
984             textPaneName = getTabPane().getTitleAt(getTabPane().getSelectedIndex());
985             if (textPaneName.charAt(0) == '*') {
986                 newTitle.append(textPaneName.substring(1, textPaneName.length()));
987             } else {
988                 newTitle.append(textPaneName);
989             }
990         }
991         getTabPane().setTitleAt(getTabPane().getSelectedIndex() , newTitle.toString());
992     }
993
994     /**
995      * @param button the UndoButton used in this editor
996      */
997     public void setUndoButton(PushButton button) {
998         undoButton = button;
999         enableUndoButton(false);
1000     }
1001
1002     /**
1003      * @param b true to enable the button
1004      */
1005     public void enableUndoButton(boolean b) {
1006         if (undoButton != null) {
1007             undoButton.setEnabled(b);
1008         }
1009     }
1010
1011     /**
1012      * Undo last modification.
1013      */
1014     public void undo() {
1015         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1016         synchronized (doc) {
1017             doc.getUndoManager().undo();
1018         }
1019     }
1020
1021     /**
1022      * @param button the RedoButton used in this editor
1023      */
1024     public void setRedoButton(PushButton button) {
1025         redoButton = button;
1026         enableRedoButton(false);
1027     }
1028
1029     /**
1030      * @param b true to enable the button
1031      */
1032     public void enableRedoButton(boolean b) {
1033         if (redoButton != null) {
1034             redoButton.setEnabled(b);
1035         }
1036     }
1037
1038     /**
1039      * Redo last modification.
1040      */
1041     public void redo() {
1042         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1043         synchronized (doc) {
1044             doc.getUndoManager().redo();
1045         }
1046     }
1047
1048     /**
1049      * Reload a file inside SciNotes.
1050      * @param index the index
1051      */
1052     public void reload(int index) {
1053         ScilabEditorPane textPaneAt = getTextPane(index);
1054         if ((index == 0) && (getTabPane().getTabCount() == 1)) {
1055             for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1056                 tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1057             }
1058         }
1059         tabPane.remove(index);
1060         File f = new File(textPaneAt.getName());
1061         if (f.exists()) {
1062             loadFile(f, index);
1063         } else {
1064             createNewFile(f);
1065         }
1066     }
1067
1068     /**
1069      * Load a file inside SciNotes.
1070      * @param f the file to open
1071      */
1072     public void readFile(File f) {
1073         /** Is this file already opened */
1074         boolean alreadyOpened = false;
1075         for (int i = 0; i < tabPane.getTabCount(); i++) {
1076             ScilabEditorPane textPaneAt = getTextPane(i);
1077             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1078                 /* File is already opnened */
1079                 tabPane.setSelectedIndex(i);
1080                 alreadyOpened = true;
1081                 break;
1082             }
1083         }
1084
1085         if (!alreadyOpened) {
1086             if (f.exists()) {
1087                 loadFile(f);
1088             } else {
1089                 createNewFile(f);
1090             }
1091         }
1092
1093         // Get current file path for Execute file into Scilab
1094         fileFullPath = f.getAbsolutePath();
1095     }
1096
1097     /**
1098      * Load a file inside SciNotes.
1099      * @param file the file to open
1100      */
1101     public void readFileAndWait(File file) {
1102         /** Is this file already opened */
1103         File f = file;
1104         boolean alreadyOpened = false;
1105         int index = -1;
1106         for (int i = 0; i < tabPane.getTabCount(); i++) {
1107             ScilabEditorPane textPaneAt = getTextPane(i);
1108             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1109                 /* File is already opened */
1110                 tabPane.setSelectedIndex(i);
1111                 if (f.lastModified() > textPaneAt.getLastModified()) {
1112
1113                     /*
1114                      * Create a new messagebox to know what the user wants to do
1115                      * if the file has been modified outside SciNotes
1116                      */
1117                     MessageBox messageBox = ScilabMessageBox.createMessageBox();
1118                     messageBox.setTitle(SciNotesMessages.REPLACE_FILE_TITLE);
1119                     messageBox.setMessage(String.format(SciNotesMessages.EXTERNAL_MODIFICATION, textPaneAt.getName()));
1120
1121                     String[] labels = new String[]{SciNotesMessages.RELOAD, SciNotesMessages.OVERWRITE, SciNotesMessages.IGNORE};
1122                     messageBox.setButtonsLabels(labels);
1123
1124                     messageBox.setIcon("question"); // Question icon
1125
1126                     messageBox.setParentForLocation(this); // Centered on SciNotes main window
1127
1128                     messageBox.displayAndWait(); // Waits for a user action
1129
1130                     switch (messageBox.getSelectedButton()) {
1131                     case 1: // Reload
1132                         if ((i == 0) && (getTabPane().getTabCount() == 1)) {
1133                             for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1134                                 tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1135                             }
1136                         }
1137                         tabPane.remove(i);
1138                         f = new File(textPaneAt.getName());
1139                         index = i;
1140                         break;
1141                     case 2: // Overwrite 2
1142                         overwrite(i);
1143                         alreadyOpened = true;
1144                         break;
1145                     default: // Ignore
1146                         alreadyOpened = true;
1147                     }
1148                 } else {
1149                     alreadyOpened = true;
1150                 }
1151                 break;
1152             }
1153         }
1154
1155         if (!alreadyOpened) {
1156             if (f.exists()) {
1157                 loadFile(f, index);
1158             } else {
1159                 createNewFile(f);
1160             }
1161         }
1162     }
1163
1164     /**
1165      * Get current text component. If the window is splitted, then
1166      * return the focused text component.
1167      * @return the text component
1168      */
1169     public ScilabEditorPane getTextPane() {
1170         try {
1171             Component c = tabPane.getSelectedComponent();
1172             if (c instanceof JScrollPane) {
1173                 return (ScilabEditorPane) ((JScrollPane) c).getViewport().getComponent(0);
1174             } else if (c instanceof JSplitPane) {
1175                 ScilabEditorPane sep = (ScilabEditorPane) ((JScrollPane) ((JSplitPane) c).getLeftComponent()).getViewport().getComponent(0);
1176                 if (sep == ScilabEditorPane.getFocusedPane()) {
1177                     return sep;
1178                 } else {
1179                     return (ScilabEditorPane) ((JScrollPane) ((JSplitPane) c).getRightComponent()).getViewport().getComponent(0);
1180                 }
1181             }
1182             return null;
1183         } catch (NullPointerException e) {
1184             return null;
1185         } catch (ArrayIndexOutOfBoundsException e) {
1186             return null;
1187         }
1188     }
1189
1190     /**
1191      * Get text component at index.
1192      * @param index the index of the textpane
1193      * @return the text component
1194      */
1195     public ScilabEditorPane getTextPane(int index) {
1196         try {
1197             Component c = tabPane.getComponentAt(index);
1198             if (c instanceof JScrollPane) {
1199                 return (ScilabEditorPane) ((JScrollPane) c).getViewport().getComponent(0);
1200             } else if (c instanceof JSplitPane) {
1201                 ScilabEditorPane sep = (ScilabEditorPane) ((JScrollPane) ((JSplitPane) c).getLeftComponent()).getViewport().getComponent(0);
1202                 if (sep == ScilabEditorPane.getFocusedPane()) {
1203                     return sep;
1204                 } else {
1205                     return (ScilabEditorPane) ((JScrollPane) ((JSplitPane) c).getRightComponent()).getViewport().getComponent(0);
1206                 }
1207             }
1208             return null;
1209         } catch (NullPointerException e) {
1210             return null;
1211         } catch (ArrayIndexOutOfBoundsException e) {
1212             return null;
1213         }
1214     }
1215
1216     /**
1217      * Enable the whereami-line numbering
1218      * @param state int
1219      */
1220     public void setWhereamiLineNumbering(int state) {
1221         int n = tabPane.getTabCount();
1222         for (int i = 0; i < n; i++) {
1223             ScilabEditorPane sep = (ScilabEditorPane) getTextPane(i);
1224             sep.getXln().setWhereamiLineNumbering(state);
1225             if (sep.getOtherPaneInSplit() != null) {
1226                 sep.getOtherPaneInSplit().getXln().setWhereamiLineNumbering(state);
1227             }
1228         }
1229         repaint();
1230         whereami = state;
1231     }
1232
1233     /**
1234      * Auto-indent mode management
1235      * @param b true to activate auto-indent mode
1236      */
1237     public void setAutoIndent(boolean b) {
1238         int n = tabPane.getTabCount();
1239         for (int i = 0; i < n; i++) {
1240             ScilabEditorPane sep = (ScilabEditorPane) getTextPane(i);
1241             ((ScilabDocument) sep.getDocument()).setAutoIndent(b);
1242             if (sep.getOtherPaneInSplit() != null) {
1243                 ((ScilabDocument) sep.getOtherPaneInSplit().getDocument()).setAutoIndent(b);
1244             }
1245         }
1246     }
1247
1248     /**
1249      * Enable the highlighted line in this editor
1250      * @param b boolean
1251      */
1252     public void enableHighlightedLine(boolean b) {
1253         int n = tabPane.getTabCount();
1254         for (int i = 0; i < n; i++) {
1255             ScilabEditorPane sep = (ScilabEditorPane) getTextPane(i);
1256             sep.enableHighlightedLine(b);
1257             if (sep.getOtherPaneInSplit() != null) {
1258                 sep.getOtherPaneInSplit().enableHighlightedLine(b);
1259             }
1260         }
1261         highlight = b;
1262     }
1263
1264     /**
1265      * Enable the help on typing in the current textPane
1266      * @param pane the pane
1267      */
1268     public void setHelpOnTyping(ScilabEditorPane pane) {
1269         pane.activateHelpOnTyping(helpOnTyping);
1270     }
1271
1272     /**
1273      * Enable the help on typing in this editor
1274      * @param b boolean
1275      */
1276     public void setHelpOnTyping(boolean b) {
1277         int n = tabPane.getTabCount();
1278         for (int i = 0; i < n; i++) {
1279             ScilabEditorPane sep = (ScilabEditorPane) getTextPane(i);
1280             sep.activateHelpOnTyping(b);
1281             if (sep.getOtherPaneInSplit() != null) {
1282                 sep.getOtherPaneInSplit().activateHelpOnTyping(b);
1283             }
1284         }
1285         helpOnTyping = b;
1286     }
1287
1288     /**
1289      * Enable the help on typing in this editor according to scinotesConfiguration.xml
1290      */
1291     public void setDefaultHelpOnTyping() {
1292         helpOnTyping = ConfigSciNotesManager.getHelpOnTypingState();
1293     }
1294
1295     /**
1296      * Set the color of the highlighted line in this editor
1297      * @param c Color
1298      */
1299     public void setHighlightedLineColor(Color c) {
1300         int n = tabPane.getTabCount();
1301         for (int i = 0; i < n; i++) {
1302             ScilabEditorPane sep = (ScilabEditorPane) getTextPane(i);
1303             sep.setHighlightedLineColor(c);
1304             if (sep.getOtherPaneInSplit() != null) {
1305                 sep.getOtherPaneInSplit().setHighlightedLineColor(c);
1306             }
1307         }
1308         highlightColor = c;
1309     }
1310
1311     /**
1312      * Set the color of the contour of the highlighted line in this editor
1313      * @param c Color
1314      */
1315     public void setHighlightedContourColor(Color c) {
1316         int n = tabPane.getTabCount();
1317         for (int i = 0; i < n; i++) {
1318             ScilabEditorPane sep = (ScilabEditorPane) getTextPane(i);
1319             sep.setHighlightedContourColor(c);
1320             if (sep.getOtherPaneInSplit() != null) {
1321                 sep.getOtherPaneInSplit().setHighlightedContourColor(c);
1322             }
1323         }
1324         highlightContourColor = c;
1325     }
1326
1327     /**
1328      * Set the defaults for the highlighted line in this editor
1329      * Defaults read in scinotesConfiguration.xml
1330      */
1331     public void setDefaultHighlight() {
1332         this.highlight = ConfigSciNotesManager.getHighlightState();
1333         Color[] arr = ConfigSciNotesManager.getHighlightColors();
1334         this.highlightColor = arr[0];
1335         this.highlightContourColor = arr[1];
1336     }
1337
1338     /**
1339      * Set the highlighted line in this textPane
1340      * @param sep ScilabEditorPane
1341      */
1342     public void setHighlight(ScilabEditorPane sep) {
1343         sep.enableHighlightedLine(highlight);
1344         sep.setHighlightedLineColor(highlightColor);
1345         sep.setHighlightedContourColor(highlightContourColor);
1346     }
1347
1348     /**
1349      * Get SciNotes as a Tab.
1350      * @return SciNotes instance
1351      * @see org.scilab.modules.gui.tab.Tab#getAsSimpleTab()
1352      */
1353     public SimpleTab getAsSimpleTab() {
1354         return this;
1355     }
1356
1357     /**
1358      * Get SciNotes parent Window.
1359      * @return parent Window
1360      * @see org.scilab.modules.gui.tab.Tab#getParentWindow()
1361      */
1362     public Window getParentWindow() {
1363         return parentWindow;
1364     }
1365
1366     /**
1367      * Add a status bar to SciNotes.
1368      * @param infoBarToAdd the status bar to be added
1369      * @see org.scilab.modules.gui.uielement.UIElement#addInfoBar(org.scilab.modules.gui.textbox.TextBox)
1370      */
1371     public void addInfoBar(TextBox infoBarToAdd) {
1372         setInfoBar(infoBarToAdd);
1373     }
1374
1375     /**
1376      * Add a menu bar to SciNotes.
1377      * @param menuBarToAdd the menu bar to be added
1378      * @see org.scilab.modules.gui.uielement.UIElement#addMenuBar(org.scilab.modules.gui.menubar.MenuBar)
1379      */
1380     public void addMenuBar(MenuBar menuBarToAdd) {
1381         setMenuBar(menuBarToAdd);
1382     }
1383
1384     /**
1385      * Add a tool bar to SciNotes.
1386      * @param toolBarToAdd the tool bar to be added
1387      * @see org.scilab.modules.gui.uielement.UIElement#addToolBar(org.scilab.modules.gui.toolbar.ToolBar)
1388      */
1389     public void addToolBar(ToolBar toolBarToAdd) {
1390         setToolBar(toolBarToAdd);
1391     }
1392
1393     /**
1394      * Get SciNotes main JTabbedPane.
1395      * @return SciNotes main JTabbedPane
1396      */
1397     public JTabbedPane getTabPane() {
1398         return tabPane;
1399     }
1400
1401     /**
1402      * Set SciNotes main JTabbedPane.
1403      * @param tabPane SciNotes main JTabbedPane
1404      */
1405     public void setTabPane(JTabbedPane tabPane) {
1406         this.tabPane = tabPane;
1407     }
1408
1409     /**
1410      * Return the Full path of the file.
1411      * @return the full path
1412      */
1413     public String getFileFullPath() {
1414         return fileFullPath;
1415     }
1416
1417     /**
1418      * Load a file and add it at the end
1419      * @param f the file to load
1420      */
1421     public void loadFile(File f) {
1422         loadFile(f, -1);
1423     }
1424
1425     /**
1426      * Load a file and add it at the index
1427      * @param f the file to load
1428      * @param index the index where to put the file
1429      */
1430     public void loadFile(File f, int index) {
1431         setFileToEncode(f);
1432         getInfoBar().setText(SciNotesMessages.LOADING);
1433         // Get current file path for Execute file into Scilab
1434         fileFullPath = f.getAbsolutePath();
1435
1436         ScilabDocument styleDocument = null;
1437         ScilabEditorPane theTextPane;
1438
1439         // File exist
1440         if (f.exists()) {
1441             if (index != -1) {
1442                 theTextPane = addTab(f.getName(), index);
1443             } else {
1444                 theTextPane = addTab(f.getName());
1445             }
1446             styleDocument = (ScilabDocument) theTextPane.getDocument();
1447             styleDocument.disableUndoManager();
1448             theTextPane.setLastModified(f.lastModified());
1449
1450             try {
1451                 styleDocument.setUpdater(false);
1452                 boolean indentMode = styleDocument.getAutoIndent();
1453                 styleDocument.setAutoIndent(false);
1454                 try {
1455                     try {
1456                         editorKit.read(new BufferedReader(new InputStreamReader(new FileInputStream(f), styleDocument.getEncoding())), styleDocument, 0);
1457                     } catch (ChangedCharSetException e) {
1458                         editorKit.read(new BufferedReader(new InputStreamReader(new FileInputStream(f), e.getCharSetSpec())), styleDocument, 0);
1459                     }
1460
1461                 } catch (BadLocationException e) {
1462                     e.printStackTrace();
1463                 }
1464                 styleDocument.setAutoIndent(indentMode);
1465                 styleDocument.setUpdater(true);
1466             } catch (IOException ioex) {
1467                 ioex.printStackTrace();
1468             }
1469
1470             theTextPane.setName(f.getAbsolutePath());
1471             getTabPane().setTitleAt(getTabPane().getSelectedIndex() , f.getName());
1472             styleDocument.setContentModified(false);
1473             styleDocument.enableUndoManager();
1474
1475             if (styleDocument.getBinary()) {
1476                 theTextPane.setBinary(true);
1477             }
1478             getInfoBar().setText(theTextPane.getInfoBarText());
1479
1480             EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
1481
1482             // Empty the undo Manager
1483             UndoManager undo = ((ScilabDocument) getTextPane().getDocument()).getUndoManager();
1484             undo.discardAllEdits();
1485         }
1486     }
1487
1488     /**
1489      * Creates a file if it doesn't exist
1490      * @param f the file to create
1491      */
1492     public void createNewFile(File f) {
1493         ScilabEditorPane theTextPane = addEmptyTab();
1494         ScilabDocument styleDocument = null;
1495         int choice = JOptionPane.showConfirmDialog(SciNotes.this,
1496                                                    String.format(SciNotesMessages.FILE_DOESNT_EXIST, f.getName()),
1497                                                    SCINOTES,
1498                                                    JOptionPane.YES_NO_OPTION);
1499         if (choice == 0) { //OK
1500             styleDocument = (ScilabDocument) theTextPane.getDocument();
1501             styleDocument.disableUndoManager();
1502
1503             BufferedWriter out = null;
1504             try {
1505                 out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), styleDocument.getEncoding()));
1506                 try {
1507                     editorKit.write(out, styleDocument, 0, styleDocument.getLength());
1508                     out.flush();
1509                     out.close();
1510                 } catch (IOException e) {
1511                     e.printStackTrace();
1512                 } catch (BadLocationException e) {
1513                     e.printStackTrace();
1514                 }
1515             } catch (UnsupportedEncodingException e2) {
1516                 e2.printStackTrace();
1517             } catch (FileNotFoundException e2) {
1518                 e2.printStackTrace();
1519             }
1520
1521             ConfigManager.saveLastOpenedDirectory(f.getPath());
1522             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
1523             theTextPane.setName(f.getPath());
1524             getTabPane().setTitleAt(getTabPane().getSelectedIndex() , f.getName());
1525             setTitle(f.getPath() + TIRET + SciNotesMessages.SCILAB_EDITOR);
1526             RecentFileAction.updateRecentOpenedFilesMenu(this);
1527
1528             styleDocument.setContentModified(false);
1529             styleDocument.enableUndoManager();
1530             theTextPane.setLastModified(f.lastModified());
1531
1532             // Get current file path for Execute file into Scilab
1533             fileFullPath = f.getAbsolutePath();
1534         }
1535
1536         getInfoBar().setText("");
1537     }
1538
1539     /**
1540      * EditorKit Getter
1541      * @return EditorKit
1542      */
1543     public EditorKit getEditorKit() {
1544         return editorKit;
1545     }
1546
1547     /**
1548      * @param scinotes the focused editor
1549      */
1550     public static void setEditor(SciNotes scinotes) {
1551         editor = scinotes;
1552     }
1553
1554     /**
1555      * EditorKit Setter
1556      * @param editorKit EditorKit
1557      */
1558     public void setEditorKit(EditorKit editorKit) {
1559         this.editorKit = editorKit;
1560     }
1561
1562     /**
1563      * Getter for file to encode
1564      * @return a File
1565      */
1566     public File getFileToEncode() {
1567         return fileToEncode;
1568     }
1569
1570     /**
1571      * Setter for file to encode
1572      * @param fileToEncode a File
1573      */
1574     public void setFileToEncode(File fileToEncode) {
1575         this.fileToEncode = fileToEncode;
1576     }
1577
1578     /**
1579      * @param find the FindAction to add
1580      */
1581     public void addFindActionWindow(FindAction find) {
1582         this.find = find;
1583     }
1584
1585     /**
1586      * Close scinotes from scilab.
1587      *
1588      * This method can be called outside the EDT thread.
1589      */
1590     public static void closeSciNotesFromScilab() {
1591         try {
1592             SwingUtilities.invokeAndWait(new Runnable() {
1593
1594                     @Override
1595                     public void run() {
1596                         SciNotes[] arr = scinotesList.toArray(new SciNotes[0]);
1597                         for (int i = 0; i < arr.length; i++) {
1598                             ExitAction.doExit(arr[i]);
1599                         }
1600                         scinotesList.clear();
1601                     }
1602                 });
1603         } catch (InterruptedException e) {
1604             LogFactory.getLog(SciNotes.class).error(e);
1605         } catch (InvocationTargetException e) {
1606             LogFactory.getLog(SciNotes.class).error(e);
1607         }
1608     }
1609
1610     /**
1611      * @param f the file
1612      * @return the canonical file if possible
1613      */
1614     public static File fileToCanonicalFile(File f) {
1615         /* Fix bug 5648 */
1616         try {
1617             return f.getCanonicalFile();
1618         } catch (IOException e) {
1619             return f;
1620         }
1621     }
1622
1623     /**
1624      * Set the shortcuts in the pane relatively to the file keysConfiguration.xml
1625      * @param sep the textpane
1626      * @param ed the SciNotes editor
1627      */
1628     private static void setKeyStrokeAction(ScilabEditorPane sep, SciNotes ed) {
1629         Map<String, KeyStroke> map = new HashMap();
1630         ConfigSciNotesManager.addMapActionNameKeys(map);
1631
1632         ClassLoader loader = ClassLoader.getSystemClassLoader();
1633         Iterator<String> iter = map.keySet().iterator();
1634         while (iter.hasNext()) {
1635             String action = iter.next();
1636             if (!action.equals("SciNotesCompletionAction")) {
1637                 String className;
1638                 if (action.lastIndexOf(DOT) != -1)  {
1639                     className = action;
1640                 } else {
1641                     className = DEFAULTACTIONPATH + DOT + action;
1642                 }
1643                 try {
1644                     Class clazz = loader.loadClass(className);
1645                     Constructor constructor = clazz.getConstructor(new Class[]{String.class, SciNotes.class});
1646                     Object act = constructor.newInstance(new Object[]{"", ed});
1647                     sep.getInputMap().put(map.get(action), act);
1648                 } catch (ClassNotFoundException e) {
1649                     System.err.println("No action: " + className);
1650                 } catch (InstantiationException e) {
1651                     System.err.println("Problem to instantiate in action: " + className);
1652                 } catch (NoSuchMethodException e) {
1653                     System.err.println("No valid constructor in action: " + className);
1654                 } catch (IllegalAccessException e) {
1655                     System.err.println("The constructor must be public: " + className);
1656                 } catch (InvocationTargetException e) {
1657                     System.err.println("The constructor in " + className + " threw an exception :");
1658                     e.printStackTrace();
1659                 }
1660             } else {
1661                 sep.getInputMap().put(map.get(action), new SciNotesCompletionAction(sep, ed));
1662             }
1663         }
1664     }
1665 }