PovClipseHoverPresenter.java from PovClipse at Krugle
Show PovClipseHoverPresenter.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.common;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.DefaultInformationControl.IInformationPresenter;
import org.eclipse.jface.text.DefaultInformationControl.IInformationPresenterExtension;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Drawable;
import org.eclipse.swt.widgets.Display;
import com.wm.povclipse.editors.scanners.PovrayStringScanner;
import com.wm.povclipse.i18n.I18nCommon;
import com.wm.povclipse.preferences.PovrayPreferenceConstants;
import com.wm.povclipse.preferences.PovrayPreferences;
import com.wm.povclipse.validator.FloatValidator;
/**
* <code>IInformationPresenter</code> used by text hovers.
*
* @author Wolfgang Mouml;stl
*/
public class PovClipseHoverPresenter implements IInformationPresenter,
IInformationPresenterExtension {
public static final int HOVER_TYPE_COLOR_MAP = 6;
public static final int HOVER_TYPE_COLOR = 5;
public static final int HOVER_TYPE_DECLARATION = 4;
public static final int HOVER_TYPE_INCLUDE = 3;
public static final int HOVER_TYPE_MACRO = 2;
public static final int HOVER_TYPE_CODE = 1;
public static final int HOVER_TYPE_DEFAULT = 0;
private Color colKeywordCommon;
private Color colString;
private Color colBracketGeschweift;
private Color colBracketSpitz;
private Color colComment;
private Color colColor;
private Color colGradient;
private Color colMath;
private Color colModifier;
private Color colObject;
private Color colTexture;
private Color colNumber;
private Color colIncludeHoverFile;
private Color colIncludeHoverMacro;
private Color colIncludeHoverDecl;
private Color colIncludeHoverFileLight;
private Color colIncludeHoverMacroLight;
private Color colIncludeHoverDeclLight;
private PovrayStringScanner stringScanner;
/**
* Construcotr reading the colors from the preference store.
*/
public PovClipseHoverPresenter(PovrayStringScanner stringScanner) {
this.stringScanner = stringScanner;
PovrayPreferences prefs = PovrayPreferences.getInstance();
colBracketGeschweift = prefs.getColor(PovrayPreferenceConstants.P_COLOR_BRACE);
colBracketSpitz = prefs.getColor(PovrayPreferenceConstants.P_COLOR_ANGLE_BRACKET);
colComment = prefs.getColor(PovrayPreferenceConstants.P_COLOR_COMMENT);
colColor = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_COLOR);
colKeywordCommon = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_COMMON);
colGradient = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_GRADIENT);
colMath = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_MATH);
colModifier = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_MODIFIER);
colObject = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_OBJECT);
colTexture = prefs.getColor(PovrayPreferenceConstants.P_COLOR_KEYWORD_TEXTURE);
colNumber = prefs.getColor(PovrayPreferenceConstants.P_COLOR_NUMBER);
colString = prefs.getColor(PovrayPreferenceConstants.P_COLOR_STRING);
colIncludeHoverFile = new Color(colString.getDevice(), 190, 0 , 0 );
colIncludeHoverMacro = new Color(colString.getDevice(), 0 , 190, 0 );
colIncludeHoverDecl = new Color(colString.getDevice(), 0 , 0 , 190);
colIncludeHoverFileLight = new Color(colString.getDevice(), 190, 150, 150);
colIncludeHoverMacroLight = new Color(colString.getDevice(), 150, 190, 150);
colIncludeHoverDeclLight = new Color(colString.getDevice(), 150, 150, 190);
}
/**
* Default implemtation, not uased by the framework as this
* class implements <code>IInformationPresenterExtension</code> as well!
* @see org.eclipse.jface.text.DefaultInformationControl$IInformationPresenter#updatePresentation(org.eclipse.swt.widgets.Display, java.lang.String, org.eclipse.jface.text.TextPresentation, int, int)
*/
public String updatePresentation(Display display, String hoverInfo,
TextPresentation presentation, int maxWidth, int maxHeight) {
return hoverInfo;
}
/**
* @see org.eclipse.jface.text.DefaultInformationControl$IInformationPresenterExtension#updatePresentation(org.eclipse.swt.graphics.Drawable, java.lang.String, org.eclipse.jface.text.TextPresentation, int, int)
*/
public String updatePresentation(Drawable drawable, String hoverInfo, TextPresentation presentation, int maxWidth, int maxHeight) {
int hoverType = getHoverType(hoverInfo);
hoverInfo = getStrippedHoverMessage(hoverInfo);
switch (hoverType) {
case HOVER_TYPE_MACRO:
presentation.clear();
createMacroStyling(presentation, hoverInfo);
break;
case HOVER_TYPE_CODE:
presentation.clear();
createCodeStyling(presentation, hoverInfo);
break;
case HOVER_TYPE_INCLUDE:
presentation.clear();
createIncludeStyling(presentation, hoverInfo);
break;
case HOVER_TYPE_DECLARATION:
presentation.clear();
createDeclarationStyling(presentation, hoverInfo);
break;
default: /* no styles added */ break;
}
return hoverInfo;
}
/**
* Creates the presentation styling for '#macro' hovers
* @param presentation The <code>TextPresentation</code> to receive the styling
* @param message The complete hover text.
*/
private void createMacroStyling(TextPresentation presentation, String message) {
int index = message.indexOf("#macro");
// '#macro' is italic and in the color used by common keywords
presentation.addStyleRange(new StyleRange(index, 6, colKeywordCommon, null, SWT.ITALIC | SWT.BOLD));
int indexStart = message.indexOf('(');
if (indexStart >= index + 6) {
// the macro name is bold
presentation.addStyleRange(new StyleRange(index+6, indexStart-(index+6), null, null, SWT.BOLD));
int indexEnd = message.indexOf(')', indexStart);
if (indexEnd == -1) {
indexEnd = message.indexOf('\n', indexStart);
if (indexEnd == -1)
indexEnd = message.length()-1;
}
// parameters are drawn bold and in the color used by string literals.
styleCommaSeparatedList(presentation, message, indexStart, indexEnd, colString, null, SWT.BOLD);
// the rest is drawn using the comment color
presentation.addStyleRange(new StyleRange(indexEnd+1, message.length()-(indexEnd+1), colComment, null, SWT.NORMAL));
}
}
/**
* Creates the presentation styling for 'declaration' hovers
* @param presentation The <code>TextPresentation</code> to receive the styling
* @param message The complete hover text.
*/
private void createDeclarationStyling(TextPresentation presentation, String message) {
createCodeStyling(presentation, message, message.indexOf("#declare"));
}
/**
* Creates the presentation styling for 'include' hovers
* @param presentation The <code>TextPresentation</code> to receive the styling
* @param message The complete hover text.
*/
private void createIncludeStyling(TextPresentation presentation, String message) {
boolean highlightMode = false;
int separatorIndex = 0;
int lineStart = 0;
for (int i=0; i<message.length(); i++) {
char c = message.charAt(i);
if (c == ':' && false == highlightMode) {
highlightMode = true;
separatorIndex = i+1;
} else if (c == '\n') {
if (highlightMode) {
setIncludePresentation(presentation, message, lineStart, separatorIndex, i);
}
highlightMode = false;
lineStart = i+1;
}
}
// the last line
if (highlightMode) {
setIncludePresentation(presentation, message, lineStart, separatorIndex, message.length());
}
}
private void setIncludePresentation(TextPresentation presentation, String message, int start, int separator, int end) {
String prefix = message.substring(start, separator-1).trim();
boolean isIndirect = message.substring(separator, end).trim().endsWith("*");
Color col = isIndirect ? colIncludeHoverFileLight : colIncludeHoverFile;
if (I18nCommon.macro.indexOf(prefix) >= 0)
col = isIndirect ? colIncludeHoverMacroLight : colIncludeHoverMacro;
else if (I18nCommon.declaration.indexOf(prefix) >= 0)
col = isIndirect ? colIncludeHoverDeclLight : colIncludeHoverDecl;
presentation.addStyleRange(new StyleRange(start, separator-start, col, null, SWT.ITALIC));
presentation.addStyleRange(new StyleRange(separator+1, end-separator-1, col, null, SWT.BOLD));
}
/**
* Creates the presentation styling for 'code-folding' hovers
* @param presentation The <code>TextPresentation</code> to receive the styling
* @param message The complete hover text.
*/
private void createCodeStyling(TextPresentation presentation, String message) {
createCodeStyling(presentation, message, 0);
}
/**
* Creates the presentation styling for 'code-folding' hovers
* @param presentation The <code>TextPresentation</code> to receive the styling
* @param message The complete hover text.
*/
private void createCodeStyling(TextPresentation presentation, String message, int switchIndex) {
if (switchIndex < 0)
switchIndex = 0;
if (switchIndex > 0)
presentation.addStyleRange(new StyleRange(0, switchIndex, colComment, null, SWT.NORMAL));
StringBuffer sb = new StringBuffer();
char c;
for (int i=switchIndex; i<message.length(); i++) {
c = message.charAt(i);
if (Character.isLetterOrDigit(c) ||
c == '_' ||
c == '.' ||
c == '-' ||
c == '"' ||
c == '\'') {
sb.append(c);
} else if (c == '{' || c == '}') {
sb = processStringBuffer(presentation, sb, i-1 - sb.length());
presentation.addStyleRange(new StyleRange(i, 1, colBracketGeschweift, null, SWT.NORMAL));
} else if (c == '<' || c == '>') {
sb = processStringBuffer(presentation, sb, i-1 - sb.length());
presentation.addStyleRange(new StyleRange(i, 1, colBracketSpitz, null, SWT.NORMAL));
} else {
// whitespace or similar
if (sb.length() > 0) {
sb = processStringBuffer(presentation, sb, i - sb.length());
} // else do nothing at all
}
}
}
/**
* Adds a <code>StyleRange</code> to the <code>presentation</code> if necessary.<br>
* If <code>sb</code> can be parsed into a number (US-style), a <code>StyleRange</code> for numbers is applied.<br>
* If <code>sb</code> starts end ends either with " or ', a <code>StyleRange</code> for strings is applied.<br>
* If <code>sb</code> sb can be found in the list of known keywords, a <code>StyleRange</code> for the specific keyword group is applied.<br>
* Else no <code>StyleRange</code> is added.
* @param presentation The <code>TextPresentation</code> to receive the <code>StyleRange</code>.
* @param sb The <code>StringBuffer</code> to be processed.
* @param indexFrom The index of the given <code>StringBuffer</code> within the processing message.
* @return A new, fresh, clear instance of a <code>StringBuffer</code>.
*/
private StringBuffer processStringBuffer(TextPresentation presentation, StringBuffer sb, int indexFrom) {
if (sb.length() > 0) {
// is it a number?
if (FloatValidator.isNumber(sb.toString())) {
presentation.addStyleRange(new StyleRange(indexFrom, sb.length(), colNumber, null, SWT.NORMAL));
sb = new StringBuffer();
}
// is it a string?
else if ((sb.charAt(0) == '"' && sb.charAt(sb.length()-1) == '"') ||
(sb.charAt(0) == '\'' && sb.charAt(sb.length()-1) == '\'')) {
presentation.addStyleRange(new StyleRange(indexFrom, sb.length(), colString, null, SWT.NORMAL));
sb = new StringBuffer();
}
// ceck the keyword lists
else {
Color col = getKeywordColor(sb.toString());
if (null != col) {
presentation.addStyleRange(new StyleRange(indexFrom, sb.length(), col, null, SWT.NORMAL));
}
}
}
return new StringBuffer();
}
/**
* @param keyword The word to be searched within the list of known keywords.
* @return If the given word can be foundn in the list of known keywords the color
* for the specific keyword group is returned, otherwise <code>null</code>.
*/
private Color getKeywordColor(String word) {
if (arrayContainsKeyword(stringScanner.getKeywordsColor(), word))
return colColor;
if (arrayContainsKeyword(stringScanner.getKeywordsCommon(), word))
return colKeywordCommon;
if (arrayContainsKeyword(stringScanner.getKeywordsGradient(), word))
return colGradient;
if (arrayContainsKeyword(stringScanner.getKeywordsMath(), word))
return colMath;
if (arrayContainsKeyword(stringScanner.getKeywordsModifier(), word))
return colModifier;
if (arrayContainsKeyword(stringScanner.getKeywordsObjects(), word))
return colObject;
if (arrayContainsKeyword(stringScanner.getKeywordsTexture(), word))
return colTexture;
return null;
}
/**
* @param array The array to be checked.
* @param keyword The keyword to be searched for
* @return <code>true</code> if the array contains the keyword,
* <code>false</code> otherwise.
*/
private boolean arrayContainsKeyword(String[] array, String keyword) {
for (int i=0; i<array.length; i++) {
if (array[i].equals(keyword)) return true;
}
return false;
}
/**
* Gets the hover type usingthe hover message.
* @param msg The hover message including the ttype prefix.
* @return One of the <code>HOVER_TYPE_*</code> constants. If the
* <code>msg</code> is null or the type is either unknown or not set
* <code>HOVER_TYPE_DEFAULT</code> is returned.
*/
public static int getHoverType(String msg) {
if (null == msg) return HOVER_TYPE_DEFAULT;
int index = msg.indexOf(PovClipseMessageTypeIndication.TYPE_DELIMETER);
if (index == -1)
return HOVER_TYPE_DEFAULT;
else {
if (PovClipseMessageTypeIndication.TYPE_MACRO.equals(msg.substring(0, PovClipseMessageTypeIndication.TYPE_MACRO.length())))
return HOVER_TYPE_MACRO;
else if (PovClipseMessageTypeIndication.TYPE_CODE.equals(msg.substring(0, PovClipseMessageTypeIndication.TYPE_CODE.length())))
return HOVER_TYPE_CODE;
else if (PovClipseMessageTypeIndication.TYPE_INCLUDE.equals(msg.substring(0, PovClipseMessageTypeIndication.TYPE_INCLUDE.length())))
return HOVER_TYPE_INCLUDE;
else if (PovClipseMessageTypeIndication.TYPE_DECLARATION.equals(msg.substring(0, PovClipseMessageTypeIndication.TYPE_DECLARATION.length())))
return HOVER_TYPE_DECLARATION;
else if (PovClipseMessageTypeIndication.TYPE_COLOR.equals(msg.substring(0, PovClipseMessageTypeIndication.TYPE_COLOR.length())))
return HOVER_TYPE_COLOR;
else if (PovClipseMessageTypeIndication.TYPE_COLOR_MAP.equals(msg.substring(0, PovClipseMessageTypeIndication.TYPE_COLOR_MAP.length())))
return HOVER_TYPE_COLOR_MAP;
else
return HOVER_TYPE_DEFAULT;
}
}
/**
* Checks whether the hover message belongs to a color or not.
* @param msg The message to be processed.
* @return <code>true</code> it the message belongs to a color hover.
*/
public static boolean isHoverTypeColor(String msg) {
return HOVER_TYPE_COLOR == getHoverType(msg);
}
/**
* Checks whether the hover message belongs to a color_map or not.
* @param msg The message to be processed.
* @return <code>true</code> it the message belongs to a color_map hover.
*/
public static boolean isHoverTypeColorMap(String msg) {
return HOVER_TYPE_COLOR_MAP == getHoverType(msg);
}
/**
* Checks whether the hover message belongs to a macro or not.
* @param msg The message to be processed.
* @return <code>true</code> it the message belongs to a macro hover.
*/
public static boolean isHoverTypeMacro(String msg) {
return HOVER_TYPE_MACRO == getHoverType(msg);
}
/**
* Checks whether the hover message belongs to a code-folding or not.
* @param msg The message to be processed.
* @return <code>true</code> it the message belongs to a code-folding hover.
*/
public static boolean isHoverTypeCode(String msg) {
return HOVER_TYPE_CODE == getHoverType(msg);
}
/**
* Checks whether the hover message belongs to a include statement or not.
* @param msg The message to be processed.
* @return <code>true</code> it the message belongs to a include hover.
*/
public static boolean isHoverTypeInclude(String msg) {
return HOVER_TYPE_INCLUDE == getHoverType(msg);
}
/**
* Checks whether the hover message belongs to a declare statement or not.
* @param msg The message to be processed.
* @return <code>true</code> it the message belongs to a declare hover.
*/
public static boolean isHoverTypeDeclaration(String msg) {
return HOVER_TYPE_DECLARATION == getHoverType(msg);
}
/**
* Gets the extra information stored between the <code>TYPE</code> information
* and the <code>TYPE_DELIMETER</code>.
* @param msg The message to be processed.
* @return See above.
*/
public static String getExtraInfo(String msg) {
int type = getHoverType(msg);
if (type == HOVER_TYPE_DEFAULT) return "";
int index = msg.indexOf(PovClipseMessageTypeIndication.TYPE_DELIMETER);
if (index == -1) return "";
if (type == HOVER_TYPE_MACRO) {
return msg.substring(PovClipseMessageTypeIndication.TYPE_MACRO.length(),index);
}
if (type == HOVER_TYPE_DECLARATION) {
return msg.substring(PovClipseMessageTypeIndication.TYPE_DECLARATION.length(),index);
}
return "";
}
public static String getStrippedHoverMessage(String msg) {
int index = msg.indexOf(PovClipseMessageTypeIndication.TYPE_DELIMETER);
if (index == -1)
return msg;
else
return msg.substring(index + PovClipseMessageTypeIndication.TYPE_DELIMETER.length());
}
/**
* Adds a new <code>StyleRange</code> for each comma separated entry found
* in the given string between the start and end position.
* @param presentation The <code>TextPresentation</code> object to
* receive the styled ranges.
* @param msg The message to be processed
* @param start The start position of the comma separated list
* @param end The end position of the comma separated list
* @param foregroundColor The foreground color to be used or <code>NULL</code> to use the default color.
* @param backgroundColor The backround color to be used or <code>NULL</code> to use the default color.
* @param style The text style bits, <code>SWT.NORMAL</code>, <code>SWT.ITALIC</code> or <code>SWT.BOLD</code>.
*/
private void styleCommaSeparatedList(TextPresentation presentation, String msg, int start, int end, Color foregroundColor, Color backgroundColor, int style) {
int indexLastComma = start;
int indexComma = msg.indexOf(',', indexLastComma);
if (indexComma == -1) { // only 1 parameter, no list!
presentation.addStyleRange(new StyleRange(start+1, end-start-1, foregroundColor, backgroundColor, style));
}
else {
while (indexComma > -1 && indexComma <= end && indexLastComma < indexComma) {
// add the style
presentation.addStyleRange(new StyleRange(indexLastComma+1, indexComma-indexLastComma-1, foregroundColor, backgroundColor, style));
indexLastComma = indexComma;
indexComma = msg.indexOf(',', indexLastComma+1);
if (indexComma > end)
indexComma = end;
// handle the last list entry
if (indexComma == -1) {
presentation.addStyleRange(new StyleRange(indexLastComma+1, end-indexLastComma-1, foregroundColor, backgroundColor, style));
}
}
}
}
}
See more files for this project here