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); } } } } }