/******************************************************************************* * 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(); } }