Package abstrasy.consoleui

Source Code of abstrasy.consoleui.OutputTextArea

package abstrasy.consoleui;


import abstrasy.Interpreter;
import abstrasy.Main;
import abstrasy.Node;

import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.SilentException;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;


/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
*   http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/

public class OutputTextArea extends JTextPane {

    private OutputTextArea Me;

    /*
     * Sortie console (partiellement) compatible ANSI:
     * ==============================================
     *
     *    Le support des séquence d'échapement ANSI est actuellement partiel et uniquement en sortie.
     *    Les codes supportés sont les suivants:
     *
     *    - \e[ (...) m  où (...) peut être une liste de nombres sous forme de caractères séparés par des ';':
     *
     *                              0   : Réinitialiser la sortie
     *
     *                              1   : Bold on
     *                              3   : Italic on
     *                              4   : Underline on
     *
     *                              22  : Bold off
     *                              23  : Italic off
     *                              24  : Underline off
     *
     *                              30  : black (fg)
     *                              31  : red (fg)
     *                              32  : green (fg)
     *                              33  : yellow (fg)
     *                              34  : blue (fg)
     *                              35  : magenta (fg)
     *                              36  : cyan (fg)
     *                              37  : white (fg)
     *
     *                              40  : black (bg)
     *                              41  : red (bg)
     *                              42  : green (bg)
     *                              43  : yellow (bg)
     *                              44  : blue (bg)
     *                              45  : magenta (bg)
     *                              46  : cyan (bg)
     *                              47  : white (bg)
     *
     *                              38;5;n : Utilise la couleur n de la palette de 256 couleurs pour fg.
     *                              48;5;n : utilise la couleur n de la palette de 256 couleurs pour bg.
     *
     *    - \e[nC                       : Insère n caractères d'espacement sans appliquer les styles.
     *
     *    - \e]4;n;rgb:rr/gg/bb\e\\     : Enregistre les composentes rgb rr, gg et bb dans la palette de 256 couleurs à la position n.
     *                                    Noter que rr, gg et bb sont fournies en hexadécimal et sont compris dans [00..ff].
     *
     */
    private static final int MAXCOLORS = 256;
    private Color[] colors = new Color[MAXCOLORS];

    public static final Color COLOR_Reset_FG = Color.green;
    public static final Color COLOR_Reset_BG = Color.black;
    private Color currentFG = COLOR_Reset_FG;
    private Color currentBG = COLOR_Reset_BG;
    private boolean currentBOLD = false;
    private boolean currentITALIC = false;
    private boolean currentUNDERLINE = false;

    public void resetStyles() {
        currentFG = COLOR_Reset_FG;
        currentBG = COLOR_Reset_BG;
        currentBOLD = false;
        currentITALIC = false;
        currentUNDERLINE = false;
    }

    /**
     * Convertir l'offset en numéro de ligne.
     *
     * @param offset >= 0
     * @return numéro de la ligne >= 0
     * @exception BadLocationException
     */
    public int getLineOfOffset(int offset) throws BadLocationException {
        Document doc = getDocument();
        if (offset < 0) {
            throw new BadLocationException("Can't translate offset to line", -1);
        }
        else if (offset > doc.getLength()) {
            throw new BadLocationException("Can't translate offset to line", doc.getLength() + 1);
        }
        else {
            Element map = getDocument().getDefaultRootElement();
            return map.getElementIndex(offset);
        }
    }

    /**
     * Determine le nombre de lignes dans le document.
     *
     * @return NbrLignes > 0
     */
    public int getLineCount() {
        Element map = getDocument().getDefaultRootElement();
        return map.getElementCount();
    }

    /**
     * Determine l'offset du début de la ligne.
     * Cette méthode est inspirée de la méthode du même nom dans JTextArea.
     *
     * @param line >= 0
     * @return offset >= 0
     * @exception BadLocationException
     */
    public int getLineStartOffset(int line) throws BadLocationException {
        int lineCount = getLineCount();
        if (line < 0) {
            throw new BadLocationException("Negative line", -1);
        }
        else if (line >= lineCount) {
            throw new BadLocationException("No such line", getDocument().getLength() + 1);
        }
        else {
            Element map = getDocument().getDefaultRootElement();
            Element lineElem = map.getElement(line);
            return lineElem.getStartOffset();
        }
    }

    /**
     * Determine l'offset de la fin de la ligne fournie en arguement.
     * Cette méthode est inspirée de JTextArea.
     *
     * @param line  >= 0
     * @return offset >= 0
     * @exception BadLocationException
     */
    public int getLineEndOffset(int line) throws BadLocationException {
        int lineCount = getLineCount();
        if (line < 0) {
            throw new BadLocationException("Negative line", -1);
        }
        else if (line >= lineCount) {
            throw new BadLocationException("No such line", getDocument().getLength() + 1);
        }
        else {
            Element map = getDocument().getDefaultRootElement();
            Element lineElem = map.getElement(line);
            int endOffset = lineElem.getEndOffset();
            // hide the implicit break at the end of the document
            return ((line == lineCount - 1) ? (endOffset - 1): endOffset);
        }
    }


    public void append(String s) {
        StyleContext sc = StyleContext.getDefaultStyleContext();
        SimpleAttributeSet attributes = new SimpleAttributeSet();
        attributes.addAttribute(StyleConstants.Foreground, currentFG);
        //if(currentBG.getRGB()!=this.getBackground().getRGB()){
        attributes.addAttribute(StyleConstants.Background, currentBG);
        //}
        attributes.addAttribute(StyleConstants.Bold, currentBOLD);
        attributes.addAttribute(StyleConstants.Italic, currentITALIC);
        attributes.addAttribute(StyleConstants.Underline, currentUNDERLINE);
        int len = this.getDocument().getLength();
        this.setCaretPosition(len); // placer le caret à la fin.
        this.setSelectionStart(len);
        this.setSelectionEnd(len);
        setCharacterAttributes(attributes, false); // pas de style.
        replaceSelection(s); // c'est un moyen pour insérer là où est le caret.
    }

    private String appendANSI_cache = "";

    private int endOfANSI(String src, int deb) {
        int i = deb;
        if (i < src.length() && src.charAt(++i) == '[') {
            /* séquence CSI */
            String dico = "0123456789;";
            while (i < src.length()) {
                if (dico.indexOf(src.charAt(++i)) < 0) {
                    return i;
                }
            }
        }
        else if (i < src.length()) {
            /* séquence non-CSI */
            while (i < src.length()) {
                if (src.charAt(++i) == '\\' && src.charAt(i - 1) == '\u001B') {
                    return i;
                }
            }
        }
        return -1;
    }

    public void appendANSI(String s) {
        int aPos = 0;
        int aIndex = 0;
        int xIndex = 0;
        String tmpString = "";
        boolean stillSearching = true; // vrai tant qu'il y a des CSI à traiter...
        String addString = appendANSI_cache + s;
        appendANSI_cache = "";

        if (addString.length() > 0) {
            aIndex = addString.indexOf("\u001B");
            if (aIndex == -1) { // pas de séquence, on termine...
                append(addString);
                return;
            }

            if (aIndex > 0) { // S'il y a des caractères avant la séquence...
                tmpString = addString.substring(0, aIndex);
                append(tmpString);
                aPos = aIndex;
            }

            // A partir d'ici aPos est positionné sur le début de la séquence...

            stillSearching = true;
            while (stillSearching) {
                xIndex = endOfANSI(addString, aPos); // on recherche la fin de la séquence...
                if (xIndex >= 0) {
                    tmpString = addString.substring(aPos, xIndex + 1);
                    char lastChar = tmpString.charAt(tmpString.length() - 1);
                    if (lastChar == 'C') {
                        doANSI_Com(tmpString);
                    }
                    else if (lastChar == 'm') {
                        tmpString = addString.substring(aPos, xIndex + 1);
                        parseANSI_FG_Color(tmpString);
                        parseANSI_BG_Color(tmpString);
                        parseANSI_BOLD(tmpString);
                        parseANSI_ITALIC(tmpString);
                        parseANSI_UNDERLINE(tmpString);
                    }
                    else if (lastChar == '\\') {
                        /* non CSI sequence */
                        parseANSI_SelectRGB(tmpString);
                    }
                    aPos = xIndex + 1;
                }
                else { // the buffer ends halfway through the ansi string!
                    appendANSI_cache = addString.substring(aPos, addString.length());
                    stillSearching = false;
                    continue;
                }

                aIndex = addString.indexOf("\u001B", aPos);

                if (aIndex == -1) { // S'il n'y a pas de séquence, on ajoute les caractères
                    tmpString = addString.substring(aPos, addString.length());
                    append(tmpString);
                    stillSearching = false;
                    continue; // puis au saute au début de la boucle suivante...
                }

                // S'il y a une autre séquence, on vide les caractères avant de procéder...
                tmpString = addString.substring(aPos, aIndex);
                aPos = aIndex;
                append(tmpString);

            }
        }
    }

    private final static String spaces(int sc) {
        String s = "";
        for (int i = 0; i < sc; i++) {
            s += " ";
        }
        return s;
    }

    public void doANSI_Com(String src) {
        //System.out.println("*"+src+"*");
        if (src.startsWith("\u001B[")) {
            if (src.charAt(src.length() - 1) == 'C') {
                try {
                    int nc = Integer.parseInt(src.substring(2, src.length() - 1));
                    Color tmpFG = currentFG;
                    Color tmpBG = currentBG;
                    boolean tmpB = currentBOLD;
                    boolean tmpI = currentITALIC;
                    boolean tmpU = currentUNDERLINE;
                    this.resetStyles();
                    append(spaces(nc));
                    currentFG = tmpFG;
                    currentBG = tmpBG;
                    currentBOLD = tmpB;
                    currentITALIC = tmpI;
                    currentUNDERLINE = tmpU;
                }
                catch (Exception e) {
                    // rien faire...
                }
            }
        }
    }

    private Color getANSI_fg(String code, Color precedColor) {
        //System.out.println(code);
        if (code.equals("0")) {
            return COLOR_Reset_FG;
        }
        else if (code.equals("30")) {
            return Color.black;
        }
        else if (code.equals("31")) {
            return Color.red;
        }
        else if (code.equals("32")) {
            return Color.green;
        }
        else if (code.equals("33")) {
            return Color.yellow;
        }
        else if (code.equals("34")) {
            return Color.blue;
        }
        else if (code.equals("35")) {
            return Color.magenta;
        }
        else if (code.equals("36")) {
            return Color.cyan;
        }
        else if (code.equals("37")) {
            return Color.white;
        }
        else {
            return precedColor;
        }

    }

    public void parseANSI_FG_Color(String src) {
        Color fg = currentFG;
        if (src.startsWith("\u001B[") && src.endsWith("m")) {
            String[] decomp = (src.substring(2, src.length() - 1) + ";").split(";");
            for (int i = 0; i < decomp.length; i++) {
                if (decomp[i].equals("38") && ((i + 2) < decomp.length) && decomp[i + 1].equals("5")) {
                    /* 256 colors */
                    int ncolor = 0;
                    try {
                        ncolor = Integer.parseInt(decomp[i + 2]);
                    }
                    catch (Exception e) {
                        Interpreter.Log("ANSI CSI error: \\e" + src.substring(1) + " ...");
                    }
                    if (ncolor < 0 || ncolor >= MAXCOLORS) {
                        Interpreter.Log("ANSI CSI error: \\e" + src.substring(1) + " (the color number must be in [0.." + MAXCOLORS + "[) ...");
                    }
                    else {
                        fg = colors[ncolor];
                    }
                    i += 2;
                    i += 2;
                }
                else {
                    /* basic */
                    fg = getANSI_fg(decomp[i], fg);
                }
            }
        }
        currentFG = fg;
    }

    private Color getANSI_bg(String code, Color precedColor) {
        //System.out.println(code);
        if (code.equals("0")) {
            return COLOR_Reset_BG;
        }
        else if (code.equals("40")) {
            return Color.black;
        }
        else if (code.equals("41")) {
            return Color.red;
        }
        else if (code.equals("42")) {
            return Color.green;
        }
        else if (code.equals("43")) {
            return Color.yellow;
        }
        else if (code.equals("44")) {
            return Color.blue;
        }
        else if (code.equals("45")) {
            return Color.magenta;
        }
        else if (code.equals("46")) {
            return Color.cyan;
        }
        else if (code.equals("47")) {
            return Color.white;
        }
        else {
            return precedColor;
        }

    }

    public void parseANSI_BG_Color(String src) {
        Color bg = currentBG;
        if (src.startsWith("\u001B[") && src.endsWith("m")) {
            String[] decomp = (src.substring(2, src.length() - 1) + ";").split(";");
            for (int i = 0; i < decomp.length; i++) {
                if (decomp[i].equals("48") && ((i + 2) < decomp.length) && decomp[i + 1].equals("5")) {
                    /* 256 colors */
                    int ncolor = 0;
                    try {
                        ncolor = Integer.parseInt(decomp[i + 2]);
                    }
                    catch (Exception e) {
                        Interpreter.Log("ANSI CSI error: \\e" + src.substring(1) + " ...");
                    }
                    if (ncolor < 0 || ncolor >= MAXCOLORS) {
                        Interpreter.Log("ANSI CSI error: \\e" + src.substring(1) + " (the color number must be in [0.." + MAXCOLORS + "[) ...");
                    }
                    else {
                        bg = colors[ncolor];
                    }
                    i += 2;
                }
                else {
                    /* basic */
                    bg = getANSI_bg(decomp[i], bg);
                }
            }
        }
        currentBG = bg;
    }

    public void parseANSI_SelectRGB(String src) {
        if (src.startsWith("\u001B]4;") && src.endsWith("\u001B\\")) {
            String[] decomp = src.substring(4, src.length() - 2).split(";");
            if (decomp.length == 2) {
                // lire le numéro de couleur...
                int ncolor = 0;
                try {
                    ncolor = Integer.parseInt(decomp[0]);
                }
                catch (Exception e) {
                    Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ ...");
                }
                if (ncolor < 0 || ncolor >= MAXCOLORS) {
                    Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ (the color number must be in [0.." + MAXCOLORS + "[) ...");
                }
                else {
                    // numéro de couleur correct...
                    if (decomp[1].startsWith("rgb:")) {
                        decomp = decomp[1].substring(4).split("/");
                        if (decomp.length == 3) {
                            int r = 0;
                            int g = 0;
                            int b = 0;
                            try {
                                r = Integer.parseInt(decomp[0], 16);
                                g = Integer.parseInt(decomp[1], 16);
                                b = Integer.parseInt(decomp[2], 16);
                            }
                            catch (Exception e) {
                                Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ ...");
                            }
                            if (r < 0 || r > 255) {
                                Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ (red value must be in [0..255]) ...");
                            }
                            else if (g < 0 || g > 255) {
                                Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ (green value must be in [0..255]) ...");
                            }
                            else if (b < 0 || b > 255) {
                                Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ (blue value must be in [0..255]) ...");
                            }
                            else {
                                colors[ncolor] = new Color(r, g, b);
                            }
                        }
                        else {
                            Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ ...");
                        }
                    }
                }
            }
            else {
                Interpreter.Log("ANSI non-CSI sequence error: \\e]4;" + src.substring(4, src.length() - 2) + "\\e\\ ...");
            }
        }
    }

    public void parseANSI_BOLD(String src) {
        boolean b = currentBOLD;
        if (src.startsWith("\u001B[") && src.endsWith("m")) {
            String[] decomp = (src.substring(2, src.length() - 1) + ";").split(";");
            for (int i = 0; i < decomp.length; i++) {
                if (decomp[i].equals("0")) {
                    b = false;
                }
                else if (decomp[i].equals("1")) {
                    b = true;
                }
                else if (decomp[i].equals("22")) {
                    b = false;
                }
            }
        }
        currentBOLD = b;
    }

    public void parseANSI_ITALIC(String src) {
        boolean b = currentITALIC;
        if (src.startsWith("\u001B[") && src.endsWith("m")) {
            String[] decomp = (src.substring(2, src.length() - 1) + ";").split(";");
            for (int i = 0; i < decomp.length; i++) {
                if (decomp[i].equals("0")) {
                    b = false;
                }
                else if (decomp[i].equals("3")) {
                    b = true;
                }
                else if (decomp[i].equals("23")) {
                    b = false;
                }
            }
        }
        currentITALIC = b;
    }

    public void parseANSI_UNDERLINE(String src) {
        boolean b = currentUNDERLINE;
        if (src.startsWith("\u001B[") && src.endsWith("m")) {
            String[] decomp = (src.substring(2, src.length() - 1) + ";").split(";");
            for (int i = 0; i < decomp.length; i++) {
                if (decomp[i].equals("0")) {
                    b = false;
                }
                else if (decomp[i].equals("4")) {
                    b = true;
                }
                else if (decomp[i].equals("24")) {
                    b = false;
                }
            }
        }
        currentUNDERLINE = b;
    }

    private transient Border border5;
    private JPopupMenu jPopupMenu1 = new JPopupMenu();
    private JMenuItem jMenuItem1 = new JMenuItem();

    public OutputTextArea() {
        super();
        try {
            Me = this;
            initColors();
            jbInit();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }


    //Initialiser le composant

    private void initColors() {
        for (int i = 0; i < MAXCOLORS; i++) {
            colors[i] = new Color(i, i, i);
        }
    }

    public void setDocument(Document doc) {
        if (doc instanceof DefaultStyledDocument)
            super.setDocument(doc);
    }

    private static final String _getDefaultConsoleFontName_() {
        Font[] fonts = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
        //for(int i=0;i<fonts.length;i++)
        //    if(fonts[i].getFontName().toLowerCase().startsWith("dejavu sans mono"))
        //        return fonts[i].getFontName();
        for(int i=0;i<fonts.length;i++)
            if(fonts[i].getFontName().toLowerCase().startsWith("lucida sans typewriter regular"))
                return fonts[i].getFontName();
        return "Monospaced";
    }
   
    private void jbInit() throws Exception {
        border5 = BorderFactory.createEmptyBorder(4, 4, 4, 4);
        this.setOpaque(false);
        this.setDocument(new DefaultStyledDocument());
        this.setBackground(Color.black);
        this.setFont(new Font(_getDefaultConsoleFontName_(), 0, 12));
        this.setBorder(border5);


        /**
         * Eviter this.setEditable(false);
         *
         * Peut bloquer le processus!
         *
         **/


        this.addMouseListener(new MouseAdapter() {

            public void mouseClicked(MouseEvent e) {
                this_mouseClicked(e);
            }

        });
        jPopupMenu1.setLabel("jPopupMenu1");
        jMenuItem1.setText("Copy");
        jMenuItem1.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                jMenuItem1_actionPerformed(e);
            }

        });

        jPopupMenu1.add(jMenuItem1);


    }

    public void setBackground(Color color) {
        super.setBackground(color);
        this.setCaretColor(color);
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        if (!Main.onOpenJDK) {
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        }
        else {
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        }
        g2.setPaint(this.getBackground());
        g2.fillRect(0, 0, this.getWidth(), this.getHeight());
        super.paintComponent(g);
    }

    public int getCurrentCaret() {
        int mcaret = -1;
        try {
            mcaret = this.getCaretPosition();
        }
        catch (Exception e) {
            Interpreter.Log("OutpuTextArea:Catch Exception:");
            e.printStackTrace();
        }
        return mcaret;
    }

    public void lockCaretPos() {
        caretpos = getCurrentCaret();
        //Interpreter.Log("caretLock:"+caretpos);
    }

    public void unlockCaretPos() {
        //Interpreter.Log("UnLockCaret:"+caretpos);
        caretpos = -1;
    }
    private int caretpos = -1;

    private String readString = "";

    public void processKeyEvent(KeyEvent e) {
        // this is what one would expect to work but it doesn't because
        // KEY_TYPED events never get here and they are the only ones
        // that when consumed will successfully stop a non numeric
        // character from being displayed in the text field.
        char ckey = e.getKeyChar();
        boolean isTyped = e.getID() == KeyEvent.KEY_TYPED;

        int action = e.getKeyCode();
        boolean isAction = e.isActionKey();
        boolean ignoreKey = false;

        if (caretpos < 0) {
            e.consume();
            return;
        }

        if (isAction) {
            if (action == KeyEvent.VK_PAGE_UP) {
                ignoreKey = true;
            }
            else if (action == KeyEvent.VK_PAGE_DOWN) {
                ignoreKey = true;
            }
            else if (action == KeyEvent.VK_UP) {
                ignoreKey = true;
            }
            else if (action == KeyEvent.VK_DOWN) {
                ignoreKey = true;
            }
            else if (action == KeyEvent.VK_HOME) {
                // if(e.getID()==KeyEvent.KEY_RELEASED){this.lockCaretPos();}
                ignoreKey = true;
            }
            else if (action == KeyEvent.VK_END) {
                ignoreKey = true;
            }
            else if (action == KeyEvent.VK_LEFT) {
                if (caretpos >= 0 && this.getCaretPosition() <= caretpos) {
                    ignoreKey = true;
                }
            }
        }
        if (ckey == '\n' || ckey == '\r') {
            if (caretpos >= 0 && isTyped) {
                String readS = this.getText();
                readS = readS.substring(readln_start_pos, readS.length());
                readString = "";
                for (int i = 0; i < readS.length(); i++) {
                    char c = readS.charAt(i);
                    if (c != '\n' && c != '\r') {
                        readString += c;
                    }
                }
                //Interpreter.Log("Saisie = \""+readString+"\"");
                this.unlockCaretPos();
            }
        }


        if (ignoreKey) {
            e.consume();
        }
        else {
            super.processKeyEvent(e);
        }

    }

    public void processMouseEvent(MouseEvent e) {
        if (caretpos != -1) {
            e.consume();
        }
        else {
            super.processMouseEvent(e);
        }
    }

    public void processMouseMotionEvent(MouseEvent e) {
        if (caretpos != -1) {
            e.consume();
        }
        else {
            super.processMouseMotionEvent(e);
        }
    }

    //
    private Object syncIO = new Object();
    private Object waitIO = new Object();
    private volatile boolean procIO = false;
    private String _write_str_;


    public void write(String str) throws Exception {
        /**
         * ATTENTION! ne doit pas être exécuté par le processus Swing!!!
         */
        if (EventQueue.isDispatchThread())
            throw new Error("Cannot call this method from the event dispatcher thread");

        /*
         * Un seul processus à la fois peut écrire à l'aide de write()...
         */
        synchronized (syncIO) {

            _write_str_ = str;

            Runnable proc = new Runnable() {

                public void run() {
                    try {
                        Me.appendANSI(_write_str_);
                        Me.setCaretPosition(Me.getDocument().getLength()); //this.getLineEndOffset(this.getLineCount() - 1));
                    }
                    catch (Exception e) {
                        if (Interpreter.isDebugMode()) {
                            e.printStackTrace();
                        }
                        if (e instanceof InterpreterException || e instanceof SilentException) {
                            //throw e;
                            e.printStackTrace();
                        }
                    }
                    //
                    SwingUtilities.invokeLater(new Runnable() {

                        public void run() {
                            procIO = false;
                            synchronized (waitIO) {
                                waitIO.notify();
                            }
                        }

                    });
                    //
                }

            };

            procIO = true;
            SwingUtilities.invokeLater(proc);
            do {
                synchronized (waitIO) {
                    waitIO.wait();
                }
            }
            while (procIO);
        }

    }

    public void clr() throws Exception {
        clr("");
    }

    public void clr(String texte) throws Exception {
        /**
         * ATTENTION! ne doit pas être exécuté par le processus Swing!!!
         */
        if (EventQueue.isDispatchThread())
            throw new Error("Cannot call this method from the event dispatcher thread");

        /*
         * Un seul processus à la fois peut écrire à l'aide de write()...
         */
        synchronized (syncIO) {

            _write_str_ = texte;

            Runnable proc = new Runnable() {

                public void run() {
                    try {
                        Me.setText("");
                        Me.appendANSI(_write_str_);

                        Me.setCaretPosition(Me.getDocument().getLength()); //this.getLineEndOffset(this.getLineCount() - 1));
                    }
                    catch (Exception e) {
                        if (Interpreter.isDebugMode()) {
                            e.printStackTrace();
                        }
                    }
                    //
                    SwingUtilities.invokeLater(new Runnable() {

                        public void run() {
                            procIO = false;
                            synchronized (waitIO) {
                                waitIO.notify();
                            }
                        }

                    });
                    //
                }

            };

            procIO = true;
            SwingUtilities.invokeLater(proc);
            do {
                synchronized (waitIO) {
                    waitIO.wait();
                }
            }
            while (procIO);
        }

    }

    public String readln() throws Exception {

        synchronized (syncIO) {

            readString = "";
            readln_start_pos = this.getText().length();
            try {
                this.setCaretPosition(this.getDocument().getLength());
            }
            catch (Exception e) {
                Interpreter.Log("OutpuTextArea:Catch Exception:");
                e.printStackTrace();
            }
            final OutputTextArea fout = this;
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    //fout.setEditable(true);
                    fout.setCaretColor(Color.lightGray);
                    fout.setFocusable(true);
                    fout.requestFocus();
                    fout.invalidate();
                }

            });

            this.lockCaretPos();
            while (caretpos >= 0) {
                //try {

                Thread.sleep(100);

                //}
                //catch (Exception e) {
                //  this.unlockCaretPos();
                //  throw e;
                //}

            }
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    fout.setCaretColor(getBackground());
                    //fout.setEditable(false);
                    //fout.setFocusable(false);
                }

            });

        }
        return readString;
    }

    private int readln_start_pos = 0;

    public String readln(Node startAt) throws Exception {

        synchronized (syncIO) {
            readString = "";
            readln_start_pos = this.getText().length();
            try {
                this.setCaretPosition(this.getDocument().getLength());
            }
            catch (Exception e) {
                Interpreter.Log("OutpuTextArea:Catch Exception:");
                e.printStackTrace();
            }
            final OutputTextArea fout = this;
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    //fout.setEditable(true);
                    fout.setCaretColor(Color.lightGray);
                    fout.setFocusable(true);
                    fout.requestFocus();
                    fout.invalidate();
                }

            });

            this.lockCaretPos();
            while (caretpos >= 0) {
                Interpreter myself = Interpreter.mySelf();
                Interpreter.getSemaphore().sleep(100);
                if (myself.isThreadRaising()) {
                    this.unlockCaretPos();
                    SwingUtilities.invokeLater(new Runnable() {

                        public void run() {
                            fout.setCaretColor(getBackground());
                            //fout.setEditable(false);
                            //fout.setFocusable(false);
                        }

                    });
                    Interpreter.mySelf().throwInterThreadException();
                }
            }
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    fout.setCaretColor(getBackground());
                    //fout.setEditable(false);
                    //fout.setFocusable(false);
                }

            });
        }

        return readString;
    }

    private void this_mouseClicked(MouseEvent e) {

        boolean isRightButton = (SwingUtilities.isRightMouseButton(e)) || (SwingUtilities.isLeftMouseButton(e) && e.isControlDown());
        if (isRightButton) {
            jMenuItem1.setEnabled(this.getSelectionStart() < this.getSelectionEnd());
            jPopupMenu1.show(this, e.getX(), e.getY());
        }


    }

    private void jMenuItem1_actionPerformed(ActionEvent e) {
        this.copy();
    }

    public void setCurrentFG(Color colorCurrent) {
        this.currentFG = colorCurrent;
    }

    public Color getCurrentFG() {
        return currentFG;
    }

    public void setCurrentBG(Color currentBG) {
        this.currentBG = currentBG;
    }

    public Color getCurrentBG() {
        return currentBG;
    }

    public void setCurrentBOLD(boolean currentBOLD) {
        this.currentBOLD = currentBOLD;
    }

    public boolean isCurrentBOLD() {
        return currentBOLD;
    }

    public void setCurrentITALIC(boolean currentITALIC) {
        this.currentITALIC = currentITALIC;
    }

    public boolean isCurrentITALIC() {
        return currentITALIC;
    }

    public void setCurrentUNDERLINE(boolean currentUNDERLINE) {
        this.currentUNDERLINE = currentUNDERLINE;
    }

    public boolean isCurrentUNDERLINE() {
        return currentUNDERLINE;
    }

}
TOP

Related Classes of abstrasy.consoleui.OutputTextArea

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.