--- /dev/null
+package net.sourceforge.phpeclipse.wiki.editor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.phpeclipse.wiki.editor.model.WikipediaText;
+import net.sourceforge.phpeclipse.wiki.editor.model.WikipediaSection;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+
+public class WikiFoldingStructureProvider {
+
+ private WikiEditor fEditor;
+
+ private IDocument fDocument;
+
+ private IProgressMonitor fProgressMonitor;
+
+ public WikiFoldingStructureProvider(WikiEditor editor) {
+ fEditor = editor;
+ }
+
+ public void setProgressMonitor(IProgressMonitor progressMonitor) {
+ fProgressMonitor = progressMonitor;
+ }
+
+ public void setDocument(IDocument document) {
+ fDocument = document;
+ }
+
+ public void updateFoldingRegions(WikipediaSection section) {
+ try {
+
+ ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
+ if (model == null)
+ return;
+
+ Set currentRegions = new HashSet();
+ addFoldingRegions(currentRegions, section.getChildren());
+ updateFoldingRegions(model, currentRegions);
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void updateFoldingRegions(ProjectionAnnotationModel model, Set currentRegions) {
+ Annotation[] deletions = computeDifferences(model, currentRegions);
+
+ Map additionsMap = new HashMap();
+ for (Iterator iter = currentRegions.iterator(); iter.hasNext();)
+ additionsMap.put(new ProjectionAnnotation(), iter.next());
+
+ if ((deletions.length != 0 || additionsMap.size() != 0) && (fProgressMonitor == null || !fProgressMonitor.isCanceled()))
+ model.modifyAnnotations(deletions, additionsMap, new Annotation[] {});
+ }
+
+ private Annotation[] computeDifferences(ProjectionAnnotationModel model, Set current) {
+ List deletions = new ArrayList();
+ for (Iterator iter = model.getAnnotationIterator(); iter.hasNext();) {
+ Object annotation = iter.next();
+ if (annotation instanceof ProjectionAnnotation) {
+ Position position = model.getPosition((Annotation) annotation);
+ if (current.contains(position))
+ current.remove(position);
+ else
+ deletions.add(annotation);
+ }
+ }
+ return (Annotation[]) deletions.toArray(new Annotation[deletions.size()]);
+ }
+
+ private void addFoldingRegions(Set regions, Object[] elements) throws BadLocationException {
+ for (int i = 0; i < elements.length; i++) {
+ WikipediaSection element = (WikipediaSection) elements[i];
+ if (element.getOffset() >= 0) {
+ int startLine = fDocument.getLineOfOffset(element.getOffset());
+ int endLine = fDocument.getLineOfOffset(element.getOffset() + element.getLength());
+ if (startLine < endLine) {
+ int start = fDocument.getLineOffset(startLine);
+ int end = fDocument.getLineOffset(endLine) + fDocument.getLineLength(endLine);
+ Position position = new Position(start, end - start);
+ regions.add(position);
+ }
+
+ Object[] children = element.getChildren();
+ if (children != null) {
+ addFoldingRegions(regions, children);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file