package com.fitbank.javascript; import java.awt.Color; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.event.UndoableEditEvent; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.Style; import javax.swing.text.StyleConstants; import javax.swing.text.StyleContext; import javax.swing.undo.CompoundEdit; import com.fitbank.util.Debug; /** * Clase que extiende un DefaultStyledDocument para que contenga un documento de * javascript. * * @author Fit-Bank */ public class JavascriptDocument extends DefaultStyledDocument { /** * */ private static final long serialVersionUID = 1L; private static final String[] palabrasclaveArray = { "if", "else", "while", "for", "var", "in", "null", "function", "new", "return", "try", "catch", "switch", "case", "break", "default", "false", "true" }; private boolean cambiando = false; private Pattern palabrasclave; private Pattern cadena = Pattern .compile("(\"[^\"\\\\\\n]*(\\\\.[^\"\\\\]*)*\")|('[^'\\\\\\n]*(\\\\.[^'\\\\]*)*')"); private Pattern comentario1 = Pattern.compile("(//)[^\n]*$"); private Pattern comentario2 = Pattern.compile("(/\\*)[^(\\*/)]*(\\*/)"); private CompoundEdit ce = new CompoundEdit(); private boolean editado = false; private int inicio = 0; private int fin = 0; /** * Constructor por defecto. */ public JavascriptDocument() { super(); String p = "(\\b" + palabrasclaveArray[0] + "\\b)"; for (int a = 1; a < palabrasclaveArray.length; a++) { p += "|(\\b" + palabrasclaveArray[a] + "\\b)"; } palabrasclave = Pattern.compile(p); Style def = StyleContext.getDefaultStyleContext().getStyle( StyleContext.DEFAULT_STYLE); Style regular = addStyle("normal", def); StyleConstants.setForeground(def, Color.BLACK); Style s; s = addStyle("palabraclave", regular); StyleConstants.setForeground(s, new Color(0, 110, 180)); StyleConstants.setBold(s, true); s = addStyle("cadena", regular); StyleConstants.setForeground(s, Color.BLUE); s = addStyle("numero", regular); StyleConstants.setForeground(s, Color.ORANGE); s = addStyle("comentario", regular); StyleConstants.setForeground(s, new Color(0, 196, 0)); } /** * Pinta de colores el texto. * * @param lugar * Lugar donde pintar */ public void pintar(int lugar) { int inicio = Math.max(this.getText().lastIndexOf("\n", lugar - 1), 0); int fin = Math.min(this.getText().indexOf("\n", lugar), getLength()); fin = fin == -1 ? getLength() : fin; setInicio(inicio); setFin(fin); this.pintar(); } /** * Pinta de colores el texto. */ public void pintarTodo() { if (!cambiando) { setInicio(0); setFin(getLength()); this.pintar(); } } /** * Pinta de colores el texto. */ public void pintar() { cambiando = true; try { Matcher m; Style s; fin = Math.min(fin, getLength()); setCharacterAttributes(inicio, fin - inicio, StyleContext .getDefaultStyleContext().getStyle( StyleContext.DEFAULT_STYLE), true); if (fin - inicio > 0) { String texto = this.getText(inicio, fin - inicio); m = palabrasclave.matcher(texto); s = getStyle("palabraclave"); while (m.find()) { setCharacterAttributes(inicio + m.start(), m.end() - m.start(), s, true); } m = cadena.matcher(texto); s = getStyle("cadena"); while (m.find()) { setCharacterAttributes(inicio + m.start(), m.end() - m.start(), s, true); } m = comentario1.matcher(texto); s = getStyle("comentario"); while (m.find()) { setCharacterAttributes(inicio + m.start(), m.end() - m.start(), s, true); } m = comentario2.matcher(texto); while (m.find()) { setCharacterAttributes(inicio + m.start(), inicio + m.end() - m.start(), s, true); } } } catch (Exception e) { Debug.error("Error al encontrar una posicion: [" + inicio + "-" + fin + "] de " + getLength(), e); } cambiando = false; } /** * Maneja cambios en el documento. * * @param e * Evento */ @Override protected void fireUndoableEditUpdate(UndoableEditEvent e) { if (ce != null) { if (!editado) { editado = true; ce.addEdit(e.getEdit()); e.getEdit().replaceEdit(ce); super.fireUndoableEditUpdate(e); } else if (!cambiando) { this.pintar(); ce = new CompoundEdit(); ce.addEdit(e.getEdit()); e.getEdit().replaceEdit(ce); super.fireUndoableEditUpdate(e); } else { ce.addEdit(e.getEdit()); } } } /** * Cambia el inicio de lo que se debe pintar. * * @param inicio * Inicio */ public void setInicio(int inicio) { this.inicio = inicio < 0 ? 0 : inicio; } /** * Cambia el fin de lo que se debe pintar. * * @param fin * Fin */ public void setFin(int fin) { this.fin = fin > getLength() - 1 ? getLength() - 1 : fin; } /** * Devuelve el texto de este documento. * * @return String con el texto */ public String getText() { String t = null; try { t = this.getText(0, getLength()); } catch (BadLocationException b) { System.err.println("Este error nunca deberia ocurrir"); } return t; } /** * Inserta un texto en el documento. * * @param offs * Punto inicial * @param str * Texto a insertar * * @throws BadLocationException * en caso de error */ public void insert(int offs, String str) throws BadLocationException { insertString(offs, str, StyleContext.getDefaultStyleContext().getStyle( StyleContext.DEFAULT_STYLE)); this.pintar(offs); } }