initial contribution
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.wiki / src / net / sourceforge / phpeclipse / wiki / editor / WikiFoldingStructureProvider.java
1 package net.sourceforge.phpeclipse.wiki.editor;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import net.sourceforge.phpeclipse.wiki.editor.model.WikipediaText;
12 import net.sourceforge.phpeclipse.wiki.editor.model.WikipediaSection;
13
14 import org.eclipse.core.runtime.IProgressMonitor;
15
16 import org.eclipse.jface.text.BadLocationException;
17 import org.eclipse.jface.text.IDocument;
18 import org.eclipse.jface.text.Position;
19 import org.eclipse.jface.text.source.Annotation;
20 import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
21 import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
22
23 public class WikiFoldingStructureProvider {
24
25   private WikiEditor fEditor;
26
27   private IDocument fDocument;
28
29   private IProgressMonitor fProgressMonitor;
30
31   public WikiFoldingStructureProvider(WikiEditor editor) {
32     fEditor = editor;
33   }
34
35   public void setProgressMonitor(IProgressMonitor progressMonitor) {
36     fProgressMonitor = progressMonitor;
37   }
38
39   public void setDocument(IDocument document) {
40     fDocument = document;
41   }
42
43   public void updateFoldingRegions(WikipediaSection section) {
44     try {
45
46       ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
47       if (model == null)
48         return;
49
50       Set currentRegions = new HashSet();
51       addFoldingRegions(currentRegions, section.getChildren());
52       updateFoldingRegions(model, currentRegions);
53     } catch (BadLocationException e) {
54       e.printStackTrace();
55     }
56   }
57
58   private void updateFoldingRegions(ProjectionAnnotationModel model, Set currentRegions) {
59     Annotation[] deletions = computeDifferences(model, currentRegions);
60
61     Map additionsMap = new HashMap();
62     for (Iterator iter = currentRegions.iterator(); iter.hasNext();)
63       additionsMap.put(new ProjectionAnnotation(), iter.next());
64
65     if ((deletions.length != 0 || additionsMap.size() != 0) && (fProgressMonitor == null || !fProgressMonitor.isCanceled()))
66       model.modifyAnnotations(deletions, additionsMap, new Annotation[] {});
67   }
68
69   private Annotation[] computeDifferences(ProjectionAnnotationModel model, Set current) {
70     List deletions = new ArrayList();
71     for (Iterator iter = model.getAnnotationIterator(); iter.hasNext();) {
72       Object annotation = iter.next();
73       if (annotation instanceof ProjectionAnnotation) {
74         Position position = model.getPosition((Annotation) annotation);
75         if (current.contains(position))
76           current.remove(position);
77         else
78           deletions.add(annotation);
79       }
80     }
81     return (Annotation[]) deletions.toArray(new Annotation[deletions.size()]);
82   }
83
84   private void addFoldingRegions(Set regions, Object[] elements) throws BadLocationException {
85     for (int i = 0; i < elements.length; i++) {
86       WikipediaSection element = (WikipediaSection) elements[i];
87       if (element.getOffset() >= 0) {
88         int startLine = fDocument.getLineOfOffset(element.getOffset());
89         int endLine = fDocument.getLineOfOffset(element.getOffset() + element.getLength());
90         if (startLine < endLine) {
91           int start = fDocument.getLineOffset(startLine);
92           int end = fDocument.getLineOffset(endLine) + fDocument.getLineLength(endLine);
93           Position position = new Position(start, end - start);
94           regions.add(position);
95         }
96
97         Object[] children = element.getChildren();
98         if (children != null) {
99           addFoldingRegions(regions, children);
100         }
101       }
102     }
103   }
104 }