/*
* SqlEditorKit.java
*
* Created on 2004
* Created by Arsenio Molinero
* Copyright (C) 2004, 2005 Arsenio Molinero
*
* GestDB - a Java multi database client
*
* This file is part of GestDB.
*
* GestDB 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 2 of the License, or
* (at your option) any later version.
*
* GestDB 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 GestDB; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.GestDB.sql;
import java.awt.*;
import javax.swing.text.*;
import java.util.Vector;
public class SqlEditorKit extends DefaultEditorKit {
public static int anchoNumeracion = 38;
/**
* default constructor for SqlEditorKit
*/
public SqlEditorKit() {
super();
}
/**
* Gets the MIME type of the data that this
* kit represents support for. The default
* is <code>text/plain</code>.
*
* @return the type
*/
public String getContentType() {
return "text/sql";
}
/**
* Create a copy of the editor kit. This
* allows an implementation to serve as a prototype
* for others, so that they can be quickly created.
*/
public Object clone() {
SqlEditorKit kit = new SqlEditorKit();
kit.sqlcon = sqlcon;
return kit;
}
/**
* Creates an uninitialized text storage model (PlainDocument)
* that is appropriate for this type of editor.
*
* @return the model
*/
public Document createDefaultDocument() {
//******************* el mio
return new PlainDocument();
}
/**
* Fetches a factory that is suitable for producing
* views of any models that are produced by this
* kit. The default is to have the UI produce the
* factory, so this method has no implementation.
*
* @return the view factory
*/
public ViewFactory getViewFactory() {
if (sqlcon == null) {
sqlcon = new SqlContext();
}
return sqlcon;
}
SqlContext sqlcon = null;
public class SqlContext extends StyleContext implements ViewFactory
{
Color unselected;
Color selected;
/**
* Constructs a set of styles to represent java lexical
* tokens. By default there are no colors or fonts specified.
*/
public SqlContext()
{
super();
Style root = getStyle(DEFAULT_STYLE);
tokenStyles = new Style[Token.MaximumScanValue + 1];
Token[] tokens = Token.all;
int n = tokens.length;
for (int i = 0; i < n; i++) {
Token t = tokens[i];
Style parent = getStyle(t.getCategory());
if (parent == null) {
parent = addStyle(t.getCategory(), root);
}
Style s = addStyle(null, parent);
s.addAttribute(Token.TokenAttribute, t);
tokenStyles[t.getScanValue()] = s;
}
}
/**
* Fetch the foreground color to use for a lexical
* token with the given value.
*
* @param attr attribute set from a token element
* that has a Token in the set.
*/
public Color getForeground(int code)
{
if (tokenColors == null)
{
tokenColors = new Color[Token.MaximumScanValue + 1];
}
if ((code >= 0) && (code < tokenColors.length))
{
Color c = tokenColors[code];
if (c == null)
{
Style s = tokenStyles[code];
c = StyleConstants.getForeground(s);
}
return c;
}
return Color.black;
}
/**
* Fetch the font to use for a lexical
* token with the given scan value.
*/
public Font getFont(int code)
{
if (tokenFonts == null)
{
tokenFonts = new Font[Token.MaximumScanValue + 1];
}
if (code < tokenFonts.length)
{
Font f = tokenFonts[code];
if (f == null)
{
Style s = tokenStyles[code];
f = getFont(s);
}
return f;
}
return null;
}
/**
* Fetches the attribute set to use for the given
* scan code. The set is stored in a table to
* facilitate relatively fast access to use in
* conjunction with the scanner.
*/
public Style getStyleForScanValue(int code)
{
if (code < tokenStyles.length)
{
return tokenStyles[code];
}
return null;
}
// --- ViewFactory methods -------------------------------------
public View create(Element elem)
{
return new SqlView(elem);
}
// --- variables -----------------------------------------------
/**
* The styles representing the actual token types.
*/
Style[] tokenStyles;
/**
* Cache of foreground colors to represent the
* various tokens.
*/
transient Color[] tokenColors;
/**
* Cache of fonts to represent the various tokens.
*/
transient Font[] tokenFonts;
/**
* View that uses the lexical information to determine the
* style characteristics of the text that it renders. This
* simply colorizes the various tokens and assumes a constant
* font family and size.
*/
class SqlView extends WrappedPlainView
{
/**
* Construct a simple colorized view of java
* text.
*/
SqlView(Element elem)
{
super(elem);
}
/**
* Renders using the given rendering surface and area
* on that surface. This is implemented to invalidate
* the lexical scanner after rendering so that the next
* request to drawUnselectedText will set a new range
* for the scanner.
*
* @param g the rendering surface to use
* @param a the allocated region to render into
*
* @see View#paint
*/
public void paint(Graphics g, Shape a)
{
Rectangle zona = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
super.paint(g, zona);
}
/**
* Renders the given range in the model as normal unselected
* text. This is implemented to paint colors based upon the
* token-to-color translations. To reduce the number of calls
* to the Graphics object, text is batched up until a color
* change is detected or the entire requested range has been
* reached.
*
* @param g the graphics context
* @param x the starting X coordinate
* @param y the starting Y coordinate
* @param p0 the beginning position in the model
* @param p1 the ending position in the model
* @returns the location of the end of the range
* @exception BadLocationException if the range is invalid
*/
protected int drawUnselectedText(Graphics g, int x, int y,
int p0, int p1) throws BadLocationException
{
Color cLiteral = new Color(0, 128, 0);
Color cTexto = Color.black;
Document doc = getDocument();
Segment stexto = new Segment();
Segment stexto2 = null;
int mark = p0;
doc.getText(p0, p1 - p0, stexto); //coge todo el texto
String cadena = stexto.toString();
char [] cadena2 = cadena.toCharArray();
int tam = cadena.length();
int ultimosep = 0;
char caracter = '\0';
boolean bencontrado = false;
Color color = null;
int ntmp = 0;
Token[] tokens = Token.all;
int ntk = tokens.length;
Token t = null;
int n2 = Token.separadores.length;
Vector separadores = new Vector(n2+2);
for (int j = 0; j < n2; j++)
separadores.addElement(Token.separadores[j].toString());
// pinta la l�nea en la que esta. Esta numeraci�n la puede realizar por que se le dar margen al documento.
//cuenta los parrafos anteriores.
int parrafo = 1,pos=0;
stexto2 = new Segment();
doc.getText(0,p0, stexto2); //coge todo el texto hasta la posicion
while(pos < stexto2.count)
if(stexto2.array[pos++] == '\n') parrafo++;
FontMetrics fm = g.getFontMetrics();
g.setColor(new Color(240,240,240)); // para el fondo
// rellenamos anchonumeracion menos dos para dejar un poco de aire entre la numeraci�n y el texto
g.fillRect(0, y-fm.getMaxAscent()-2, anchoNumeracion-5, fm.getMaxAscent() + fm.getMaxDescent() + 2); // pinta el fondo de gris
// dibujamos un l�nea divisoria
g.setColor(Color.lightGray);
g.drawLine(anchoNumeracion-5,y-fm.getMaxAscent()-2,anchoNumeracion-5,fm.getMaxAscent() + fm.getMaxDescent() + 2);
g.setColor(new Color(31,159,9)); // para la fuente
String linea = Integer.toString(parrafo);
char clinea[] = new char[50];
linea.getChars(0, linea.length(), clinea, 0);
Segment stexto3 = new Segment(clinea,0,linea.length());
int xold = x;
// el texto tiene que ir alineado a la derecha
Utilities.drawTabbedText(stexto3, (anchoNumeracion-6) - fm.stringWidth(linea), y, g, this, 0);
x = xold;
// se recorre el texto buscando separadores y comprobando las palabras
for(int i = 0;i < tam;i++)
{
caracter = cadena.charAt(i);
if(caracter == 13 || caracter == 10 || caracter == ' ' || caracter == '('
|| caracter == ')' || caracter == '=' || caracter == '*' || caracter == '.'
|| caracter == '<' || caracter == '>'|| caracter == '%' || caracter == ','
|| caracter == '\t' || caracter == ';'|| caracter == '\'' || caracter == '"'
|| caracter == '/' || caracter == '#'|| caracter == '|' || caracter == ':'
|| caracter == '&')
{
if(i != ultimosep)
{
// prepara el texto a pintar, coge desde donde se quedo hasta el car�cter encontrado
stexto2 = new Segment( cadena2, ultimosep, i - ultimosep);
bencontrado = false;
// se recorre los tokens buscado las coincidencias
for (int j = 0; j < ntk; j++)
{
t = tokens[j];
if(t.toString().equals(cadena.substring(ultimosep,i).toUpperCase()))
{
bencontrado = true;
color = t.getColor();
break;
}
}
// si la ha encontrado la pinta con su color y si no con el de por defecto
if(bencontrado)
g.setColor(color);
else
g.setColor(cTexto);
x = Utilities.drawTabbedText(stexto2, x, y, g, this, ultimosep); // he cambiado i por 0
stexto2 = null;
} // fin del if(i == ultimosep)
// si el caracter de separaci�n hay que pintarlo lo pinta
ntmp = separadores.indexOf(String.valueOf(caracter));
if(ntmp != -1)
{
stexto2 = new Segment( cadena2, i, 1);
g.setColor(Token.separadores[ntmp].getColor());
x = Utilities.drawTabbedText(stexto2, x, y, g, this, i); // he cambiado i por un 0
stexto2 = null;
}
ultimosep = i+1;
} // fin del if(caracter
} // fin del for
// dibuja lo ultimo
if(ultimosep < tam)
{
stexto2 = new Segment( cadena2, ultimosep, tam - ultimosep);
g.setColor(cTexto);
x = Utilities.drawTabbedText(stexto2, x, y, g, this, ultimosep); // he cambiado ultimosep por un 0
stexto2 = null;
}
return x;
}
protected int drawSelectedText(Graphics g, int x, int y,
int p0, int p1) throws BadLocationException
{
Color cLiteral = new Color(0, 128, 0);
Color cTexto = Color.black;
Document doc = getDocument();
Segment stexto = new Segment();
Segment stexto2 = null;
int mark = p0;
doc.getText(p0, p1 - p0, stexto); //coge todo el texto
String cadena = stexto.toString();
char [] cadena2 = cadena.toCharArray();
int tam = cadena.length();
int ultimosep = 0;
char caracter = '\0';
boolean bencontrado = false;
Color color = null;
int ntmp = 0;
Token[] tokens = Token.all;
int ntk = tokens.length;
Token t = null;
int n2 = Token.separadores.length;
Vector separadores = new Vector(n2+2);
for (int j = 0; j < n2; j++)
separadores.addElement(Token.separadores[j].toString());
// pinta la l�nea en la que esta. Esta numeraci�n la puede realizar por que se le dar margen al documento.
//cuenta los parrafos anteriores.
int parrafo = 1,pos=0;
stexto2 = new Segment();
doc.getText(0,p0, stexto2); //coge todo el texto hasta la posicion
while(pos < stexto2.count)
if(stexto2.array[pos++] == '\n') parrafo++;
FontMetrics fm = g.getFontMetrics();
g.setColor(new Color(240,240,240)); // para el fondo
// rellenamos anchonumeracion menos dos para dejar un poco de aire entre la numeraci�n y el texto
g.fillRect(0, y-fm.getMaxAscent()-2, anchoNumeracion-5, fm.getMaxAscent() + fm.getMaxDescent() + 2); // pinta el fondo de gris
// dibujamos un l�nea divisoria
g.setColor(Color.lightGray);
g.drawLine(anchoNumeracion-5,y-fm.getMaxAscent()-2,anchoNumeracion-5,fm.getMaxAscent() + fm.getMaxDescent() + 2);
g.setColor(new Color(31,159,9)); // para la fuente
String linea = Integer.toString(parrafo);
char clinea[] = new char[50];
linea.getChars(0, linea.length(), clinea, 0);
Segment stexto3 = new Segment(clinea,0,linea.length());
int xold = x;
// el texto tiene que ir alineado a la derecha
Utilities.drawTabbedText(stexto3, (anchoNumeracion-6) - fm.stringWidth(linea), y, g, this, 0);
x = xold;
// se recorre el texto buscando separadores y comprobando las palabras
for(int i = 0;i < tam;i++)
{
caracter = cadena.charAt(i);
if(caracter == 13 || caracter == 10 || caracter == ' ' || caracter == '('
|| caracter == ')' || caracter == '=' || caracter == '*' || caracter == '.'
|| caracter == '<' || caracter == '>'|| caracter == '%' || caracter == ','
|| caracter == '\t' || caracter == ';'|| caracter == '\'' || caracter == '"'
|| caracter == '/' || caracter == '#'|| caracter == '|' || caracter == ':'
|| caracter == '&')
{
if(i != ultimosep)
{
// prepara el texto a pintar, coge desde donde se quedo hasta el car�cter encontrado
stexto2 = new Segment( cadena2, ultimosep, i - ultimosep);
bencontrado = false;
// se recorre los tokens buscado las coincidencias
for (int j = 0; j < ntk; j++)
{
t = tokens[j];
if(t.toString().equals(cadena.substring(ultimosep,i).toUpperCase()))
{
bencontrado = true;
color = t.getColor();
break;
}
}
// si la ha encontrado la pinta con su color y si no con el de por defecto
if(bencontrado)
g.setColor(color);
else
g.setColor(cTexto);
x = Utilities.drawTabbedText(stexto2, x, y, g, this, ultimosep); // he cambiado i por 0
stexto2 = null;
} // fin del if(i == ultimosep)
// si el caracter de separaci�n hay que pintarlo lo pinta
ntmp = separadores.indexOf(String.valueOf(caracter));
if(ntmp != -1)
{
stexto2 = new Segment( cadena2, i, 1);
g.setColor(Token.separadores[ntmp].getColor());
x = Utilities.drawTabbedText(stexto2, x, y, g, this, i); // he cambiado i por un 0
stexto2 = null;
}
ultimosep = i+1;
} // fin del if(caracter
} // fin del for
// dibuja lo ultimo
if(ultimosep < tam)
{
stexto2 = new Segment( cadena2, ultimosep, tam - ultimosep);
g.setColor(cTexto);
x = Utilities.drawTabbedText(stexto2, x, y, g, this, ultimosep); // he cambiado ultimosep por un 0
stexto2 = null;
}
return x;
}
} // fin del class sqlview
}
}