"Components, and Creating a Custom Property Editor,"
Volume: 4 Issue: 11, p. 32

Listing 1:

package CodeEditor;

import com.sun.java.swing.*;
import com.sun.java.swing.text.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class CodeTextPane extends JTextPane implements Serializable{
public CodeTextPane() {

}

void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
}

void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
}

public void setKeywords(Vector aNewSetOfKeywords) {
Document doc = getDocument();
if (doc instanceof CodeDocument) {
CodeDocument codeDoc = (CodeDocument) doc;
codeDoc.setKeywords(aNewSetOfKeywords);
}
}

public void setKeywords(String aNewSetOfKeywords[]){
Vector v = new Vector();
for (int i=0;i< aNewSetOfKeywords.length;i++){
v.addElement(aNewSetOfKeywords[i]);
}
setKeywords(v);
}

public Vector getKeywords() {
Vector keywords = null;

Document doc = getDocument();
if (doc instanceof CodeDocument) {
CodeDocument codeDoc = (CodeDocument) doc;
keywords = codeDoc.getKeywords();
}

return keywords;
}

}

Listing 2:

//Title: Your Product Name
//Version:
//Copyright: Copyright (c) 1998
//Author: Your Name
//Company: Your Company
//Description: Your description

package CodeEditor;

import java.beans.*;

public class CodeTextPaneBeanInfo extends SimpleBeanInfo {
Class beanClass = CodeTextPane.class;
String iconColor16x16Filename;
String iconColor32x32Filename;
String iconMono16x16Filename;
String iconMono32x32Filename;

public CodeTextPaneBeanInfo() {
}

public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor _keywords = new PropertyDescriptor("keywords", beanClass, "getKeywords", "setKeywords");
_keywords.setDisplayName("keywords");
_keywords.setShortDescription("keywords");
_keywords.setPropertyEditorClass(CodeEditor.KeywordsEditor.class);

PropertyDescriptor[] pds = new PropertyDescriptor[] {
_keywords,
};
return pds;
}
catch (IntrospectionException ex) {
ex.printStackTrace();
return null;
}
}

public java.awt.Image getIcon(int iconKind) {
switch (iconKind) {
case BeanInfo.ICON_COLOR_16x16:
return iconColor16x16Filename != null ? loadImage(iconColor16x16Filename) : null;
case BeanInfo.ICON_COLOR_32x32:
return iconColor32x32Filename != null ? loadImage(iconColor32x32Filename) : null;
case BeanInfo.ICON_MONO_16x16:
return iconMono16x16Filename != null ? loadImage(iconMono16x16Filename) : null;
case BeanInfo.ICON_MONO_32x32:
return iconMono32x32Filename != null ? loadImage(iconMono32x32Filename) : null;
}
return null;
}

public BeanInfo[] getAdditionalBeanInfo() {
Class superclass = beanClass.getSuperclass();
try {
BeanInfo superBeanInfo = Introspector.getBeanInfo(superclass);
return new BeanInfo[] { superBeanInfo };
}
catch (IntrospectionException ex) {
ex.printStackTrace();
return null;
}
}
}

Listing 3:

//Title: Your Product Name
//Version:
//Copyright: Copyright (c) 1998
//Author: Your Name
//Company: Your Company
//Description: Your description

package CodeEditor;

import java.awt.*;
import java.beans.*;
import java.util.*;

public class KeywordsEditor extends PropertyEditorSupport {
private KeywordsEditorComponent editor;

public KeywordsEditor() {
}

public boolean supportsCustomEditor() {
return true;
}

public Component getCustomEditor() {
if (editor == null) {
editor = new KeywordsEditorComponent(this);
}
return editor;
}

public String getJavaInitializationString() {
//TODO: Implement this for your property type
Vector v = (Vector)getValue();
String s = "new String[] {";
Enumeration enum = v.elements();
while (enum.hasMoreElements()){
String keyword = (String)enum.nextElement();
if ( enum.hasMoreElements() ){
s += "\"" + keyword + "\",";
}
else{
s += "\"" + keyword + "\"}";
}
}
return s;
}
}

Listing 4:
//Title: Your Product Name
//Version:
//Copyright: Copyright (c) 1998
//Author: Your Name
//Company: Your Company
//Description: Your description

package CodeEditor;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;
import java.util.*;

public class KeywordsEditorComponent extends Panel{
private PropertyEditor editor;
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
DefaultListModel keywords = new DefaultListModel();
JList keywordList = new JList(keywords);
JTextField keywordEdit = new JTextField();
JButton addBtn = new JButton();
JButton deleteBtn = new JButton();
JScrollPane listScroller = new JScrollPane(keywordList);

private void initEditor(){
addBtn.setText("Add to keywords list");
addBtn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
addBtn_actionPerformed(e);
}
});

deleteBtn.setText("Delete item from list");
deleteBtn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
deleteBtn_actionPerformed(e);
}
});

label1.setText("Keywords List");
label2.setText("Keyword: ");

keywordEdit.setText("");
keywordEdit.setPreferredSize(new Dimension(80, 25));

listScroller.setPreferredSize(new Dimension(150, 200));

if (editor != null){
keywords.removeAllElements();
Vector v = (Vector)editor.getValue();
Enumeration enum = v.elements();
while (enum.hasMoreElements()){
keywords.addElement(enum.nextElement());
}
}
keywords.addListDataListener(new ListDataListener(){
public void contentsChanged(ListDataEvent e){
keywords_changed(e);
}
public void intervalAdded(ListDataEvent e){
keywords_changed(e);
}

public void intervalRemoved(ListDataEvent e){
keywords_changed(e);
}
});

//set the layout manager
GridBagLayout gb = new GridBagLayout();
this.setLayout(gb);
GridBagConstraints gridConst = new GridBagConstraints();
gridConst.gridx = 0;
gridConst.gridy = 0;
gridConst.gridheight = 1;
gridConst.gridwidth = 1;
gridConst.anchor = GridBagConstraints.NORTHWEST;
gb.setConstraints(label1,gridConst);
this.add(label1);

gridConst = new GridBagConstraints();
gridConst.gridx = 0;
gridConst.gridy = 1;
gridConst.gridheight = 3;
gridConst.gridwidth = 2;
gridConst.anchor = GridBagConstraints.NORTHWEST;
gb.setConstraints(listScroller,gridConst);
this.add(listScroller);

gridConst = new GridBagConstraints();
gridConst.gridx = 2;
gridConst.gridy = 0;
gridConst.gridheight = 1;
gridConst.gridwidth = 1;
gridConst.anchor = GridBagConstraints.NORTHEAST;
gb.setConstraints(label2,gridConst);
this.add(label2);

gridConst = new GridBagConstraints();
gridConst.gridx = 1;
gridConst.gridy = 1;
gridConst.gridheight = 1;
gridConst.gridwidth = 2;
gridConst.anchor = GridBagConstraints.NORTHEAST;
gb.setConstraints(keywordEdit,gridConst);
this.add(keywordEdit);

gridConst = new GridBagConstraints();
gridConst.gridx = 2;
gridConst.gridy = 3;
gridConst.gridheight = 1;
gridConst.gridwidth = 1;
gridConst.anchor = GridBagConstraints.SOUTHEAST;
gb.setConstraints(addBtn,gridConst);
this.add(addBtn);

gridConst = new GridBagConstraints();
gridConst.gridx = 2;
gridConst.gridy = 4;
gridConst.gridheight = 1;
gridConst.gridwidth = 1;
gridConst.anchor = GridBagConstraints.SOUTHEAST;
gb.setConstraints(deleteBtn,gridConst);
this.add(deleteBtn);
}

public KeywordsEditorComponent(PropertyEditor editor) {
this.editor = editor;
initEditor();
}

private void addBtn_actionPerformed(ActionEvent e) {
keywords.addElement(keywordEdit.getText());
}

private void deleteBtn_actionPerformed(ActionEvent e) {
Object selectedObj = this.keywordList.getSelectedValue();
if (selectedObj != null){
keywords.remove(keywordList.getSelectedIndex());
}
}

private void keywords_changed(ListDataEvent e){
if (editor != null){
Vector v = new Vector();
Enumeration enum = keywords.elements();
while (enum.hasMoreElements()){
v.addElement(enum.nextElement());
}
editor.setValue(v);
}
}

}

Listing 5:
package CodeEditor;

public class ClassElement {
private String displayValue = "";
private String elementValue = "";
public ClassElement() {
}

public ClassElement(String displayText, String elementText) {
elementValue = elementText;
displayValue = displayText;
}

public String getDisplayValue(){
return displayValue;
}

public String getElementValue(){
return elementValue;
}

public void setElementValue(String aValue){
this.elementValue = aValue;
}

public void setDisplayValue(String aValue){
this.displayValue = aValue;
}

public String toString(){
return displayValue;
}
}

Listing 6
package CodeEditor;
import java.util.*;
import java.lang.reflect.*;

public class ClassLister {
private String currentClassName = "";
private Class currentClass = null;
private Vector knownPackages = null;

public ClassLister(){
currentClassName = "";
knownPackages = new Vector();
knownPackages.addElement("java.lang.");
}

public ClassLister(String aClassName) {
currentClassName = aClassName;
knownPackages = new Vector();
knownPackages.addElement("java.lang.");
}

public ClassLister(String aClassName, Vector aPackageList) {
currentClassName = aClassName;
if (knownPackages == null){
knownPackages = aPackageList;
}
else{
Enumeration enum = aPackageList.elements();
while (enum.hasMoreElements()){
String aPackage = (String)enum.nextElement();
knownPackages.addElement(aPackage);
}
}
}

public void setClassName(String aClassName){
this.currentClassName = aClassName;
}

public String getClassName(){
return this.currentClassName;
}

public boolean isNameAClass(String aClassName){
Enumeration packages = knownPackages.elements();
Class aClass = null;
String fullClassName = "";
boolean result = false;
while (packages.hasMoreElements()){
try{
fullClassName = (String)packages.nextElement() + aClassName;
aClass = Class.forName(fullClassName);
result = true;//if we get here then the class was successfully found - find first matching class name
break;
}
catch (Exception ex){
//ex.printStackTrace();
System.out.println("no class");
result = false;
}
}
return result;
}

public void addPackage(String aPackage){
String s = aPackage.trim();
if (s.charAt(s.length() - 1) == '*'){
aPackage = s.substring(0, s.length() - 1);
s = aPackage;
System.out.println(s);
}
if (this.knownPackages.contains(s)){return;}
this.knownPackages.addElement(s);
}

public String listMethodArgs(String aMethod) throws ClassNotFoundException{
String result = "";
currentClass = null;
try{
currentClass = Class.forName(currentClassName);

}
catch (ClassNotFoundException noClassEx){
boolean notFound = true;
if (knownPackages == null){
throw noClassEx;
}
Enumeration packages = knownPackages.elements();

String fullClassName = "";
while (packages.hasMoreElements()){
try{
fullClassName = (String)packages.nextElement() + currentClassName;
currentClass = Class.forName(fullClassName);
break;//if we get here then the class was successfully found - find first matching class name
}
catch (ClassNotFoundException ex){
//ex.printStackTrace();
System.out.println("no class");
}
}
//noClassEx.printStackTrace();
}
catch (Exception ex){
//ex.printStackTrace();
System.out.println("Whoops");
}

if (currentClass == null) {
throw new ClassNotFoundException();
}
Method foundMethod = null;
Method[] methods = currentClass.getDeclaredMethods();
for (int i=0;i<methods.length;i++){
Method m = methods[i];
if (m.getName().equalsIgnoreCase(aMethod)){
foundMethod = m;
break;
}
}
if (foundMethod != null){
Class[] args = foundMethod.getParameterTypes();
for (int i=0;i<args.length;i++){
Class arg = args[i];
result += arg.getName() + " argument" + String.valueOf(i)+ " ";
/*e = new ClassElement("Method " + aMethod.getName() + " : " +
aMethod.getReturnType().getName(),
aMethod.getName());
results.addElement(e);*/
}
}
return result;
}
public Vector listMethods() throws ClassNotFoundException{
Vector results = new Vector();
currentClass = null;
try{
currentClass = Class.forName(currentClassName);

}
catch (ClassNotFoundException noClassEx){
boolean notFound = true;
if (knownPackages == null){
throw noClassEx;
}
Enumeration packages = knownPackages.elements();

String fullClassName = "";
while (packages.hasMoreElements()){
try{
fullClassName = (String)packages.nextElement() + currentClassName;
currentClass = Class.forName(fullClassName);
break;//if we get here then the class was successfully found - find first matching class name
}
catch (ClassNotFoundException ex){
//ex.printStackTrace();
System.out.println("no class");
}
}
//noClassEx.printStackTrace();
}
catch (Exception ex){
//ex.printStackTrace();
System.out.println("Whoops");
}

if (currentClass == null) {
throw new ClassNotFoundException();
}

Method[] methodList = currentClass.getDeclaredMethods();
ClassElement e = null;
for (int i =0; i < methodList.length; i++){
Method aMethod = methodList[i];
e = new ClassElement("Method " + aMethod.getName() + " : " +
aMethod.getReturnType().getName(),
aMethod.getName());
results.addElement(e);
}

return results;
}

public Vector listAll() throws ClassNotFoundException{
Vector results = new Vector();
currentClass = null;
try{
currentClass = Class.forName(currentClassName);

}
catch (ClassNotFoundException noClassEx){
boolean notFound = true;
if (knownPackages == null){
throw noClassEx;
}
Enumeration packages = knownPackages.elements();

String fullClassName = "";
while (packages.hasMoreElements()){
try{
fullClassName = (String)packages.nextElement() + currentClassName;
currentClass = Class.forName(fullClassName);
break;//if we get here then the class was successfully found - find first matching class name
}
catch (ClassNotFoundException ex){
//ex.printStackTrace();
System.out.println("no class");
}
}
//noClassEx.printStackTrace();
}
catch (Exception ex){
//ex.printStackTrace();
System.out.println("Whoops");
}

if (currentClass == null) {
throw new ClassNotFoundException();
}

Method[] methodList = currentClass.getDeclaredMethods();
ClassElement e = null;
for (int i =0; i < methodList.length; i++){
Method aMethod = methodList[i];
e = new ClassElement("Method " + aMethod.getName() + " : " +
aMethod.getReturnType().getName(),
aMethod.getName());
results.addElement(e);
}

Field[] fieldList = currentClass.getDeclaredFields();
for (int i =0; i < fieldList.length; i++){
Field aField = fieldList[i];
e = new ClassElement("Member " + aField.getName() + " : " +
aField.getClass().getName(),
aField.getName());
results.addElement(e);
}

return results;
}
}

Listing 7

package CodeEditor;
import java.util.*;

public class CodeClass {
public Vector attributes = new Vector(); //list of CodeAttribute
public Vector methods = new Vector(); //list of CodeMethod
public Vector constructors = new Vector(); //list of CodeConstructor
public String className = "";
public String superClass = "";
public Vector interfaces = new Vector(); //list of strings
public String scope = "public";

public CodeClass() {

}

}

Listing 8:
package CodeEditor;

import com.sun.java.swing.*;
import com.sun.java.swing.text.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;

public class CodeDocument extends DefaultStyledDocument implements ActionListener{
//////////////////////////////////////
//these are for the States
///////////////////////////////////////
private static final int STATE_TEXT_INPUT = 10;
private static final int STATE_CLASS_INPUT = 11;
private static final int STATE_VARIABLE_INPUT = 12;
private static final int STATE_PACKAGE_INPUT = 13;
private static final int STATE_IMPORT_INPUT = 14;
private static final int STATE_VARIABLE_TYPE_INPUT = 15;

private static final boolean DEBUG = true; //turns off the diagnostic System.out statements

//class reflection stuff
private ClassLister classLister = new ClassLister();
private Hashtable codeElements = new Hashtable();
private String currentClassName = "";
private String currentTypeName = "";
private Class currentClass = null;
private int currentState = STATE_TEXT_INPUT;
private CodePackage thePackage = new CodePackage();
private Vector methodListeners = new Vector();
private String currentMethod = "";
private String currentKeyWord = "";
private String oldKeyWord = "";
private int listOffs = 0;
private boolean codeReflectionOn = true;
//syntax stuff here
private String word = "";
private SimpleAttributeSet bold = new SimpleAttributeSet();
private SimpleAttributeSet string = new SimpleAttributeSet();
private SimpleAttributeSet normal = new SimpleAttributeSet();
private SimpleAttributeSet number = new SimpleAttributeSet();
private SimpleAttributeSet comments = new SimpleAttributeSet();

private int currentPos = 0;
private Vector keywords = new Vector();
public static int STRING_MODE = 10;
public static int TEXT_MODE = 11;
public static int NUMBER_MODE = 12;
public static int COMMENT_MODE = 13;
private int mode = TEXT_MODE;

public CodeDocument() {
//set the bold attribute
StyleConstants.setBold(bold, true);
StyleConstants.setForeground(string, Color.red);
StyleConstants.setForeground(number, Color.magenta);
StyleConstants.setForeground(comments, Color.blue);
StyleConstants.setItalic(comments, true);
}

//reflection methods
/**
*/
private void checkState(){
switch (this.currentState){
case (this.STATE_CLASS_INPUT):{
this.thePackage.outerClass.className = word;
if (DEBUG) {
System.out.println("Class is " + thePackage.outerClass.className);
}
}
break;
case (this.STATE_IMPORT_INPUT):{
if (DEBUG) {
System.out.println(word);
}
this.thePackage.imports.addElement(word);
classLister.addPackage(word);
}
break;
case (this.STATE_PACKAGE_INPUT):{
if (DEBUG) {
System.out.println(word);
}
this.thePackage.packageName = word;
}
break;
case (this.STATE_TEXT_INPUT):{
if (DEBUG) {
System.out.println(word);
}
}
break;
case (this.STATE_VARIABLE_INPUT):{
if (DEBUG) {
System.out.println("Variable: " + word);
System.out.println("Variable Type: " + currentTypeName);
}
}
break;
case (this.STATE_VARIABLE_TYPE_INPUT):{
if (DEBUG) {
System.out.println("Current variable type: " + word);
}
currentTypeName = word;
}
break;
}//end of switch
}

/**
This method checks for a possible state change
*/
private void changeState(){
String s = word.trim();
if (s.equalsIgnoreCase("package")){
//package state
this.currentState = this.STATE_PACKAGE_INPUT;
}
else if (s.equalsIgnoreCase("import")){
this.currentState = this.STATE_IMPORT_INPUT;
}
else if (s.equalsIgnoreCase("class")){
this.currentState = this.STATE_CLASS_INPUT;
this.thePackage.outerClass.scope = this.oldKeyWord;
}
else if (this.currentState != this.STATE_VARIABLE_TYPE_INPUT){
String tmp = word.trim();
if (tmp == ""){
return;
}
if (classLister.isNameAClass(word)){
this.currentState = this.STATE_VARIABLE_INPUT;
this.currentTypeName = word;
}
else{
this.currentTypeName = "";
}
if (DEBUG) {
System.out.println("Current variable type: " + currentTypeName);
}
}
else if ((this.currentState == this.STATE_VARIABLE_TYPE_INPUT) &&
(this.currentTypeName != "")){
this.currentState = this.STATE_VARIABLE_INPUT;
}

if (this.DEBUG){
stateOut();
}
}

/**
*/
private void handleDot(){
SimpleAttributeSet inputAttributes = new SimpleAttributeSet();
classLister.setClassName(this.currentTypeName);
try{
Vector listing = classLister.listAll();
JComboBox c = new JComboBox(listing);
c.addActionListener(this);

StyleConstants.setComponent(inputAttributes, c);

super.insertString(currentPos + 1, " ", inputAttributes);
}
catch (Exception ex){
ex.printStackTrace();
}
}

/**
*/
public void handleOpenParen(){
classLister.setClassName(this.currentTypeName);
try{
String args = classLister.listMethodArgs(currentMethod);
ActionEvent ev = new ActionEvent(this, 0, args);
this.fireMethodEvent(ev);
}
catch (Exception ex){
ex.printStackTrace();
}
}

/**
*/
private void checkForStateChange(char chr){
switch (chr){
case ' ': case '\n':{
checkState();
changeState();
}
break;
case ('.'):{
int oldOffs = currentPos;
if ((this.currentState == this.STATE_VARIABLE_INPUT) |
(this.currentState == this.STATE_VARIABLE_TYPE_INPUT)){
checkState();
handleDot();
}
listOffs = oldOffs + 1;
if (this.DEBUG){
stateOut();
}
}
break;
case ('('):{
int oldOffs = currentPos;
if ((this.currentState == this.STATE_VARIABLE_INPUT) |
(this.currentState == this.STATE_VARIABLE_TYPE_INPUT)){
checkState();
handleOpenParen();
}
listOffs = oldOffs + 1;
if (this.DEBUG){
stateOut();
}
}
case (';'):case ('{'):{
oldKeyWord = currentKeyWord;
checkState();
this.currentState = this.STATE_TEXT_INPUT;
if (this.DEBUG){
stateOut();
}
}
}// end switch
}

/**
*/
private void stateOut(){
String s = "";
switch (this.currentState){
case (this.STATE_CLASS_INPUT):{
s = "STATE_CLASS_INPUT";
}
break;
case (this.STATE_IMPORT_INPUT):{
s = "STATE_IMPORT_INPUT";
}
break;
case (this.STATE_PACKAGE_INPUT):{
s = "STATE_PACKAGE_INPUT";
}
break;
case (this.STATE_TEXT_INPUT):{
s = "STATE_TEXT_INPUT";
}
break;
case (this.STATE_VARIABLE_INPUT):{
s = "STATE_VARIABLE_INPUT";
}
break;
case (this.STATE_VARIABLE_TYPE_INPUT):{
s = "STATE_VARIABLE_TYPE_INPUT";
}
break;
}
System.out.println(s);
}

//////////////////////////////////////////////////////////////////////////////
//events
//////////////////////////////////////////////////////////////////////////////
/**
*/
public void actionPerformed(ActionEvent e) {
//TODO: implement this java.awt.event.ActionListener method;

try{
JComboBox comp = (JComboBox)e.getSource();
ClassElement elem = (ClassElement) comp.getSelectedItem();
String item = elem.getElementValue();
this.remove(listOffs, 1);
super.insertString(listOffs, item, null);
currentMethod = item;
}
catch (Exception ex){
ex.printStackTrace();
}
}

//////////////////////////////////////////////////////////////////////////////
//Event notification
//////////////////////////////////////////////////////////////////////////////
/**
*/
public void fireMethodEvent(ActionEvent ev){
Enumeration e = methodListeners.elements();
while(e.hasMoreElements()){
MethodListener listener = (MethodListener)e.nextElement();
listener.methodAction(ev);
}
}

//////////////////////////////////////////////////////////////////////////////
//Event registration
//////////////////////////////////////////////////////////////////////////////
/**
*/
public void addMethodListener(MethodListener listener){
methodListeners.addElement(listener);
}

////////////////////////////////////////////////////////////////////////////
//syntax methods
////////////////////////////////////////////////////////////////////////////
private void insertKeyword(String str, int pos){
try{
//remove the old word and formatting
this.remove(pos - str.length(), str.length());
/*replace it with the same word, but new formatting
*we MUST call the super class insertString method here, otherwise we
*would end up in an infinite loop !!!!!*/
super.insertString(pos - str.length(), str, bold);
}
catch (Exception ex){
ex.printStackTrace();
}
}

private void insertTextString(String str, int pos){
try{
//remove the old word and formatting
this.remove(pos,str.length());
super.insertString(pos, str, string);
}
catch (Exception ex){
ex.printStackTrace();
}
}

private void insertNumberString(String str, int pos){
try{
//remove the old word and formatting
this.remove(pos,str.length());
super.insertString(pos, str, number);
}
catch (Exception ex){
ex.printStackTrace();
}
}

private void insertCommentString(String str, int pos){
try{
//remove the old word and formatting
this.remove(pos,str.length());
super.insertString(pos, str, comments);
}
catch (Exception ex){
ex.printStackTrace();
}
}

private void checkForString(){
int offs = this.currentPos;
Element element = this.getParagraphElement(offs);
String elementText = "";
try{
//this gets our chuck of current text for the element we're on
elementText = this.getText(element.getStartOffset(),
element.getEndOffset() - element.getStartOffset());
}
catch(Exception ex){
//whoops!
System.out.println("no text");
}
int strLen = elementText.length();
if (strLen == 0) {return;}
int i = 0;

if (element.getStartOffset() > 0){
//translates backward if neccessary
offs = offs - element.getStartOffset();
}
int quoteCount = 0;
if ((offs >= 0) && (offs <= strLen-1)){
i = offs;
while (i >0){
//the while loop walks back until we hit a delimiter

char charAt = elementText.charAt(i);
if ((charAt == '"')){
quoteCount ++;
}
i--;
}
int rem = quoteCount % 2;
//System.out.println(rem);
mode = (rem == 0) ? TEXT_MODE: STRING_MODE;
}
}

private void checkForKeyword(){
if (mode != TEXT_MODE) {
return;
}
int offs = this.currentPos;
Element element = this.getParagraphElement(offs);
String elementText = "";
try{
//this gets our chuck of current text for the element we're on
elementText = this.getText(element.getStartOffset(), element.getEndOffset() - element.getStartOffset());
}
catch(Exception ex){
//whoops!
System.out.println("no text");
}
int strLen = elementText.length();
if (strLen == 0) {return;}
int i = 0;

if (element.getStartOffset() > 0){
//translates backward if neccessary
offs = offs - element.getStartOffset();
}
if ((offs >= 0) && (offs <= strLen-1)){
i = offs;
while (i >0){
//the while loop walks back until we hit a delimiter
i--;
char charAt = elementText.charAt(i);
if ((charAt == ' ') | (i == 0) | (charAt =='(') | (charAt ==')') |
(charAt == '{') | (charAt == '}')){ //if i == 0 then we're at the begininng
if(i != 0){
i++;
}
word = elementText.substring(i, offs);//skip the period

String s = word.trim().toLowerCase();
//this is what actually checks for a matching keyword
if (keywords.contains(s)){
insertKeyword(word, currentPos);
}
break;
}
}
}
}

private void checkForNumber(){
int offs = this.currentPos;
Element element = this.getParagraphElement(offs);
String elementText = "";
try{
//this gets our chuck of current text for the element we're on
elementText = this.getText(element.getStartOffset(),
element.getEndOffset() - element.getStartOffset());
}
catch(Exception ex){
//whoops!
System.out.println("no text");
}
int strLen = elementText.length();
if (strLen == 0) {return;}
int i = 0;

if (element.getStartOffset() > 0){
//translates backward if neccessary
offs = offs - element.getStartOffset();
}
mode = TEXT_MODE;
if ((offs >= 0) && (offs <= strLen-1)){
i = offs;
while (i >0){
//the while loop walks back until we hit a delimiter
char charAt = elementText.charAt(i);
if ((charAt == ' ') | (i == 0) | (charAt =='(') | (charAt ==')') |
(charAt == '{') | (charAt == '}')){ //if i == 0 then we're at the begininng
if(i != 0){
i++;
}
mode = NUMBER_MODE;
break;
}
else if (!(charAt >= '0' & charAt <= '9' | charAt=='.'
| charAt=='+' | charAt=='-'
| charAt=='/' | charAt=='*'| charAt=='%' | charAt=='=')){
mode = TEXT_MODE;
break;
}
i--;
}
}
}

private void checkForComment(){
int offs = this.currentPos;
Element element = this.getParagraphElement(offs);
String elementText = "";
try{
//this gets our chuck of current text for the element we're on
elementText = this.getText(element.getStartOffset(), element.getEndOffset() - element.getStartOffset());
}
catch(Exception ex){
//whoops!
System.out.println("no text");
}
int strLen = elementText.length();
if (strLen == 0) {return;}
int i = 0;

if (element.getStartOffset() > 0){
//translates backward if neccessary
offs = offs - element.getStartOffset();
}
if ((offs >= 1) && (offs <= strLen-1)){
i = offs;
char commentStartChar1 = elementText.charAt(i-1);
char commentStartChar2 = elementText.charAt(i);
if (commentStartChar1 == '/' && commentStartChar2 == '*'){
mode = COMMENT_MODE;
this.insertCommentString("/*", currentPos-1);
}
else if (commentStartChar1 == '*' && commentStartChar2 == '/'){
mode = TEXT_MODE;
this.insertCommentString("*/", currentPos-1);
}
}
}

private void processChar(String str){
char strChar = str.charAt(0);
if (mode != this.COMMENT_MODE){
mode = TEXT_MODE;
}
switch (strChar){
case ('{'):case ('}'):case (' '): case('\n'):
case ('('):case (')'):case (';'):case ('.'):{
checkForKeyword();
if (mode == STRING_MODE && strChar == '\n'){
mode = TEXT_MODE;
}
if (codeReflectionOn){
checkForStateChange(strChar);
}
}
break;
case ('"'):{
insertTextString(str, currentPos);
this.checkForString();
}
break;
case ('0'):case ('1'):case ('2'):case ('3'):case ('4'):
case ('5'):case ('6'):case ('7'):case ('8'):case ('9'):{
checkForNumber();
}
break;
case ('*'):case ('/'):{
checkForComment();
}
break;
}
if (mode == this.TEXT_MODE){
this.checkForString();
}
if (mode == this.STRING_MODE){
insertTextString(str, this.currentPos);
}
else if (mode == this.NUMBER_MODE){
insertNumberString(str, this.currentPos);
}
else if (mode == this.COMMENT_MODE){
insertCommentString(str, this.currentPos);
}

}

private void processChar(char strChar){
char[] chrstr = new char[1];
chrstr[0] = strChar;
String str = new String(chrstr);
processChar(str);
}

public void insertString(int offs,
String str,
AttributeSet a) throws BadLocationException{
super.insertString(offs, str, normal);

int strLen = str.length();
int endpos = offs + strLen;
int strpos;
codeReflectionOn = strLen == 1;
for (int i=offs;i<endpos;i++){
currentPos = i;
strpos = i - offs;
processChar(str.charAt(strpos));
}
currentPos = offs;
}

public Vector getKeywords(){
return this.keywords;
}

public void setKeywords(Vector aKeywordList){
if (aKeywordList != null){
this.keywords = aKeywordList;
}
}
}

Listing 9:

package CodeEditor;
import java.util.*;

public class CodePackage {
public String packageName = "";
public Vector imports = new Vector();
public CodeClass outerClass = new CodeClass();
public Vector innerClasses = new Vector();
public CodePackage() {
}
}

Listing 10:
package CodeEditor;
import java.awt.event.*;

public interface MethodListener {
public void methodAction(ActionEvent e);

}