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