/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Common Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors: IBM Corporation - initial API and implementation
******************************************************************************/
package com.liferay.ide.velocity.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 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;
import com.liferay.ide.velocity.vaulttec.ui.model.ITreeNode;
public class VelocityFoldingStructureProvider
{
private VelocityEditor fEditor;
private IDocument fDocument;
private IProgressMonitor fProgressMonitor;
public VelocityFoldingStructureProvider(VelocityEditor editor)
{
fEditor = editor;
}
public void setProgressMonitor(IProgressMonitor progressMonitor)
{
fProgressMonitor = progressMonitor;
}
public void setDocument(IDocument document)
{
fDocument = document;
}
public void updateFoldingRegions(ITreeNode recipe)
{
try
{
ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
if (model == null || recipe == null) return;
Set currentRegions = new HashSet();
Object[] children = recipe.getChildren();
if (children != null)
{
addFoldingRegions(currentRegions, children);
}
updateFoldingRegions(model, currentRegions);
}
catch (ClassCastException e)
{
e.printStackTrace();
}
catch (BadLocationException e)
{
e.printStackTrace();
}
}
public void updateFoldingRegions(Object[] children)
{
try
{
ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
if (model == null || children == null) return;
Set currentRegions = new HashSet();
if (children != null)
{
addFoldingRegions(currentRegions, children);
}
updateFoldingRegions(model, currentRegions);
}
catch (ClassCastException e)
{
e.printStackTrace();
}
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++)
{
ITreeNode element = (ITreeNode) elements[i];
int startLine = element.getStartLine() - 1;
int endLine = element.getEndLine() - 1;
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 = (Object[]) element.getChildren();
if (children != null) addFoldingRegions(regions, children);
}
}
}