NetBeans Code Folding API

The Code Folding was created to address requirements described in Code Folding UI Specification

See:
          Description

Code Folding API
org.netbeans.api.editor.fold  
org.netbeans.spi.editor.fold  

 

The Code Folding was created to address requirements described in Code Folding UI Specification

It is a module located under /cvs/editor/fold directory.

It consists of

Code Folding defines CodeFoldingAPI.

The Javadoc documentation can be generated by using

    cd /cvs/editor/fold
    ant javadoc

What is New (see all changes)?

Use Cases

API Use Cases

Exploring of the Folds

The code folding structure (fold hierarchy) relates to javax.swing.JTextComponent instance in one-to-one relationship.
To find the code folding hierarchy instance for the given non-null text component the following code snippet can be used:

    JTextComponent editorComponent = ...
    FoldHierarchy hierarchy = FoldHierarchy.get(editorComponent);

Explore the Folds Hierarchy

The tree-based hierarchy has one non-removable and non-collapsable root fold that covers the whole document. It can be obtained by

    FoldHierarchy foldHierarchy = ...
    Fold rootFold = hierarchy.getRootFold();

The children folds of the root fold (or children folds) can be obtained by

    // the hierarchy must be locked prior exploration or manipulation
    hierarchy.lock();
    try {
        Fold rootFold = ...
        int foldCount = rootFold.getFoldCount();
        for (int i = 0; i < foldCount; i++) {
            Fold childFold = rootFold.getFold(i);
        }
    } finally {
        hierarchy.unlock();
    }

Index of the child in its parent can be found by

    hierarchy.lock();
    try {
        Fold rootFold = ...
        int foldIndex = rootFold.getFoldIndex(childFold);
    } finally {
        hierarchy.unlock();
    }

Collapse Nearest Fold

In the given fold hierarchy find the nearest fold right at or after the given offset and collapse it.

    hierarchy.lock();
    try {
        Fold fold = FoldUtilities.findNearestFold(hierarchy, offset);
        hierarchy.collapse(fold);
    } finally {
        hierarchy.unlock();
    }

Expand All Folds

In the given fold hierarchy expand all folds that are currently collapsed.

    FoldUtilities.expand(hierarchy, null);

Collapse All Folds of Certain Type

In the given fold hierarchy collapse all e.g. javadoc folds that are currently collapsed.
The example can be generalized to any fold type.

    FoldUtilities.collapse(hierarchy, JAVADOC_FOLD_TYPE);

Force Fold Expansion for Caret Moving Into Collapsed Fold

In the given fold hierarchy expand the fold into which the caret is going to be moved by Caret.setDot(offset).
The hierarchy must be locked and this example assumes that the underlying document is already read-locked e.g. by Document.render().

    FoldHierarchy hierarchy = FoldHierarchy.get(caretComponent);
    hierarchy.lock();
    try {
        Fold collapsed = FoldUtilities.findCollapsedFold(hierarchy, offset, offset);
        if (collapsed != null && collapsed.getStartOffset() < offset &&
            collapsed.getEndOffset() > offset) {
            hierarchy.expand(collapsed);
        }
    } finally {
        hierarchy.unlock();
    }

Start Listening on Fold Hierarchy Changes

In the given fold hierarchy start to listen on all changes done in the hierarchy.
This is actually used e.g. in the Editor's View Hierarchy that needs to refresh views based on the fold changes.

    hierarchy.addFoldHierarchyListener(new FoldHierarchyListener() {
        public void foldHierarchyChanged(FoldHierarchyEvent evt) {
            // Hierarchy does not need to be locked here
            //
            // evt.getAffectedStartOffset() and getAffectedEndOffset()
            // give text area affected by the fold changes in the event
        }
    });

Inspect Collapsed Folds in Affected Area

Listen on the hierarchy changes and refresh the views in the text area affected by the fold change.
Inspect the collapsed folds in the affected area because special views need to be created for the collapsed folds.
The actual code in the View Hierarchy is somewhat different but the one given here is more descriptive.

    hierarchy.addFoldHierarchyListener(new FoldHierarchyListener() {
        public void foldHierarchyChanged(FoldHierarchyEvent evt) {
            for (Iterator collapsedFoldIterator
                = FoldUtilities.collapsedFoldIterator(hierarchy,
                    evt.getAffectedStartOffset(),
                    evt.getAffectedEndOffset()
                );
                it.hasNext();
            ) {
                Fold collapsedFold = (Fold)it.next();
                // Create special view for the collapsedFold
            }
        }
    });

SPI Use Cases

Create a New Fold Manager

Manipulation of the folds is designed to be done by fold managers.
Those classes implement FoldManager interface in the SPI.
At initialization time they are given instance of FoldOperation through which they can create, add or remove the fold instances.

To create and use a new FoldManager instance it's necessary to

Create a New Fold by Fold Manager

Create a new fold and add it to the hierarchy. The operation is performed by the fold manager either at initialization phase (in the initFolds() which gets called automatically by the infrastructure) or at any other time when the fold manager's operation gets invoked (usually by a listener that the fold manager attaches to be notified about changes that can cause the folds structure to be changed - e.g. a parsing listener for java folds).

Operations that manipulate the hierarchy are done in terms of a valid transaction over the fold hierarchy.
Transactions allow to fire the collected changes as a single FoldHierarchyEvent at the time when they are committed.

    // In the FoldManager's context
    FoldOperation operation = getOperation();
    FoldHierarchyTransaction transaction = operation.openTransaction();
    try {
        Fold fold = operation.createFold(...);
        operation.addFoldToHierarchy(fold, transaction);
    } finally {
        transaction.commit();
    }

Remove Fold from Hierarchy by Fold Manager

Remove the existing fold from the hierarchy

    // In the FoldManager's context
    FoldOperation operation = getOperation();
    FoldHierarchyTransaction transaction = operation.openTransaction();
    try {
        Fold fold = ...
        operation.removeFoldFromHierarchy(fold, transaction);
    } finally {
        transaction.commit();
    }

Exported Interfaces

This table lists all of the module exported APIs with defined stability classifications. It is generated based on answers to questions about the architecture of the module. Read them all...
Group of java interfaces
Interface NameIn/OutStabilitySpecified in What Document?
CodeFoldingAPIExportedOfficial

Implementation Details

What do other modules need to do to declare a dependency on this one?
OpenIDE-Module-Module-Dependencies: org.netbeans.modules.editor.fold/1 > 1.5.1

Read more about the implementation in the answers to architecture questions.


 

Built on May 3 2007.  |  Portions Copyright 1997-2005 Sun Microsystems, Inc. All rights reserved.