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