/*****************************************************************************
* 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 ar.com.tadp.xml.rinzo.core.indenting;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextUtilities;
import ar.com.tadp.xml.rinzo.XMLEditorPlugin;
import ar.com.tadp.xml.rinzo.core.RinzoXMLEditor;
import ar.com.tadp.xml.rinzo.core.model.XMLNode;
/**
* Possible automatic indentation implementation
*
* @author ccancinos
*/
public class XMLAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
private RinzoXMLEditor xmlEditor;
public XMLAutoIndentStrategy(RinzoXMLEditor xmlEditor) {
this.xmlEditor = xmlEditor;
}
public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
if (command.length == 0 && command.text != null && command.offset != -1 && document.getLength() != 0
&& TextUtilities.endsWith(document.getLegalLineDelimiters(), command.text) != -1) {
try {
this.smartIndentAfterNewLine(document, command);
} catch (Exception e) {
throw new RuntimeException("Error trying to autoindent line.\n" + "text: \"" + command.text + "\""
+ "caret offset: \"" + command.caretOffset + "\"", e);
}
}
}
private void smartIndentAfterNewLine(IDocument document, DocumentCommand command) throws BadLocationException {
StringBuffer buf = new StringBuffer(command.text);
XMLNode previousNode = this.xmlEditor.getModel().getTree().getPreviousNode(command.offset);
XMLNode previousPreviousNode = this.xmlEditor.getModel().getTree().getPreviousNode(previousNode.getOffset());
if (previousNode != null) {
String indentOfPreviousNode = getIndentOfLine(document, previousNode.getOffset());
buf.append(indentOfPreviousNode);
String indentationToken = this.getIndentationToken();
String lineSeparator = this.xmlEditor.getLineSeparator();
command.shiftsCaret = false;
command.caretOffset = command.offset + indentOfPreviousNode.length() + lineSeparator.length()
+ indentationToken.length();
if ((previousNode.isEmpty() || previousNode.isTextTag()) && !previousPreviousNode.isEndTag()) {
buf.append(indentationToken);
}
if (previousNode.isEndTag() || (previousPreviousNode != null && previousPreviousNode.isEndTag())) {
command.caretOffset = command.offset + indentOfPreviousNode.length() + lineSeparator.length();
}
if (previousNode.isTag()) {
if (previousNode.getCorrespondingNode().getOffset() == command.offset) {
buf.append(indentationToken);
buf.append(lineSeparator);
buf.append(indentOfPreviousNode);
}
if (previousNode.getCorrespondingNode().getOffset() > command.offset) {
buf.append(indentationToken);
}
}
}
command.text = buf.toString();
}
private String getIndentationToken() {
return XMLEditorPlugin.getDefault().getIndentToken();
}
protected String getIndentOfLine(IDocument document, int offset) throws BadLocationException {
int line = document.getLineOfOffset(offset);
if (line <= -1) {
return "";
}
int start = document.getLineOffset(line);
int end = (start + document.getLineLength(line)) - 1;
int whiteend = findEndOfWhiteSpace(document, start, end);
return document.get(start, whiteend - start);
}
}