|
It is a module located under /cvs/editor/fold directory.
It consists of
The Javadoc documentation can be generated by using
cd /cvs/editor/fold ant javadocQuestion (arch-usecases): Describe the main use cases of the new API. Who will use it under what circumstances? What kind of code would typically need to be written to use the module? Answer:
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);
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(); }
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(); }
In the given fold hierarchy expand all folds that are currently collapsed.
FoldUtilities.expand(hierarchy, null);
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);
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 } });
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 } } });
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
public class MyFoldManager implements FoldManager { // or extends AbstractFoldManager ... }
public class MyFoldManager ... ... public static final class Factory implements FoldManagerFactory { public FoldManager createFoldManager() { return new MyFoldManager(); } } }
NbJavaSettingsInitializer
)
public class MySettingsInitializer ... public void updateSettingsMap(Class kitClass, Map settingsMap) { ... settingsMap.put(SettingsNames.CODE_FOLDING_ENABLE, Boolean.TRUE); } }
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 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(); }
// create new fold positional information for all folds. Collection<FoldInfo> 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 { }The
update()
operation performs a diff, creates new folds, discards old ones, and updates the folds, which
prevailed.
operation.foldIterator
. The iterator
will enumerate all folds, including (recursively) blocked ones.
Question (arch-time):
What are the time estimates of the work?
Answer:
The cvs/editor/fold module is currently maintained
under fold_api branch of the editor module.
Question (arch-quality):
How will the quality
of your code be tested and
how are future regressions going to be prevented?
Answer:
The unit tests will be created to cover the functionality testing.
We are also considering to create randomized tests that would construct artificial fold managers and randomly insert/remove folds and do random modifications to the file. This way we could make a stress test for the fold merging algorithms present in FoldHierarchyTransaction (and FoldHierarchySpi).
Question (arch-where): Where one can find sources for your module? Answer:
The sources for the module are in the NetBeans Mercurial repositories.
Specific fold managers can have their own additional dependencies (e.g. Java fold manager depends on Java Source Hierarchy etc.).
The default answer to this question is:
These modules are required in project.xml:
XXX no answer for compat-deprecation
java.io.File
directly?
Answer:
No.
Question (resources-layer):
Does your module provide own layer? Does it create any files or
folders in it? What it is trying to communicate by that and with which
components?
Answer:
No.
Question (resources-read):
Does your module read any resources from layers? For what purpose?
Answer:
Module reads fold managers registered fold manager factories for the given mime-type
from the Editors/<mime-type>/FoldManager folder.
Question (resources-mask):
Does your module mask/hide/override any resources provided by other modules in
their layers?
Answer:
No.
Question (resources-preferences):
Does your module uses preferences via Preferences API? Does your module use NbPreferences or
or regular JDK Preferences ? Does it read, write or both ?
Does it share preferences with other modules ? If so, then why ?
Answer:
XXX no answer for resources-preferences
org.openide.util.Lookup
or any similar technology to find any components to communicate with? Which ones?
Answer:
No
Question (lookup-register):
Do you register anything into lookup for other code to find?
Answer:
No.
Question (lookup-remove):
Do you remove entries of other modules from lookup?
Answer:
No.
System.getProperty
) property?
On a similar note, is there something interesting that you
pass to java.util.logging.Logger
? Or do you observe
what others log?
Answer:
No.
Question (exec-component):
Is execution of your code influenced by any (string) property
of any of your components?
Answer:
The FoldHierarchy instance is physically stored as client property of the text component with key FoldHierarchy.class.
Question (exec-ant-tasks):
Do you define or register any ant tasks that other can use?
Answer:
XXX no answer for exec-ant-tasks
Question (exec-classloader): Does your code create its own class loader(s)? Answer: No. Question (exec-reflection): Does your code use Java Reflection to execute other code? Answer: No. Question (exec-privateaccess): Are you aware of any other parts of the system calling some of your methods by reflection? Answer: No. Question (exec-process): Do you execute an external process from your module? How do you ensure that the result is the same on different platforms? Do you parse output? Do you depend on result code? Answer: No. Question (exec-introspection): Does your module use any kind of runtime type information (instanceof
,
work with java.lang.Class
, etc.)?
Answer:
No.
Question (exec-threading):
What threading models, if any, does your module adhere to? How the
project behaves with respect to threading?
Answer:
FoldHierarchy needs to be locked exclusively prior manipulation; FoldHierarchy.render(Runnable)
(or FoldHierarchy.lock()
) can be used to lock the hierarchy for an exclusive use.
java.awt.datatransfer.Transferable
?
Answer:
No clipboard support.
Typically the physical fold creation
and updating is fast compared to the collecting of the underlying
information. For example collecting of the information
for java folds requires consulting of parser information
which may not be present at the time yet so this may result
in even a few seconds delay waiting for document parsing.
Therefore the fold managers are encouraged to prepare
the fold-related data (resulting into fold boundary positions)
in a separate thread and schedule the physical fold creation
and fold hierarchy updates (which are reasonably fast)
into EDT thread (due to consistency purposes as the EDT
controls the document switching in the editor text component).
The FoldManager class javadoc contains the guiding information
as well.