/*******************************************************************************
* Copyright (c) 2007, 2011 David Green 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 Green - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.wikitext.ui.editor.preferences;
import java.util.Iterator;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.mylyn.internal.wikitext.ui.viewer.CssStyleManager;
import org.eclipse.mylyn.wikitext.parser.css.CssParser;
import org.eclipse.mylyn.wikitext.parser.css.CssRule;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Composite;
/**
* A field editor for CSS styles. Adds validation to CSS rule input.
*
* @author David Green
*/
public class CssStyleFieldEditor extends StringFieldEditor {
private final CssStyleManager cssStyleManager;
public CssStyleFieldEditor(CssStyleManager cssStyleManager, String preferenceKey, String key, Composite parent) {
super(preferenceKey, key, parent);
this.cssStyleManager = cssStyleManager;
}
/**
* validate the input
*/
@Override
protected boolean doCheckState() {
String value = getStringValue();
if (value != null && value.trim().length() > 0) {
// here we validate that the value looks like it is composed of valid CSS rules
int offset = 0;
Iterator<CssRule> ruleIterator = new CssParser().createRuleIterator(value);
while (ruleIterator.hasNext()) {
CssRule rule = ruleIterator.next();
// detect gaps between rules. Such gaps are areas of text that weren't detected as a CSS rule.
if (rule.offset > offset) {
String gap = value.substring(offset, rule.offset);
if (gap.trim().length() != 0) {
setErrorMessage(NLS.bind(Messages.CssStyleFieldEditor_unexpectedToken,
new Object[] { gap.trim(), offset }));
return false;
}
}
offset = rule.offset + rule.length;
// unknown rules should create an error
if (!cssStyleManager.isKnownRule(rule)) {
StringBuilder recognizedNames = new StringBuilder();
for (String recognizedName : cssStyleManager.getRecognizedRuleNames()) {
if (recognizedNames.length() > 0) {
recognizedNames.append(Messages.CssStyleFieldEditor_1);
}
recognizedNames.append(recognizedName);
}
setErrorMessage(NLS.bind(Messages.CssStyleFieldEditor_unsupportedRule,
new Object[] { rule.name, recognizedNames }));
return false;
}
if (CssStyleManager.RULE_COLOR.equals(rule.name)
|| CssStyleManager.RULE_BACKGROUND_COLOR.equals(rule.name)) {
Integer rgb = CssStyleManager.cssColorRgb(rule.value);
if (rgb == null) {
setErrorMessage(
NLS.bind(Messages.CssStyleFieldEditor_invalidColor, new Object[] { rule.value }));
return false;
}
}
}
// detect trailing text that wasn't detected as a CSS rule.
if (offset < value.length() - 1) {
String gap = value.substring(offset, value.length());
if (gap.trim().length() != 0) {
setErrorMessage(NLS.bind(Messages.CssStyleFieldEditor_unexpectedToken,
new Object[] { gap.trim(), offset }));
return false;
}
}
}
return super.doCheckState();
}
}