Remove autogenerated comments
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / console / SwingScilabConsole.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007-2008 - INRIA - Vincent Couvert
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.gui.bridge.console;
14
15 import java.awt.Dimension;
16 import java.awt.Toolkit;
17 import java.awt.datatransfer.Clipboard;
18 import java.awt.datatransfer.DataFlavor;
19 import java.awt.datatransfer.StringSelection;
20 import java.awt.datatransfer.UnsupportedFlavorException;
21 import java.awt.event.FocusEvent;
22 import java.awt.event.FocusListener;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.io.IOException;
26 import java.util.StringTokenizer;
27
28 import javax.swing.JEditorPane;
29 import javax.swing.JPanel;
30 import javax.swing.JTextPane;
31 import javax.swing.SwingUtilities;
32 import javax.swing.text.BadLocationException;
33 import javax.swing.text.Document;
34 import javax.swing.text.StyleContext;
35 import javax.swing.text.StyledDocument;
36
37 import org.scilab.modules.action_binding.InterpreterManagement;
38 import org.scilab.modules.console.OneCharKeyEventListener;
39 import org.scilab.modules.console.SciConsole;
40 import org.scilab.modules.console.SciHistoryManager;
41 import org.scilab.modules.console.SciOutputView;
42 import org.scilab.modules.gui.bridge.contextmenu.SwingScilabContextMenu;
43 import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem;
44 import org.scilab.modules.gui.console.SimpleConsole;
45 import org.scilab.modules.gui.events.callback.ScilabCallBack;
46 import org.scilab.modules.gui.utils.ConfigManager;
47 import org.scilab.modules.gui.utils.Position;
48 import org.scilab.modules.gui.utils.Size;
49 import org.scilab.modules.history_manager.HistoryManagement;
50 import org.scilab.modules.localization.Messages;
51
52 import com.artenum.rosetta.interfaces.ui.InputCommandView;
53 import com.artenum.rosetta.util.StringConstants;
54
55 /**
56  * Swing implementation for Scilab Console in GUIs
57  * @author Vincent COUVERT
58  */
59 public class SwingScilabConsole extends SciConsole implements SimpleConsole {
60
61     private static final long serialVersionUID = 1L;
62
63     /**
64      * Constructor
65      */
66     public SwingScilabConsole() {
67         super(ConfigManager.getUserConfigFile());
68
69         SwingScilabContextMenu menu = new SwingScilabContextMenu();
70
71         SwingScilabMenuItem cutMenu = new SwingScilabMenuItem();
72         cutMenu.setText(Messages.gettext("Cut"));
73         cutMenu.setCallback(ScilabCallBack.createCallback(
74                                 "org.scilab.modules.gui.bridge.CallScilabBridge.cutConsoleSelection",
75                                 ScilabCallBack.JAVA));
76         cutMenu.setMnemonic('U');
77
78         SwingScilabMenuItem copyMenu = new SwingScilabMenuItem();
79         copyMenu.setText(Messages.gettext("Copy"));
80         copyMenu.setCallback(ScilabCallBack.createCallback(
81                                  "org.scilab.modules.gui.bridge.CallScilabBridge.copyConsoleSelection",
82                                  ScilabCallBack.JAVA));
83         copyMenu.setMnemonic('C');
84
85         SwingScilabMenuItem pasteMenu = new SwingScilabMenuItem();
86         pasteMenu.setText(Messages.gettext("Paste"));
87         pasteMenu.setCallback(ScilabCallBack.createCallback(
88                                   "org.scilab.modules.gui.bridge.CallScilabBridge.pasteClipboardIntoConsole",
89                                   ScilabCallBack.JAVA));
90         pasteMenu.setMnemonic('P');
91
92         SwingScilabMenuItem clearHistoryMenu = new SwingScilabMenuItem();
93         clearHistoryMenu.setText(Messages.gettext("Clear History"));
94         clearHistoryMenu.setCallback(ScilabCallBack.createCallback(
95                                          "org.scilab.modules.gui.bridge.CallScilabBridge.clearHistory",
96                                          ScilabCallBack.JAVA));
97         clearHistoryMenu.setMnemonic('H');
98
99         SwingScilabMenuItem clearMenu = new SwingScilabMenuItem();
100         clearMenu.setText(Messages.gettext("Clear Console"));
101         clearMenu.setCallback(ScilabCallBack.createCallback(
102                                   "org.scilab.modules.gui.bridge.CallScilabBridge.clear",
103                                   ScilabCallBack.JAVA));
104         clearMenu.setMnemonic('O');
105
106         SwingScilabMenuItem selectMenu = new SwingScilabMenuItem();
107         selectMenu.setText(Messages.gettext("Select All"));
108         selectMenu.setCallback(ScilabCallBack.createCallback(
109                                    "org.scilab.modules.gui.bridge.CallScilabBridge.selectAllConsoleContents",
110                                    ScilabCallBack.JAVA));
111         selectMenu.setMnemonic('S');
112
113
114         final SwingScilabMenuItem helpMenu = new SwingScilabMenuItem();
115         helpMenu.setText(Messages.gettext("Help on a selected keyword"));
116         helpMenu.setCallback(ScilabCallBack.createCallback(
117                                  "org.scilab.modules.gui.bridge.CallScilabBridge.helpOnTheKeyword",
118                                  ScilabCallBack.JAVA));
119         helpMenu.setMnemonic('M');
120         PropertyChangeListener listener = new PropertyChangeListener() {
121                 public void propertyChange(PropertyChangeEvent arg0) {
122                     String keyword = getSelectedText();
123                     if (keyword == null || keyword.length() == 0) {
124                         helpMenu.setText(Messages.gettext("Help about a selected text"));
125                     } else {
126                         int nbOfDisplayedOnlyXChar=10;
127                         if (keyword.length() > nbOfDisplayedOnlyXChar) {
128                             keyword = keyword.substring(0, nbOfDisplayedOnlyXChar) + "...";
129                         }
130                         helpMenu.setText(Messages.gettext("Help about '") +keyword+"'");
131                     }
132                 }
133             };
134         helpMenu.addPropertyChangeListener(listener);
135
136         final SwingScilabMenuItem evalWithEchoMenu = new SwingScilabMenuItem();
137         evalWithEchoMenu.setText(Messages.gettext("Evaluate selection with echo"));
138         evalWithEchoMenu.setCallback(ScilabCallBack.createCallback("org.scilab.modules.gui.bridge.CallScilabBridge.evaluateSelectionWithEcho",
139                                                                    ScilabCallBack.JAVA));
140         evalWithEchoMenu.setMnemonic('E');
141         listener = new PropertyChangeListener() {
142                 public void propertyChange(PropertyChangeEvent arg0) {
143                     String str = getSelectedText();
144                     evalWithEchoMenu.setEnabled(str != null && !str.isEmpty());
145                 }
146             };
147         evalWithEchoMenu.addPropertyChangeListener(listener);
148
149         final SwingScilabMenuItem evalWithNoEchoMenu = new SwingScilabMenuItem();
150         evalWithNoEchoMenu.setText(Messages.gettext("Evaluate selection with no echo"));
151         evalWithNoEchoMenu.setCallback(ScilabCallBack.createCallback("org.scilab.modules.gui.bridge.CallScilabBridge.evaluateSelectionWithNoEcho",
152                                                                      ScilabCallBack.JAVA));
153         evalWithNoEchoMenu.setMnemonic('N');
154         listener = new PropertyChangeListener() {
155                 public void propertyChange(PropertyChangeEvent arg0) {
156                     String str = getSelectedText();
157                     evalWithNoEchoMenu.setEnabled(str != null && !str.isEmpty());
158                 }
159             };
160         evalWithEchoMenu.addPropertyChangeListener(listener);
161
162         menu.add(cutMenu);
163         menu.add(copyMenu);
164         menu.add(pasteMenu);
165
166         menu.addSeparator();
167
168         menu.add(clearHistoryMenu);
169         menu.add(clearMenu);
170
171         menu.addSeparator();
172
173         menu.add(selectMenu);
174         menu.addSeparator();
175
176         menu.add(evalWithEchoMenu);
177         menu.add(evalWithNoEchoMenu);
178         menu.addSeparator();
179
180         menu.add(helpMenu);
181
182         ((JEditorPane) getConfiguration().getOutputView()).setComponentPopupMenu(menu);
183         ((JTextPane) getConfiguration().getInputCommandView()).setComponentPopupMenu(menu);
184         ((JPanel) getConfiguration().getPromptView()).setComponentPopupMenu(menu);
185
186         ((JTextPane) getConfiguration().getInputCommandView()).requestFocus();
187
188         addFocusListener(new FocusListener() {
189                 public void focusGained(FocusEvent e) {
190                     ((JTextPane) getConfiguration().getInputCommandView()).requestFocus();
191                 }
192
193                 public void focusLost(FocusEvent e) { }
194             });
195     }
196
197     /**
198      * Displays data in the console
199      * @param dataToDisplay the data to be displayed
200      * @see fr.scilab.console.HelpBrowser#display(java.lang.String)
201      */
202     public void display(String dataToDisplay) {
203         this.getConfiguration().getOutputView().append(dataToDisplay);
204     }
205
206     /**
207      * This method is used to display the prompt
208      */
209     public void displayPrompt() {
210         SwingUtilities.invokeLater(new Runnable() {
211                 public void run() {
212                     InputCommandView inputCmdView = SwingScilabConsole.this.getConfiguration().getInputCommandView();
213
214                     // Show the prompt
215                     SwingScilabConsole.this.getConfiguration().getPromptView().setVisible(true);
216
217                     // Show the input command view and its hidden components
218                     inputCmdView.setEditable(true);
219                     ((JTextPane) inputCmdView).setCaretColor(((JTextPane) inputCmdView).getForeground());
220                     ((JTextPane) inputCmdView).getCaret().setVisible(true);
221                     setToHome();
222                 }
223             });
224
225         ((SciOutputView) this.getConfiguration().getOutputView()).resetLastEOL();
226
227         updateScrollPosition();
228     }
229
230     /**
231      * Unblock the console if needed
232      */
233     public void unblock() {
234         if (getCanReadUserInputValue().availablePermits() == 0) {
235             setUserInputValue((int) 'n');
236         }
237     }
238
239     /**
240      * Reads one user input char
241      * @return the data entered by the user
242      * @see fr.scilab.console.HelpBrowser#getCharWithoutOutput()
243      */
244     public int getCharWithoutOutput() {
245         int retChar;
246
247         updateScrollPosition();
248
249         // Avoids reading of an empty buffer
250         try {
251             ((SciConsole) this).getCanReadUserInputValue().acquire();
252         } catch (InterruptedException e) {
253             e.printStackTrace();
254         }
255
256         this.getConfiguration().getPromptView().setVisible(false);
257         this.getConfiguration().getInputCommandView().setEditable(false);
258
259         // Add a keylistener which will set the returned char
260         OneCharKeyEventListener keyListener = new OneCharKeyEventListener(this);
261         ((JTextPane) this.getConfiguration().getInputCommandView()).addKeyListener(keyListener);
262         ((JEditorPane) this.getConfiguration().getOutputView()).addKeyListener(keyListener);
263
264         // Reads the buffer
265         retChar = this.getUserInputValue();
266         ((SciConsole) this).getCanReadUserInputValue().release();
267
268         // Remove the "more" message and replace it by an empty line
269         this.clear(-1);
270         this.display(StringConstants.NEW_LINE);
271
272         // Remove the key listener
273         ((JTextPane) this.getConfiguration().getInputCommandView()).removeKeyListener(keyListener);
274         ((JEditorPane) this.getConfiguration().getOutputView()).removeKeyListener(keyListener);
275
276         this.getConfiguration().getPromptView().setVisible(true);
277         this.getConfiguration().getInputCommandView().setEditable(true);
278
279         // Send back the focus the the input view
280         this.getConfiguration().getInputCommandView().reset();
281         this.getConfiguration().getInputCommandView().requestFocus();
282
283         final JTextPane cmdView = (JTextPane) this.getConfiguration().getInputCommandView();
284         SwingUtilities.invokeLater(new Runnable() {
285                 public void run() {
286                     cmdView.getCaret().setVisible(true);
287                 }
288             });
289
290         return retChar;
291     }
292
293     /**
294      * Draw a console
295      */
296     public void draw() {
297         super.setVisible(true);
298         super.doLayout();
299     }
300
301     /**
302      * Gets the dimensions (width and height) of a Scilab console
303      * @return the size of the console
304      */
305     public Size getDims() {
306         return new Size(super.getWidth(), super.getHeight());
307     }
308
309     /**
310      * Gets the position (X-coordinate and Y-coordinates) of a Scilab console
311      * @return the position of the console
312      */
313     public Position getPosition() {
314         return new Position(this.getX(), this.getY());
315     }
316
317     /**
318      * Gets the visibility status of a console
319      * @return the visibility status of the console (true if the console is visible, false if not)
320      */
321     public boolean isVisible() {
322         return super.isVisible();
323     }
324
325     /**
326      * Sets the dimensions (width and height) of a Scilab console
327      * @param newSize the size we want to set to the console
328      */
329     public void setDims(Size newSize) {
330         this.setPreferredSize(new Dimension(newSize.getWidth(), newSize.getHeight()));
331     }
332
333     /**
334      * Sets the position (X-coordinate and Y-coordinate) of a Scilab console
335      * @param newPosition the position we want to set to the console
336      */
337     public void setPosition(Position newPosition) {
338         this.setLocation(newPosition.getX(), newPosition.getY());
339     }
340
341     /**
342      * Sets the visibility status of a Scilab console
343      * @param newVisibleState the visibility status we want to set to the console
344      */
345     public void setVisible(boolean newVisibleState) {
346         super.setVisible(newVisibleState);
347     }
348
349     /**
350      * Clears the Console
351      */
352     public void clear() {
353         super.clear();
354     }
355
356     /**
357      * Sets the prompt displayed in the console
358      * @param prompt the prompt to be displayed in the console
359      */
360     public void setPrompt(String prompt) {
361         this.getConfiguration().getPromptView().setDefaultPrompt(prompt);
362     }
363
364     /**
365      * Clear the commands history
366      */
367     public void clearHistory() {
368         ((SciHistoryManager) this.getConfiguration().getHistoryManager()).reset();
369     }
370
371     /**
372      * Paste clipboard contents in Console input line
373      */
374     public void pasteClipboard() {
375         // Gets the contents of the clipboard
376         Toolkit toolkit = Toolkit.getDefaultToolkit();
377         Clipboard systemClipboard = toolkit.getSystemClipboard();
378
379         // Verify that clibpboard data is of text type
380         boolean dataAvailable;
381         try {
382             dataAvailable = systemClipboard.isDataFlavorAvailable(DataFlavor.stringFlavor);
383         } catch (IllegalStateException exception) {
384             return;
385         }
386
387         // Exit if text data not available
388         if (!dataAvailable) {
389             return;
390         }
391
392         // Read data
393         String clipboardContents = null;
394         try {
395             clipboardContents = (String) systemClipboard.getData(DataFlavor.stringFlavor);
396         } catch (UnsupportedFlavorException e1) {
397             // Should never be here
398             e1.printStackTrace();
399         } catch (IOException e1) {
400             // Should never be here
401             e1.printStackTrace();
402         }
403
404         JTextPane input = ((JTextPane) this.getConfiguration().getInputCommandView());
405         StyledDocument doc = input.getStyledDocument();
406
407         // If some text selected then it is replaced
408         if (input.getSelectedText() != null) {
409             try {
410                 doc.remove(input.getSelectionStart(), input.getSelectionEnd() - input.getSelectionStart());
411             } catch (BadLocationException e) {
412                 e.printStackTrace();
413             }
414         }
415         // Insert clipboard contents
416         try {
417             doc.insertString(((JTextPane) this.getConfiguration().getInputCommandView()).getCaretPosition(),
418                              clipboardContents, doc.getStyle(StyleContext.DEFAULT_STYLE));
419         } catch (BadLocationException e) {
420             e.printStackTrace();
421         }
422     }
423
424     /**
425      * Select all the console contents
426      */
427     public void selectAll() {
428         JEditorPane output = (JEditorPane) this.getConfiguration().getOutputView();
429         output.setSelectionStart(0);
430         output.setSelectionEnd(output.getText().length());
431         // TODO should also select the prompt and the input
432     }
433
434     /**
435      * Return the selected text in the console
436      * @return The selected text in the console
437      */
438     private String getSelectedText() {
439         JEditorPane output = (JEditorPane) this.getConfiguration().getOutputView();
440         JTextPane input = (JTextPane) this.getConfiguration().getInputCommandView();
441
442         String selection = "";
443         if (output.getSelectedText() != null) {
444             selection += output.getSelectedText();
445         }
446         // TODO should also copy the prompt
447         if (input.getSelectedText() != null) {
448             selection += input.getSelectedText();
449         }
450         return selection;
451
452     }
453
454     /**
455      * Launch the help on the selected text into the Console
456      */
457     public void helpOnTheKeyword() {
458         String keyword = getSelectedText();
459         /* Double the quote/double quote in order to avoid
460          * and error with the call of help()
461          */
462         keyword=keyword.replaceAll("'", "''");
463         keyword=keyword.replaceAll("\"", "\"\"");
464
465         /* @TODO: Check if it is possible to call directly
466          * from the Java engine the help
467          * Last time I check, we needed some information
468          * provided by the Scilab native engine
469          */
470         InterpreterManagement.requestScilabExec("help('"+keyword+"')");
471     }
472
473     /**
474      * Evaluate the selection with echo
475      */
476     public void evaluateSelectionWithEcho() {
477         String selection = getSelectedText();
478         if (selection.compareTo("") != 0) {
479             StringTokenizer tokens = new StringTokenizer(selection, "\n");
480             String[] lines = new String[tokens.countTokens()];
481             int i = 0;
482             while (tokens.hasMoreTokens()) {
483                 lines[i++] = tokens.nextToken();
484             }
485             HistoryManagement.appendLinesToScilabHistory(lines, lines.length);
486             sendCommandsToScilab(selection, true, false);
487         }
488     }
489
490     /**
491      * Evaluate the selection with no echo
492      */
493     public void evaluateSelectionWithNoEcho() {
494         sendCommandsToScilab(getSelectedText(), false, false);
495     }
496
497     /**
498      * Put the console selected text in the clipboard
499      */
500     public void copyToClipboard() {
501         String selection = getSelectedText();
502         Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(selection), null);
503     }
504
505     /**
506      * Cut selected text in the Console input line
507      */
508     public void cutSelection() {
509         JTextPane input = (JTextPane) this.getConfiguration().getInputCommandView();
510         StyledDocument doc = input.getStyledDocument();
511
512         // If some text selected then it is replaced
513         if (input.getSelectedText() != null) {
514             try {
515                 /* Put the selection in the clipboard */
516                 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(input.getSelectedText()), null);
517                 /* Remove selected text */
518                 doc.remove(input.getSelectionStart(), input.getSelectionEnd() - input.getSelectionStart());
519             } catch (BadLocationException e) {
520                 e.printStackTrace();
521             }
522         }
523     }
524
525     /**
526      * Set the maximum number of lines stored in the Output
527      * @param nbLines the number of lines
528      */
529     public void setMaxOutputSize(int nbLines) {
530         ((SciOutputView) this.getConfiguration().getOutputView()).setMaxSize(nbLines);
531     }
532 }