package jmathlib.ui.swing;
import java.awt.event.*;
import javax.swing.text.*;
import java.util.*;
import jmathlib.core.interpreter.Interpreter;
import jmathlib.core.interfaces.JMathLibOutput;
/**
* Console-keys class handler.
* <p>Provides <i>command history</i> handling via the <i>up</i> and
* <i>down</i> keys.</p>
* <p>See <kbd>MathLib/Source/UI/Swing/releasenotes.txt</kbd> for more information.</p>
* <p><table style="background-color='#FEE'"><td>This class is not guaranteed to work on older releases than <i>jdk1.4.0-b92</i>.<br>
* See GN0004 for more information.</td></table></p>
* @version 3.1.1
*/
public class KeyHandler implements KeyListener, JMathLibOutput
{
public static KeyHandler runningReference = null;
final CommandHistoryManager commandHistory = CommandHistoryManager.getDefaultInstance();
// The interpreter
Interpreter interpreter = new Interpreter(true);
Console con = null;
/**
* Main constructor.
* Initializes the interpreter.
* @param con Where the interpreter will place its output.
*/
public KeyHandler(Console _con)
{
con = _con;
if (runningReference == null)
{
runningReference = this;
}
interpreter.setOutputPanel(this);
}
public void displayText(String text)
{
con.displayText(text);
}
public void setStatusText(String status)
{
}
/**
* Handles key-typing not handled by keyPressed.
* <p>This method only takes care of the backspace key</p>
* @param e The event
*/
public void keyTyped(KeyEvent e)
{
if (this.isOutsideTyping(e))
{
return ;
}
int x = e.getKeyChar();
switch (e.getKeyChar())
{
case '\b':
// We must take care not deleting the prompt ;-)
Console source = (Console) e.getSource();
int lc = source.getLineCount() - 1;
try
{
int i = source.getLineStartOffset(lc);
i = source.getCaretPosition() - i;
if (i <= 2)
{
e.consume();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
break;
}
}
/**
* Handles key-typing.
* @param e The event
*/
public void keyPressed(KeyEvent e)
{
Console source = (Console) e.getSource();
int keyValue = e.getKeyCode();
int i, j, k, lc;
if (this.isOutsideTyping(e))
{
return ;
}
switch (keyValue)
{
// When the ENTER key is pressed...
case KeyEvent.VK_ENTER:
e.consume();
lc = source.getLineCount() - 1;
try
{
i = source.getLineStartOffset(lc);
j = source.getLineEndOffset(lc);
String s = source.getText().substring(i+2, j);
if (s.equals(""))
{
break;
}
this.commandHistory.addCommand(s);
interpreter.executeExpression(s);
}
catch (Exception ex)
{
ex.printStackTrace();
}
source.append('\n' + source.prompt);
source.setCaretPosition(source.getText().length());
break;
case KeyEvent.VK_UP:
// Scroll back the command input history.
e.consume();
lc = source.getLineCount() - 1;
try
{
i = source.getLineStartOffset(lc);
j = source.getLineEndOffset(lc);
String s = commandHistory.prevCommand();
if (s != null)
source.replaceRange(s, i+2, j);
}
catch (Exception ex)
{
ex.printStackTrace();
}
break;
// When the DOWN key is pressed
case KeyEvent.VK_DOWN:
// Scroll forward the command input history.
e.consume();
lc = source.getLineCount() - 1;
try
{
i = source.getLineStartOffset(lc);
j = source.getLineEndOffset(lc);
String s = commandHistory.nextCommand();
if (s != null)
// Skip the prompt (i+2) and the end (j)
source.replaceRange(s, i+2, j);
}
catch (Exception ex)
{
ex.printStackTrace();
}
break;
// When the ESCAPE key is pressed...
case KeyEvent.VK_ESCAPE:
// Erase the current editing line
e.consume();
lc = source.getLineCount() - 1;
try
{
i = source.getLineStartOffset(lc);
j = source.getLineEndOffset(lc);
// Skip the prompt (i+2) and the end (j-1)
source.replaceRange("", i+2, j);
}
catch (Exception ex)
{
ex.printStackTrace();
}
commandHistory.resetToLastCommand();
break;
case KeyEvent.VK_LEFT:
// We must take care not entering through the prompt ;-)
lc = source.getLineCount() - 1;
try
{
i = source.getLineStartOffset(lc);
j = source.getCaretPosition();
if (j-i <= 2)
{
e.consume();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
break;
case KeyEvent.VK_HOME:
// We go to the first position after the prompt
e.consume();
lc = source.getLineCount() - 1;
try
{
i = source.getLineStartOffset(lc);
source.setCaretPosition(i+2);
}
catch (Exception ex)
{
ex.printStackTrace();
}
break;
case KeyEvent.VK_PAGE_UP:
e.consume();
break;
case KeyEvent.VK_TAB:
e.consume();
String s = source.getCurrentCommand();
String[] sa = AutoCompletion.runningReference.getMatched(s);
if (sa.length == 1)
{
// Let's trim the extension
String s2 = sa[0].substring(0, sa[0].indexOf("."));
source.setSelectionStart(source.getCaretPosition() - s.length());
source.setSelectionEnd(source.getCaretPosition());
source.replaceSelection(s2 + "()");
source.setCaretPosition(source.getCaretPosition() - 1);
}
else
{
source.append("" + '\n');
for(i = 0; i < sa.length; i++) {
source.append(sa[i] + '\t');
}
source.append("" + '\n' + source.prompt + s);
}
break;
default:
break;
}
}
public void keyReleased(KeyEvent e)
{
}
/**
* Checks if we type a key out the last line.
* It never <i>consume's</i> the key.
* @param e The event
* @return <kbd>True</kbd> - The key was typed out the last line or
* inside the prompt.
*/
private boolean isOutsideTyping(KeyEvent e)
{
Console source = (Console) e.getSource();
int i, j, k, lc;
// Ensure we are not editing outside the last line
lc = source.getLineCount();
i = source.getCaretPosition();
k = 0;
try
{
k = source.getLineOfOffset(i) - lc;
i = source.getLineStartOffset(lc - 1);
i = source.getCaretPosition() - i;
}
catch (BadLocationException ble)
{
ble.printStackTrace();
}
if (k != -1 || i < 2)
{
return true;
}
return false;
}
}