blob: 7b2ca5d75618c6aeea2ab3ecd12a925f718a4f0d [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_181) on Fri Sep 14 11:35:15 BST 2018 -->
<title>Overview (Editor Code Folding)</title>
<meta name="date" content="2018-09-14">
<link rel="stylesheet" type="text/css" href="javadoc.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="Overview (Editor Code Folding)";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li class="navBarCell1Rev">Overview</li>
<li>Package</li>
<li>Class</li>
<li>Use</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-files/index-1.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
<div class="aboutLanguage">org.netbeans.modules.editor.fold/1 1.47.1 </div>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?overview-summary.html" target="_top">Frames</a></li>
<li><a href="overview-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 class="title">Editor Code Folding<br/><span style='font-style:normal; font-size:medium; font-weight:normal; background-color:#ffffff;'><a href='http://wiki.netbeans.org/API_Stability#Official' target='_blank'>Official</a></span></h1>
</div>
<div class="header">
<div class="subTitle">
<div class="block">
The Code Folding was created to address requirements
described in
<a href="http://ui.netbeans.org/docs/ui/code_folding/cf_uispec.html" shape="rect">
Code Folding UI Specification
</a></div>
</div>
<p>See: <a href="#overview.description">Description</a></p>
</div>
<div class="contentContainer">
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Editor Code Folding table, listing packages, and an explanation">
<caption><span>Editor Code Folding</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Package</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="org/netbeans/api/editor/fold/package-summary.html">org.netbeans.api.editor.fold</a></td>
<td class="colLast">&nbsp;</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/netbeans/spi/editor/fold/package-summary.html">org.netbeans.spi.editor.fold</a></td>
<td class="colLast">&nbsp;</td>
</tr>
</tbody>
</table>
</div>
<div class="contentContainer"><a name="overview.description">
<!-- -->
</a>
<div class="block"><p>
The Code Folding was created to address requirements
described in
<a href="http://ui.netbeans.org/docs/ui/code_folding/cf_uispec.html" shape="rect">
Code Folding UI Specification
</a>
<p>
It is a module located under /cvs/editor/fold directory.
</p>
<p>
It consists of
</p>
<ul>
<li>API in org.netbeans.api.editor.fold</li>
<li>SPI in org.netbeans.spi.editor.fold</li>
<li>Implementation in org.netbeans.modules.editor.fold</li>
</ul>
Code Folding defines CodeFoldingAPI.
<p>
The Javadoc documentation can be generated by using
</p>
<pre xml:space="preserve">
cd /cvs/editor/fold
ant javadoc
</pre>
</p>
<h3>What is New (see <a href="apichanges.html">all changes</a>)?</h3>
<ul>
<!--Search for dates that are later or equal to 1997-09-01 in
.-->
<!--Checking date 2013-3-12 with count of newer 0--><!--year ok-->
<li>Mar 12 '13 <a href="apichanges.html#fold-api-enhancements">Extensible FoldTypes, enhanced support for fold updates</a>
<p>
<p>
<code>FoldTypes</code> can be defined for a <i>mime type</i> by <code>FoldTypeProviders</code>. They
can form a type hierarchy. <code>FoldUtilities</code> provide methods to check fold enablement and
available FoldTypes. Working directly with Preferences is not advised.
</p>
<p>
Fold can provide offsets to start and end of its content excluding <i>guard areas</i>. <code>FoldingSupport</code>
provides factories for comment-driven <code>FoldManager</code> and for fold <code>ContentReader</code> capable
of reading javadoc-style comments or similar.
</p>
<p>
<code>FoldOperation</code> allows to <code>update</code> folds with <code>FoldInfos</code>, removing, adding
or updating Folds as necessary. Existing FoldManagers can be simplified. Folds can be defined wihtout
initial state - the state will be determined form the options by the infrastructure. All folds defined
by a FoldManager can be retrieved from <code>FoldOperation.foldIterator()</code>, even though they are
blocked.
</p>
</p>
</li>
<!--Checking date 2013-3-8 with count of newer 1--><!--year ok-->
<li>Mar 8 '13 <a href="apichanges.html#fold-editorlib-separation">Fold UI separation from Editor Library</a>
<p>
<p>
<code>FoldHierarchyMonitor</code> was introduced to allow hooking into UI when
a FoldHierarchy is produced for a JTextComponent. The 'active' flag is provided on
the <code>FoldHierarchy</code> to determine whether the hierarchy be popuplated with folds
at all.
</p>
<p>
Using <code>FoldingSupport</code> utility class, clients can create instance of
<code>FoldManager</code> that creates folds based on comments, previously <code>CustomFoldManager</code>
in editor.lib module.
</p>
</p>
</li>
<!--Checking date 2008-3-3 with count of newer 2--><!--year ok-->
<li>Mar 3 '08 <a href="apichanges.html#FoldOperation-owns-added">FoldOperation.owns(Fold) added</a>
<p>
<p>
Added FoldOperation.owns(Fold) to check whether fold was produced
by a particular FoldOperation.
</p>
</p>
</li>
</ul>
<h3>Use Cases</h3>
<answer id="arch-usecases">
<h2>
API Use Cases
</h2>
<h3>
Exploring of the Folds
</h3>
<p>
The code folding structure (fold hierarchy) relates
to <code>javax.swing.JTextComponent</code> instance in one-to-one relationship.
<br>
To find the code folding hierarchy instance for the given non-null text component
the following code snippet can be used:
</p>
<pre xml:space="preserve">
JTextComponent editorComponent = ...
FoldHierarchy hierarchy = FoldHierarchy.get(editorComponent);
</pre>
<h3>
Explore the Folds Hierarchy
</h3>
<p>
The tree-based hierarchy has one non-removable and non-collapsable root fold
that covers the whole document. It can be obtained by
</p>
<pre xml:space="preserve">
FoldHierarchy foldHierarchy = ...
Fold rootFold = hierarchy.getRootFold();
</pre>
<p>
The children folds of the root fold (or children folds)
can be obtained by
</p>
<pre xml:space="preserve">
// the hierarchy must be locked prior exploration or manipulation
hierarchy.lock();
try {
Fold rootFold = ...
int foldCount = rootFold.getFoldCount();
for (int i = 0; i &lt; foldCount; i++) {
Fold childFold = rootFold.getFold(i);
}
} finally {
hierarchy.unlock();
}
</pre>
<p>
Index of the child in its parent can be found by
</p>
<pre xml:space="preserve">
hierarchy.lock();
try {
Fold rootFold = ...
int foldIndex = rootFold.getFoldIndex(childFold);
} finally {
hierarchy.unlock();
}
</pre>
<h3>
Collapse Nearest Fold
</h3>
<p>
In the given fold hierarchy find the nearest fold right at or after the given offset
and collapse it.
</p>
<pre xml:space="preserve">
hierarchy.lock();
try {
Fold fold = FoldUtilities.findNearestFold(hierarchy, offset);
hierarchy.collapse(fold);
} finally {
hierarchy.unlock();
}
</pre>
<h3>
Expand All Folds
</h3>
<p>
In the given fold hierarchy expand all folds that are currently collapsed.
</p>
<pre xml:space="preserve">
FoldUtilities.expand(hierarchy, null);
</pre>
<h3>
Collapse All Folds of Certain Type
</h3>
<p>
In the given fold hierarchy collapse all e.g. javadoc folds that are currently collapsed.
<br>
The example can be generalized to any fold type.
</p>
<pre xml:space="preserve">
FoldUtilities.collapse(hierarchy, JAVADOC_FOLD_TYPE);
</pre>
<h3>
Start Listening on Fold Hierarchy Changes
</h3>
<p>
In the given fold hierarchy start to listen on all changes
done in the hierarchy.
<br>
This is actually used e.g. in the Editor's View Hierarchy that needs
to refresh views based on the fold changes.
</p>
<pre xml:space="preserve">
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
}
});
</pre>
<h3>
Inspect Collapsed Folds in Affected Area
</h3>
<p>
Listen on the hierarchy changes
and refresh the views in the text area affected by the fold change.
<br>
Inspect the collapsed folds in the affected area
because special views need to be created for the collapsed folds.
<br>
The actual code in the View Hierarchy is somewhat different
but the one given here is more descriptive.
</p>
<pre xml:space="preserve">
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
}
}
});
</pre>
<h2>
SPI Use Cases
</h2>
<h3>
Create a New Fold Manager
</h3>
<p>
Manipulation of the folds is designed to be done by fold managers.
<br>
Those classes implement <code>FoldManager</code> interface in the SPI.
<br>
At initialization time they are given instance of <code>FoldOperation</code>
through which they can create, add or remove the fold instances.
</p>
<p>
To create and use a new <code>FoldManager</code> instance
it's necessary to
</p>
<ul>
<li> Define the class of the FoldManager.
<pre xml:space="preserve">
public class MyFoldManager implements FoldManager { // or extends AbstractFoldManager
...
}
</pre>
</li>
<li> Create FoldManagerFactory for the FoldManager.
<pre xml:space="preserve">
public class MyFoldManager ...
...
public static final class Factory implements FoldManagerFactory {
public FoldManager createFoldManager() {
return new MyFoldManager();
}
}
}
</pre>
</li>
<li> Register FoldManagerFactory into xml layer into the directory
"Editors/&lt;mime-type&gt;/FoldManager/"
</li>
<li> Enable Code Folding in editor's Settings initializer
(please see e.g. <code>NbJavaSettingsInitializer</code>)
<pre xml:space="preserve">
public class MySettingsInitializer ...
public void updateSettingsMap(Class kitClass, Map settingsMap) {
...
settingsMap.put(SettingsNames.CODE_FOLDING_ENABLE, Boolean.TRUE);
}
}
</pre>
</li>
</ul>
<h3>
Create a New Fold by Fold Manager
</h3>
<p>
Create a new fold and add it to the hierarchy. The operation
is performed by the fold manager either at initialization phase
(in the <code>initFolds()</code> 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).
</p>
<p>
Operations that manipulate the hierarchy are done
in terms of a valid transaction over the fold hierarchy.
<br>
Transactions allow to fire the collected changes as a single
<code>FoldHierarchyEvent</code> at the time when they are committed.
</p>
<pre xml:space="preserve">
// In the FoldManager's context
FoldOperation operation = getOperation();
FoldHierarchyTransaction transaction = operation.openTransaction();
try {
Fold fold = operation.createFold(...);
operation.addFoldToHierarchy(fold, transaction);
} finally {
transaction.commit();
}
</pre>
<h3>
Remove Fold from Hierarchy by Fold Manager
</h3>
<p>
Remove the existing fold from the hierarchy
</p>
<pre xml:space="preserve">
// In the FoldManager's context
FoldOperation operation = getOperation();
FoldHierarchyTransaction transaction = operation.openTransaction();
try {
Fold fold = ...
operation.removeFoldFromHierarchy(fold, transaction);
} finally {
transaction.commit();
}
</pre>
<h3>Updating Fold hierarchy</h3>
In the preceding cases, maintaining Folds was the FoldManager's responsibility. The FoldManager typically
held a copy of the Folds added to the hierarchy, and during the refresh, it compared them to the new data
and decided what folds to remove.
For simple cases, which only create/remove folds based on text positions, part of the work can be offloaded to the
FoldOperation:
<pre xml:space="preserve">
// create new fold positional information for all folds.
Collection&lt;FoldInfo&gt; newInfos = ...;
// create FoldInfo for each of the fold
newInfos.add(
FoldInfo.range(start, end, type).
withTemplate(customTemplate).
withDescription(veryCustomDescription).
collapse(true)
);
// the hierarchy must be locked prior to update
doc.readLock();
hierarchy.lock();
try {
operation.update(newInfos, null, null);
} finally {
}
</pre>
The <code>update()</code> operation performs a diff, creates new folds, discards old ones, and updates the folds, which
prevailed.
<h3>Accessing folds</h3>
Instead of keeping a copy of created folds, the FoldManager may call <code>operation.foldIterator</code>. The iterator
will enumerate all folds, including (recursively) blocked ones.
</answer>
<h3>Exported Interfaces</h3>
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. <a href="architecture-summary.html">Read them all</a>...
<a name="group-java">
<h5>Group of java interfaces</h5>
</a>
<table cellpadding="1" cellspacing="0" border="0" class="tablebg" width="100%">
<tr>
<td>
<table border="0" cellpadding="3" cellspacing="1" width="100%">
<tr class="tablersh">
<td align="CENTER" width="25%"><span class="titlectable">Interface Name</span></td><td align="CENTER" width="10%"><span class="titlectable">In/Out</span></td><td align="CENTER" width="10%"><span class="titlectable">Stability</span></td><td align="CENTER"><span class="titlectable">Specified in What Document?</span></td>
</tr>
<tr class="tabler">
<td>CodeFoldingAPI</td><td>Exported</td><td><a href="http://wiki.netbeans.org/API_Stability#Official">Official</a></td><td><a name="java-CodeFoldingAPI"></a></td>
</tr>
</table>
</td>
</tr>
</table>
<p></p>
<h3>Implementation Details</h3>
<h5>Where are the sources for the module?</h5>
<p>
<p>
The sources for the module are in the
<a href="http://hg.netbeans.org/" shape="rect">NetBeans Mercurial repositories</a>.
</p>
</p>
<h5>What do other modules need to do to declare a dependency on this one, in addition to or instead of a plain module dependency?</h5>
Nothing.
<p>
Read more about the implementation in the <a href="architecture-summary.html">answers to
architecture questions</a>.
</p></div>
</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li class="navBarCell1Rev">Overview</li>
<li>Package</li>
<li>Class</li>
<li>Use</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-files/index-1.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
<div class="aboutLanguage">org.netbeans.modules.editor.fold/1 1.47.1 </div>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?overview-summary.html" target="_top">Frames</a></li>
<li><a href="overview-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
<p class="legalCopy"><small><span class="footnote">Built on September 14 2018.&nbsp;&nbsp;|&nbsp;&nbsp; Copyright &#169; 2017-2018 Apache Software Foundation. All Rights Reserved.</span></small></p>
</body>
</html>