Bug 4840 fixed: The more there was text in the console, the slower was the display
[scilab.git] / scilab / modules / console / src / java / org / scilab / modules / console / SciInputCommandView.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.console;
14
15 import org.scilab.modules.history_manager.HistoryManagement;
16 import org.scilab.modules.commons.gui.ScilabCaret;
17 import java.awt.Component;
18 import java.awt.EventQueue;
19 import java.awt.FontMetrics;
20 import java.awt.Point;
21 import java.awt.event.KeyEvent;
22 import java.awt.dnd.DnDConstants;
23 import java.awt.dnd.DropTarget;
24 import java.awt.event.KeyListener;
25 import java.util.concurrent.BlockingQueue;
26 import java.util.concurrent.LinkedBlockingQueue;
27
28 import javax.swing.BorderFactory;
29 import javax.swing.JPanel;
30 import javax.swing.event.DocumentEvent;
31 import javax.swing.event.DocumentListener;
32 import javax.swing.text.BadLocationException;
33
34 import com.artenum.rosetta.interfaces.ui.InputCommandView;
35 import com.artenum.rosetta.interfaces.ui.OutputView;
36 import com.artenum.rosetta.interfaces.ui.PromptView;
37 import com.artenum.rosetta.ui.ConsoleTextPane;
38 import com.artenum.rosetta.util.StringConstants;
39
40 /**
41  * Scilab UI that contains the line edited by the user
42  * @author Vincent COUVERT
43  */
44 public class SciInputCommandView extends ConsoleTextPane implements InputCommandView {
45
46     private static final long serialVersionUID = 1L;
47     private static final String END_LINE = "\n";
48     private static final Point ERROR_POINT = new Point(0, 0);
49     private static final int TOP_BORDER = 1;
50     private static final int BOTTOM_BORDER = 2;
51
52     private static BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
53     private static BlockingQueue<Boolean> displayQueue = new LinkedBlockingQueue<Boolean>();
54
55     private Thread concurrentThread = null;
56
57     private SciConsole console;
58
59     /**
60      * Constructor
61      */
62     public SciInputCommandView() {
63         super();
64         setBorder(BorderFactory.createEmptyBorder(TOP_BORDER, 0, BOTTOM_BORDER, 0));
65
66         // Input command line is not editable when created
67         this.setEditable(false);
68         ScilabCaret caret = new ScilabCaret(this);
69         caret.setBlinkRate(getCaret().getBlinkRate());
70         setCaret(caret);
71     }
72
73     /**
74      * Gets the location of the caret in the UI
75      * @return the location as a Point object
76      * @see com.artenum.rosetta.interfaces.ui.InputCommandView#getCaretLocation()
77      */
78     public Point getCaretLocation() {
79         FontMetrics fontMetric = getFontMetrics(getFont());
80         String[] lines = null;
81         try {
82             lines = getStyledDocument().getText(0, getCaretPosition()).split(END_LINE);
83         } catch (BadLocationException e1) {
84             e1.printStackTrace();
85             return ERROR_POINT;
86         }
87
88         Point result = new Point(fontMetric.stringWidth(lines[lines.length - 1]), (lines.length * fontMetric.getHeight()));
89
90         // Translate for absolute coordinates
91         Component currentComponent = this;
92         while (currentComponent != null) {
93             result.translate(currentComponent.getLocation().x, currentComponent.getLocation().y);
94             currentComponent = currentComponent.getParent();
95             if (currentComponent instanceof JPanel) {
96                 return result;
97             }
98         }
99         return result;
100     }
101
102     /**
103      * Gets the command buffer
104      * @return the command buffer
105      */
106     public String getCmdBuffer() {
107         String command = null;
108         try {
109             if (concurrentThread == null) {
110                 concurrentThread = Thread.currentThread();
111             }
112             else {
113                 concurrentThread.interrupt();
114             }
115             command = queue.take();
116             if (displayQueue.take()) {
117                 OutputView outputView = console.getConfiguration().getOutputView();
118                 PromptView promptView = console.getConfiguration().getPromptView();
119                 outputView.append(StringConstants.NEW_LINE + promptView.getDefaultPrompt() + command + StringConstants.NEW_LINE);
120             }
121         } catch (InterruptedException e) {
122             /*
123              * If we have concurrent access let's interrupt the first one, then allow
124              * the second to return the command.
125              */
126             return "";
127         }
128         concurrentThread = null;
129         return command;
130     }
131
132     /**
133      * Sets the command buffer after a user input in input command view
134      * @param command the string to set to the buffer
135      * @param displayFlag boolean indicating if the command has to be displayed
136      */
137     public void setCmdBuffer(String command, boolean displayFlag) {
138         try {
139             queue.put(command);
140             displayQueue.put(displayFlag);
141         } catch (InterruptedException e) {
142             e.printStackTrace();
143         }
144     }
145
146     /**
147      * Sets the console object containing this input view
148      * @param c the console associated
149      */
150     public void setConsole(SciConsole c) {
151         console = c;
152
153         // Drag n' Drop handling
154         this.setDropTarget(new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, new SciDropTargetListener(console)));
155
156         // BUG 2510 fix: automatic validation of pasted lines
157         this.getDocument().addDocumentListener(new DocumentListener() {
158                 public void changedUpdate(DocumentEvent e) {
159                     // Nothing to do in Scilab
160                 }
161
162                 public void insertUpdate(DocumentEvent e) {
163                     // Validates commands if followed by a carriage return
164                     String wholeTxt = console.getConfiguration().getInputParsingManager().getCommandLine();
165                     if ((e.getLength()) > 1 && (wholeTxt.lastIndexOf(StringConstants.NEW_LINE) == (wholeTxt.length() - 1))) {
166                         EventQueue.invokeLater(new Runnable() {
167                                 public void run() {
168                                     String wholeTxt = console.getConfiguration().getInputParsingManager().getCommandLine();
169                                     console.sendCommandsToScilab(wholeTxt, true, true);
170                                 };
171                             });
172                     }
173                 }
174
175                 public void removeUpdate(DocumentEvent e) {
176                     // Nothing to do in Scilab
177                 }
178             });
179
180         this.addKeyListener(new KeyListener() {
181                 public void keyPressed (KeyEvent e) {
182                     if (e.getKeyCode()==KeyEvent.VK_BACK_SPACE) {
183                         if (console.getConfiguration().getHistoryManager().isInHistory()) {
184                             //console.getConfiguration().getInputParsingManager().reset();
185                             //console.getConfiguration().getInputParsingManager().append(console.getConfiguration().getHistoryManager().getTmpEntry());
186                             console.getConfiguration().getHistoryManager().setInHistory(false);
187                         }
188                     }
189                 }
190
191                 public void keyReleased (KeyEvent e) {
192                     // Nothing to do in Scilab
193                 }
194
195                 public void keyTyped (KeyEvent e) {
196                     // Nothing to do in Scilab
197                 }
198             });
199     }
200 }