X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FScriptWindow.java;h=adebec84d53a6375229941d206376bcfd8210f83;hb=797df64fa2a0a30773d0f48f5494d4155e5a8be3;hp=8e6958432742771fe9616ece51861524df8fd41b;hpb=d8df6dc37ed09db9f3cb5b61140967754226f1fe;p=jalview.git diff --git a/src/jalview/gui/ScriptWindow.java b/src/jalview/gui/ScriptWindow.java index 8e69584..adebec8 100644 --- a/src/jalview/gui/ScriptWindow.java +++ b/src/jalview/gui/ScriptWindow.java @@ -1,616 +1,732 @@ -/* $RCSfile$ - * $Author$ - * $Date$ - * $Revision$ - * - * Copyright (C) 2002-2005 The Jmol Development Team - * - * Contact: jmol-developers@lists.sf.net - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - - * - * Modified and added to Jalview by A Waterhouse to extend JInternalFrame - * - - */ -package jalview.gui; - -import org.jmol.api.*; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.text.*; -import java.util.Vector; - -import org.jmol.i18n.GT; -import org.jmol.util.Logger; -import org.jmol.util.CommandHistory; - -public final class ScriptWindow extends JPanel - implements ActionListener, EnterListener{ - - private ConsoleTextPane console; - private JButton closeButton; - private JButton runButton; - private JButton haltButton; - private JButton clearButton; - private JButton historyButton; - private JButton stateButton; - JmolViewer viewer; - AppJmol appJmol; - - public ScriptWindow(AppJmol appJmol) - { - this.viewer = appJmol.viewer; - this.appJmol = appJmol; - - - setLayout(new BorderLayout()); - - console = new ConsoleTextPane(this); - - - console.setPrompt(); - add(new JScrollPane(console) - , BorderLayout.CENTER); - - JPanel buttonPanel = new JPanel(); - add(buttonPanel, BorderLayout.SOUTH); - - runButton = new JButton(GT._("Run")); - haltButton = new JButton(GT._("Halt")); - runButton.addActionListener(this); - // buttonPanel.add(runButton); - haltButton.addActionListener(this); - // buttonPanel.add(haltButton); - haltButton.setEnabled(false); - - clearButton = new JButton(GT._("Clear")); - clearButton.addActionListener(this); - buttonPanel.add(clearButton); - - historyButton = new JButton(GT._("History")); - historyButton.addActionListener(this); - buttonPanel.add(historyButton); - - stateButton = new JButton(GT._("State")); - stateButton.addActionListener(this); - buttonPanel.add(stateButton); - - closeButton = new JButton(GT._("Close")); - closeButton.addActionListener(this); - buttonPanel.add(closeButton); - - for(int i=0; i= 0) { - console.outputError(strStatus); - isError = true; - } else if (!isError) { - console.outputStatus(strStatus); - } - } - - public void notifyScriptTermination(String strMsg, int msWalltime) { - if (strMsg != null && strMsg.indexOf("ERROR") >= 0) { - console.outputError(strMsg); - } - runButton.setEnabled(true); - haltButton.setEnabled(false); - } - - public void enterPressed() { - runButton.doClick(100); - // executeCommand(); - } - - - class ExecuteCommandThread extends Thread { - - String strCommand; - ExecuteCommandThread (String command) { - strCommand = command; - } - - public void run() { - try { - executeCommand(strCommand); - } catch (Exception ie) { - Logger.debug("execution command interrupted!"+ie); - } - } - } - - ExecuteCommandThread execThread; - void executeCommandAsThread(){ - String strCommand = console.getCommandString().trim(); - if (strCommand.length() > 0) { - execThread = new ExecuteCommandThread(strCommand); - execThread.start(); - } - } - - void executeCommand(String strCommand) { - boolean doWait; - setError(false); - console.appendNewline(); - console.setPrompt(); - if (strCommand.length() > 0) { - String strErrorMessage = null; - doWait = (strCommand.indexOf("WAIT ") == 0); - if (doWait) { //for testing, mainly - // demonstrates using the statusManager system. - runButton.setEnabled(false); - haltButton.setEnabled(true); - - Vector info = (Vector) viewer - .scriptWaitStatus(strCommand.substring(5), - "+fileLoaded,+scriptStarted,+scriptStatus,+scriptEcho,+scriptTerminated"); - runButton.setEnabled(true); - haltButton.setEnabled(false); - /* - * info = [ statusRecortSet0, statusRecortSet1, statusRecortSet2, ...] - * statusRecordSet = [ statusRecord0, statusRecord1, statusRecord2, ...] - * statusRecord = [int msgPtr, String statusName, int intInfo, String msg] - */ - for (int i = 0; i < info.size(); i++) { - Vector statusRecordSet = (Vector) info.get(i); - for (int j = 0; j < statusRecordSet.size(); j++) { - Vector statusRecord = (Vector) statusRecordSet.get(j); - Logger.info("msg#=" + statusRecord.get(0) + " " - + statusRecord.get(1) + " intInfo=" + statusRecord.get(2) - + " stringInfo=" + statusRecord.get(3)); - } - } - console.appendNewline(); - } else { - boolean isScriptExecuting = viewer.isScriptExecuting(); - if (viewer.checkHalt(strCommand)) - strErrorMessage = (isScriptExecuting ? "string execution halted with " + strCommand : "no script was executing"); - else - strErrorMessage = "";//viewer.scriptCheck(strCommand); - //the problem is that scriptCheck is synchronized, so these might get backed up. - if (strErrorMessage != null && strErrorMessage.length() > 0) { - console.outputError(strErrorMessage); - } else { - //runButton.setEnabled(false); - haltButton.setEnabled(true); - viewer.script(strCommand); - } - } - } - console.grabFocus(); - } - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (source == closeButton) { - appJmol.showConsole(false); - } else if (source == runButton) { - executeCommandAsThread(); - } else if (source == clearButton) { - console.clearContent(); - } else if (source == historyButton) { - console.clearContent(viewer.getSetHistory(Integer.MAX_VALUE)); - } else if (source == stateButton) { - console.clearContent(viewer.getStateInfo()); - } else if (source == haltButton) { - viewer.haltScriptExecution(); - } - console.grabFocus(); // always grab the focus (e.g., after clear) - } -} - -class ConsoleTextPane extends JTextPane { - - ConsoleDocument consoleDoc; - EnterListener enterListener; - JmolViewer viewer; - - ConsoleTextPane(ScriptWindow scriptWindow) { - super(new ConsoleDocument()); - consoleDoc = (ConsoleDocument)getDocument(); - consoleDoc.setConsoleTextPane(this); - this.enterListener = (EnterListener) scriptWindow; - this.viewer = scriptWindow.viewer; - } - - public String getCommandString() { - String cmd = consoleDoc.getCommandString(); - return cmd; - } - - public void setPrompt() { - consoleDoc.setPrompt(); - } - - public void appendNewline() { - consoleDoc.appendNewline(); - } - - public void outputError(String strError) { - consoleDoc.outputError(strError); - } - - public void outputErrorForeground(String strError) { - consoleDoc.outputErrorForeground(strError); - } - - public void outputEcho(String strEcho) { - consoleDoc.outputEcho(strEcho); - } - - public void outputStatus(String strStatus) { - consoleDoc.outputStatus(strStatus); - } - - public void enterPressed() { - if (enterListener != null) - enterListener.enterPressed(); - } - - public void clearContent() { - clearContent(null); - } - public void clearContent(String text) { - consoleDoc.clearContent(); - if (text != null) - consoleDoc.outputEcho(text); - setPrompt(); - } - - /* (non-Javadoc) - * @see java.awt.Component#processKeyEvent(java.awt.event.KeyEvent) - */ - - /** - * Custom key event processing for command 0 implementation. - * - * Captures key up and key down strokes to call command history - * and redefines the same events with control down to allow - * caret vertical shift. - * - * @see java.awt.Component#processKeyEvent(java.awt.event.KeyEvent) - */ - protected void processKeyEvent(KeyEvent ke) - { - // Id Control key is down, captures events does command - // history recall and inhibits caret vertical shift. - if (ke.getKeyCode() == KeyEvent.VK_UP - && ke.getID() == KeyEvent.KEY_PRESSED - && !ke.isControlDown()) - { - recallCommand(true); - } - else if ( - ke.getKeyCode() == KeyEvent.VK_DOWN - && ke.getID() == KeyEvent.KEY_PRESSED - && !ke.isControlDown()) - { - recallCommand(false); - } - // If Control key is down, redefines the event as if it - // where a key up or key down stroke without modifiers. - // This allows to move the caret up and down - // with no command history recall. - else if ( - (ke.getKeyCode() == KeyEvent.VK_DOWN - || ke.getKeyCode() == KeyEvent.VK_UP) - && ke.getID() == KeyEvent.KEY_PRESSED - && ke.isControlDown()) - { - super - .processKeyEvent(new KeyEvent( - (Component) ke.getSource(), - ke.getID(), - ke.getWhen(), - 0, // No modifiers - ke.getKeyCode(), - ke.getKeyChar(), - ke.getKeyLocation())); - } - // Standard processing for other events. - else - { - super.processKeyEvent(ke); - //check command for compiler-identifyable syntax issues - //this may have to be taken out if people start complaining - //that only some of the commands are being checked - //that is -- that the script itself is not being fully checked - - //not perfect -- help here? - if (ke.getID() == KeyEvent.KEY_RELEASED - && (ke.getKeyCode() > KeyEvent.VK_DOWN) || ke.getKeyCode() == KeyEvent.VK_BACK_SPACE) - checkCommand(); - } - } - - /** - * Recall command history. - * - * @param up - history up or down - */ - void recallCommand(boolean up) { - String cmd = viewer.getSetHistory(up ? -1 : 1); - if (cmd == null) { - return; - } - try { - if (cmd.endsWith(CommandHistory.ERROR_FLAG)) { - cmd = cmd.substring(0, cmd.indexOf(CommandHistory.ERROR_FLAG)); - consoleDoc.replaceCommand(cmd, true); - } else { - consoleDoc.replaceCommand(cmd, false); - } - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - void checkCommand() { - String strCommand = consoleDoc.getCommandString(); - if (strCommand.length() == 0) - return; - consoleDoc - .colorCommand(viewer.scriptCheck(strCommand) == null ? consoleDoc.attUserInput - : consoleDoc.attError); - } - - -} - -class ConsoleDocument extends DefaultStyledDocument { - - ConsoleTextPane consoleTextPane; - - SimpleAttributeSet attError; - SimpleAttributeSet attEcho; - SimpleAttributeSet attPrompt; - SimpleAttributeSet attUserInput; - SimpleAttributeSet attStatus; - - ConsoleDocument() { - super(); - - attError = new SimpleAttributeSet(); - StyleConstants.setForeground(attError, Color.red); - - attPrompt = new SimpleAttributeSet(); - StyleConstants.setForeground(attPrompt, Color.magenta); - - attUserInput = new SimpleAttributeSet(); - StyleConstants.setForeground(attUserInput, Color.black); - - attEcho = new SimpleAttributeSet(); - StyleConstants.setForeground(attEcho, Color.blue); - StyleConstants.setBold(attEcho, true); - - attStatus = new SimpleAttributeSet(); - StyleConstants.setForeground(attStatus, Color.black); - StyleConstants.setItalic(attStatus, true); - } - - void setConsoleTextPane(ConsoleTextPane consoleTextPane) { - this.consoleTextPane = consoleTextPane; - } - - Position positionBeforePrompt; // starts at 0, so first time isn't tracked (at least on Mac OS X) - Position positionAfterPrompt; // immediately after $, so this will track - int offsetAfterPrompt; // only still needed for the insertString override and replaceCommand - - /** - * Removes all content of the script window, and add a new prompt. - */ - void clearContent() { - try { - super.remove(0, getLength()); - } catch (BadLocationException exception) { - System.out.println("Could not clear script window content: " + exception.getMessage()); - } - } - - void setPrompt() { - try { - super.insertString(getLength(), "$ ", attPrompt); - setOffsetPositions(); - consoleTextPane.setCaretPosition(offsetAfterPrompt); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - void setOffsetPositions() { - try { - offsetAfterPrompt = getLength(); - positionBeforePrompt = createPosition(offsetAfterPrompt - 2); - // after prompt should be immediately after $ otherwise tracks the end - // of the line (and no command will be found) at least on Mac OS X it did. - positionAfterPrompt = createPosition(offsetAfterPrompt - 1); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - void setNoPrompt() { - try { - offsetAfterPrompt = getLength(); - positionAfterPrompt = positionBeforePrompt = createPosition(offsetAfterPrompt); - consoleTextPane.setCaretPosition(offsetAfterPrompt); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - // it looks like the positionBeforePrompt does not track when it started out as 0 - // and a insertString at location 0 occurs. It may be better to track the - // position after the prompt in stead - void outputBeforePrompt(String str, SimpleAttributeSet attribute) { - try { - int pt = consoleTextPane.getCaretPosition(); - Position caretPosition = createPosition(pt); - pt = positionBeforePrompt.getOffset(); - super.insertString(pt, str+"\n", attribute); - setOffsetPositions(); - pt = caretPosition.getOffset(); - consoleTextPane.setCaretPosition(pt); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - void outputError(String strError) { - outputBeforePrompt(strError, attError); - } - - void outputErrorForeground(String strError) { - try { - super.insertString(getLength(), strError+"\n", attError); - consoleTextPane.setCaretPosition(getLength()); - } catch (BadLocationException e) { - e.printStackTrace(); - - } - } - - void outputEcho(String strEcho) { - outputBeforePrompt(strEcho, attEcho); - } - - void outputStatus(String strStatus) { - outputBeforePrompt(strStatus, attStatus); - } - - void appendNewline() { - try { - super.insertString(getLength(), "\n", attUserInput); - consoleTextPane.setCaretPosition(getLength()); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - // override the insertString to make sure everything typed ends up at the end - // or in the 'command line' using the proper font, and the newline is processed. - public void insertString(int offs, String str, AttributeSet a) - throws BadLocationException { - int ichNewline = str.indexOf('\n'); - if (ichNewline > 0) - str = str.substring(0, ichNewline); - if (ichNewline != 0) { - if (offs < offsetAfterPrompt) { - offs = getLength(); - } - super.insertString(offs, str, a == attError ? a : attUserInput); - consoleTextPane.setCaretPosition(offs+str.length()); - } - if (ichNewline >= 0) { - consoleTextPane.enterPressed(); - } - } - - String getCommandString() { - String strCommand = ""; - try { - int cmdStart = positionAfterPrompt.getOffset(); - strCommand = getText(cmdStart, getLength() - cmdStart); - while (strCommand.length() > 0 && strCommand.charAt(0) == ' ') - strCommand = strCommand.substring(1); - } catch (BadLocationException e) { - e.printStackTrace(); - } - return strCommand; - } - - public void remove(int offs, int len) - throws BadLocationException { - if (offs < offsetAfterPrompt) { - len -= offsetAfterPrompt - offs; - if (len <= 0) - return; - offs = offsetAfterPrompt; - } - super.remove(offs, len); -// consoleTextPane.setCaretPosition(offs); - } - - public void replace(int offs, int length, String str, AttributeSet attrs) - throws BadLocationException { - if (offs < offsetAfterPrompt) { - if (offs + length < offsetAfterPrompt) { - offs = getLength(); - length = 0; - } else { - length -= offsetAfterPrompt - offs; - offs = offsetAfterPrompt; - } - } - super.replace(offs, length, str, attrs); -// consoleTextPane.setCaretPosition(offs + str.length()); - } - - /** - * Replaces current command on script. - * - * @param newCommand new command value - * @param isError true to set error color ends with #?? - * - * @throws BadLocationException - */ - void replaceCommand(String newCommand, boolean isError) throws BadLocationException { - if (positionAfterPrompt == positionBeforePrompt) - return; - replace(offsetAfterPrompt, getLength() - offsetAfterPrompt, newCommand, - isError ? attError : attUserInput); - } - - void colorCommand(SimpleAttributeSet att) { - if (positionAfterPrompt == positionBeforePrompt) - return; - setCharacterAttributes(offsetAfterPrompt, getLength() - offsetAfterPrompt, att, true); - } -} - -interface EnterListener { - public void enterPressed(); -} - +/* + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7) + * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Jalview. If not, see . + */ +package jalview.gui; + +import org.jmol.api.*; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.text.*; +import java.util.Vector; + +import org.jmol.i18n.GT; +import org.jmol.util.Logger; +import org.jmol.util.CommandHistory; + +// TODO: this class is copied in from jmol 11.0.2 - upgrade to 12.0.2 ? +public final class ScriptWindow extends JPanel implements ActionListener, + EnterListener +{ + + private ConsoleTextPane console; + + private JButton closeButton; + + private JButton runButton; + + private JButton haltButton; + + private JButton clearButton; + + private JButton historyButton; + + private JButton stateButton; + + JmolViewer viewer; + + AppJmol appJmol; + + public ScriptWindow(AppJmol appJmol) + { + this.viewer = appJmol.jmb.viewer; + this.appJmol = appJmol; + + setLayout(new BorderLayout()); + + console = new ConsoleTextPane(this); + + console.setPrompt(); + add(new JScrollPane(console), BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(); + add(buttonPanel, BorderLayout.SOUTH); + + runButton = new JButton(GT._("Run")); + haltButton = new JButton(GT._("Halt")); + runButton.addActionListener(this); + // buttonPanel.add(runButton); + haltButton.addActionListener(this); + // buttonPanel.add(haltButton); + haltButton.setEnabled(false); + + clearButton = new JButton(GT._("Clear")); + clearButton.addActionListener(this); + buttonPanel.add(clearButton); + + historyButton = new JButton(GT._("History")); + historyButton.addActionListener(this); + buttonPanel.add(historyButton); + + stateButton = new JButton(GT._("State")); + stateButton.addActionListener(this); + buttonPanel.add(stateButton); + + closeButton = new JButton(GT._("Close")); + closeButton.addActionListener(this); + buttonPanel.add(closeButton); + + for (int i = 0; i < buttonPanel.getComponentCount(); i++) + { + // ((JButton)buttonPanel.getComponent(i)) + // .setMargin(new Insets(0, 0, 0, 0)); + } + + } + + public void sendConsoleEcho(String strEcho) + { + if (strEcho != null && !isError) + { + + console.outputEcho(strEcho); + + } + setError(false); + } + + boolean isError = false; + + void setError(boolean TF) + { + isError = TF; + // if (isError) + // console.recallCommand(true); + } + + public void sendConsoleMessage(String strStatus) + { + if (strStatus == null) + { + console.clearContent(); + console.outputStatus(""); + } + else if (strStatus.indexOf("ERROR:") >= 0) + { + console.outputError(strStatus); + isError = true; + } + else if (!isError) + { + console.outputStatus(strStatus); + } + } + + public void notifyScriptTermination(String strMsg, int msWalltime) + { + if (strMsg != null && strMsg.indexOf("ERROR") >= 0) + { + console.outputError(strMsg); + } + runButton.setEnabled(true); + haltButton.setEnabled(false); + } + + public void enterPressed() + { + runButton.doClick(100); + // executeCommand(); + } + + class ExecuteCommandThread extends Thread + { + + String strCommand; + + ExecuteCommandThread(String command) + { + strCommand = command; + } + + public void run() + { + try + { + executeCommand(strCommand); + } catch (Exception ie) + { + Logger.debug("execution command interrupted!" + ie); + } + } + } + + ExecuteCommandThread execThread; + + void executeCommandAsThread() + { + String strCommand = console.getCommandString().trim(); + if (strCommand.length() > 0) + { + execThread = new ExecuteCommandThread(strCommand); + execThread.start(); + } + } + + void executeCommand(String strCommand) + { + boolean doWait; + setError(false); + console.appendNewline(); + console.setPrompt(); + if (strCommand.length() > 0) + { + String strErrorMessage = null; + doWait = (strCommand.indexOf("WAIT ") == 0); + if (doWait) + { // for testing, mainly + // demonstrates using the statusManager system. + runButton.setEnabled(false); + haltButton.setEnabled(true); + + Vector info = (Vector) viewer + .scriptWaitStatus(strCommand.substring(5), + "+fileLoaded,+scriptStarted,+scriptStatus,+scriptEcho,+scriptTerminated"); + runButton.setEnabled(true); + haltButton.setEnabled(false); + /* + * info = [ statusRecortSet0, statusRecortSet1, statusRecortSet2, ...] + * statusRecordSet = [ statusRecord0, statusRecord1, statusRecord2, ...] + * statusRecord = [int msgPtr, String statusName, int intInfo, String + * msg] + */ + for (int i = 0; i < info.size(); i++) + { + Vector statusRecordSet = (Vector) info.get(i); + for (int j = 0; j < statusRecordSet.size(); j++) + { + Vector statusRecord = (Vector) statusRecordSet.get(j); + Logger.info("msg#=" + statusRecord.get(0) + " " + + statusRecord.get(1) + " intInfo=" + + statusRecord.get(2) + " stringInfo=" + + statusRecord.get(3)); + } + } + console.appendNewline(); + } + else + { + boolean isScriptExecuting = viewer.isScriptExecuting(); + if (viewer.checkHalt(strCommand, true)) + strErrorMessage = (isScriptExecuting ? "string execution halted with " + + strCommand + : "no script was executing"); + else + strErrorMessage = "";// viewer.scriptCheck(strCommand); + // the problem is that scriptCheck is synchronized, so these might get + // backed up. + if (strErrorMessage != null && strErrorMessage.length() > 0) + { + console.outputError(strErrorMessage); + } + else + { + // runButton.setEnabled(false); + haltButton.setEnabled(true); + viewer.script(strCommand); + } + } + } + console.grabFocus(); + } + + public void actionPerformed(ActionEvent e) + { + Object source = e.getSource(); + if (source == closeButton) + { + // appJmol.showConsole(false); + } + else if (source == runButton) + { + executeCommandAsThread(); + } + else if (source == clearButton) + { + console.clearContent(); + } + else if (source == historyButton) + { + console.clearContent(viewer.getSetHistory(Integer.MAX_VALUE)); + } + else if (source == stateButton) + { + console.clearContent(viewer.getStateInfo()); + } + else if (source == haltButton) + { + viewer.haltScriptExecution(); + } + console.grabFocus(); // always grab the focus (e.g., after clear) + } +} + +class ConsoleTextPane extends JTextPane +{ + + ConsoleDocument consoleDoc; + + EnterListener enterListener; + + JmolViewer viewer; + + ConsoleTextPane(ScriptWindow scriptWindow) + { + super(new ConsoleDocument()); + consoleDoc = (ConsoleDocument) getDocument(); + consoleDoc.setConsoleTextPane(this); + this.enterListener = (EnterListener) scriptWindow; + this.viewer = scriptWindow.viewer; + } + + public String getCommandString() + { + String cmd = consoleDoc.getCommandString(); + return cmd; + } + + public void setPrompt() + { + consoleDoc.setPrompt(); + } + + public void appendNewline() + { + consoleDoc.appendNewline(); + } + + public void outputError(String strError) + { + consoleDoc.outputError(strError); + } + + public void outputErrorForeground(String strError) + { + consoleDoc.outputErrorForeground(strError); + } + + public void outputEcho(String strEcho) + { + consoleDoc.outputEcho(strEcho); + } + + public void outputStatus(String strStatus) + { + consoleDoc.outputStatus(strStatus); + } + + public void enterPressed() + { + if (enterListener != null) + enterListener.enterPressed(); + } + + public void clearContent() + { + clearContent(null); + } + + public void clearContent(String text) + { + consoleDoc.clearContent(); + if (text != null) + consoleDoc.outputEcho(text); + setPrompt(); + } + + /* + * (non-Javadoc) + * + * @see java.awt.Component#processKeyEvent(java.awt.event.KeyEvent) + */ + + /** + * Custom key event processing for command 0 implementation. + * + * Captures key up and key down strokes to call command history and redefines + * the same events with control down to allow caret vertical shift. + * + * @see java.awt.Component#processKeyEvent(java.awt.event.KeyEvent) + */ + protected void processKeyEvent(KeyEvent ke) + { + // Id Control key is down, captures events does command + // history recall and inhibits caret vertical shift. + if (ke.getKeyCode() == KeyEvent.VK_UP + && ke.getID() == KeyEvent.KEY_PRESSED && !ke.isControlDown()) + { + recallCommand(true); + } + else if (ke.getKeyCode() == KeyEvent.VK_DOWN + && ke.getID() == KeyEvent.KEY_PRESSED && !ke.isControlDown()) + { + recallCommand(false); + } + // If Control key is down, redefines the event as if it + // where a key up or key down stroke without modifiers. + // This allows to move the caret up and down + // with no command history recall. + else if ((ke.getKeyCode() == KeyEvent.VK_DOWN || ke.getKeyCode() == KeyEvent.VK_UP) + && ke.getID() == KeyEvent.KEY_PRESSED && ke.isControlDown()) + { + super.processKeyEvent(new KeyEvent((Component) ke.getSource(), ke + .getID(), ke.getWhen(), 0, // No modifiers + ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation())); + } + // Standard processing for other events. + else + { + super.processKeyEvent(ke); + // check command for compiler-identifyable syntax issues + // this may have to be taken out if people start complaining + // that only some of the commands are being checked + // that is -- that the script itself is not being fully checked + + // not perfect -- help here? + if (ke.getID() == KeyEvent.KEY_RELEASED + && (ke.getKeyCode() > KeyEvent.VK_DOWN) + || ke.getKeyCode() == KeyEvent.VK_BACK_SPACE) + checkCommand(); + } + } + + /** + * Recall command history. + * + * @param up + * - history up or down + */ + void recallCommand(boolean up) + { + String cmd = viewer.getSetHistory(up ? -1 : 1); + if (cmd == null) + { + return; + } + try + { + if (cmd.endsWith(CommandHistory.ERROR_FLAG)) + { + cmd = cmd.substring(0, cmd.indexOf(CommandHistory.ERROR_FLAG)); + consoleDoc.replaceCommand(cmd, true); + } + else + { + consoleDoc.replaceCommand(cmd, false); + } + } catch (BadLocationException e) + { + e.printStackTrace(); + } + } + + void checkCommand() + { + String strCommand = consoleDoc.getCommandString(); + if (strCommand.length() == 0) + return; + consoleDoc + .colorCommand(viewer.scriptCheck(strCommand) == null ? consoleDoc.attUserInput + : consoleDoc.attError); + } + +} + +class ConsoleDocument extends DefaultStyledDocument +{ + + ConsoleTextPane consoleTextPane; + + SimpleAttributeSet attError; + + SimpleAttributeSet attEcho; + + SimpleAttributeSet attPrompt; + + SimpleAttributeSet attUserInput; + + SimpleAttributeSet attStatus; + + ConsoleDocument() + { + super(); + + attError = new SimpleAttributeSet(); + StyleConstants.setForeground(attError, Color.red); + + attPrompt = new SimpleAttributeSet(); + StyleConstants.setForeground(attPrompt, Color.magenta); + + attUserInput = new SimpleAttributeSet(); + StyleConstants.setForeground(attUserInput, Color.black); + + attEcho = new SimpleAttributeSet(); + StyleConstants.setForeground(attEcho, Color.blue); + StyleConstants.setBold(attEcho, true); + + attStatus = new SimpleAttributeSet(); + StyleConstants.setForeground(attStatus, Color.black); + StyleConstants.setItalic(attStatus, true); + } + + void setConsoleTextPane(ConsoleTextPane consoleTextPane) + { + this.consoleTextPane = consoleTextPane; + } + + Position positionBeforePrompt; // starts at 0, so first time isn't tracked + + // (at least on Mac OS X) + + Position positionAfterPrompt; // immediately after $, so this will track + + int offsetAfterPrompt; // only still needed for the insertString override and + + // replaceCommand + + /** + * Removes all content of the script window, and add a new prompt. + */ + void clearContent() + { + try + { + super.remove(0, getLength()); + } catch (BadLocationException exception) + { + System.out.println("Could not clear script window content: " + + exception.getMessage()); + } + } + + void setPrompt() + { + try + { + super.insertString(getLength(), "$ ", attPrompt); + setOffsetPositions(); + consoleTextPane.setCaretPosition(offsetAfterPrompt); + } catch (BadLocationException e) + { + e.printStackTrace(); + } + } + + void setOffsetPositions() + { + try + { + offsetAfterPrompt = getLength(); + positionBeforePrompt = createPosition(offsetAfterPrompt - 2); + // after prompt should be immediately after $ otherwise tracks the end + // of the line (and no command will be found) at least on Mac OS X it did. + positionAfterPrompt = createPosition(offsetAfterPrompt - 1); + } catch (BadLocationException e) + { + e.printStackTrace(); + } + } + + void setNoPrompt() + { + try + { + offsetAfterPrompt = getLength(); + positionAfterPrompt = positionBeforePrompt = createPosition(offsetAfterPrompt); + consoleTextPane.setCaretPosition(offsetAfterPrompt); + } catch (BadLocationException e) + { + e.printStackTrace(); + } + } + + // it looks like the positionBeforePrompt does not track when it started out + // as 0 + // and a insertString at location 0 occurs. It may be better to track the + // position after the prompt in stead + void outputBeforePrompt(String str, SimpleAttributeSet attribute) + { + try + { + int pt = consoleTextPane.getCaretPosition(); + Position caretPosition = createPosition(pt); + pt = positionBeforePrompt.getOffset(); + super.insertString(pt, str + "\n", attribute); + setOffsetPositions(); + pt = caretPosition.getOffset(); + consoleTextPane.setCaretPosition(pt); + } catch (BadLocationException e) + { + e.printStackTrace(); + } + } + + void outputError(String strError) + { + outputBeforePrompt(strError, attError); + } + + void outputErrorForeground(String strError) + { + try + { + super.insertString(getLength(), strError + "\n", attError); + consoleTextPane.setCaretPosition(getLength()); + } catch (BadLocationException e) + { + e.printStackTrace(); + + } + } + + void outputEcho(String strEcho) + { + outputBeforePrompt(strEcho, attEcho); + } + + void outputStatus(String strStatus) + { + outputBeforePrompt(strStatus, attStatus); + } + + void appendNewline() + { + try + { + super.insertString(getLength(), "\n", attUserInput); + consoleTextPane.setCaretPosition(getLength()); + } catch (BadLocationException e) + { + e.printStackTrace(); + } + } + + // override the insertString to make sure everything typed ends up at the end + // or in the 'command line' using the proper font, and the newline is + // processed. + public void insertString(int offs, String str, AttributeSet a) + throws BadLocationException + { + int ichNewline = str.indexOf('\n'); + if (ichNewline > 0) + str = str.substring(0, ichNewline); + if (ichNewline != 0) + { + if (offs < offsetAfterPrompt) + { + offs = getLength(); + } + super.insertString(offs, str, a == attError ? a : attUserInput); + consoleTextPane.setCaretPosition(offs + str.length()); + } + if (ichNewline >= 0) + { + consoleTextPane.enterPressed(); + } + } + + String getCommandString() + { + String strCommand = ""; + try + { + int cmdStart = positionAfterPrompt.getOffset(); + strCommand = getText(cmdStart, getLength() - cmdStart); + while (strCommand.length() > 0 && strCommand.charAt(0) == ' ') + strCommand = strCommand.substring(1); + } catch (BadLocationException e) + { + e.printStackTrace(); + } + return strCommand; + } + + public void remove(int offs, int len) throws BadLocationException + { + if (offs < offsetAfterPrompt) + { + len -= offsetAfterPrompt - offs; + if (len <= 0) + return; + offs = offsetAfterPrompt; + } + super.remove(offs, len); + // consoleTextPane.setCaretPosition(offs); + } + + public void replace(int offs, int length, String str, AttributeSet attrs) + throws BadLocationException + { + if (offs < offsetAfterPrompt) + { + if (offs + length < offsetAfterPrompt) + { + offs = getLength(); + length = 0; + } + else + { + length -= offsetAfterPrompt - offs; + offs = offsetAfterPrompt; + } + } + super.replace(offs, length, str, attrs); + // consoleTextPane.setCaretPosition(offs + str.length()); + } + + /** + * Replaces current command on script. + * + * @param newCommand + * new command value + * @param isError + * true to set error color ends with #?? + * + * @throws BadLocationException + */ + void replaceCommand(String newCommand, boolean isError) + throws BadLocationException + { + if (positionAfterPrompt == positionBeforePrompt) + return; + replace(offsetAfterPrompt, getLength() - offsetAfterPrompt, newCommand, + isError ? attError : attUserInput); + } + + void colorCommand(SimpleAttributeSet att) + { + if (positionAfterPrompt == positionBeforePrompt) + return; + setCharacterAttributes(offsetAfterPrompt, getLength() + - offsetAfterPrompt, att, true); + } +} + +interface EnterListener +{ + public void enterPressed(); +}