// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package com.amalto.workbench.widgets.xmlviewer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IOverviewRuler;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.jface.text.source.projection.ProjectionSupport;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import com.amalto.workbench.MDMWorbenchPlugin;
import com.amalto.workbench.widgets.xmlviewer.action.IXMLActionDefinitionIds;
import com.amalto.workbench.widgets.xmlviewer.action.TextViewerOperationHandler;
import com.amalto.workbench.widgets.xmlviewer.annotation.TagPairMatcher;
import com.amalto.workbench.widgets.xmlviewer.model.XMLTreeModel;
import com.amalto.workbench.widgets.xmlviewer.model.tags.XMLTagDefinitionProvider;
import com.amalto.workbench.widgets.xmlviewer.model.tags.nodef.NoDefTagDefinitionProvider;
import com.amalto.workbench.widgets.xmlviewer.model.visitor.FoldingNodesVisitor;
import com.amalto.workbench.widgets.xmlviewer.partition.XMLDocumentPartitioner;
import com.amalto.workbench.widgets.xmlviewer.resources.DocumentStructureDeclaration;
import com.amalto.workbench.widgets.xmlviewer.scanner.XMLPartitionScanner;
import com.amalto.workbench.widgets.xmlviewer.validator.XMLValidator;
/**
* DOC hbhong class global comment. Detailled comment
*/
public class XMLSourceViewer extends ProjectionViewer {
/**
* Preference key for showing the line number ruler.
*/
private final static String LINE_NUMBER_RULER = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
/**
* Preference key for showing the overview ruler.
*/
private final static String OVERVIEW_RULER = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER;
/**
* Preference key for highlighting current line.
*/
private final static String CURRENT_LINE = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE;
/**
* Preference key for highlight color of current line.
*/
private final static String CURRENT_LINE_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
/**
* Preference key for showing print margin ruler.
*/
private final static String PRINT_MARGIN = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN;
/**
* Preference key for print margin ruler color.
*/
private final static String PRINT_MARGIN_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
/**
* Preference key for print margin ruler column.
*/
private final static String PRINT_MARGIN_COLUMN = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
public static final String ID = "testxmleditor.XMLView"; //$NON-NLS-1$
private IOverviewRuler fOverviewRuler;
// private IVerticalRuler fVerticalRuler;
private MarkerAnnotationPreferences fAnnotationPreferences;
private SourceViewerDecorationSupport fSourceViewerDecorationSupport;
private ProjectionAnnotationModel annotationModel;
private XMLTreeModel treeModel;
private ProjectionSupport projectionSupport;
// shared command handlers
static Map<String, IHandler> handlers = new HashMap<String, IHandler>();
// handler service
IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
// command handler activations
Map<IHandler, IHandlerActivation> handlerActivations = new HashMap<IHandler, IHandlerActivation>();
/**
* DOC hbhong XMLSourceViewer constructor comment.
*
* @param parent
* @param ruler
* @param overviewRuler
* @param showsAnnotationOverview
* @param styles
*/
public XMLSourceViewer(Composite parent, IVerticalRuler ruler, IOverviewRuler overviewRuler, boolean showsAnnotationOverview,
int styles) {
super(parent, ruler, overviewRuler, showsAnnotationOverview, styles);
this.fOverviewRuler = overviewRuler;
}
private MarkerAnnotationPreferences getAnnotationPreferences() {
if (fAnnotationPreferences == null) {
fAnnotationPreferences = new MarkerAnnotationPreferences();
// force init
fAnnotationPreferences.getAnnotationPreferences();
}
return fAnnotationPreferences;
}
public void initilize() {
document = getNewDocument();
initAnnotationModel();
intallDocument(document);
installProjectSupport();
getSourceViewerDecorationSupport(this);
// IColumnSupport columnSupport = (IColumnSupport) getAdapter(IColumnSupport.class);
// RulerColumnDescriptor lineNumberColumnDescriptor = RulerColumnRegistry.getDefault().getColumnDescriptor(
// LineNumberColumn.ID);
// if (lineNumberColumnDescriptor != null)
// columnSupport.setColumnVisible(lineNumberColumnDescriptor, true);
installValidator();
createHandlers();
updateFont();
//
setEditable(true);
}
/**
* DOC hbhong Comment method "updateFont".
*/
private void updateFont() {
getTextWidget().setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
}
/**
* DOC hbhong Comment method "installProjectSupport".
*/
private void installProjectSupport() {
XMLSourceViewerHelper helper = XMLSourceViewerHelper.getInstance();
projectionSupport = new ProjectionSupport(this, helper.getAnnotationAccess(), helper.getSharedColors());
projectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
projectionSupport.install();
// turn projection mode on
this.doOperation(ProjectionViewer.TOGGLE);
}
private void installValidator() {
if (document != null) {
final XMLValidator validator = new XMLValidator(document, annotationModel);
IDocumentListener validateListener = new IDocumentListener() {
public void documentChanged(DocumentEvent event) {
validator.validate(document);
}
public void documentAboutToBeChanged(DocumentEvent event) {
}
};
document.addDocumentListener(validateListener);
}
}
private void initAnnotationModel() {
annotationModel = new ProjectionAnnotationModel();
}
private IDocument getNewDocument() {
final IDocument document = new Document();
return document;
}
private void intallDocument(IDocument document) {
if (document != null) {
IDocumentPartitioner partitioner = new XMLDocumentPartitioner(new XMLPartitionScanner(),
XMLPartitionScanner.CONTENT_TYPES);
partitioner.connect(document);
document.setDocumentPartitioner(partitioner);
treeModel = new XMLTreeModel(this);
treeModel.createTree(document);
document.addDocumentListener(treeModel);
}
setDocument(document, annotationModel);
}
public XMLTreeModel getTreeModel() {
return this.treeModel;
}
protected IOverviewRuler getOverviewRuler() {
return fOverviewRuler;
}
protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) {
if (fSourceViewerDecorationSupport == null) {
fSourceViewerDecorationSupport = new SourceViewerDecorationSupport(viewer, getOverviewRuler(), XMLSourceViewerHelper
.getInstance().getAnnotationAccess(), XMLSourceViewerHelper.getInstance().getSharedColors());
// patch see SourceViewerDecorationSupport
AnnotationPreference info = new AnnotationPreference();
info.setAnnotationType(XMLValidator.TYPE);
info.setTextPreferenceKey("errorIndication"); //$NON-NLS-1$
info.setTextStylePreferenceKey("errorTextStyle"); //$NON-NLS-1$
info.setColorPreferenceKey("errorIndicationColor"); //$NON-NLS-1$
getPreferenceStore().setValue(info.getTextPreferenceKey(), true);
getPreferenceStore().setValue(info.getTextStylePreferenceKey(), "PROBLEM_UNDERLINE"); //$NON-NLS-1$
getPreferenceStore().setValue(info.getColorPreferenceKey(), "255, 0, 0"); //$NON-NLS-1$
configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
}
return fSourceViewerDecorationSupport;
}
protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
Iterator e = getAnnotationPreferences().getAnnotationPreferences().iterator();
while (e.hasNext()) {
support.setAnnotationPreference((AnnotationPreference) e.next());
// support.setAnnotationPainterPreferenceKeys(DefaultMarkerAnnotationAccess.UNKNOWN,
// UNKNOWN_INDICATION_COLOR,
// UNKNOWN_INDICATION, UNKNOWN_INDICATION_IN_OVERVIEW_RULER, 0);
}
support.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
support.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
support.setSymbolicFontName(getFontPropertyPreferenceKey());
support.setCharacterPairMatcher(new TagPairMatcher());
support.install(getPreferenceStore());
}
private IPreferenceStore getPreferenceStore() {
return MDMWorbenchPlugin.getDefault().getPreferenceStore();
}
/*
* Create command handlers
*/
protected void createHandlers() {
// content assist
IHandler handler = new TextViewerOperationHandler(this, ISourceViewer.CONTENTASSIST_PROPOSALS);
handlers.put(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, handler);
// quick assist
handler = new TextViewerOperationHandler(this, ISourceViewer.QUICK_ASSIST);
handlers.put(ITextEditorActionDefinitionIds.QUICK_ASSIST, handler);
// text formatting
handler = new TextViewerOperationHandler(this, ISourceViewer.FORMAT);
handlers.put(IXMLActionDefinitionIds.FORMAT, handler);
// activate handlers
activateHandlers();
}
/**
* Activate all handlers
*/
protected void activateHandlers() {
// if handler service is null, return
if (handlerService == null) {
return;
}
// activate handlers if it is not active
Iterator<String> i = handlers.keySet().iterator();
while (i.hasNext()) {
String id = i.next();
IHandler handler = handlers.get(id);
IHandlerActivation activation = handlerActivations.get(handler);
if (activation == null) {
activation = handlerService.activateHandler(id, handler);
handlerActivations.put(handler, activation);
}
}
}
@Override
protected void handleDispose() {
if (handlerService != null) {
for (IHandlerActivation activation : handlerActivations.values()) {
handlerService.deactivateHandler(activation);
}
}
super.handleDispose();
}
public XMLTagDefinitionProvider getTagContainersRegistry() {
try {
Collection<DocumentStructureDeclaration> schemaDefinitions = treeModel.getSchemaDefinitions();
DocumentStructureDeclaration structureDeclaration = treeModel.getDTDDefinition();
XMLTagDefinitionProvider registry = this.containersRegistry;
return registry;
} catch (Exception exception) {
return this.containersRegistry;
}
}
private NoDefTagDefinitionProvider containersRegistry = new NoDefTagDefinitionProvider();
private Annotation[] oldAnnotations;
private IDocument document;
private IConfigurationElement configElement;
public NoDefTagDefinitionProvider getCodeTagContainersRegistry() {
return this.containersRegistry;
}
public void updateFoldingStructure() {
FoldingNodesVisitor visitor = new FoldingNodesVisitor(document);
treeModel.getTree().accept(visitor);
HashMap<ProjectionAnnotation, Position> newAnnotations = visitor.getAnnotationsMap();
Annotation[] annotations = visitor.getAnnotations();
if (annotationModel != null) {
annotationModel.modifyAnnotations(oldAnnotations, newAnnotations, null);
}
oldAnnotations = annotations;
}
//
protected final String getFontPropertyPreferenceKey() {
String symbolicFontName = getSymbolicFontName();
if (symbolicFontName != null) {
return symbolicFontName;
}
return JFaceResources.TEXT_FONT;
}
protected IConfigurationElement getConfigurationElement() {
return configElement;
}
private String getSymbolicFontName() {
if (getConfigurationElement() != null) {
return getConfigurationElement().getAttribute("symbolicFontName"); //$NON-NLS-1$
}
return null;
}
public void setText(String text) {
document.set(text);
}
public String getText() {
return document.get();
}
}