dc533bea5a706c393280b42e0654d759c12b1740
[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         ScilabEditorPane sep = new ScilabEditorPane(this);
1357         initPane(sep);
1358         int ind = Math.min(Math.max(0, index), tabPane.getTabCount());
1359         tabPane.insertTab(title, null, sep.getEditorComponent(), "", ind);
1360         tabPane.setSelectedIndex(ind);
1361         initInputMap(sep);
1362         updateTabTitle();
1363         getInfoBar().setText(sep.getInfoBarText());
1364         repaint();
1365         sep.init();
1366         return sep;
1367     }
1368
1369     /**
1370      * Init a pane
1371      *
1372      * @param pane
1373      *            the pane to init
1374      */
1375     public void initPane(ScilabEditorPane pane) {
1376         initPane(pane, !SciNotesOptions.getSciNotesDisplay().wrapLines);
1377     }
1378
1379     /**
1380      * Init the EditorPane.
1381      *
1382      * @param pane
1383      *            the EditorPane
1384      * @param plain
1385      *            true for a plain view or false for a wrapped view
1386      */
1387     public void initPane(ScilabEditorPane pane, boolean plain) {
1388         setHighlight(pane);
1389         ScilabEditorKit kit = new ScilabEditorKit(plain);
1390         pane.setEditorKit(kit);
1391
1392         // Panel of line number for the text pane
1393         pane.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1394         activateHelpOnTyping(pane);
1395
1396         pane.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
1397         pane.setFont(kit.getStylePreferences().tokenFonts[0]);
1398
1399         // TODO rajouter ca ds les prefs
1400         pane.setBackground(ConfigSciNotesManager.getSciNotesBackgroundColor());
1401         pane.setCaretColor(ConfigSciNotesManager.getSciNotesForegroundColor());
1402
1403         pane.setFocusable(true);
1404         pane.setRequestFocusEnabled(true);
1405         pane.setDragEnabled(true); /* Bug 5497 */
1406
1407         DropFilesListener dndTarget = new DropFilesListener(pane);
1408
1409         pane.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(this));
1410     }
1411
1412     /**
1413      * Init the EditorPane with the InputMap found in ConfigSciNotesManager
1414      *
1415      * @param pane
1416      *            the EditorPane
1417      */
1418     public void initInputMap(ScilabEditorPane pane) {
1419         setKeyStrokeAction(pane, this);
1420         LineBeautifierAction.putInInputMap(pane);
1421         InsertOverwriteAction.putInInputMap(pane);
1422     }
1423
1424     /**
1425      * Split the EditorPane
1426      *
1427      * @param vertical
1428      *            true for a vertical split
1429      */
1430     public void splitTab(boolean vertical) {
1431         ScilabEditorPane pane = getTextPane();
1432         Component bottom = pane.getEditorComponent().getBottom();
1433         int state = pane.getXln().getState();
1434         ScilabEditorPane leftPane = new ScilabEditorPane(editor);
1435         ScilabEditorPane rightPane = new ScilabEditorPane(editor);
1436         if (navigator != null) {
1437             navigator.changePaneOnSplit(pane, leftPane);
1438         }
1439         initPane(leftPane, true);
1440         initPane(rightPane, true);
1441         leftPane.setOtherPaneInSplit(rightPane);
1442         rightPane.setOtherPaneInSplit(leftPane);
1443         pane.copyProps(leftPane);
1444         pane.copyProps(rightPane);
1445         ScilabDocument doc = (ScilabDocument) pane.getDocument();
1446         leftPane.setDocument(doc);
1447         rightPane.setDocument(doc);
1448         leftPane.setCaretPosition(0);
1449         rightPane.setCaretPosition(0);
1450         JSplitPane split;
1451         if (vertical) {
1452             split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
1453         } else {
1454             split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
1455         }
1456         leftPane.getXln().setWhereamiLineNumbering(state);
1457         rightPane.getXln().setWhereamiLineNumbering(state);
1458         split.setLeftComponent(leftPane.getScrollPane());
1459         split.setRightComponent(rightPane.getScrollPane());
1460         split.setResizeWeight(0.5);
1461         rightPane.setEditorComponent(leftPane.getEditorComponent());
1462         leftPane.setSplitPane(split);
1463         rightPane.setSplitPane(split);
1464
1465         activateHelpOnTyping(leftPane);
1466         activateHelpOnTyping(rightPane);
1467         initInputMap(leftPane);
1468         initInputMap(rightPane);
1469         if (doc.getBinary()) {
1470             leftPane.setBinary(true);
1471             rightPane.setBinary(true);
1472         }
1473         getInfoBar().setText(leftPane.getInfoBarText());
1474         updateTabTitle();
1475         tabPane.setComponentAt(tabPane.getSelectedIndex(), leftPane.getEditorComponent());
1476         leftPane.getEditorComponent().insertBottomComponent(bottom);
1477         leftPane.requestFocus();
1478     }
1479
1480     /**
1481      * Remove a split
1482      */
1483     public void removeSplit() {
1484         if (((EditorComponent) tabPane.getSelectedComponent()).isSplited()) {
1485             ScilabEditorPane pane = new ScilabEditorPane(editor);
1486             ScilabEditorPane textpane = getTextPane();
1487             Component bottom = textpane.getEditorComponent().getBottom();
1488             if (navigator != null) {
1489                 navigator.changePaneOnSplit(textpane, pane);
1490             }
1491             initPane(pane);
1492             textpane.setOtherPaneInSplit(null);
1493             textpane.copyProps(pane);
1494             ScilabDocument doc = (ScilabDocument) textpane.getDocument();
1495             pane.setDocument(doc);
1496             pane.setCaretPosition(0);
1497             activateHelpOnTyping(pane);
1498             tabPane.setComponentAt(tabPane.getSelectedIndex(), pane.getEditorComponent());
1499             initInputMap(pane);
1500             if (doc.getBinary()) {
1501                 pane.setBinary(true);
1502             }
1503             getInfoBar().setText(pane.getInfoBarText());
1504             updateTabTitle();
1505             pane.getEditorComponent().insertBottomComponent(bottom);
1506             pane.requestFocus();
1507         }
1508     }
1509
1510     /**
1511      * Create an empty tab inside SciNotes.
1512      *
1513      * @return the text component inside the tab
1514      */
1515     public ScilabEditorPane addEmptyTab() {
1516         ScilabEditorPane sep;
1517         int n = getNumberForEmptyTab();
1518         sep = addTab(SciNotesMessages.UNTITLED + n);
1519         sep.setShortName(SciNotesMessages.UNTITLED + n);
1520         sep.setTitle(SciNotesMessages.UNTITLED + n);
1521         setTitle(sep.getTitle());
1522
1523         return sep;
1524     }
1525
1526     /**
1527      * Get an integer used for untitled document
1528      */
1529     public int getNumberForEmptyTab() {
1530         if (closedTabList.size() > 0) {
1531             Integer n = Collections.min(closedTabList);
1532             closedTabList.remove(n);
1533             return n.intValue();
1534         } else {
1535             numberOfUntitled++;
1536             tabList.add(Integer.valueOf(numberOfUntitled));
1537             return numberOfUntitled;
1538         }
1539     }
1540
1541     /**
1542      * Add or remove '*' prefix in current tab tile according to
1543      * isContentModified().
1544      */
1545     public void updateTabTitle() {
1546         StringBuffer newTitle = new StringBuffer();
1547         ScilabEditorPane currentTextPane = getTextPane();
1548         if (((ScilabDocument) currentTextPane.getDocument()).isContentModified()) {
1549             newTitle.append('*');
1550         }
1551
1552         String textPaneName = currentTextPane.getName();
1553         try {
1554             File f = new File(textPaneName);
1555             newTitle.append(f.getName());
1556         } catch (NullPointerException e) { // not a file name, no path prefix to
1557             // remove, but maybe a '*'
1558             textPaneName = getTabPane().getScilabTitleAt(getTabPane().getSelectedIndex());
1559             if (textPaneName.charAt(0) == '*') {
1560                 newTitle.append(textPaneName.substring(1, textPaneName.length()));
1561             } else {
1562                 newTitle.append(textPaneName);
1563             }
1564         }
1565         getTabPane().setTitleAt(getTabPane().getSelectedIndex(), newTitle.toString());
1566     }
1567
1568     /**
1569      * @param button
1570      *            the UndoButton used in this editor
1571      */
1572     public void setUndoButton(PushButton button) {
1573         undoButton = button;
1574         enableUndoButton(false);
1575     }
1576
1577     /**
1578      * @param b
1579      *            true to enable the button
1580      */
1581     public void enableUndoButton(boolean b) {
1582         if (undoButton != null) {
1583             undoButton.setEnabled(b);
1584         }
1585     }
1586
1587     /**
1588      * Undo last modification.
1589      */
1590     public void undo() {
1591         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1592         synchronized (doc) {
1593             doc.getUndoManager().undo();
1594         }
1595     }
1596
1597     /**
1598      * @param button
1599      *            the RedoButton used in this editor
1600      */
1601     public void setRedoButton(PushButton button) {
1602         redoButton = button;
1603         enableRedoButton(false);
1604     }
1605
1606     /**
1607      * @param b
1608      *            true to enable the button
1609      */
1610     public void enableRedoButton(boolean b) {
1611         if (redoButton != null) {
1612             redoButton.setEnabled(b);
1613         }
1614     }
1615
1616     /**
1617      * Redo last modification.
1618      */
1619     public void redo() {
1620         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1621         synchronized (doc) {
1622             doc.getUndoManager().redo();
1623         }
1624     }
1625
1626     /**
1627      * Reload a file inside SciNotes.
1628      *
1629      * @param index
1630      *            the index
1631      */
1632     public void reload(int index) {
1633         ScilabEditorPane textPaneAt = getTextPane(index);
1634         if (textPaneAt.getName() != null) {
1635             if ((index == 0) && (getTabPane().getTabCount() == 1)) {
1636                 for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1637                     tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1638                 }
1639             }
1640             ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt);
1641             tabPane.remove(index);
1642             File f = new File(textPaneAt.getName());
1643             if (f.exists()) {
1644                 loadFile(f, index);
1645             } else {
1646                 createNewFile(f);
1647             }
1648         }
1649     }
1650
1651     /**
1652      * Load a file inside SciNotes.
1653      *
1654      * @param f
1655      *            the file to open
1656      */
1657     public void readFile(File f) {
1658         /** Is this file already opened */
1659         boolean alreadyOpened = false;
1660         for (int i = 0; i < tabPane.getTabCount(); i++) {
1661             ScilabEditorPane textPaneAt = getTextPane(i);
1662             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1663                 /* File is already opnened */
1664                 tabPane.setSelectedIndex(i);
1665                 alreadyOpened = true;
1666                 break;
1667             }
1668         }
1669
1670         if (!alreadyOpened) {
1671             if (f.exists()) {
1672                 loadFile(f);
1673             } else {
1674                 createNewFile(f);
1675             }
1676         }
1677     }
1678
1679     /**
1680      * Load a file inside SciNotes.
1681      *
1682      * @param file
1683      *            the file to open
1684      */
1685     public void readFileAndWait(File file) {
1686         /** Is this file already opened */
1687         File f = file;
1688         boolean alreadyOpened = false;
1689         int index = -1;
1690         for (int i = 0; i < tabPane.getTabCount(); i++) {
1691             ScilabEditorPane textPaneAt = getTextPane(i);
1692             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1693                 /* File is already opened */
1694                 tabPane.setSelectedIndex(i);
1695                 if (f.lastModified() > textPaneAt.getLastModified()) {
1696
1697                     /*
1698                      * Create a new messagebox to know what the user wants to do
1699                      * if the file has been modified outside SciNotes
1700                      */
1701                     MessageBox messageBox = ScilabMessageBox.createMessageBox();
1702                     messageBox.setTitle(SciNotesMessages.REPLACE_FILE_TITLE);
1703                     messageBox.setMessage(String.format(SciNotesMessages.EXTERNAL_MODIFICATION, textPaneAt.getName()));
1704
1705                     String[] labels = new String[] { SciNotesMessages.RELOAD, SciNotesMessages.OVERWRITE, SciNotesMessages.IGNORE };
1706                     messageBox.setButtonsLabels(labels);
1707
1708                     messageBox.setIcon("question"); // Question icon
1709
1710                     messageBox.setParentForLocation(this); // Centered on
1711                     // SciNotes main
1712                     // window
1713
1714                     messageBox.displayAndWait(); // Waits for a user action
1715
1716                     switch (messageBox.getSelectedButton()) {
1717                         case 1: // Reload
1718                             if ((i == 0) && (getTabPane().getTabCount() == 1)) {
1719                                 for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1720                                     tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1721                                 }
1722                             }
1723                             tabPane.remove(i);
1724                             f = new File(textPaneAt.getName());
1725                             index = i;
1726                             break;
1727                         case 2: // Overwrite 2
1728                             overwrite(i);
1729                             alreadyOpened = true;
1730                             break;
1731                         default: // Ignore
1732                             alreadyOpened = true;
1733                     }
1734                 } else {
1735                     alreadyOpened = true;
1736                 }
1737                 break;
1738             }
1739         }
1740
1741         if (!alreadyOpened) {
1742             if (f.exists()) {
1743                 loadFile(f, index);
1744             } else {
1745                 createNewFile(f);
1746             }
1747         }
1748     }
1749
1750     /**
1751      * Get current text component. If the window is splitted, then return the
1752      * focused text component.
1753      *
1754      * @return the text component
1755      */
1756     public ScilabEditorPane getTextPane() {
1757         try {
1758             EditorComponent c = (EditorComponent) tabPane.getSelectedComponent();
1759             return c.getEditorPane();
1760         } catch (NullPointerException e) {
1761             return null;
1762         } catch (ArrayIndexOutOfBoundsException e) {
1763             return null;
1764         }
1765     }
1766
1767     /**
1768      * Get text component at index.
1769      *
1770      * @param index
1771      *            the index of the textpane
1772      * @return the text component
1773      */
1774     public ScilabEditorPane getTextPane(int index) {
1775         try {
1776             EditorComponent c = (EditorComponent) tabPane.getComponentAt(index);
1777             return c.getEditorPane();
1778         } catch (NullPointerException e) {
1779             return null;
1780         } catch (ArrayIndexOutOfBoundsException e) {
1781             return null;
1782         }
1783     }
1784
1785     /**
1786      * Set the keystroke actions
1787      */
1788     public static void setAllMenus() {
1789         for (SciNotes ed : scinotesList) {
1790             SciNotesGUI.reinitMenus(ed);
1791             int n = ed.getTabPane().getTabCount();
1792             for (int i = 0; i < n; i++) {
1793                 ScilabEditorPane sep = ed.getTextPane(i);
1794                 sep.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(ed));
1795                 if (sep.getOtherPaneInSplit() != null) {
1796                     sep.getOtherPaneInSplit().setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(ed));
1797                 }
1798             }
1799         }
1800     }
1801
1802     /**
1803      * Set the keystroke actions
1804      */
1805     public static void setKeyStrokeActions() {
1806         for (SciNotes ed : scinotesList) {
1807             int n = ed.getTabPane().getTabCount();
1808             for (int i = 0; i < n; i++) {
1809                 ScilabEditorPane sep = ed.getTextPane(i);
1810                 ed.initInputMap(sep);
1811                 if (sep.getOtherPaneInSplit() != null) {
1812                     ed.initInputMap(sep.getOtherPaneInSplit());
1813                 }
1814             }
1815         }
1816     }
1817
1818     /**
1819      * Enable the whereami-line numbering
1820      *
1821      * @param state
1822      *            int
1823      */
1824     public static void setWhereamiLineNumbering() {
1825         for (SciNotes ed : scinotesList) {
1826             int n = ed.getTabPane().getTabCount();
1827             for (int i = 0; i < n; i++) {
1828                 ScilabEditorPane sep = ed.getTextPane(i);
1829                 sep.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1830                 if (sep.getOtherPaneInSplit() != null) {
1831                     sep.getOtherPaneInSplit().getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1832                 }
1833             }
1834             ed.repaint();
1835         }
1836     }
1837
1838     /**
1839      * Auto-indent mode management
1840      *
1841      * @param b
1842      *            true to activate auto-indent mode
1843      */
1844     public static void setAutoIndent() {
1845         for (SciNotes ed : scinotesList) {
1846             int n = ed.getTabPane().getTabCount();
1847             for (int i = 0; i < n; i++) {
1848                 ScilabEditorPane sep = ed.getTextPane(i);
1849                 ((ScilabDocument) sep.getDocument()).setAutoIndent(SciNotesOptions.getSciNotesDisplay().automaticIndent);
1850                 if (sep.getOtherPaneInSplit() != null) {
1851                     ((ScilabDocument) sep.getOtherPaneInSplit().getDocument()).setAutoIndent(SciNotesOptions.getSciNotesDisplay().automaticIndent);
1852                 }
1853             }
1854         }
1855     }
1856
1857     /**
1858      * Auto-indent mode management
1859      *
1860      * @param b
1861      *            true to activate auto-indent mode
1862      */
1863     public static void setSuppressComments(boolean b) {
1864         for (SciNotes ed : scinotesList) {
1865             int n = ed.getTabPane().getTabCount();
1866             for (int i = 0; i < n; i++) {
1867                 ScilabEditorPane sep = ed.getTextPane(i);
1868                 sep.suppressCommentsInExecutingCode(b);
1869                 if (sep.getOtherPaneInSplit() != null) {
1870                     sep.getOtherPaneInSplit().suppressCommentsInExecutingCode(b);
1871                 }
1872             }
1873         }
1874     }
1875
1876     /**
1877      * Horizontal Wrap mode management
1878      *
1879      * @param b
1880      *            true to activate horizontal wrapping mode
1881      */
1882     public static void setHorizontalWrap() {
1883         if (SciNotesOptions.getSciNotesDisplay().wrapLines != mustWrapLines) {
1884             mustWrapLines = SciNotesOptions.getSciNotesDisplay().wrapLines;
1885             for (SciNotes ed : scinotesList) {
1886                 int n = ed.getTabPane().getTabCount();
1887                 for (int i = 0; i < n; i++) {
1888                     ScilabEditorPane sep = ed.getTextPane(i);
1889                     if (sep.getOtherPaneInSplit() == null) {
1890                         ScilabEditorPane pane = new ScilabEditorPane(editor);
1891                         ed.initPane(pane, !mustWrapLines);
1892                         sep.copyProps(pane);
1893                         pane.setDocument(sep.getDocument());
1894                         pane.setCaretPosition(sep.getCaretPosition());
1895                         pane.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1896                         ed.tabPane.setComponentAt(i, pane.getEditorComponent());
1897                         ed.activateHelpOnTyping(pane);
1898                         ed.initInputMap(pane);
1899                         if (((ScilabDocument) sep.getDocument()).getBinary()) {
1900                             pane.setBinary(true);
1901                         }
1902                         ed.getInfoBar().setText(pane.getInfoBarText());
1903                     }
1904                 }
1905             }
1906         }
1907     }
1908
1909     /**
1910      * Set a line numbering compatible with the whereami function
1911      * @param state 0 for nothing, 1 for normal and 2 for whereami
1912      */
1913
1914     /**
1915      * Enable the highlighted line in this editor
1916      *
1917      * @param b
1918      *            boolean
1919      */
1920     public static void enableHighlightedLine(boolean b) {
1921         for (SciNotes ed : scinotesList) {
1922             int n = ed.getTabPane().getTabCount();
1923             for (int i = 0; i < n; i++) {
1924                 ScilabEditorPane sep = ed.getTextPane(i);
1925                 sep.enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
1926                 if (sep.getOtherPaneInSplit() != null) {
1927                     sep.getOtherPaneInSplit().enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
1928                 }
1929             }
1930         }
1931     }
1932
1933     /**
1934      * Enable the help on typing in the current textPane
1935      *
1936      * @param pane
1937      *            the pane
1938      */
1939     public static void activateHelpOnTyping(ScilabEditorPane pane) {
1940         pane.activateHelpOnTyping();
1941     }
1942
1943     /**
1944      * Enable the help on typing in this editor
1945      */
1946     public static void activateHelpOnTyping() {
1947         for (SciNotes ed : scinotesList) {
1948             int n = ed.getTabPane().getTabCount();
1949             for (int i = 0; i < n; i++) {
1950                 ScilabEditorPane sep = ed.getTextPane(i);
1951                 sep.activateHelpOnTyping();
1952                 if (sep.getOtherPaneInSplit() != null) {
1953                     sep.getOtherPaneInSplit().activateHelpOnTyping();
1954                 }
1955             }
1956         }
1957     }
1958
1959     /**
1960      * Set the color of the highlighted line in this editor
1961      *
1962      * @param c
1963      *            Color
1964      */
1965     public static void setDefaultTabulation() {
1966         TabManager.Tabulation tab = new TabManager.Tabulation();
1967         for (SciNotes ed : scinotesList) {
1968             int n = ed.getTabPane().getTabCount();
1969             for (int i = 0; i < n; i++) {
1970                 ScilabEditorPane sep = ed.getTextPane(i);
1971                 sep.getTabManager().setTabulation(tab);
1972                 View view = ((ScilabDocument) sep.getDocument()).getView();
1973                 if (view != null) {
1974                     if (view instanceof ScilabView) {
1975                         ((ScilabView) view).setTabRepresentation(tab);
1976                         ((ScilabView) view).reinitialize();
1977                     } else {
1978                         ((ScilabPlainView) view).setTabRepresentation(tab);
1979                         ((ScilabPlainView) view).reinitialize();
1980                     }
1981                 }
1982             }
1983         }
1984     }
1985
1986     /**
1987      * Set the color of the highlighted line in this editor
1988      *
1989      * @param c
1990      *            Color
1991      */
1992     public static void updatePanes(SciNotesConfiguration.Conf conf) {
1993         for (SciNotes ed : scinotesList) {
1994             int n = ed.getTabPane().getTabCount();
1995             for (int i = 0; i < n; i++) {
1996                 ScilabEditorPane sep = ed.getTextPane(i);
1997                 sep.configurationChanged(conf);
1998                 if (sep.getOtherPaneInSplit() != null) {
1999                     sep.getOtherPaneInSplit().configurationChanged(conf);
2000                 }
2001                 sep.repaint();
2002             }
2003         }
2004     }
2005
2006     /**
2007      * Set the color of the highlighted line in this editor
2008      *
2009      * @param c
2010      *            Color
2011      */
2012     public static void setHighlightedLineColor() {
2013         for (SciNotes ed : scinotesList) {
2014             int n = ed.getTabPane().getTabCount();
2015             for (int i = 0; i < n; i++) {
2016                 ScilabEditorPane sep = ed.getTextPane(i);
2017                 sep.setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
2018                 if (sep.getOtherPaneInSplit() != null) {
2019                     sep.getOtherPaneInSplit().setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
2020                 }
2021             }
2022         }
2023     }
2024
2025     /**
2026      * Set the color of the contour of the highlighted line in this editor
2027      *
2028      * @param c
2029      *            Color
2030      */
2031     public static void setHighlightedContourColor() {
2032         for (SciNotes ed : scinotesList) {
2033             int n = ed.getTabPane().getTabCount();
2034             for (int i = 0; i < n; i++) {
2035                 ScilabEditorPane sep = ed.getTextPane(i);
2036                 sep.setHighlightedContourColor(null);
2037                 if (sep.getOtherPaneInSplit() != null) {
2038                     sep.getOtherPaneInSplit().setHighlightedContourColor(null);
2039                 }
2040             }
2041         }
2042     }
2043
2044     /**
2045      * Set the highlighted line in this textPane
2046      *
2047      * @param sep
2048      *            ScilabEditorPane
2049      */
2050     public static void setHighlight(ScilabEditorPane sep) {
2051         sep.enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
2052         sep.setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
2053         sep.setHighlightedContourColor(null);
2054     }
2055
2056     /**
2057      * Get SciNotes as a Tab.
2058      *
2059      * @return SciNotes instance
2060      * @see org.scilab.modules.gui.tab.Tab#getAsSimpleTab()
2061      */
2062     public SimpleTab getAsSimpleTab() {
2063         return this;
2064     }
2065
2066     /**
2067      * Get SciNotes parent Window.
2068      *
2069      * @return parent Window
2070      * @see org.scilab.modules.gui.tab.Tab#getParentWindow()
2071      */
2072     public SwingScilabWindow getParentWindow() {
2073         return parentWindow;
2074     }
2075
2076     /**
2077      * Get the UUID associated with the editor instance.
2078      *
2079      * @return unique identifier
2080      */
2081     public UUID getUUID() {
2082         return uuid;
2083     }
2084
2085     /**
2086      * Add a status bar to SciNotes.
2087      *
2088      * @param infoBarToAdd
2089      *            the status bar to be added
2090      * @see org.scilab.modules.gui.uielement.UIElement#addInfoBar(org.scilab.modules.gui.textbox.TextBox)
2091      */
2092     public void addInfoBar(TextBox infoBarToAdd) {
2093         setInfoBar(infoBarToAdd);
2094     }
2095
2096     /**
2097      * Add a menu bar to SciNotes.
2098      *
2099      * @param menuBarToAdd
2100      *            the menu bar to be added
2101      * @see org.scilab.modules.gui.uielement.UIElement#addMenuBar(org.scilab.modules.gui.menubar.MenuBar)
2102      */
2103     public void addMenuBar(MenuBar menuBarToAdd) {
2104         setMenuBar(menuBarToAdd);
2105     }
2106
2107     /**
2108      * Add a tool bar to SciNotes.
2109      *
2110      * @param toolBarToAdd
2111      *            the tool bar to be added
2112      * @see org.scilab.modules.gui.uielement.UIElement#addToolBar(org.scilab.modules.gui.toolbar.ToolBar)
2113      */
2114     public void addToolBar(ToolBar toolBarToAdd) {
2115         setToolBar(toolBarToAdd);
2116     }
2117
2118     /**
2119      * Get SciNotes main ScilabTabbedPane.
2120      *
2121      * @return SciNotes main ScilabTabbedPane
2122      */
2123     public ScilabTabbedPane getTabPane() {
2124         return tabPane;
2125     }
2126
2127     /**
2128      * Set SciNotes main ScilabTabbedPane.
2129      *
2130      * @param tabPane
2131      *            SciNotes main ScilabTabbedPane
2132      */
2133     public void setTabPane(ScilabTabbedPane tabPane) {
2134         this.tabPane = tabPane;
2135     }
2136
2137     /**
2138      * Load a file and add it at the end
2139      *
2140      * @param f
2141      *            the file to load
2142      */
2143     public void loadFile(File f) {
2144         loadFile(f, -1);
2145     }
2146
2147     /**
2148      * Load a file and add it at the index
2149      *
2150      * @param f
2151      *            the file to load
2152      * @param index
2153      *            the index where to put the file
2154      */
2155     public void loadFile(File f, int index) {
2156         ScilabDocument styleDocument = null;
2157         ScilabEditorPane theTextPane;
2158
2159         // File exist
2160         if (f.exists()) {
2161             if (!f.canRead()) {
2162                 ScilabModalDialog.show(this, SciNotesMessages.NOTREADABLE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON);
2163                 if (getTabPane().getTabCount() == 0) {
2164                     addEmptyTab();
2165                 }
2166                 return;
2167             }
2168
2169             getInfoBar().setText(SciNotesMessages.LOADING);
2170
2171             if (index != -1) {
2172                 theTextPane = addTab(f.getName(), index);
2173             } else {
2174                 theTextPane = addTab(f.getName());
2175             }
2176             styleDocument = (ScilabDocument) theTextPane.getDocument();
2177             styleDocument.disableUndoManager();
2178             theTextPane.setLastModified(f.lastModified());
2179
2180             try {
2181                 styleDocument.setUpdater(false);
2182                 boolean indentMode = styleDocument.getAutoIndent();
2183                 styleDocument.setAutoIndent(false);
2184                 try {
2185                     ((ScilabEditorKit) editorKit).read(this, f, styleDocument, 0);
2186                 } catch (BadLocationException e) {
2187                     e.printStackTrace();
2188                 }
2189                 styleDocument.setAutoIndent(indentMode);
2190                 styleDocument.setUpdater(true);
2191             } catch (IOException ioex) {
2192                 ioex.printStackTrace();
2193             }
2194
2195             theTextPane.setName(f.getAbsolutePath());
2196             getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
2197             setTitle(theTextPane.getTitle());
2198             styleDocument.setContentModified(false);
2199             styleDocument.enableUndoManager();
2200
2201             if (styleDocument.getBinary()) {
2202                 theTextPane.setBinary(true);
2203             }
2204
2205             if (!f.canWrite()) {
2206                 getTextPane().setReadOnly(true);
2207                 JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.READONLY);
2208             }
2209
2210             getInfoBar().setText(theTextPane.getInfoBarText());
2211
2212             EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
2213
2214             ConfigManager.saveLastOpenedDirectory(f.getPath());
2215             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
2216             ConfigSciNotesManager.saveToOpenFiles(f.getPath(), this, getTextPane());
2217
2218             // Empty the undo Manager
2219             UndoManager undo = ((ScilabDocument) getTextPane().getDocument()).getUndoManager();
2220             undo.discardAllEdits();
2221
2222             if (getTabPane().getTabCount() == 2) {
2223                 ScilabEditorPane pane = getTextPane(0);
2224                 if (pane.getName() == null && !((ScilabDocument) pane.getDocument()).isContentModified()) {
2225                     closeTabAt(0);
2226                 }
2227             }
2228         }
2229     }
2230
2231     /**
2232      * Creates a file if it doesn't exist
2233      *
2234      * @param f
2235      *            the file to create
2236      */
2237     public void createNewFile(File f) {
2238         ScilabEditorPane theTextPane = addEmptyTab();
2239         ScilabDocument styleDocument = null;
2240         int choice = JOptionPane.showConfirmDialog(SciNotes.this, String.format(SciNotesMessages.FILE_DOESNT_EXIST, f.getName()), SCINOTES,
2241                      JOptionPane.YES_NO_OPTION);
2242         if (choice == 0) { // OK
2243             styleDocument = (ScilabDocument) theTextPane.getDocument();
2244             styleDocument.disableUndoManager();
2245
2246             BufferedWriter bw = null;
2247             OutputStreamWriter osw = null;
2248             FileOutputStream fos = null;
2249
2250             try {
2251                 fos = new FileOutputStream(f);
2252                 osw = new OutputStreamWriter(fos, styleDocument.getEncoding());
2253                 bw = new BufferedWriter(osw);
2254                 editorKit.write(bw, styleDocument, 0, styleDocument.getLength());
2255                 bw.flush();
2256             } catch (IOException e) {
2257                 System.err.println(e);
2258             } catch (BadLocationException e) {
2259                 System.err.println(e);
2260             } finally {
2261                 try {
2262                     if (fos != null) {
2263                         fos.close();
2264                     }
2265                     if (osw != null) {
2266                         osw.close();
2267                     }
2268                     if (bw != null) {
2269                         bw.close();
2270                     }
2271                 } catch (IOException e) {
2272                     System.err.println(e);
2273                 }
2274             }
2275
2276             ConfigManager.saveLastOpenedDirectory(f.getPath());
2277             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
2278             ConfigSciNotesManager.saveToOpenFiles(theTextPane.getName(), this, theTextPane);
2279
2280             theTextPane.setName(f.getPath());
2281             getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
2282             setTitle(theTextPane.getTitle());
2283             RecentFileAction.updateRecentOpenedFilesMenu(this);
2284
2285             styleDocument.setContentModified(false);
2286             styleDocument.enableUndoManager();
2287             theTextPane.setLastModified(f.lastModified());
2288         }
2289
2290         getInfoBar().setText("");
2291     }
2292
2293     /**
2294      * EditorKit Getter
2295      *
2296      * @return EditorKit
2297      */
2298     public EditorKit getEditorKit() {
2299         return editorKit;
2300     }
2301
2302     /**
2303      * @param scinotes
2304      *            the focused editor
2305      */
2306     public static void setEditor(SciNotes scinotes) {
2307         editor = scinotes;
2308     }
2309
2310     /**
2311      * @return the focused editor
2312      */
2313     public static SciNotes getEditor() {
2314         return editor;
2315     }
2316
2317     /**
2318      * EditorKit Setter
2319      *
2320      * @param editorKit
2321      *            EditorKit
2322      */
2323     public void setEditorKit(EditorKit editorKit) {
2324         this.editorKit = editorKit;
2325     }
2326
2327     /**
2328      * Close scinotes from scilab.
2329      *
2330      * This method can be called outside the EDT thread.
2331      */
2332     public static void closeSciNotesFromScilab() {
2333         try {
2334             SwingUtilities.invokeAndWait(new Runnable() {
2335
2336                 @Override
2337                 public void run() {
2338                     SciNotes[] arr = scinotesList.toArray(new SciNotes[0]);
2339                     for (int i = 0; i < arr.length; i++) {
2340                         arr[i].setProtectOpenFileList(true);
2341                         ExitAction.doExit(arr[i]);
2342                     }
2343                     scinotesList.clear();
2344                 }
2345             });
2346         } catch (InterruptedException e) {
2347             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
2348         } catch (InvocationTargetException e) {
2349             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
2350         }
2351     }
2352
2353     /**
2354      * @param f
2355      *            the file
2356      * @return the canonical file if possible
2357      */
2358     public static File fileToCanonicalFile(File f) {
2359         /* Fix bug 5648 */
2360         try {
2361             return f.getCanonicalFile();
2362         } catch (IOException e) {
2363             return f;
2364         }
2365     }
2366
2367     /**
2368      * Set the shortcuts in the pane relatively to the file
2369      * keysConfiguration.xml
2370      *
2371      * @param sep
2372      *            the textpane
2373      * @param ed
2374      *            the SciNotes editor
2375      */
2376     private static void setKeyStrokeAction(ScilabEditorPane sep, SciNotes ed) {
2377         if (ed.getTextPane(0) != sep) {
2378             ScilabEditorPane s = ed.getTextPane(0);
2379             sep.setInputMap(JComponent.WHEN_FOCUSED, s.getInputMap());
2380             return;
2381         }
2382
2383         Map<String, KeyStroke> map = getActionKeys();
2384
2385         ClassLoader loader = ClassLoader.getSystemClassLoader();
2386         Iterator<String> iter = map.keySet().iterator();
2387         while (iter.hasNext()) {
2388             String actionName = iter.next();
2389             KeyStroke key = map.get(actionName);
2390             String action = actionToName.get(actionName);
2391             if (key != null) {
2392                 if (!action.equals("SciNotesCompletionAction")) {
2393                     String className;
2394                     if (action.lastIndexOf(DOT) != -1) {
2395                         className = action;
2396                     } else {
2397                         className = DEFAULTACTIONPATH + DOT + action;
2398                     }
2399                     try {
2400                         Class clazz = loader.loadClass(className);
2401                         Constructor constructor = clazz.getConstructor(new Class[] { String.class, SciNotes.class });
2402                         Object act = constructor.newInstance(new Object[] { "", ed });
2403                         sep.getInputMap().put(key, act);
2404                     } catch (ClassNotFoundException e) {
2405                         System.err.println("No action: " + className);
2406                     } catch (InstantiationException e) {
2407                         System.err.println("Problem to instantiate in action: " + className);
2408                     } catch (NoSuchMethodException e) {
2409                         System.err.println("No valid constructor in action: " + className);
2410                     } catch (IllegalAccessException e) {
2411                         System.err.println("The constructor must be public: " + className);
2412                     } catch (InvocationTargetException e) {
2413                         System.err.println("The constructor in " + className + " threw an exception :");
2414                         e.printStackTrace();
2415                     }
2416                 } else {
2417                     sep.getInputMap().put(key, new SciNotesCompletionAction(sep, ed));
2418                 }
2419             }
2420         }
2421     }
2422 }