Javadoc

Please see the Javadoc for further details; of greatest interest will be the documentation for NbDocument.

Contents

Editor API

This document describes the NetBeans Editor API, attempting to give a summary of what you need to know about it for different purposes.

The Open APIs only cover certain aspects of working with the editor. For example, you can open documents, modify them, add annotations, register editor kits you built from scratch, and so on. Some more specific capabilities that are frequently requested are not guaranteed by the Open APIs but may be possible using NetBeans modules which may have differing standards of API design, documentation, and compatibility from release to release. Here are some resources that may also be of interest:

Overview

The Editor API may be used at a first cut for two purposes: accessing editor-related functionality from within NetBeans for use by other modules; and implementing a custom editor that can be inserted into NetBeans as a module, replacing or supplementing the NetBeans-supplied one.

Typical use scenario

Here is an example sequence of events describing how an editor is used with Java source code and cooperates with the Form Editor.

Accessing an Open Document

Starting from other APIs, it is not difficult to make use of the Editor API to get access to an editor window displaying a particular file.

Getting the document object for a data object

Here is an example of how to find a file by name stored in some filesystem in the Repository; get its data object (assuming you do not already have its data object, or a node representing the data object); and get the Swing document to edit it, opening a new Editor window with that document if necessary. Naturally this example is somewhat long, because it demonstrates how to do all of this from scratch. Also, exception handling is not illustrated here.
File f = new File("/home/me/sources/my/pkg/MyFile.java");
FileObject fo = FileUtil.fromFile(f)[0];
DataObject d = DataObject.find(fo);
EditorCookie ec = (EditorCookie)d.getCookie(EditorCookie.class);
ec.open();
StyledDocument doc = ec.openDocument();

Common operations on resulting document

You can check such things as whether or not the file is modified in the Editor:
if (ec.isModified()) ...
Then see what the current contents of line 26 are (zero-based):
int start=NbDocument.findLineOffset(doc, 25);
int end=NbDocument.findLineOffset(doc, 26);
String contents=doc.getText(start, end-start);
And display this line in the Editor window:
ec.getLineSet().getCurrent(25).show(Line.SHOW_TRY_SHOW);
Now insert a new line here after it:
final BadLocationException[] exc = new BadLocationException[] {null};
NbDocument.runAtomicAsUser(doc, new Runnable() {
    public void run() {
        try {
            doc.insertString(NbDocument.findLineOffset(doc, 26),
                             "// New text.\n",
                             SimpleAttributeSet.EMPTY);
        } catch (BadLocationException e) {
            exc[0] = e;
        }
    }
});
if (exc[0] != null) throw exc[0];
All done! Prompt to save the file, and close the editor window:
ec.close();

Advanced Editor Automation

For advanced modules on a level with the Form Editor or the Compiler and Debugger, it is necessary to take more complete control over the actions and content of an editor.

Using guard blocks

Manipulating guarded blocks should not be very difficult, if your application requires it. They are used by the FormEditor, but any module which needs to prevent the user from editing certain portions of a text document (typically because they will be mechanically recreated by other means), can do so.

Using annotations

In order to provide richer interactions between the editor and other modules, the APIs provide for a system of annotations which are used for things like debugger breakpoints, erroneous lines, and so on. From an API perspective, anyone can create annotations and attach them to a document; the editor implementation should attempt to display these annotations as it sees fit, taking hints from the annotation provider.

Using annotations on a document need not be difficult. Everything you need to do is to define the visual appearance of your annotation and to provide a class which will represent it programmatically. For example, if you are writing a module which interacts with an open document containing some sort of program code, and the user has made a syntax error in the code which you were able to detect and want to point out, you may want to mark the line or part of the line as "erroneous". To achieve this you must:

  1. Describe the appearance of your annotation. This is the so-called annotation type which consist of attributes like colors and so on. After you have defined the annotation type you will be able to create document annotations which will reference this annotation type. Definition of an annotation type involves creation of an XML file with the format specified by a standard DTD. This XML file must be registered in your module installation layer in the folder Editors/AnnotationTypes. Here is an example XML file Editors/AnnotationTypes/org-nb-modules-foo-some-annotation.xml (the file name within this folder is arbitrary but should be distinctive to prevent collisions between modules):
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE type PUBLIC
              "-//NetBeans//DTD annotation type 1.0//EN"
              "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
    <type name="org-nb-modules-foo-some-annotation"
          description_key="LBL_some-annotation"
          localizing_bundle="org.nb.modules.foo.Bundle"
          visible="true" 
          glyph="nbresloc:/org/nb/modules/foo/some-annotation-glyph.gif"
          highlight="#FFFF00"
          type="line"/>
    

    As you can see the definition of the annotation type consists of the highlight color; the glyph icon which could be shown in the left margin of the editing area - the glyph gutter; the localized name; and so on. For more details about each field in the DTD see below.

  2. Extend the Annotation abstract class and define your own annotation. You must specify the type - which matches the code name given in the XML description - and a short description, which can form tool-tip text for the annotation. For example:
    public final class SomeAnnotation extends Annotation {
        private final String error;
        public SomeAnnotation(String error) {
            this.error = error;
        }
        public String getAnnotationType() {
            return "org-nb-modules-foo-some-annotation";
        }
        public String getShortDescription() {
            // Localize this with NbBundle:
            return "The error was: " + error;
        }
    }
    
    Note that you can return the tooltip text asynchronously, on demand, or dynamically: you may return null for no tooltip, and you may later return a new or changed tooltip - just use:
    firePropertyChange(PROP_SHORT_DESCRIPTION, null, null);
    
    to inform the editor of the change. The tooltip should be refreshed on-screen.
  3. Finally, attach an annotation instance you make to some Annotatable object. Normally this will be a Line representing a whole line of text, or a Line.Part representing a section of a line. For example:
    // Given error output like: "pkg/Name.java:123: You made a mistake"
    FileObject fileWithError = fs.findResource("pkg/Name.java");
    DataObject objWithError = DataObject.find(fileWithError);
    LineCookie cookie = (LineCookie)objWithError.getCookie(LineCookie.class);
    Line.Set lineSet = cookie.getLineSet();
    final Line line = lineSet.getOriginal(123);
    final Annotation ann = new SomeAnnotation("You made a mistake");
    ann.attach(line);
    
  4. In this example the user may correct the erroneous line, or at least do something to it - in this case we assume that the annotation is no longer needed, and should be removed. It is a simple call to do this; of course you need to know when it is appropriate, so for example:

    line.addPropertyChangeListener(new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent ev) {
            String type = ev.getPropertyName();
            if (type == null || type == Annotatable.PROP_TEXT) {
                // User edited the line, assume error should be cleared.
                ann.detach();
                line.removePropertyChangeListener(this);
            }
        }
    });
    

It is possible that there might be more than one annotation on the same line. In this case it depends on the capabilities of the editor how the annotations will be displayed. The simplest scenario is that only one annotation is visible at time and the user can cycle through them. If this is the case it may be helpful to force the editor to move your annotation in front of any others:

ann.moveToFront();

NetBeans presents GUI settings to the user in which it is possible to customize the attributes of annotation types - for example, foreground and background color. Remember however that some editor implementations may find it difficult or impossible to accurately display all of these settings (for example display of arbitrary glyphs may be infeasible).

Detailed description of annotation XML files

Attributes of the <type> element are:
name
Unique non-localized name of the annotation type. Should match the result of Annotation.getAnnotationType().
description_key
Bundle key for the localized name of the annotation type. This name is shown in annotation settings as the name of the annotation type.
localizing_bundle
Name of the bundle (dot-separated and sans extension or locale suffix) which contains the localized annotation name under the description_key.
visible
Whether the annotation type is visible or not.
glyph
URL of the glyph icon. Typically this would use the nbresloc protocol to access module resources and automatically localize them. A 16x16 GIF is common.
highlight
RGB value of the highlight color.
foreground
RGB value of the foreground color. If the color is not specified, the line's normal text color is inherited.
type
Style of annotation. Currently two styles are permitted: line (full-line annotation) and linepart (may be applied to a column range within a line).
actions
The name of a subfolder (rooted from Editors/AnnotationTypes/) in which actions for this annotation type may be specified. The editor may present these actions to the user when the annotation glyph is right-clicked, for example. The actions may be defined by listing instances:
<folder name="YourAnnotationTypeActions">
  <file name="org-foo-BarAction.instance"/>
</folder>
severity
Severity of this annotation. Allowed values are error, warning, ok and none. Annotations with severity other then none will be shown in the Error Stripe using default color or color specified in custom_sidebar_color. Default value is none.
custom_sidebar_color
A color which should be used when showing this annotation in the Error Stripe. Specify this color if the default color derived from the severity is not feasible. Note that this setting has no effect if severity is set to none.
browseable
Whether this annotation should be "browseable" using action like Show Next Error. Valid values are true and false, default is false.
priority
Priority of this annotation with respect to other annotations with the same severity. Valid values are integer numbers. Default is 0.

The annotation <type> may also contain the <combinations> element - a definition of annotation combinations. If two or more annotations from the same module (or otherwise mutually known) are on the same line it might make sense to combine them into one annotation visually. For example, if a debugger module attached a breakpoint to a line and the current program counter reached the same line, it is more pleasant to show a combination of these two annotations rather than two separate annotations. This can be accomplished using a combination definition. A combined annotation type is otherwise normal (it may have a glyph icon and colors), but it also contains the definition of annotation types which are subsumed by this type. For example the combination of program counter with breakpoint could be defined as follows:

<combinations tiptext_key="PC_BREAKPOINT_COMBINATION_TOOLTIP_TEXT">
  <combine annotationtype="NameOfTheBreakpointAnnotationType"/>
  <combine annotationtype="NameOfTheCurrentPCAnnotationType"/>
</combinations>

It is the responsibility of the editor to display combinations where the criteria for combinations as defined in available annotation types are met.

Attributes of the <combinations> element are:

tiptext_key
Bundle key for the localized tooltip text of the combining annotation. The same bundle is used as was specified in description_key on <type>. Since multiple annotation types are being combined, each of which might have its own tooltip, the combined annotation has just a static tooltip which might explain that several annotations are combined in it.
order
If necessary, the order in which the combinations should be processed can be specified. This might be useful for more complicated combinations. If the value is not specified, the combination is added to the end of the list.
min_optionals
This is related to the attribute optional of the <combine/> element. The combination is defined as a list of annotation types to be combined. To make creation of the combination more flexible, some annotation types can be optional (optional attribute on <combine/>). min_optionals is then used to specify the minimum number of optional annotation types which must be found to make the combination valid. For example, you may have have a conditional breakpoint and disabled breakpoint and wish to combine either of them with the current program counter. You can define it as follows:
<combinations tiptext_key="COMBINATION_TOOLTIP_TEXT" min_optionals="1">
  <combine annotationtype="debugger-disabledbreakpoint" optional="true"/>
  <combine annotationtype="debugger-conditionalbreakpoint" optional="true"/>
  <combine annotationtype="debugger-currentpc"/>
</combinations>
This way you specify that both breakpoints are optional, but that at least one must be found to make the combination succeed.
The <combinations> element can contain only <combine/> elements (one for each annotation type) and they can have these attributes:
annotationtype
Name of the annotation which is subsumed by this combination; matches name on <type>.
absorb_all
Whether all occurrences of this annotation type should be absorbed by this combination or only one. This might be useful in case there are for example multiple breakpoints on the same line.
optional
Whether this annotation type is optional for the combination or not.
min
Minimum count of annotations of this annotation type which must be on the line for the combination to match with this type. This can be used to define combinations such as collapsed multiple breakpoints.

Loader Interactions with Guard Blocks

The NetBeans-supplied data object for Java source code automatically sets up guard blocks in the source documents it opens, if they contain the magic tokens in comments which delimit guard blocks on disk. So, if you are working with Java sources, you need do nothing special to load and save guarded documents; you may set guard blocks on them in memory, and this will be retained; or you may add the special tokens to them on disk, triggering guard block creation when the file is opened.

If you would like to add something akin to guard blocks to a custom file type handled by your module, you will need to insert the appropriate hooks. The best thing to do is to subclass EditorSupport, and use this subclass to implement cookies such as EditorCookie. Now just provide appropriate implementations of CloneableEditorSupport.loadFromStreamToKit(...) (to interpret special markings in the saved file and convert them into document attributes); and CloneableEditorSupport.saveFromKitToStream(...) (to translate these attributes back into ASCII markings).

Implementing a Custom Editor

It is possible to integrate a custom editor (presumably for textual content types) into NetBeans, in place of the default editor. The basic requirement is that it conform to the Swing EditorKit conventions. The Swing Text system is rather complex, so if you are not familiar with it you should look at Using the Swing Text Package.

Beyond being a generic EditorKit, there are two significant pieces of functionality used by NetBeans which the editor should support if at all possible:

Creating editor kit

You should not need to do anything special to create the editor kit beyond what is normally required by Swing.

Creating styled document

You will need to create an implementation of javax.swing.text.StyledDocument to hold the content of the buffer being edited.

Actually, you could get away with a plain Document if you really wanted, but you would be unable to support guard blocks and would have a harder time supporting annotations and line numbering; while this would probably suffice for an editor that was not to be used on Java source code, in general it is very much recommended that StyledDocument be used instead.

Handling guards

This is really the central problem in creating a compliant editor. If you want to completely skip this step, it is possible to return a plain Document from the registered editor kit; however this will not support guards (or NetBeans attributes either), and so if the user edits what should have been a guarded block, they may cause errors in the code, and their edits may be overwritten by NetBeans. If you implement StyledDocument, it is assumed you are handling guard blocks, but again it is up to you to actually do so correctly - NetBeans cannot determine this.

There is very little to the way NetBeans indicates guarding. Essentially, it is just a character attribute, NbDocument.GUARDED, which will be set to Boolean.TRUE for guarded characters, and Boolean.FALSE (or unset) for others; it is typically placed on the document by means of the NbDocument.markGuarded(...) and NbDocument.unmarkGuarded(...) methods, which just call StyledDocument.setCharacterAttributes(...). Very likely you will want to override this method, calling its superclass method but first checking to see if the attribute setting mentions GUARDED, whether setting it to TRUE or FALSE, and if so keeping track in another data structure of which ranges of characters are currently guarded or not; or you might already have a good way of keeping track of attributes in general and would rather just query this attribute when it is needed. If overriding setCharacterAttributes for this purpose, also remember to check the attributes on insertString, etc.

Note that currently guarded areas always consist of entire lines or sets of lines, so if you make this assumption your editor will be acceptable - but please handle sub-line granularity of guard blocks if you can do so easily, in case this situation changes. Along the same lines, you should make sure that users may only insert a newline immediately before a guarded block, and not any other character, for otherwise a half-guarded line would be created.

It is important to understand that the guarded attribute applies only to user modifications, i.e. those undertaken in the context of a user-initiated Swing action, or by NbDocument.runAtomicAsUser(...). Internal NetBeans module code may freely insert or remove text (typically using NbDocument.insertGuarded(...) and Document.remove(...)). For example, this would be done by the Form Editor component while adding a new event handler. The editor implementation should permit such programmatic inserts and removes, while corresponding user actions must be forbidden.

It is preferable, though optional, for the editor to visually mark guarded areas, say with a special background color. It is your responsibility to choose a color or another appearance for this purpose, however. Possibly NetBeans will specify a StyleConstants.ColorConstants.Background attribute describing which color will actually be used, and make this color settable in a control panel, but assume that you need to colorize based on this attribute yourself.

The recommended way to handle guards

It is highly recommended that all of the Swing actions (such as those returned by EditorKit.getActions()) applicable to your editor kit be reviewed for the possibility that they might attempt to change the content of the document (so, not only character inserts but search-and-replace, block paste, etc.). Any that do perform some kind of mutation should be reimplemented (or a wrapper written for them) so that they check to make sure that a guarded block is not being violated.

Even better, whenever possible an action should be disabled when it can easily be determined in advance that it would be in violation if performed at that time. As an example, if the user moves the caret into the middle of a guarded block, it would be much preferable for the editor to disable "Paste" (say, on a right-click context menu) for the time being, rather than permitting a Paste action to be invoked but then displaying an error dialog or beeping!

The cheap way to handle guards

If you think the recommended path is too much work, you can try a cheaper trick - but this is not recommended, and we do not guarantee that it is even possible to do satisfactorily. This applies only to people who are trying to adapt an existing StyledDocument, such as Swing's DefaultStyledDocument, which already has a full implementation of important things but no recognition of guard blocks.

The idea is to first get a list of all actions which might involve buffer modification - or, to be conservative, just all actions. For each of these, create a new action which calls the original actionPerformed, but "dynamically binds" some special flag stored with the document to true - dynamic binding here means that it should be restored (turned back off) in a finally block, and also that its value should be specific to the executing thread (and its children, perhaps). This flag indicates that operations are currently being performed from a user action.

Override the insertString(...) and remove methods. They should check the flag just mentioned. If it is turned off, just call the superclass method normally. If it is turned on, check whether the requested insertion or removal is affecting a guarded area (insertion within, or removal within or overlapping). If not, again call the superclass method. If there is an attempted violation, you might do one or more of the following:

Now bind all invocation objects (such as keymaps) to the new "wrapper" actions. Note that just returning them from the editor kit may not suffice.

If you go to the trouble of identifying specifically which actions could cause a violation, and under what circumstances they would or would not do so, then you could make specific wrappers that could disable actions, or safely invoke them only when possible, calling the original action if all is well - this is just one way to do the recommended implementation.

Testing guard blocks

If you are not able to test live in NetBeans, try doing something like this:

SimpleAttributeSet sas=new SimpleAttributeSet();
sas.addAttribute(NbDocument.GUARDED, Boolean.TRUE);
doc.setCharacterAttributes(0, 100, sas, false);

Now verify that modification attempts in this block are disabled.

Lines and elements

You should make sure that lines in the editor are separated by exactly one text character - a newline. The APIs may rely on this to count character positions during parsing, so that this functionality may be efficient.

Furthermore you should ensure that the default root element of the document has child elements corresponding to all text lines; and if using StyledDocument, that "paragraph" elements again correspond to text lines. Proper use of elements corresponding to lines will enable the APIs to accurately translate between buffer offsets and line numbers. It is fine to have additional element structures not corresponding to lines so long as the two conditions above are met.

Handling annotations

An editor must do two things to support annotations:

NbDocument.Annotatable

This interface has two methods. One adds an annotation to the document:
public void addAnnotation(Position startPos, int length, Annotation annotation);
The method is called with a Position in the document; the length of the annotation (if the annotation is of the whole-line type, the length will be -1); and the annotation instance. Now it is the responsibility of editor to collect all annotations for the document and to display them properly. It may be helpful to take advantage of StyledDocument for changing the style of the line (or part of the line). As for the glyph icon, it is fully up to the editor how to represent it (if at all). The NetBeans standard editor displays it in the left gutter.

The second method removed an annotation previously added:

public void removeAnnotation(Annotation annotation);
This method will be called when the annotation is programmatically detached, or the document is about to be closed.

The editor should combine annotation types where requested if this behavior is supported.

Annotation type XML files

As for visual attributes of annotations, the editor should parse the XML files in the Editors/AnnotationTypes/ directory. The NetBeans standard editor can serve as a source of examples for how to do this. In the future there may be shared parsing support.

Printing

If you want your editor to support printing of its contents, you might just provide no special support. In this case, printing should be able to work with plain text. If you have a styled document, it is possible that NetBeans will be able to run through the entire contents of the document; for each paragraph, retrieve its Style, and for each character, its attribute set; and then attempt to convert these (Swing) formatting specifications into (AWT) attributed character descriptions, for purposes of printing.

However, this process could be rather slow; is not terribly exact; and may not be implemented. To better support printing, it is desirable for the StyledDocument to implement org.openide.text.NbDocument.Printable, which will allow it to specify exactly how it wants to be printed. The method NbDocument.Printable.createPrintIterators(...) should return a list of java.text.AttributedCharacterIterators, providing attributes taken from java.awt.font.TextAttribute.

Also, if your document supports either java.awt.print.Printable or java.awt.print.Pageable, then these interfaces will be used to perform the printing directly. You should only need to do this if attributed characters do not satisfactorily capture everything that you are interested in printing - for example, if your editor is working on HTML and it is desired to print embedded images.

Locking

It is desirable for your StyledDocument implementation to be able to lock the document against write access, as this will make certain operations (performed by NetBeans, not in response to user events) more reliable and safer. In order to do this, please implement org.openide.text.NbDocument.WriteLockable and its runAtomic(...) method. The Runnable passed in this way should be executed with all other write actions (and reads) disabled, i.e. blocked.

If you are extending javax.swing.text.AbstractDocument, please note that just enclosing the Runnable block in calls to writeLock() and writeUnlock() will not do the trick - these calls do take out exclusive locks, however they specifically do not nest. This means that you cannot lock and then enter a runnable this way, because any modifications attempted within the runnable will throw an illegal state exception. Also, the locking methods are final and cannot be advised to nest. So you must find some other way to implement this, e.g. your own locks.

You must also implement NbDocument.WriteLockable.runAtomicAsUser(...), which is very similar but is invoked on behalf of user actions unrelated to whatever component created the guard blocks - e.g., this would be used to rename a method from the Explorer, in which case the rename ought to check that the renamed method is not guarded due to being used by the Form Editor. Thus, it should attempt to make modifications requested by the Runnable, locking out other modifications, but ensure that guard blocks are not violated. Any attempted violation should be prevented (or rolled back at the end of the runnable), and after the end of the runnable an appropriate exception should be thrown.

Note that while both methods in this interface ought to provide a transactional interface if at all possible - i.e., either succeed at executing the entire Runnable, or fail and leave the document untouched - the transactional aspect is much more important to implement properly for runAtomicAsUser. This is because it is quite possible for an innocent user action (e.g. attempting to rename a JavaBean property) to interfere with a guard block, and the document should not be left half-modified after such a mistake. On the other hand, a failure in the block of runAtomic is more likely to be an bug in some module, and not the user's fault; so perfect recovery is of course less important, as the bug should be fixed anyway.

There is currently no default convenience implementation of runAtomicAsUser, as any implementation may well be closely tied to how guard blocks are implemented in that particular editor - e.g. in Emacs there will be a quite idiosyncratic implementation.

Biases

Please consider implementing org.openide.text.NbDocument.PositionBiasable and its createPosition(...) method, to create a position marker which not only moves freely with insertions and deletions in nearby text, but also specifies the direction the marker will move to when text is inserted at that position.

If this is not done, NetBeans creates its own replacement.

Scrolling to display

NetBeans sometimes asks the editor to scroll the display so that a given line will be displayed. You should not need to do anything special to support this; Caret.setDot() will be called and ought to perform the scrolling appropriately.

Presentable actions

It is desirable for the editor to present actions to the user that may be invoked on the document and may be accessed in various ways. For example, if your editor provides an action for reindenting a section of text, it is best if this action can be integrated into the rest of NetBeans consistently: a "Reindent" item under the "Edit" menu on the main toolbar, active when your editor has focus; a button with an icon representing reindentation placed onto the NetBeans toolbar; a context menu item within the editor pane named "Reindent"; a keyboard shortcut Ctrl-R; etc.

While it might be possible to add some of these things manually into the NetBeans action containers (like the "Main Window" entry in the Environment, visible in the Explorer), this is discouraged as that makes it more difficult for NetBeans to manage actions added by various modules.

Instead, you should use the Actions API to add CallbackSystemActions (e.g.) to your module.

Default toolbar

Although it is best to use the Actions API to specify in your module's manifest file which actions to install where, NetBeans may also create a toolbar attached to the editor window which will reflect all displayable actions supported by your editor, automatically. This may be better for less-commonly used actions which it would be inappropriate to install into the main control window.

You do not need to do much to support this editor toolbar: in the getActions() method of your editor kit, if there are any actions which are also SystemActions implementing Presenter.Toolbar, then this interface will be used to get a java.awt.Component which will be displayed in the editor toolbar. You are free to make this component be whatever you like, e.g. a button to run some routine, or a checkbox to toggle an option; just add the appropriate event listeners to it.

Standard actions

A few basic editing commands you do not need to explicitly present to NetBeans; this will be done for you automatically. NetBeans tests whether an editor kit provides (from its EditorKit.getActions() method) any actions with certain names. Default instances of these are also available in the DefaultEditorKit class, but your actions will be recognized based on a call to getValue(Action.NAME):

NameStatic field in DefaultEditorKit
copy-to-clipboardcopyAction
cut-to-clipboardcutAction
paste-from-clipboardpasteAction

There are a few more which unfortunately do not exist in the DefaultEditorKit, and therefore have no standard names. The following may be used:

NameDescription
findPop up dialog to find a string in the text.
replacePop up dialog to find & replace a string in the text.
gotoPop up dialog to go to some place in the text, e.g. a specific line number.
deleteDelete the selection, without affecting clipboard.
undoUndo action. See package javax.swing.undo for help. Currently not specially supported, except to call your action.
redoRedo action. Ditto.

The corresponding items in the NetBeans "Edit" menu, and other standard invocations such as from the system toolbar, will automatically invoke these actions on your document, if you supply them. You should use Action.isEnabled() to indicate whether your action is ready, and thus whether or not the corresponding UI elements should be grayed out.

Undo/redo support

It is desirable for your document's user-level edit actions to implement UndoableEdit, so that NetBeans can smoothly provide Undo/Redo support for the editor from the standard places (e.g. in the Edit menu). Note that AbstractDocument, for example, already provides this support.

Customization

This API does not provide any special mechanism for allowing the user to customize aspects of the editor's operation from the GUI; if you want to do this, please use NbPreferences or similar.

Installing

It should be straightforward to install the new editor - you will make a JAR file containing a manifest with attributes recognized by NetBeans as constituting a module, and just call javax.swing.JEditorPane.registerEditorKitForContentType(...), and NetBeans should subsequently use it.

Implementing a module with editor support

It is possible that there will be special support in the Modules API for registering editors. Although doing it manually in the module's installed() method is not difficult, properly the module should also restore the original editor kit for each content type upon an uninstall, and ideally there would be a user-visible control panel permitting selection of the editor for each content type from among those claiming to support it.

This is not likely to be done unless it turns out to be popular to have multiple editors installed, and conflicts become a problem.

In the meantime, please refer to the Modules API for instructions on creating a module to contain your editor.

Registering unusual MIME types

If your editor has support for an unusual MIME type that is not currently recognized, you may wish to use the MIME resolution infrastructure in the Filesystems API to help your files be recognized. Additionally, CloneableEditorSupport.setMIMEType(String) may be used to control the MIME type of an editor kit regardless of the type of the underlying file.