ColorMapEntryParser.java from PovClipse at Krugle
Show ColorMapEntryParser.java syntax highlighted
/*
* PovClipse - Eclipse plugin for editing and rendering Povray sceene files.
* Copyright (C) 2006-2007 Wolfgang Moestl wmoestl@web.de
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package com.wm.povclipse.code.parser;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import com.wm.povclipse.LoggerProvider;
import com.wm.povclipse.PovClipseEditorPlugin;
import com.wm.povclipse.code.data.ColorData;
import com.wm.povclipse.code.data.ColorMapReplaceData;
import com.wm.povclipse.code.data.ColorReplaceData;
import com.wm.povclipse.common.Formatter;
import com.wm.povclipse.preferences.PovClipseSoundsPreferencePage;
import com.wm.povclipse.preferences.PovrayPreferenceConstants;
import com.wm.povclipse.tools.AudioPlayer;
import com.wm.povclipse.utils.StringUtils;
/**
* <p>Parses a Povray <code>color_map</code> entry statement and returns it as a List of
* <code>ColorData</code> objects.</p>
* <p>Both, the old and the newer <code>color_map</code> syntax styles are supported.
*
* @author Wolfgang Möstl
*/
public class ColorMapEntryParser {
/**
* Logger instance
*/
private static Logger logger = LoggerProvider.getLogger(ColorMapEntryParser.class.getName());
private static Logger soundLogger = LoggerProvider.getLogger(AudioPlayer.class.getName());
private static void playSound() {
IPreferenceStore store = PovClipseEditorPlugin.getDefault().getPreferenceStore();
String file = store.getString(PovrayPreferenceConstants.P_SOUND_EDITOR_ERROR);
if (false == PovClipseSoundsPreferencePage.SOUND_NONE.equals(file)) {
AudioPlayer player = new AudioPlayer(file, soundLogger);
player.start();
}
}
private static void setValuesForNewColormap(IDocument doc, IRegion region, ColorMapReplaceData replaceData) {
try {
// get the line prefix
int lineOffset = doc.getLineOffset(doc.getLineOfOffset(region.getOffset()));
replaceData.setStatementPrefix(doc.get(lineOffset, region.getOffset() - lineOffset));
} catch (BadLocationException e) {
logger.warn("BadLocationException: " + e.getMessage());
replaceData.setStatementPrefix("");
}
replaceData.setStatementPrefix(StringUtils.ensureOnlyWhiteSpaces(replaceData.getStatementPrefix()));
replaceData.setMapEntryPrefix(replaceData.getStatementPrefix() + "\t");
replaceData.setReplaceRegion(region);
}
public static ColorMapReplaceData parseColorMap(IDocument doc, IRegion region) {
boolean newStatement = false;
IRegion mapRegionOpening = null;
IRegion mapRegionClosing = null;
ColorMapReplaceData replaceData = new ColorMapReplaceData();
try {
List<ColorData> initList = new ArrayList<ColorData>();
// search backwards until we find a "color_map" string
FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(doc);
IRegion colormapRegion = finder.find(region.getOffset()+8 > doc.getLength()-1 ? doc.getLength()-1 : region.getOffset()+8, "color_map", false, false, false, false);
if (null == colormapRegion) {
logger.trace("[color_map] not found!");
newStatement = true;
setValuesForNewColormap(doc, region, replaceData);
} else {
// get the line prefix
int lineOffset = doc.getLineOffset(doc.getLineOfOffset(colormapRegion.getOffset()));
replaceData.setStatementPrefix(doc.get(lineOffset, colormapRegion.getOffset() - lineOffset));
replaceData.setStatementPrefix(StringUtils.ensureOnlyWhiteSpaces(replaceData.getStatementPrefix()));
mapRegionOpening = finder.find(colormapRegion.getOffset(), "{", true, false, false, false);
mapRegionClosing = finder.find(colormapRegion.getOffset(), "}", true, false, false, false);
if (mapRegionOpening == null) {
logger.debug("[{] not found!");
playSound();
return null;
}
if (mapRegionClosing == null) {
logger.debug("[}] not found!");
playSound();
return null;
}
replaceData.setReplaceRegion(new Region(colormapRegion.getOffset(), mapRegionClosing.getOffset() - colormapRegion.getOffset()));
logger.debug("act pos: " + region.getOffset() + "; [color_map]=" + colormapRegion.getOffset() + ", [{]=" + mapRegionOpening.getOffset() + ", [}]=" + mapRegionClosing.getOffset());
if (mapRegionClosing.getOffset() < region.getOffset()) {
logger.debug("[}] BEFOR actual position!");
newStatement = true;
setValuesForNewColormap(doc, region, replaceData);
}
if (colormapRegion.getOffset() > region.getOffset()) {
logger.debug("[color_map] AFTER actual position!");
newStatement = true;
setValuesForNewColormap(doc, region, replaceData);
}
if (!newStatement) {
List braces = splitBrackets(doc, finder, mapRegionOpening.getOffset(), mapRegionClosing.getOffset());
HashMap<String, Integer> prefixMap = new HashMap<String, Integer>();
for (int i=0; i<braces.size(); i++) {
IRegion braceRegion = (IRegion)braces.get(i);
// get the line prefix
lineOffset = doc.getLineOffset(doc.getLineOfOffset(braceRegion.getOffset()));
String prefix = doc.get(lineOffset, braceRegion.getOffset()-lineOffset);
if (StringUtils.containsOnlySpaces(prefix)) {
Integer counter = (Integer)prefixMap.get(prefix);
if (null == counter)
prefixMap.put(prefix, new Integer(1));
else
prefixMap.put(prefix, new Integer(counter.intValue() + 1));
}
List<ColorData> colorList = ColorMapEntryParser.parseColorList(doc, braceRegion);
// avoide dulicate entries
for (int j=0; j<colorList.size(); j++) {
ColorData obj = (ColorData)colorList.get(j);
if (!initList.contains(obj))
initList.add(obj);
}
replaceData.setColorList(initList);
}
Iterator it = prefixMap.keySet().iterator();
int max = -1;
while (it.hasNext()) {
String key = (String)it.next();
Integer val = (Integer)prefixMap.get(key);
if (val.intValue() > max)
replaceData.setMapEntryPrefix(key);
}
}
}
replaceData.setNewStatement(newStatement);
replaceData.setMapEntryPrefix(ensureLinePrefixValue(replaceData.getMapEntryPrefix()));
logger.trace("Entry prefix: [" + replaceData.getMapEntryPrefix() + "]");
return replaceData;
} catch (BadLocationException e) {
logger.warn("BadLocationException: " + e.getMessage());
return null;
}
}
private static String ensureLinePrefixValue(String linePrefix) {
return (null == linePrefix) ? "\t\t\t" : linePrefix;
}
/**
* Parses a Povray <code>color_map entry</code> statement extracted from the document and returns
* it as a <code>ColorData</code> object.<br>
* The entry is everything between a [] bracket pair.
* @param doc The document being used for extracting the <code>color_map entry</code> statement.
* @param region The <code>IRegion</code> within the document containing the <code>color_map entry</code> statement.
* @return A List of <code>ColorData</code> object(s) representing the <code>color_map entry</code> statement or
* an <code>EMPTY</code> List if the statement can not be parsed. Never <code>NULL</code>.
*/
public static List<ColorData> parseColorList(IDocument doc, IRegion region) {
List<ColorData> retList = new ArrayList<ColorData>();
ColorData colorData;
try {
FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(doc);
IRegion colorRegionOne = finder.find(region.getOffset(), "rgb", true, false, false, false);
if (null == colorRegionOne) return retList;
// ensure we're within our allowed region
if (colorRegionOne.getOffset() >= region.getOffset() + region.getLength()) return retList;
IRegion colorRegionTwo = finder.find(colorRegionOne.getOffset() + 3, "rgb", true, false, false, false);
if (null != colorRegionTwo && colorRegionTwo.getOffset() >= region.getOffset() + region.getLength())
colorRegionTwo = null; // restrict to allowed region
IRegion parseColorRegion;
if (null == colorRegionTwo) {
// no second statement present
parseColorRegion = new Region(colorRegionOne.getOffset()-2, 2+region.getOffset() + region.getLength() - colorRegionOne.getOffset());
} else {
// second statement IS present
parseColorRegion = new Region(colorRegionOne.getOffset()-2, 2+colorRegionTwo.getOffset() - colorRegionOne.getOffset());
}
// try the first color statement
ColorReplaceData repaceData = ColorParser.parse(doc, parseColorRegion, true);
if (repaceData != null) {
colorData = repaceData.getColorData();
try {
String number = StringUtils.extractUSNumber(doc.get(region.getOffset(), colorRegionOne.getOffset() - region.getOffset()), 1);
colorData.setPosition(Formatter.floatFormatter.parse(number).floatValue());
} catch (ParseException e) {
// set a default value
colorData.setPosition(0.0f);
}
logger.debug("Adding color_map entry " + colorData.toString());
retList.add(colorData);
}
if (null != colorRegionTwo) {
// try the second color statement
parseColorRegion = new Region(colorRegionTwo.getOffset(), region.getOffset() + region.getLength() - colorRegionTwo.getOffset());
repaceData = ColorParser.parse(doc, parseColorRegion, true);
if (repaceData != null) {
colorData = repaceData.getColorData();
try {
String number = StringUtils.extractUSNumber(doc.get(region.getOffset(), colorRegionOne.getOffset() - region.getOffset()), 2);
colorData.setPosition(Formatter.floatFormatter.parse(number).floatValue());
} catch (ParseException e) {
// set a default value
colorData.setPosition(0.0f);
}
logger.trace("Adding color_map entry " + colorData.toString());
retList.add(colorData);
}
}
} catch (BadLocationException e) {
logger.warn("BadLocationException: " + e.getMessage());
return null;
}
return retList;
}
/**
* Finds "[]" pairs and returns them as List of <code>IRegion</code> objects.
* @param doc Teh document to process
* @param finder The <code>FindReplaceDocumentAdapter</code> to be used.
* @param offsetOpeningBrace The offset to start with
* @param offsetClosingBrace The offset to end with.
* @return A list of <code>IRegion</code> objects
*/
private static List<Region> splitBrackets(IDocument doc, FindReplaceDocumentAdapter finder, int offsetOpeningBrace, int offsetClosingBrace) {
ArrayList<Region> lst = new ArrayList<Region>();
boolean found = true;
int startOffset = offsetOpeningBrace;
while (found) {
try {
IRegion matchStart = finder.find(startOffset, "[", true, true, false, false);
IRegion matchEnd = finder.find(startOffset, "]", true, true, false, false);
found = (matchStart != null && matchEnd != null) ;
if (found && (matchEnd.getOffset() < offsetClosingBrace)) {
lst.add(new Region(matchStart.getOffset(), matchEnd.getOffset() - matchStart.getOffset()));
startOffset = matchEnd.getOffset()+1;
logger.trace("found: " + matchStart.getOffset() + " - " + matchEnd.getOffset());
} else
found = false;
} catch (BadLocationException e) {
found = false;
}
}
return lst;
}
}
See more files for this project here