[an error occurred while processing this directive]

Page One
Page Two
The Databank
What Is Swing?
Special Report
IDE Roundup
Swing and the Web
Swing Text
Tech Topics
Friends
Tips and Tricks
The PLAF Papers
Call 911
The Archive
JFC Home
Download Swing
Swing API Docs
Download JDK
JDK Docs
Java Tutorial
 
The Swing Connection Swing Text

Customizing a Text Editor
'JavaEditorKit' Plug-in Shows How It's Done

NOTE: This article was written before the release of Swing 1.1 Beta 3 and JDKTM 1.2 RC1, a set of APIs that introduced the package names now used in Swing.

Image: Man at computerTo compile and run the example program under current versions of the JFCTM software, you must use an alternative version of the example that is contained in zipped form a downloadable jar file named javakit.zip. When you unzip the file, the sample it produces is in a jar file named javakit.jar. This newer example uses the lexical scanner that is part of the java compiler found in JDK 1.1, which you can download from the JFC Web page. (If you use the JavaTM 2 SDK or another JVM implementation, the compiler may not be included. With Java 2, the old compiler classes can be found in the tools.jar file, which must be included in your classpath when running under Java 2.)

In upcoming issues of The Swing Connection, this article will be replaced by newer articles illustrating other approaches for creating an EditorKit implementation and an editor that uses it.


This article shows how to add customized features to the ready-made text-editor kits that are supplied with Swing.

More specifically, it shows how to create a "plug-in" for JEditorPane that can handle different kinds of content are not handled by default.

To show you how to create plug-ins for Swing text-editor kits, we supply all the source files you'll need to create, compile, and execute a plug-in that adds color highlighting capabilities to a text editor.

Once you know how to do that, you can use similar techniques to provide text editors with other kinds of custom capabilities.

This article is designed to accompany a longer and more comprehensive article, titled "The Swing Text Package," that is also presented in this issue. Before you start working with the sample program we'll be presenting here, we recommend that you read "The Swing Text Package."

Once you learn the techniques outlined in this article, you can use them to add any kind of special capabilities you like to any text editor that's compatible with the Swing text API.

The major topics we'll be covering are:

Horizontal rule

Introducing the JavaEditorKit

To create the customized source-code editor demonstrated in this article, we created a customized implementation of the Swing EditorKit class and used it to add color highlighting to the Swing JEditorPane class.

The new editor kit that we created is designed for editing source code written in the Java programming language, so we've named it the JavaEditorKit.

Later in this article, you find links to the all source-code files that we used to create the JavaEditorKit. You can download the source code, study it, and modify it to create any kind of customized text editor you'd like to build.


The JEditorPane class

JEditorPane -- the foundation class for the customized editor that we'll create in this article -- separates the management of look-and-feel features from the management of document content.

By default, JEditorPane supports plain text, HTML text, and RTF text. To create the JavaEditorKit that we built for this article, we added some specialized support for text written in the JavaTM programming language.

When you learn how the JavaEditorKit example works, you know all you need to know to add just about any kind of support for new kinds of content to a Swing text editor.


A preview of the JavaEditorKit program

When you complete the JavaEditorKit example and execute it, the program displays a window like the one shown below. As you can see, the JavaEditorKit provides color text highlighting that is specially designed for use with the Java programming language.

Editor kit screen shot

Horizontal rule

Planning a strategy

When you want to customize a Swing text editor, the first thing you should do is plan a strategy for the kind of support that your new editor kit will provide. In the example that we'll present in this article, we'' provide the bare bones of what a programmer would need to edit code written in the Java programming language.

At this level, we won’t be dealing with the overall environment of an IDE; that would be, a higher-level task. Instead, we'll just create a plug-in that provides some basic services. By building on that foundation, we could easily create a higher-level environment. There are many directions we could go in, but for now, we'll keep it simple by dealing primarily with syntax highlighting.

To perform the task of syntax highlighting, it might be tempting to use the styled-text support that Swing provides. But we'll be building a source-code editor, and in terms of modeling, source code is really oriented more towards plain text than towards styled text. Furthermore, different programmers may want to view the documents using different style settings.

Also, if the syntax of a program gets too broken it can always be treated as plain text. So embedding styles in documents is not very desirable -- at least not in the kind of editor we are building.

The JavaEditorKit example extends a plain-text document, forming semi-styled views (in color) over it. To accomplish this task, we could use a model that maintains a lexical structure of the program in addition to the line-mapping services already provided by the PlainDocument class. The lexical structure provided by PlainDocument is designed primarily to provide a beautification service that is nice but not essential, so we could build and store a lexical structure on a separate lower-priority thread in such a way that it would not get in the way of any editing or text viewing. If an application opened a large document, it could be used as soon as the plain-text part Became available. This strategy would free the user from having to wait for the scanner to finish -- an operation that could take a while if the region to be "lexed" was a large one.

Alternatively, we could "lex" the region being displayed and not store any lexical information. This is the approach we have taken --because it reduces the complexity of the example and avoids storing a lot of extra information that we do not use in our JavaEditorKit example.

Horizontal rule

Implementation

As noted in the article title "The Swing Text Package," the EditorKit class is the primary mechanism for extending Swing text components. To create an EditorKit, you register it with a JEditorPane object.

When you start building a new editor kit, the first thing you need to do is create an EditorKit implementation -- which, in turn, forms the plug-in for whatever new type of content you want to support.

In the JavaEditorKit example, we create a content type named TEXT/JAVA -- and, as noted previously, we call our EditorKit implementation JavaEditorKit. So JavaEditorKit is the class name that we register with JEditorPane, and is also the class name that we use for all requests that we issue to edit Java text.

The two primary duties of the EditorKit class (beyond the duties provided by the superclass) are to hand out Java programming language documents that model the text with optional lexical information, and to produce views that display those models.

The class that we use to model text is called JavaDocument. It extends the PlainDocument class because it fundamentally deals with plain text. In the JavaEditorKit example, we add to the PlainDocument class the ability to produce lexical tokens for some given range of the document.

To produce lexical information, the JavaEditorKit example simply uses the freely available scanner found in the JDK. To feed the scanner, we implement a simple nested class DocumentInputStream to give the scanner a stream-based access to the content storage of the model. The document also provides a crude mechanism for marking multi-line comment areas so scanning can start at a reasonable location.

This mechanism would not be robust enough for use in a real-world application, but it serves well as an example. The comment marking is performed in the insertUpdate method, which gives the document an opportunity to update its structure after an insertion takes place. Because the insertUpdate method occurs under the protection of a write lock, attributes can be freely modified.

One other fundamental class is used in the JavaEditorKit example: a view object that highlights in color the various tokens used in the Java programming language.

The view object used in JavaEditorKit is an implementation of the View class. The Swing text package provides a PlainView class that can be used to represent a PlainDocument. In the JavaEditorKit example, we extend PlainDocument's rendering methods to take into account the lexical structure of the document.

JavaEditorKit produces views for Swing text using an implementation of the ViewFactory interface. This interface is implemented by the JavaContext class to produce a nested class JavaView. The rendering method uses the scan codes of the lexical tokens to reference into a lookup table for the color to use for the token. Making the JavaView class a nested class ensures it easy access to the style information it will use for it’s rendering operations.

To manage styles conveniently, the JavaContext class extends the StyleContext class, mapping a policy over the set of styles contained. The JavaEditorKit provides a pair of methods to set and get the JavaContext to use for building the views. This capabilities enables the developer to use serialization for saving and restoring the settings, and to have this set of settings shared for all of the views produced by it.

The names of the styles are based upon the categories of lexical tokens and actual lexical token names. This convention allows attributes to be set for different categories of tokens, and allows specific settings for particular tokens. In other words, you can use it to build an independent customization interface to configure the EditorKit. To perform this class properly, one would create a BeanInfo class for the appropriate Bean and name the customization class. Those kinds of operations are beyond the scope of this particular article, but may be examined in more detail in a future article in The Swing Connection.

The JavaContext can also serve other purposes. For example, you can use it to produce a styled document. In that case, you could export the styled views (using style preferences specified in the JavaContext) into other formats such as HTML and RTF.

The Token class represents the various possible token types that can be produced by the lexical process. These are implemented as the set of possible scan codes produced by the freely available scanner in the JDK, along with a couple of additional values. The Token class wraps up set of possible tokens as objects so that additional things can be done with them -- for example, to make the lexical information more useful. This feature makes tokens easier to manage when styles are being set up, and allows them to be used as attributes.

Horizontal rule

Using the JavaEditorKit Example

These are the source files that implement the JavaEditorKit application. Just click on their links to download them:

Source code iconWhen you have compiled the application, you can execute it using a helper program named JavaKitTest, which you can download by clicking this link.

The JavaKitTest program creates a JEditorPane component and installs the JavaEditorKit into it. The component is then used to load a file named as an argument to the method EditorKitTest.main(). The example plugs some values into the JavaContext to illustrate color highlighting.

-- Tim Prinzing

[an error occurred while processing this directive]