This documentation is preliminary and subject to change
Copyright (c) 2000 by Inprise Corporation. All rights reserved.

JBuilder OpenTools Editor Concepts

1.0 Related Documents

 KeymapConcepts

2.0 General Description

This concept talk will describe how the editor works in JBuilder.  The editor provides a way to view and modify text documents, and it also gives other tools access to the text.   Some of the tools interfacing with the editor are Code Insight, and the Structure View.  The user communicates through keyboard and mouse input, and editor keybindings, as defined in keymaps, will translate the keyboard input into meaningful editor actions that will manipulate the text in the editor.
 

3.0 Detailed Descriptions

3.1 The editor manager

There is a single instance of the EditorManager class in JBuilder, and its task is to keep track of most of the editor specific details.   The EditorManager instance is responsible for creating instances of the EditorPane class, and it will also fire events to those EditorPanes to tell them about global changes that they should act upon, such as changes to the tab size, the font, the keymap, and more.   See 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 "Attribute".

The EditorManager is also responsible for creating and managing keyMaps, and you can read all about that in the KeymapConcepts document.

Of course EditorPanes are not the only classes who would want to know about global editor changes, so the EditorManager has general support for adding and removing property change listeners.  You can either add a class as the listener of a single property change (EditorManager.addPropertyChangeListener(String, PropertyChangeListener)), or add a class as the listener of all property changes (EditorManager.addPropertyChangeListener(PropertyChangeListener)).   The class that is added as the listener should implement the java/Beans/PropertyChangeListener interface, which basically means it should have the function:  void propertyChange(PropertyChangeEvent evt);

Let's practice and write code for a class so it will know when the tab size has changed:
 

  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();
    }
  }

3.2 The editor pane

When JBuilder opens a text based file, such as files with .java or .html extensions, the browser will create a new node, which will add a new tab to the content pane, and the file will be opened in a new editor window.   This editor window is of type EditorPane , and at any time you can get an handle to the current focused editor window from EditorAction as follows:
 
  EditorPane editor = EditorAction.getFocusedEditor();


Of course open nodes in the browser that don't have the focus might have an EditorPane associated with them, in which case you can use the getEditor function from 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
    }
  }

3.3 The document

Each EditorPane has its text stored in an EditorDocument , and you can get to that document with a call to EditorPane.getDocument.   Once you have an EditorDocument object, you can get to the actual text of the document.   The text is stored in objects of type javax/swing/text/Element, and each Element object basically represents one line.   At the same time each character of the document has an index, and you can go from an Element object to its starting and ending index, and from a character index to the line Element that contains that character.   Let's try this out with some code:
  // First get the document
  EditorPane editor = EditorAction.getFocusedEditor();
  Document doc = editor.getDocument();

  // Get the base of all Elements
  Element baseElement = doc.getDefaultRootElement();

  // Just for fun, how many lines are there in the document
  int totalLines = baseElement.getElementCount();

  // Where is my caret now
  int caretIndex = editor.getCaretPosition();

  // On what line is my caret 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);

3.4 The caret

Each editor pane has a caret, and that caret will be at a certain index into the document.  The caret also holds information about the starting and ending index of a highlight, if there is one.  Note that the editor has functions about the selection highlight as well. The following code shows how to use the caret:
  // 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 highlight?
  int dot = caret.getDot();
  int mark = caret.getMark();
  if (dot != mark) {
    // There is an hightlighted selection
  }

  // Alternate way to find out about selections
  int selectBegin = editor.getSelectionStart();
  int selectEnd = editor.getSelectionEnd();
  if (selectBegin != selectEnd) {
    // There is an hightlighted selection
  }

3.5 The editor actions

There is a whole set of actions available that target the editor. These actions all live in EditorActions. One of the best ways to learn about these actions is to study the Keymap examples in the OpenTools samples. There are samples that show how to create an CUA keybinding, an Emacs keybinding, and a Brief keybinding. The keymaps map key strokes to actions that often are one of the actions defined in EditorActions.

3.6 The text utilities

Another useful class to look at is the TextUtilities class. Here you can find functions that will go from a document index to a line, or will find the beginning and end of words. If the text has hardcoded tab characters, there are some functions that will compute the width of a text, or determine the index of a character in a text, taking tabs into account.