EditorManager
class. Its task is to keep track of most of the editor specific details. The EditorManager
creates instances of the EditorPane
class. It also fires events to those EditorPanes
to notify them about
global changes they should act upon, such as changes to the tab size, the font, the keymap, and so on. See the EditorManager
class for the complete list of attributes, also called properties, such
as fontAttribute
and tabSizeAttribute
. You can recognize them because they all end with the word "Attribute."
The EditorManager
is also responsible for creating and managing keymaps. For more information about keymaps, see "JBuilder keymap concepts."
Because other classes also must be notified about global editor changes, the EditorManager
has support for adding and removing property change listeners. You can either add a class as the listener of a single property change with the
(EditorManager.addPropertyChangeListener(String, PropertyChangeListener)
) method, or add a class as the listener of all property changes with the (EditorManager.addPropertyChangeListener(PropertyChangeListener)
) method. The class that is added as the listener must implement the java.beans.PropertyChangeListener
interface, which basically means you must implement the propertyChange()
method:
void propertyChange(PropertyChangeEvent evt);
For example, this class implements the PropertyChangeListener
interface; it's called each time the EditorManager
fires a tab size property change:
public class KnowsTabSize implements PropertyChangeListener { int tabSize; public KnowsTabSize() { tabSize = 0; } public static void initOpenTool(byte majorVersion, byte minorVersion) { // Make sure the OpenTools API is compatible if (majorVersion != PrimeTime.CURRENT_MAJOR_VERSION) return; // Create our class and add it as a listener of the tabSize EditorManager changes KnowsTabSize knowItAll = new KnowsTabSize(); EditorManager.addPropertyChangeListener(EditorManager.tabSizeAttribute, knowItAll); } // Implement to satisfy the PropertyChangeListener interface // The EditorManager will call this function anytime it fires a // tab size property change public void propertyChange(PropertyChangeEvent e) { // Update our own tab size tabSize = EditorManager.getTabSize(); } }
EditorPane
. You can get a handle to the active editor window (the one with the focus) from EditorAction
with code like this:
EditorPane editor = EditorAction.getFocusedEditor();
Open nodes in the browser that don't have the focus might also have an EditorPane
associated with them. In this case you can use the getEditor()
method of EditorManager
:
Node[] nodes = Browser.getActiveBrowser().getOpenNodes(); for (int i = 0; i < nodes.length; i++) { EditorPane editor = EditorManager.getEditor(nodes[i]); if (editor != null) { // Do something with the editor } }
EditorPane
stores its text in an EditorDocument
. To access that document, call EditorPane.getDocument()
. Once you have an EditorDocument
object, you can get to the document's actual text. The text is stored in objects of type javax.swing.text.Element
. Each Element
object basically represents one line and has a starting and an ending index. Each character of the document also has an index. Here is a code sample that demonstrates how to use Element
and the indexes:
// First get the document EditorPane editor = EditorAction.getFocusedEditor(); Document doc = editor.getDocument(); // Get the base of all Elements Element baseElement = doc.getDefaultRootElement(); // How many lines are there in the document? int totalLines = baseElement.getElementCount(); // Where is my caret now? int caretIndex = editor.getCaretPosition(); // Find the line the caret is on and get the Element of that line int lineIndex = baseElement.getElementIndex(caretIndex); Element lineElement = baseElement.getElement(lineIndex); // Get the boundaries of that line int startingIndex = lineElement.getStartOffset(); int endingIndex = lineElement.getEndOffset(); //Get the actual text of the line String lineText = doc.getText(startingIndex, endingIndex - startingIndex);
// Get the editor and the caret EditorPane editor = EditorAction.getFocusedEditor(); Caret caret = editor.getCaret(); // Where is the caret? int caretPosition = editor.getCaretPosition(); // Does the caret say there is a highlighted selection? int dot = caret.getDot(); int mark = caret.getMark(); if (dot != mark) { // There is an highlighted selection } // Alternate way to find out about selections int selectBegin = editor.getSelectionStart(); int selectEnd = editor.getSelectionEnd(); if (selectBegin != selectEnd) { // There is an highlighted selection }
EditorActions
class contains a set of actions for the editor. Learn about these actions by studying the Keymap examples in the OpenTools samples. You can find samples that show how to create an CUA key binding, an Emacs key binding, and a Brief key binding. The keymaps associate keystrokes with many of the actions defined in EditorActions
.
When a new action is written, you must hook it up to a keystroke.
Also, the action should register itself so it will be displayed in the keymap editor. There are several steps involved in this process, and these steps can be
studied in the samples/OpenToolsAPI/LineCommentHandler
example, which shows how to
create a new action and register it. Here is some of that code:
public static void initOpenTool(byte majorVersion, byte minorVersion) { // Register our LineCommentHandler action so it will show up // in the keymap editor. // We register it as an Editor action because this action only // makes sense if the focus is in the editor. EditorActions.addBindableEditorAction(ACTION_LineCommentHandler); } public static EditorAction ACTION_LineCommentHandler = // The "line_comment_handler" name is used in the // keymap editor to name our action. new LineCommentHandlerAction("line_comment_handler"); public LineCommentHandlerAction(String nm) { super(nm); // The long description property is used in the keymap editor // to fill up the description memo. this.putValue(Action.LONG_DESCRIPTION, "Adds //DBG at the start of the line if it's not already there, otherwise deletes it." ); // The ActionGroup property is used to put this action // in the specified group of actions. this.putValue("ActionGroup", "Miscellaneous"); }
TextUtilities
is another useful class. It has methods that you can use to move from a document index to a particular line or to find the beginning and end of words. If the text has hard-coded tab characters, methods exist that compute the width of the text, or that determine the index of a character in the text, taking tabs into account.