/***************************************************************************** * This file is part of Rinzo * * Author: Claudio Cancinos WWW: https://sourceforge.net/projects/editorxml Copyright (C): 2008, Claudio Cancinos * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this program; If not, see * <http://www.gnu.org/licenses/> ****************************************************************************/ package com.amalto.workbench.widgets.xmlviewer.model.visitor; import java.util.HashMap; import java.util.Set; 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 com.amalto.workbench.widgets.xmlviewer.model.XMLNode; import com.amalto.workbench.widgets.xmlviewer.utils.FileUtils; /** * Generates the list of segments to fold/unfold in the editor's projection * */ public class FoldingNodesVisitor implements HierarchicalVisitor { private HashMap<ProjectionAnnotation, Position> newAnnotations = new HashMap<ProjectionAnnotation, Position>(); private final IDocument document; public FoldingNodesVisitor(IDocument document) { this.document = document; } public boolean visitStart(XMLNode node) { try { if(!node.isEmpty() && (node.isTag() || node.isCdata()) && !node.isEndTag() && !this.isInSameLine(node, node.getCorrespondingNode())) { int end = node.getCorrespondingNode().getOffset() + node.getCorrespondingNode().getLength(); int length = end - node.getOffset() + FileUtils.LINE_SEPARATOR.length(); if ((node.getOffset() + length) > this.document.getLength()) { length = length - FileUtils.LINE_SEPARATOR.length(); } Position position = new Position(node.getOffset(), length); this.newAnnotations.put(new ProjectionAnnotation(), position); } } catch (Exception e) { // DO NOTHING. Failing folding detection should not cause an error. } return true; } public boolean visitEnd(XMLNode node) { return true; } public boolean visitChild(XMLNode node) { try { if((node.isCommentTag() || node.isCdata()) && !this.isInSameLine(node.getOffset(), node.getOffset() + node.getLength())) { int length = node.getLength() + FileUtils.LINE_SEPARATOR.length(); Position position = new Position(node.getOffset(), length); this.newAnnotations.put(new ProjectionAnnotation(), position); } } catch (Exception e) { // DO NOTHING. Failing folding detection should not cause an error. } return true; } public HashMap<ProjectionAnnotation, Position> getAnnotationsMap() { return this.newAnnotations; } public Annotation[] getAnnotations() { Set<ProjectionAnnotation> keySet = this.newAnnotations.keySet(); Annotation[] keys = new Annotation[keySet.size()]; keySet.toArray(keys); return keys; } private boolean isInSameLine(XMLNode node, XMLNode correspondingNode) { if(node == null || correspondingNode == null) { return false; } else { return this.isInSameLine(node.getOffset(), correspondingNode.getOffset()); } } private boolean isInSameLine(int start, int end) { try { return this.document.getLineOfOffset(start) == this.document.getLineOfOffset(end); } catch (BadLocationException e) { return false; } } }