001: package org.jsqltool.gui;
002:
003: import javax.swing.*;
004: import java.awt.*;
005: import javax.swing.event.*;
006: import javax.swing.text.*;
007: import java.util.*;
008: import java.io.Reader;
009:
010: /**
011: * <p>Title: </p>
012: * <p>Description: </p>
013: * <p>Copyright: Copyright (c) 2006</p>
014: * <p>Company: </p>
015: * @author not attributable
016: * @version 1.0
017: */
018:
019: public class TestSQLFrame extends JFrame implements DocumentListener {
020:
021: JScrollPane jScrollPane1 = new JScrollPane();
022: JScrollPane jScrollPane2 = new JScrollPane();
023: JTextPane in = new JTextPane();
024: JTextArea out = new JTextArea();
025: Thread t = new ColoredThread();
026:
027: Object lock = new Object();
028:
029: private boolean isAlive = false;
030:
031: /**
032: * <p>Description: Thread used to color the text.</p>
033: */
034: class ColoredThread extends Thread {
035:
036: public void run() {
037: // the thread never ends: it suspends until document listener interrupt it...
038: while (true) {
039: // analyze the content...
040: highlight();
041: try {
042: sleep(0xffffff);
043: } catch (InterruptedException x) {
044: }
045: }
046: }
047:
048: }
049:
050: public TestSQLFrame() {
051: try {
052: in.getDocument().addDocumentListener(this );
053: jbInit();
054: initStyles();
055:
056: setSize(800, 500);
057: setVisible(true);
058: in.requestFocus();
059: t.start();
060: } catch (Exception e) {
061: e.printStackTrace();
062: }
063: }
064:
065: public static void main(String[] args) {
066: TestSQLFrame testSQLFrame = new TestSQLFrame();
067: }
068:
069: private void jbInit() throws Exception {
070: out.setEditable(false);
071: out.setRows(5);
072: this .getContentPane().add(jScrollPane1, BorderLayout.CENTER);
073: jScrollPane1.getViewport().add(in, null);
074: this .getContentPane().add(jScrollPane2, BorderLayout.NORTH);
075: jScrollPane2.getViewport().add(out, null);
076: }
077:
078: /**
079: * Gives notification that there was an insert into the document. The
080: * range given by the DocumentEvent bounds the freshly inserted region.
081: *
082: * @param e the document event
083: */
084: public void insertUpdate(DocumentEvent e) {
085: try {
086: synchronized (lock) {
087: if (isAlive)
088: return;
089: }
090: t.interrupt();
091:
092: } catch (Exception ex) {
093: ex.printStackTrace();
094: }
095: }
096:
097: /**
098: * Gives notification that a portion of the document has been
099: * removed. The range is given in terms of what the view last
100: * saw (that is, before updating sticky positions).
101: *
102: * @param e the document event
103: */
104: public void removeUpdate(DocumentEvent e) {
105: try {
106: synchronized (lock) {
107: if (isAlive)
108: return;
109: }
110: t.interrupt();
111: } catch (Exception ex) {
112: ex.printStackTrace();
113: }
114: }
115:
116: /**
117: * Gives notification that an attribute or set of attributes changed.
118: *
119: * @param e the document event
120: */
121: public void changedUpdate(DocumentEvent e) {
122:
123: }
124:
125: /**
126: * A hash table containing the text styles.
127: * Simple attribute sets are hashed by name (String)
128: */
129: private Hashtable styles = new Hashtable();
130:
131: /**
132: * retrieve the style for the given type of text.
133: *
134: * @param styleName the label for the type of text ("tag" for example)
135: * or null if the styleName is not known.
136: * @return the style
137: */
138: private SimpleAttributeSet getStyle(String styleName) {
139: return ((SimpleAttributeSet) styles.get(styleName));
140: }
141:
142: /**
143: * Create the styles and place them in the hash table.
144: */
145: private void initStyles() {
146: SimpleAttributeSet style;
147:
148: style = new SimpleAttributeSet();
149: StyleConstants.setFontFamily(style, "Monospaced");
150: StyleConstants.setFontSize(style, 12);
151: StyleConstants.setBackground(style, Color.white);
152: StyleConstants.setForeground(style, Color.black);
153: StyleConstants.setBold(style, true);
154: StyleConstants.setItalic(style, false);
155: styles.put("text", style);
156:
157: style = new SimpleAttributeSet();
158: StyleConstants.setFontFamily(style, "Monospaced");
159: StyleConstants.setFontSize(style, 12);
160: StyleConstants.setBackground(style, Color.white);
161: StyleConstants.setForeground(style, Color.blue);
162: StyleConstants.setBold(style, false);
163: StyleConstants.setItalic(style, false);
164: styles.put("reservedWord", style);
165:
166: style = new SimpleAttributeSet();
167: StyleConstants.setFontFamily(style, "Monospaced");
168: StyleConstants.setFontSize(style, 12);
169: StyleConstants.setBackground(style, Color.white);
170: StyleConstants.setForeground(style, Color.red);
171: StyleConstants.setBold(style, false);
172: StyleConstants.setItalic(style, false);
173: styles.put("literal", style);
174:
175: style = new SimpleAttributeSet();
176: StyleConstants.setFontFamily(style, "Monospaced");
177: StyleConstants.setFontSize(style, 12);
178: StyleConstants.setBackground(style, Color.white);
179: StyleConstants.setForeground(style, Color.green.darker());
180: StyleConstants.setBold(style, false);
181: StyleConstants.setItalic(style, false);
182: styles.put("comment", style);
183:
184: }
185:
186: private void highlight() {
187: // wait for lock and change isAlive flag state...
188: synchronized (lock) {
189: isAlive = true;
190: }
191: // now document listener cannot fires events...
192:
193: try {
194: Document doc = in.getDocument();
195: String text = doc.getText(0, doc.getLength());
196: doc.remove(0, text.length());
197: doc.insertString(0, text, getStyle("text"));
198: text = text.toUpperCase();
199: int pos;
200:
201: // search for patterns...
202: String pattern = null;
203: String[] patterns = new String[] { "SELECT", "FROM",
204: "WHERE", "ORDER BY", "GROUP BY", "HAVING", "||",
205: "+", "-", "*", "/", "(+)", "IN" };
206: for (int i = 0; i < patterns.length; i++) {
207: pos = 0;
208: pattern = patterns[i];
209: while ((pos = text.indexOf(pattern, pos)) >= 0) {
210: if ((pos == 0 || pos > 0
211: && (text.charAt(pos - 1) == ' '
212: || text.charAt(pos - 1) == '\t' || text
213: .charAt(pos - 1) == '\n'))
214: && (pos + pattern.length() == text.length() || pos
215: + pattern.length() < text.length()
216: && (text.charAt(pos
217: + pattern.length()) == ' '
218: || text.charAt(pos
219: + pattern.length()) == '\t' || text
220: .charAt(pos
221: + pattern.length()) == '\n'))) {
222: in.getDocument().remove(pos, pattern.length());
223: in.getDocument().insertString(pos, pattern,
224: getStyle("reservedWord"));
225: }
226: pos += pattern.length();
227: }
228: }
229:
230: // find out literals...
231: pos = 0;
232: int endpos;
233: while ((pos = text.indexOf("'", pos)) >= 0) {
234: endpos = text.indexOf("'", pos + 1);
235: if (endpos == -1)
236: endpos = text.length() - 1;
237: in.getDocument().remove(pos, endpos - pos + 1);
238: in.getDocument().insertString(pos,
239: text.substring(pos, endpos + 1),
240: getStyle("literal"));
241: pos = endpos + 1;
242: }
243:
244: // find out comments...
245: pos = 0;
246: while ((pos = text.indexOf("//", pos)) >= 0) {
247: endpos = text.indexOf("\n", pos);
248: if (endpos == -1)
249: endpos = text.length() - 1;
250: in.getDocument().remove(pos, endpos - pos + 1);
251: in.getDocument().insertString(pos,
252: text.substring(pos, endpos + 1),
253: getStyle("comment"));
254: pos = endpos + 1;
255: }
256:
257: pos = 0;
258: while ((pos = text.indexOf("/*", pos)) >= 0) {
259: endpos = text.indexOf("*/", pos);
260: if (endpos == -1)
261: endpos = text.length() - 2;
262: in.getDocument().remove(pos, endpos - pos + 2);
263: in.getDocument().insertString(pos,
264: text.substring(pos, endpos + 2),
265: getStyle("comment"));
266: pos += endpos + 1;
267: }
268:
269: } catch (Exception e) {
270: }
271:
272: // wait for lock and change isAlive flag state...
273: synchronized (lock) {
274: isAlive = false;
275: }
276: // now document listener can fires events...
277:
278: }
279:
280: }
|