blob: ca234c88496bf89b1d88d8041851275c217e25ff [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2009 Standards for Technology in Automotive Retail and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* David Carver (STAR) - initial api and implementation
*******************************************************************************/
package org.eclipse.wst.xsl.ui.internal.style;
import java.util.Collection;
import java.util.Map;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.ui.internal.preferences.ui.ColorHelper;
import org.eclipse.wst.sse.ui.internal.provisional.style.AbstractLineStyleProvider;
import org.eclipse.wst.sse.ui.internal.provisional.style.Highlighter;
import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
import org.eclipse.wst.sse.ui.internal.provisional.style.ReconcilerHighlighter;
import org.eclipse.wst.sse.ui.internal.util.EditorUtility;
import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
import org.eclipse.wst.xsl.ui.internal.XSLUIPlugin;
/**
* This implements a Syntax Line Style Provider for XSL. It leverages some
* information from the XML Syntax Coloring, but adds specific coloring for XSL
* specific elements and attributes.
*
* @author David Carver
* @since 1.0
*
*/
public class LineStyleProviderForXSL extends AbstractLineStyleProvider implements LineStyleProvider {
protected IStructuredDocument structuredDocument;
protected Highlighter highlighter;
private boolean initialized;
protected ReconcilerHighlighter recHighlighter = null;
private IPreferenceStore xmlPreferenceStore = null;
private IPreferenceStore xslPreferenceStore = null;
private IPreferenceStore combinedPreferenceStore = null;
private IPropertyChangeListener preferenceListener = new PropertyChangeListener();
private class PropertyChangeListener implements IPropertyChangeListener {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
// have to do it this way so others can override the method
handlePropertyChange(event);
}
}
@Override
protected void commonInit(IStructuredDocument document,
Highlighter highlighter) {
structuredDocument = document;
this.highlighter = highlighter;
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider#
* prepareRegions(org.eclipse.jface.text.ITypedRegion, int, int,
* java.util.Collection)
*/
@Override
public boolean prepareRegions(ITypedRegion typedRegion,
int lineRequestStart, int lineRequestLength, Collection holdResults) {
final int partitionStartOffset = typedRegion.getOffset();
final int partitionLength = typedRegion.getLength();
IStructuredDocumentRegion structuredDocumentRegion = getDocument()
.getRegionAtCharacterOffset(partitionStartOffset);
boolean handled = false;
handled = prepareTextRegions(structuredDocumentRegion,
partitionStartOffset, partitionLength, holdResults);
return handled;
}
/**
* @param region
* @param start
* @param length
* @param holdResults
* @return
*/
protected boolean prepareTextRegion(ITextRegionCollection blockedRegion,
int partitionStartOffset, int partitionLength,
Collection holdResults) {
boolean handled = false;
final int partitionEndOffset = partitionStartOffset + partitionLength
- 1;
ITextRegion region = null;
ITextRegionList regions = blockedRegion.getRegions();
StyleRange styleRange = null;
for (int i = 0; i < regions.size(); i++) {
region = regions.get(i);
TextAttribute attr = null;
TextAttribute previousAttr = null;
if (blockedRegion.getStartOffset(region) > partitionEndOffset)
break;
if (blockedRegion.getEndOffset(region) <= partitionStartOffset)
continue;
if (region instanceof ITextRegionCollection) {
handled = prepareTextRegion((ITextRegionCollection) region,
partitionStartOffset, partitionLength, holdResults);
} else {
attr = getAttributeFor(blockedRegion, region);
if (attr != null) {
handled = true;
styleRange = applyStyleRange(blockedRegion,
partitionStartOffset, partitionLength, holdResults,
region, styleRange, attr, previousAttr);
} else {
previousAttr = null;
}
}
}
return handled;
}
private StyleRange applyStyleRange(ITextRegionCollection blockedRegion,
int partitionStartOffset, int partitionLength,
Collection holdResults, ITextRegion region, StyleRange styleRange,
TextAttribute attr, TextAttribute previousAttr) {
if (equalsPreviousAttribute(styleRange, attr, previousAttr)) {
styleRange.length += region.getLength();
} else {
styleRange = createStyleRange(blockedRegion, region, attr,
partitionStartOffset, partitionLength);
holdResults.add(styleRange);
previousAttr = attr;
}
return styleRange;
}
private boolean equalsPreviousAttribute(StyleRange styleRange,
TextAttribute attr, TextAttribute previousAttr) {
return (styleRange != null) && (previousAttr != null)
&& (previousAttr.equals(attr));
}
protected boolean prepareTextRegions(
IStructuredDocumentRegion structuredDocumentRegion,
int partitionStartOffset, int partitionLength,
Collection holdResults) {
boolean handled = false;
final int partitionEndOffset = partitionStartOffset + partitionLength
- 1;
while (structuredDocumentRegion != null
&& structuredDocumentRegion.getStartOffset() <= partitionEndOffset) {
ITextRegion region = null;
ITextRegionList regions = structuredDocumentRegion.getRegions();
StyleRange styleRange = null;
for (int i = 0; i < regions.size(); i++) {
region = regions.get(i);
TextAttribute attr = null;
TextAttribute previousAttr = null;
if (structuredDocumentRegion.getStartOffset(region) > partitionEndOffset)
break;
if (structuredDocumentRegion.getEndOffset(region) <= partitionStartOffset)
continue;
if (region instanceof ITextRegionCollection) {
boolean handledCollection = (prepareTextRegion(
(ITextRegionCollection) region,
partitionStartOffset, partitionLength, holdResults));
handled = (!handled) ? handledCollection : handled;
} else {
attr = getAttributeFor(structuredDocumentRegion, region);
if (attr == null) {
previousAttr = null;
} else {
handled = true;
styleRange = applyStyleRange(structuredDocumentRegion,
partitionStartOffset, partitionLength,
holdResults, region, styleRange, attr,
previousAttr);
}
}
}
structuredDocumentRegion = structuredDocumentRegion.getNext();
}
return handled;
}
private StyleRange createStyleRange(
ITextRegionCollection textRegionCollection, ITextRegion textRegion,
TextAttribute attr, int startOffset, int length) {
int startingOffset = textRegionCollection.getStartOffset(textRegion);
if (startingOffset < startOffset)
startingOffset = startOffset;
int textEnd = startingOffset
+ textRegionCollection.getText(textRegion).length();
int maxOffset = startOffset + length;
int endingOffset = textRegionCollection.getEndOffset(textRegion);
if (textEnd < endingOffset)
endingOffset = textEnd;
if (endingOffset > maxOffset)
endingOffset = maxOffset;
StyleRange result = new StyleRange(startingOffset, endingOffset
- startingOffset, attr.getForeground(), attr.getBackground(),
attr.getStyle());
if ((attr.getStyle() & TextAttribute.STRIKETHROUGH) != 0) {
result.strikeout = true;
}
if ((attr.getStyle() & TextAttribute.UNDERLINE) != 0) {
result.underline = true;
}
return result;
}
@Override
protected TextAttribute getAttributeFor(ITextRegionCollection collection,
ITextRegion textRegion) {
if (textRegion == null) {
return XMLTextAttributeMap.getInstance()
.getTextAttributeMap().get(IStyleConstantsXML.CDATA_TEXT);
}
String type = textRegion.getType();
if (collection.getText().contains("xsl:")) { //$NON-NLS-1$
return getXSLAttribute(type);
}
return getXMLAttribute(type);
}
private TextAttribute getXSLAttribute(String type) {
Map<String, String> regionMap = XSLRegionMap.getInstance()
.getRegionMap();
Map<String, TextAttribute> textAttributes = XSLTextAttributeMap
.getInstance().getTextAttributeMap();
return getTextAttribute(type, regionMap, textAttributes);
}
private TextAttribute getXMLAttribute(String type) {
Map<String, String> regionMap = XMLRegionMap.getInstance()
.getRegionMap();
Map<String, TextAttribute> textAttributes = XMLTextAttributeMap
.getInstance().getTextAttributeMap();
return getTextAttribute(type, regionMap, textAttributes);
}
private TextAttribute getTextAttribute(String type,
Map<String, String> regionMap,
Map<String, TextAttribute> textAttrMap) {
return textAttrMap.get(regionMap.get(type));
}
@Override
protected void handlePropertyChange(PropertyChangeEvent event) {
String styleKey = null;
if (event == null)
return;
String prefKey = event.getProperty();
// check if preference changed is a style preference
if (IStyleConstantsXSL.TAG_NAME.equals(prefKey)) {
styleKey = IStyleConstantsXSL.TAG_NAME;
}
if (IStyleConstantsXSL.TAG_BORDER.equals(prefKey)) {
styleKey = IStyleConstantsXSL.TAG_BORDER;
}
if (IStyleConstantsXSL.TAG_ATTRIBUTE_NAME.equals(prefKey)) {
styleKey = IStyleConstantsXSL.TAG_ATTRIBUTE_NAME;
}
if (IStyleConstantsXSL.TAG_ATTRIBUTE_VALUE.equals(prefKey)) {
styleKey = IStyleConstantsXSL.TAG_ATTRIBUTE_VALUE;
}
if (styleKey == null)
return;
if (styleKey != null) {
// overwrite style preference with new value
addTextAttribute(styleKey);
}
if(recHighlighter != null)
recHighlighter.refreshDisplay();
}
/**
* Looks up the colorKey in the preference store and adds the style
* information to list of TextAttributes
*
* @param colorKey
*/
@Override
protected void addTextAttribute(String colorKey) {
if (getColorPreferences() != null) {
String prefString = getColorPreferences().getString(colorKey);
String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
if (stylePrefs != null) {
RGB foreground = ColorHelper.toRGB(stylePrefs[0]);
RGB background = ColorHelper.toRGB(stylePrefs[1]);
boolean bold = Boolean.valueOf(stylePrefs[2]).booleanValue();
boolean italic = Boolean.valueOf(stylePrefs[3]).booleanValue();
boolean strikethrough = Boolean.valueOf(stylePrefs[4]).booleanValue();
boolean underline = Boolean.valueOf(stylePrefs[5]).booleanValue();
int style = SWT.NORMAL;
if (bold) {
style = style | SWT.BOLD;
}
if (italic) {
style = style | SWT.ITALIC;
}
if (strikethrough) {
style = style | TextAttribute.STRIKETHROUGH;
}
if (underline) {
style = style | TextAttribute.UNDERLINE;
}
updateTextAttribute(colorKey, foreground, background, style);
}
}
}
private void updateTextAttribute(String colorKey, RGB foreground,
RGB background, int style) {
TextAttribute createTextAttribute = createTextAttribute(foreground, background, style);
TextAttribute textAttribute =
XSLTextAttributeMap.getInstance().getTextAttributeMap().get(colorKey);
if (textAttribute != null) {
XSLTextAttributeMap.getInstance().getTextAttributeMap().put(colorKey, createTextAttribute);
return;
}
textAttribute =
XMLTextAttributeMap.getInstance().getTextAttributeMap().get(colorKey);
if (textAttribute != null) {
XMLTextAttributeMap.getInstance().getTextAttributeMap().put(colorKey, createTextAttribute);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider#init
* (org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument,
* org.eclipse.wst.sse.ui.internal.provisional.style.Highlighter)
*/
@Override
public void init(IStructuredDocument document, Highlighter highlighter) {
commonInit(structuredDocument, highlighter);
if (isInitialized())
return;
registerPreferenceManager();
setInitialized(true);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.wst.sse.ui.internal.provisional.style.AbstractLineStyleProvider
* #
* init(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument
* , org.eclipse.jface.text.source.ISourceViewer)
*/
@Override
public void init(IStructuredDocument structuredDocument,
ISourceViewer sourceViewer) {
init(structuredDocument, (Highlighter) null);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.wst.sse.ui.internal.provisional.style.AbstractLineStyleProvider
* #
* init(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument
* ,
* org.eclipse.wst.sse.ui.internal.provisional.style.ReconcilerHighlighter)
*/
@Override
public void init(IStructuredDocument structuredDocument,
ReconcilerHighlighter highlighter) {
this.structuredDocument = structuredDocument;
recHighlighter = highlighter;
if (isInitialized())
return;
registerPreferenceManager();
setInitialized(true);
}
@Override
public void release() {
unRegisterPreferenceManager();
setInitialized(false);
}
@Override
protected void unRegisterPreferenceManager() {
IPreferenceStore pref = getColorPreferences();
if (pref != null) {
pref.removePropertyChangeListener(preferenceListener);
}
}
@Override
protected void registerPreferenceManager() {
IPreferenceStore pref = getColorPreferences();
if (pref != null) {
pref.addPropertyChangeListener(preferenceListener );
}
}
/**
* Returns the initialized.
*
* @return boolean
*/
@Override
public boolean isInitialized() {
return initialized;
}
/**
* Sets the initialized.
*
* @param initialized
* The initialized to set
*/
private void setInitialized(boolean initialized) {
this.initialized = initialized;
}
@Override
protected IStructuredDocument getDocument() {
return structuredDocument;
}
/**
*/
@Override
protected Highlighter getHighlighter() {
return highlighter;
}
@Override
protected IPreferenceStore getColorPreferences() {
if (xmlPreferenceStore == null) {
xmlPreferenceStore = XMLUIPlugin.getDefault().getPreferenceStore();
}
if (xslPreferenceStore == null) {
xslPreferenceStore = XSLUIPlugin.getDefault().getPreferenceStore();
}
combinedPreferenceStore = new ChainedPreferenceStore(new IPreferenceStore[] { xmlPreferenceStore, xslPreferenceStore });
return combinedPreferenceStore;
}
@Override
protected TextAttribute createTextAttribute(RGB foreground, RGB background, boolean bold) {
return new TextAttribute((foreground != null) ? EditorUtility.getColor(foreground) : null, (background != null) ? EditorUtility.getColor(background) : null, bold ? SWT.BOLD : SWT.NORMAL);
}
@Override
protected TextAttribute createTextAttribute(RGB foreground, RGB background, int style) {
return new TextAttribute((foreground != null) ? EditorUtility.getColor(foreground) : null, (background != null) ? EditorUtility.getColor(background) : null, style);
}
@Override
protected TextAttribute getAttributeFor(ITextRegion region) {
// TODO Auto-generated method stub
return null;
}
@Override
protected void loadColors() {
// TODO Auto-generated method stub
}
}