Content outliners

Editors often have corresponding content outliners that provide a structured view of the editor contents and assist the user in navigating through the contents of the editor.

The workbench provides a standard Outline view for this purpose.  The workbench user controls when this view is visible using the Window > Show View menu.

Since the generic TextEditor doesn't know anything about the structure of its text, it cannot provide behavior for an interesting outline view.  Therefore, the default Outline view, shown below, doesn't do much.

Default content outliner

 

Editors in the text framework can supply their own content outliner page to the outline view.  The outliner for an editor is specified when the workbench requests an adapter of type IContentOutlinePage.

public Object getAdapter(Class required) {
    if (IContentOutlinePage.class.equals(required)) {
        if (fOutlinePage == null) {
            fOutlinePage= new JavaContentOutlinePage(getDocumentProvider(), this);
            if (getEditorInput() != null)
                fOutlinePage.setInput(getEditorInput());
        }
        return fOutlinePage;
    }
    return super.getAdapter(required);
}

A content outliner page must implement IContentOutlinePage.  This interface combines the ability to notify selection change listeners (ISelectionProvider) with the behavior of being a page in a view (IPage).  Content outliners are typically implemented using JFace viewers.  The default implementation of a content outliner (ContentOutlinePage) uses a JFace tree viewer to display a hierarchical representation of the outline.  This representation is suitable for many structured outliners, including JavaContentOutlinePage.

Let's take a look at the implementation of the page. When the outline page is created by the editor in the snippet above, its input element is set to the editor's input element.  This input can often be passed directly to the outline page's viewer, as is done below.

public void createControl(Composite parent) {

    super.createControl(parent);

    TreeViewer viewer= getTreeViewer();
    viewer.setContentProvider(new ContentProvider());
    viewer.setLabelProvider(new LabelProvider());
    viewer.addSelectionChangedListener(this);

    if (fInput != null)
        viewer.setInput(fInput);
}

The tree viewer creation is inherited from ContentOutlinePage.  The standard label provider is used. The content provider is provided inside JavaContentOutlinePage and is responsible for parsing the editor input into individual segments whenever it changes.

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            ...
            if (newInput != null) {
                IDocument document= fDocumentProvider.getDocument(newInput);
                if (document != null) {
                    document.addPositionCategory(SEGMENTS);
                    document.addPositionUpdater(fPositionUpdater);
                    parse(document);
                }
            }
        }

The text is parsed into ranges, called segments, within the document.  These segments are displayed by name in the outline view.

Java example outliner

When the selection changes, the selected segment is retrieved.  Its offsets are used to set the highlight range in the editor.


public void selectionChanged(SelectionChangedEvent event) {

    super.selectionChanged(event);

    ISelection selection= event.getSelection();
    if (selection.isEmpty())
        fTextEditor.resetHighlightRange();
    else {
        Segment segment= (Segment) ((IStructuredSelection) selection).getFirstElement();
        int start= segment.position.getOffset();
        int length= segment.position.getLength();
        try {
            fTextEditor.setHighlightRange(start, length, true);
        } catch (IllegalArgumentException x) {
            fTextEditor.resetHighlightRange();
        }
    }
}