/**
* This file Copyright (c) 2005-2008 Aptana, Inc. This program is
* dual-licensed under both the Aptana Public License and the GNU General
* Public license. You may elect to use one or the other of these licenses.
*
* This program is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. Redistribution, except as permitted by whichever of
* the GPL or APL you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or modify this
* program under the terms of the GNU General Public License,
* Version 3, as published by the Free Software Foundation. You should
* have received a copy of the GNU General Public License, Version 3 along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Aptana provides a special exception to allow redistribution of this file
* with certain other free and open source software ("FOSS") code and certain additional terms
* pursuant to Section 7 of the GPL. You may view the exception and these
* terms on the web at http://www.aptana.com/legal/gpl/.
*
* 2. For the Aptana Public License (APL), this program and the
* accompanying materials are made available under the terms of the APL
* v1.0 which accompanies this distribution, and is available at
* http://www.aptana.com/legal/apl/.
*
* You may view the GPL, Aptana's exception and additional terms, and the
* APL in the file titled license.html at the root of the corresponding
* plugin containing this source file.
*
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.editors.unified.colorizer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.Color;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.aptana.ide.editors.UnifiedEditorsPlugin;
import com.aptana.ide.lexer.IToken;
import com.aptana.ide.lexer.LexerException;
/**
* @author Kevin Sawicki (ksawicki@aptana.com)
*/
public class ColorizerWriter
{
/**
* XML elements and attributes
*/
public static final String XMLNS_ATTR = "xmlns"; //$NON-NLS-1$
/**
* NAMESPACE_ATTR
*/
public static final String NAMESPACE_ATTR = "http://www.aptana.com/2007/colorizer/1.0"; //$NON-NLS-1$
/**
* Contructor for colorizer writer
*/
public ColorizerWriter()
{
// Does nothing
}
/**
* Builds a colorization preference.
*
* @param lc -
* language colorizer.
* @param language -
* language.
* @param prefID -
* preference ID.
* @throws LexerException
* IF lexer error occurs.
*/
public void buildColorizationPreference(LanguageColorizer lc, String language, String prefID) throws LexerException
{
try
{
Document document = buildDom(lc, language);
// Save file
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource domSource = new DOMSource(document);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(domSource, result);
IPreferenceStore store = UnifiedEditorsPlugin.getDefault().getPreferenceStore();
store.setValue(prefID, writer.toString());
}
catch (Exception e)
{
throw new LexerException(Messages.ColorizerWriter_ERROR_SAVING, e);
}
}
/**
* Builds colorization file.
*
* @param lc -
* language colorizer.
* @param language -
* language.
* @param file -
* file to write to.
* @throws LexerException
* IF lexer error occurs.
*/
public void buildColorizationFile(LanguageColorizer lc, String language, File file) throws LexerException
{
try
{
Document document = buildDom(lc, language);
// Save file
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource domSource = new DOMSource(document);
File output = file;
if (output != null)
{
try
{
FileOutputStream stream = new FileOutputStream(output);
StreamResult result = new StreamResult(stream);
transformer.transform(domSource, result);
stream.close();
}
catch (TransformerException e)
{
throw new LexerException(Messages.ColorizerWriter_ERROR_SAVING, e);
}
}
}
catch (Exception e)
{
throw new LexerException(Messages.ColorizerWriter_ERROR_SAVING, e);
}
}
/**
* Builds a dom from a colorizer
*
* @param lc
* @param language
* @return - DOM document
* @throws ParserConfigurationException
*/
protected Document buildDom(LanguageColorizer lc, String language) throws ParserConfigurationException
{
Collection tokenColorizers = lc.getTokenColorizers();
Collection categoryColorizers = lc.getCategoryColorizers();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
// Create document
Element root = document.createElement(ColorizationConstants.COLORIZER); //$NON-NLS-1$
document.appendChild(root);
root.setAttribute(ColorizerWriter.XMLNS_ATTR, ColorizerWriter.NAMESPACE_ATTR);
root.setAttribute(ColorizationConstants.LANGUAGE_ATTR, language);
// Set editor properties
if (lc.getBackground() != null)
{
String editorBG = createRGBString(lc.getBackground());
root.setAttribute(ColorizationConstants.BACKGROUND_ATTR, editorBG);
}
if (lc.getSelectionBackground() != null)
{
String selectionBG = createRGBString(lc.getSelectionBackground());
root.setAttribute(ColorizationConstants.SELECTIONBACKGROUND_ATTR, selectionBG);
}
if (lc.getSelectionForeground() != null)
{
String selectionFG = createRGBString(lc.getSelectionForeground());
root.setAttribute(ColorizationConstants.SELECTIONFOREGROUND_ATTR, selectionFG);
}
if (lc.getCaretColor() != null)
{
String caretColor = createRGBString(lc.getCaretColor());
root.setAttribute(ColorizationConstants.CARETCOLOR_ATTR, caretColor);
}
if (lc.getLineHighlightColor() != null)
{
String lineHighlight = createRGBString(lc.getLineHighlightColor());
root.setAttribute(ColorizationConstants.LINEHIGHLIGHT_ATTR, lineHighlight);
}
if (lc.getFoldingBg() != null)
{
String foldingBg = createRGBString(lc.getFoldingBg());
root.setAttribute(ColorizationConstants.FOLDING_BACKGROUND_ATTR, foldingBg);
}
if (lc.getFoldingFg() != null)
{
String foldingFg = createRGBString(lc.getFoldingFg());
root.setAttribute(ColorizationConstants.FOLDING_FOREGROUND_ATTR, foldingFg);
}
Iterator catIter = categoryColorizers.iterator();
while (catIter.hasNext())
{
CategoryColorizer cColorizer = (CategoryColorizer) catIter.next();
String cName = cColorizer.getName();
String cStyle = cColorizer.getStyle().getName();
Element catElement = document.createElement(ColorizationConstants.CATEGORY_ATTR);
catElement.setAttribute(ColorizationConstants.NAME_ATTR, cName);
catElement.setAttribute(ColorizationConstants.STYLE_ATTR, cStyle);
root.appendChild(catElement);
Iterator tokens = tokenColorizers.iterator();
addColorization(root, cColorizer.getStyle(), document);
while (tokens.hasNext())
{
TokenColorizer tColorizer = (TokenColorizer) tokens.next();
IToken token = tColorizer.getToken();
if (cName.equals(token.getCategory()))
{
String type = token.getType();
String token_style = tColorizer.getBaseColorization().getName();
Element tokenElement = document.createElement(ColorizationConstants.TOKEN_ELEMENT);
tokenElement.setAttribute(ColorizationConstants.TYPE_ATTR, type);
tokenElement.setAttribute(ColorizationConstants.STYLE_ATTR, token_style);
catElement.appendChild(tokenElement);
addRegions(root, tokenElement, tColorizer, document);
addColorization(root, tColorizer.getBaseColorization(), document);
}
}
}
return document;
}
private static String createRGBString(Color color)
{
return "rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
private static void addColorization(Element parent, ColorizationStyle style, Document document)
{
Color bg = style.getBackgroundColor();
Element styleElement = document.createElement(ColorizationConstants.STYLE_ELEMENT);
if (bg != null)
{
String bgColor = createRGBString(bg);
styleElement.setAttribute(ColorizationConstants.BACKGROUND_ATTR, bgColor);
}
Color fg = style.getForegroundColor();
if (fg != null)
{
String fgColor = createRGBString(fg);
styleElement.setAttribute(ColorizationConstants.FOREGROUND_ATTR, fgColor);
}
if (style.isBold())
{
styleElement.setAttribute(ColorizationConstants.FONTWEIGHT_ATTR, "bold"); //$NON-NLS-1$
}
if (style.isItalic())
{
styleElement.setAttribute(ColorizationConstants.FONTSTYLE_ATTR, "italic"); //$NON-NLS-1$
}
if (style.isUnderline())
{
styleElement.setAttribute(ColorizationConstants.TEXTDECORATION_ATTR, "underline"); //$NON-NLS-1$
}
if (style.getName() != null)
{
styleElement.setAttribute(ColorizationConstants.ID_ATTR, style.getName());
parent.appendChild(styleElement);
}
}
private static void addRegions(Element root, Element parent, TokenColorizer tokenColorizer, Document document)
{
Iterator regions = tokenColorizer.getRegions().iterator();
while (regions.hasNext())
{
Region region = (Region) regions.next();
Element regionElement = document.createElement(ColorizationConstants.REGION_ELEMENT);
regionElement.setAttribute(ColorizationConstants.NAME_ATTR, region.getName());
regionElement.setAttribute(ColorizationConstants.STYLE_ATTR, region.getStyle().getName());
regionElement.setAttribute(ColorizationConstants.OFFSET_ATTR, region.getOffsetString());
regionElement.setAttribute(ColorizationConstants.LENGTH_ATTR, region.getLengthString());
addColorization(root, region.getStyle(), document);
parent.appendChild(regionElement);
}
}
}