/*
* Copyright (c) 2003-2004 Christopher Lenz and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Christopher Lenz - initial API and implementation
*
* $Id: AbstractCssScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
*/
package net.sourceforge.phpeclipse.css.ui.internal.text;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.RGB;
/**
*
*/
public abstract class AbstractCssScanner extends BufferedRuleBasedScanner {
// Inner Classes -----------------------------------------------------------
/**
* Internal data structure for associating the various style preferences
* of tokens with each other.
*/
private static final class StyleKeys {
/**
* The preference key that determines the foreground color of the token.
*/
private String colorKey;
/**
* The preference key that indicates whether the token is to be
* displayed in bold face.
*/
private String boldKey;
/**
* Constructor.
*
* @param colorKey The color preference key
* @param boldKey The preference key determining whether the
* corresponding tokens should be rendered bold
*/
private StyleKeys(String colorKey, String boldKey) {
this.colorKey = colorKey;
this.boldKey = boldKey;
}
/**
* @see Object#equals(Object)
*/
public boolean equals(Object o) {
if (!(o instanceof StyleKeys)) {
return false;
}
StyleKeys styleKeys = (StyleKeys) o;
if (((colorKey != null) && !colorKey.equals(styleKeys.colorKey))
|| (colorKey != styleKeys.colorKey)) {
return false;
}
if (((boldKey != null) && !boldKey.equals(styleKeys.boldKey))
|| (boldKey != styleKeys.boldKey)) {
return false;
}
return true;
}
/**
* @see Object#hashCode()
*/
public int hashCode() {
int retVal = 17;
retVal = (retVal * 37) +
(colorKey != null ? colorKey.hashCode() : 0);
retVal = (retVal * 37) +
(boldKey != null ? boldKey.hashCode() : 0);
return retVal;
}
}
// Instance Variables ------------------------------------------------------
/**
* The preference store associated with the scanner.
*/
private IPreferenceStore store;
/**
* Listener for preference store changes related to tokens.
*/
private IPropertyChangeListener propertyChangeListener =
new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
String property = event.getProperty();
StyleKeys styleKeys = getStyleKeysContaining(property);
if (styleKeys != null) {
if (styleKeys.colorKey.equals(property)) {
Token token = (Token) tokens.get(styleKeys);
handleColorChange(token, event);
} else if (styleKeys.boldKey.equals(property)) {
Token token = (Token) tokens.get(styleKeys);
handleBoldChange(token, event);
}
}
}
};
/**
* The shared text colors.
*/
private IColorManager colorManager;
/**
* A map containing the defined tokens keyed by the color preference key.
*/
private Map tokens = new HashMap(4);
// Constructors ------------------------------------------------------------
/**
* Constructor.
*
* @param store the preference store
* @param manager the color manager
*/
public AbstractCssScanner(IPreferenceStore store, IColorManager manager) {
store.addPropertyChangeListener(propertyChangeListener);
this.store = store;
this.colorManager = manager;
}
// Public Methods ----------------------------------------------------------
/**
* Adapts the tokens managed by this scanner to changes made to the
* corresponding preferences.
*
* @param event the change event fired by the preference store
*/
public void adaptToPreferenceChange(PropertyChangeEvent event) {
String property = event.getProperty();
StyleKeys styleKeys = getStyleKeysContaining(property);
if (styleKeys != null) {
if (styleKeys.colorKey.equals(property)) {
Token token = (Token) tokens.get(styleKeys);
handleColorChange(token, event);
} else if (styleKeys.boldKey.equals(property)) {
Token token = (Token) tokens.get(styleKeys);
handleBoldChange(token, event);
}
}
}
/**
* Called to determine whether the change of a specific preference affects
* the presentation of the tokens managed by the scanner.
*
* @param event the preference change event
* @return true
if the change affects the presentation of one
* of the tokens managed by the scanner, false
* otherwise
*/
public boolean affectsPresentation(PropertyChangeEvent event) {
String property = event.getProperty();
return (getStyleKeysContaining(property) != null);
}
// Protected Methods -------------------------------------------------------
/**
* Creates a token with the specified color and style as associated text
* attribute. The color and style are specified as preference keys.
*
* @param colorKey The preference key of the color
* @param boldKey The preference key of the boolean value that determines
* whether the text should be rendered bold, or null
* @return the created token
*/
protected final IToken createToken(String colorKey, String boldKey) {
RGB rgb = PreferenceConverter.getColor(store, colorKey);
colorManager.unbindColor(colorKey);
colorManager.bindColor(colorKey, rgb);
int style = SWT.NORMAL;
if ((boldKey != null) && store.getBoolean(boldKey)) {
style |= SWT.BOLD;
}
IToken token = new Token(new TextAttribute(
colorManager.getColor(colorKey), null, style));
StyleKeys styleKeys = new StyleKeys(colorKey, boldKey);
tokens.put(styleKeys, token);
return token;
}
// Private Methods ---------------------------------------------------------
private StyleKeys getStyleKeysContaining(String key) {
for (Iterator i = tokens.keySet().iterator(); i.hasNext(); ) {
StyleKeys styleKeys = (StyleKeys) i.next();
if (styleKeys.colorKey.equals(key)
|| styleKeys.boldKey.equals(key)) {
return styleKeys;
}
}
return null;
}
private void handleColorChange(Token token, PropertyChangeEvent event) {
RGB rgb = null;
Object value = event.getNewValue();
if (value instanceof RGB) {
rgb = (RGB) value;
} else if (value instanceof String) {
rgb = StringConverter.asRGB((String) value);
}
if (rgb != null) {
String key = event.getProperty();
colorManager.unbindColor(key);
colorManager.bindColor(key, rgb);
Object data = token.getData();
if (data instanceof TextAttribute) {
TextAttribute oldAttr = (TextAttribute) data;
token.setData(new TextAttribute(colorManager.getColor(key),
oldAttr.getBackground(), oldAttr.getStyle()));
}
}
}
private void handleBoldChange(Token token, PropertyChangeEvent event) {
boolean bold = false;
Object value = event.getNewValue();
if (value instanceof Boolean) {
bold = ((Boolean) value).booleanValue();
} else if (value instanceof String) {
StringConverter.asBoolean((String) value);
}
Object data = token.getData();
if (data instanceof TextAttribute) {
TextAttribute oldAttr = (TextAttribute) data;
boolean wasBold = ((oldAttr.getStyle() & SWT.BOLD) != 0);
if (wasBold != bold) {
int newStyle = bold ? oldAttr.getStyle() | SWT.BOLD
: oldAttr.getStyle() ^ SWT.BOLD;
token.setData(new TextAttribute(oldAttr.getForeground(),
oldAttr.getBackground(), newStyle));
}
}
}
}