/*****************************************************************************
* 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;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.quickassist.QuickAssistAssistant;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.internal.editors.text.EditorsPlugin;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import ar.com.tadp.xml.rinzo.XMLEditorPlugin;
import ar.com.tadp.xml.rinzo.core.contentassist.processors.CompositeContentAssistProcessor;
import ar.com.tadp.xml.rinzo.core.contentassist.processors.CompositeXMLContentAssistProcessor;
import ar.com.tadp.xml.rinzo.core.contentassist.processors.IXMLContentAssistProcessor;
import ar.com.tadp.xml.rinzo.core.eclipse.copies.HTMLAnnotationHover;
import ar.com.tadp.xml.rinzo.core.eclipse.copies.HTMLTextPresenter;
import ar.com.tadp.xml.rinzo.core.highlighting.ColorManager;
import ar.com.tadp.xml.rinzo.core.highlighting.IXMLColorConstants;
import ar.com.tadp.xml.rinzo.core.highlighting.NonRuleBasedDamagerRepairer;
import ar.com.tadp.xml.rinzo.core.highlighting.XMLScanner;
import ar.com.tadp.xml.rinzo.core.highlighting.XMLTagScanner;
import ar.com.tadp.xml.rinzo.core.indenting.XMLAutoIndentStrategy;
import ar.com.tadp.xml.rinzo.core.partitioner.IXMLPartitions;
import ar.com.tadp.xml.rinzo.core.partitioner.XMLPartitionScanner;
import ar.com.tadp.xml.rinzo.core.utils.FileUtils;
/**
*
* @author ccancinos
*/
public class XMLEditorConfiguration extends SourceViewerConfiguration implements EditorConfiguration {
private static final String RINZO_XML_CONTENTASIST_EXTENSION_POINT_ID = "ar.com.tadp.xml.rinzo.core.xmlContentAssist";
private static final String RINZO_CONTENTASIST_EXTENSION_POINT_ID = "ar.com.tadp.xml.rinzo.core.contentAssist";
private ColorManager colorManager;
private ContentAssistant contentAssist;
private XMLTagScanner tagScanner;
private XMLScanner scanner;
private IPreferenceStore preferenceStore;
private final RinzoXMLEditor xmlEditor;
public XMLEditorConfiguration() {
this(null);
}
public XMLEditorConfiguration(RinzoXMLEditor xmlEditor) {
this.xmlEditor = xmlEditor;
colorManager = new ColorManager();
}
public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
return XMLPartitionScanner.CONTENT_TYPES;
}
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
PresentationReconciler reconciler = new PresentationReconciler();
DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getXMLTagScanner());
reconciler.setDamager(dr, IXMLPartitions.XML_TAG);
reconciler.setRepairer(dr, IXMLPartitions.XML_TAG);
reconciler.setDamager(dr, IXMLPartitions.XML_INCOMPLETETAG);
reconciler.setDamager(dr, IXMLPartitions.XML_ENDTAG);
reconciler.setRepairer(dr, IXMLPartitions.XML_ENDTAG);
reconciler.setDamager(dr, IXMLPartitions.XML_EMPTYTAG);
reconciler.setRepairer(dr, IXMLPartitions.XML_EMPTYTAG);
dr = new DefaultDamagerRepairer(getXMLScanner());
reconciler.setDamager(dr, IXMLPartitions.XML_TEXT);
reconciler.setRepairer(dr, IXMLPartitions.XML_TEXT);
NonRuleBasedDamagerRepairer ndr = new NonRuleBasedDamagerRepairer(new TextAttribute(colorManager.getColor(IXMLColorConstants.XML_COMMENT), null, colorManager.isBold(IXMLColorConstants.XML_COMMENT)));
reconciler.setDamager(ndr, IXMLPartitions.XML_COMMENT);
reconciler.setRepairer(ndr, IXMLPartitions.XML_COMMENT);
NonRuleBasedDamagerRepairer ndr2 = new NonRuleBasedDamagerRepairer(new TextAttribute(colorManager.getColor(IXMLColorConstants.DECLARATION), null, colorManager.isBold(IXMLColorConstants.DECLARATION)));
reconciler.setDamager(ndr2, IXMLPartitions.XML_DECLARATION);
reconciler.setRepairer(ndr2, IXMLPartitions.XML_DECLARATION);
NonRuleBasedDamagerRepairer ndr3 = new NonRuleBasedDamagerRepairer(new TextAttribute(colorManager.getColor(IXMLColorConstants.PROC_INSTR), null, colorManager.isBold(IXMLColorConstants.PROC_INSTR)));
reconciler.setDamager(ndr3, IXMLPartitions.XML_PI);
reconciler.setRepairer(ndr3, IXMLPartitions.XML_PI);
NonRuleBasedDamagerRepairer ndr4 = new NonRuleBasedDamagerRepairer(new TextAttribute(colorManager.getColor(IXMLColorConstants.CDATA), null, colorManager.isBold(IXMLColorConstants.CDATA)));
reconciler.setDamager(ndr4, IXMLPartitions.XML_CDATA);
reconciler.setRepairer(ndr4, IXMLPartitions.XML_CDATA);
return reconciler;
}
protected ITokenScanner getXMLScanner() {
if(scanner == null) {
scanner = new XMLScanner(colorManager);
scanner.setDefaultReturnToken(new Token(new TextAttribute(colorManager.getColor(IXMLColorConstants.DEFAULT))));
}
return scanner;
}
protected XMLTagScanner getXMLTagScanner() {
if(tagScanner == null) {
tagScanner = new XMLTagScanner(colorManager);
tagScanner.setDefaultReturnToken(new Token(new TextAttribute(colorManager.getColor(IXMLColorConstants.TAG))));
}
return tagScanner;
}
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
if(this.contentAssist == null) {
this.contentAssist = new ContentAssistant();
this.addContentAssistProcessors(this.contentAssist);
this.contentAssist.setProposalPopupOrientation(20);
this.contentAssist.setContextInformationPopupOrientation(10);
this.contentAssist.setInformationControlCreator(getInformationControlCreator(sourceViewer));
this.contentAssist.enableAutoActivation(true);
}
return this.contentAssist;
}
private void addContentAssistProcessors(ContentAssistant assist) {
CompositeContentAssistProcessor compositeProcessor = new CompositeContentAssistProcessor();
IConfigurationElement[] configurationElements = Platform.getExtensionRegistry().getConfigurationElementsFor(
RINZO_XML_CONTENTASIST_EXTENSION_POINT_ID);
if (configurationElements != null) {
CompositeXMLContentAssistProcessor xmlCompositeProcessor = new CompositeXMLContentAssistProcessor(
this.xmlEditor);
for (int i = 0; i < configurationElements.length; i++) {
IConfigurationElement element = configurationElements[i];
try {
IXMLContentAssistProcessor processor = (IXMLContentAssistProcessor) element
.createExecutableExtension("class");
xmlCompositeProcessor.addProcessor(processor);
} catch (CoreException e) {
XMLEditorPlugin.logErrorMessage("cannot create processor: " + element.getName());
XMLEditorPlugin.log(e);
e.printStackTrace();
}
}
compositeProcessor.addProcessor(xmlCompositeProcessor);
}
configurationElements = Platform.getExtensionRegistry().getConfigurationElementsFor(RINZO_CONTENTASIST_EXTENSION_POINT_ID);
if (configurationElements != null) {
CompositeContentAssistProcessor basicCompositeProcessor = new CompositeContentAssistProcessor();
for (int i = 0; i < configurationElements.length; i++) {
IConfigurationElement element = configurationElements[i];
try {
IContentAssistProcessor processor = (IContentAssistProcessor) element.createExecutableExtension("class");
basicCompositeProcessor.addProcessor(processor);
} catch (CoreException e) {
XMLEditorPlugin.logErrorMessage("cannot create processor: " + element.getName());
XMLEditorPlugin.log(e);
e.printStackTrace();
}
}
compositeProcessor.addProcessor(basicCompositeProcessor);
}
assist.setContentAssistProcessor(compositeProcessor, IXMLPartitions.XML_TAG);
assist.setContentAssistProcessor(compositeProcessor, IXMLPartitions.XML_EMPTYTAG);
assist.setContentAssistProcessor(compositeProcessor, IXMLPartitions.XML_INCOMPLETETAG);
assist.setContentAssistProcessor(compositeProcessor, IDocument.DEFAULT_CONTENT_TYPE);
assist.setContentAssistProcessor(compositeProcessor, IXMLPartitions.XML_TEXT);
}
public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, 0, 0, new HTMLTextPresenter());
}
};
}
public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
IQuickAssistAssistant assistant= new QuickAssistAssistant();
assistant.setQuickAssistProcessor(new XMLCorrectionProcessor(this.xmlEditor));
assistant.setInformationControlCreator(getQuickAssistAssistantInformationControlCreator());
return assistant;
}
/**
* Returns the information control creator for the quick assist assistant.
*
* @return the information control creator
* @since 3.3
*/
private IInformationControlCreator getQuickAssistAssistantInformationControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, EditorsPlugin.getAdditionalInfoAffordanceString());
}
};
}
public int getTabWidth(ISourceViewer sourceViewer) {
return getPreferenceStore().getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
}
public IPreferenceStore getPreferenceStore() {
if(preferenceStore == null)
preferenceStore = XMLEditorPlugin.getDefault().getPreferenceStore();
return preferenceStore;
}
public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
return new IAutoEditStrategy[] { new XMLAutoIndentStrategy(this.xmlEditor) };
}
public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
return new HTMLAnnotationHover();
}
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
return new MultipleLinesTextHover(sourceViewer, this.xmlEditor);
}
public void editorContextMenuAboutToShow(IMenuManager menu) {
Separator item = new Separator("rinzoAdditions");
menu.appendToGroup("group.save", item);
menu.add(item);
}
public static String[] getIndentPrefixesByPreferences() {
List<String> prefixes = new ArrayList<String>();
// prefix[0] is either '\t' or ' ' x tabWidth, depending on preference
boolean useSpaces = XMLEditorPlugin.getDefault().getPreferenceStore()
.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS);
int indentationWidth = XMLEditorPlugin.getDefault().getPreferenceStore()
.getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
for (int i = 0; i <= indentationWidth; i++) {
StringBuffer prefix = new StringBuffer();
boolean appendTab = false;
if (useSpaces) {
for (int j = 0; j + i < indentationWidth; j++) {
prefix.append(' ');
}
if (i != 0) {
appendTab = true;
}
} else {
for (int j = 0; j < i; j++) {
prefix.append(' ');
}
if (i != indentationWidth) {
appendTab = true;
}
}
if (appendTab) {
prefix.append(FileUtils.TAB);
prefixes.add(prefix.toString());
// remove the tab so that indentation - tab is also an indent prefix
prefix.deleteCharAt(prefix.length() - 1);
}
prefixes.add(prefix.toString());
}
prefixes.add("");
return (String[]) prefixes.toArray(new String[prefixes.size()]);
}
@Override
public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) {
return getIndentPrefixesByPreferences();
}
}