// niklas@protocol7.com
// 80
using System;
using System.Xml;
using System.Globalization;
using System.Text.RegularExpressions;
namespace SharpVectors.Dom.Css
{
///
/// The CSSValue interface represents a simple or a complex value. A CSSValue object only occurs in a context of a CSS property
///
public class CssValue : ICssValue
{
#region Static members
private static string numberPattern = @"[\-\+]?[0-9]*\.?[0-9]+";
public static string LengthUnitPattern = "(?in|cm|mm|px|em|ex|pc|pt|%)?";
public static string AngleUnitPattern = "(?deg|rad|grad)?";
public static string LengthPattern = @"(?" + numberPattern + ")" + LengthUnitPattern;
public static string AnglePattern = @"(?" + numberPattern + ")" + AngleUnitPattern;
private static string cssPrimValuePattern = @"^(?"
+ @"(?(?attr|url|counter|rect|rgb)\((?[^\)]+)\))"
+ @"|(?" + LengthPattern + ")"
+ @"|(?" + AnglePattern + ")"
+ @"|(?(?" + numberPattern + ")(?Hz|kHz|in|s|ms|%)?)"
+ @"|(?[""'](?(.|\n)*?)[""'])"
+ @"|(?([A-Za-z]+)|(\#[A-Fa-f0-9]{6})|(\#[A-Fa-f0-9]{3}))"
+ @")";
private static Regex reCssPrimitiveValue = new Regex(cssPrimValuePattern + "$");
private static Regex reCssValueList = new Regex(cssPrimValuePattern + @"(\s*,\s*)+$");
///
/// Detects what kind of value cssText contains and returns an instance of the correct CssValue class
///
/// The text to parse for a CSS value
/// Specifies if this instance is read-only
/// The correct type of CSS value
static public CssValue GetCssValue(string cssText, bool readOnly)
{
if(cssText == "inherit")
{
// inherit
return new CssValue(CssValueType.Inherit, cssText, readOnly);
}
else
{
Match match = reCssPrimitiveValue.Match(cssText);
if(match.Success)
{
// single primitive value
return CssPrimitiveValue.Create(match, readOnly);
}
match = reCssValueList.Match(cssText);
if(match.Success)
{
// list of primitive values
throw new NotImplementedException("Value lists not implemented");
}
else
{
// custom value
return new CssValue(CssValueType.Custom, cssText, readOnly);
}
}
}
#endregion
#region Constructors
///
/// Constructor for CssValue
///
/// The type of value
/// The entire content of the value
/// Specifies if the instance is read-only
public CssValue(CssValueType type, string cssText, bool readOnly)
{
_cssText = cssText.Trim();
_cssValueType = type;
_readOnly = readOnly;
}
///
/// Only for internal use
///
protected CssValue()
{
_readOnly = true;
}
#endregion
#region Public methods
public virtual CssValue GetAbsoluteValue(string propertyName, XmlElement elm)
{
return new CssAbsValue(this, propertyName, elm);
}
#endregion
private bool _readOnly;
public virtual bool ReadOnly
{
get
{
return _readOnly;
}
}
#region ICssValue Members
private string _cssText;
protected CssValueType _cssValueType;
///
/// A string representation of the current value.
///
/// SYNTAX_ERR: Raised if the specified CSS string value has a syntax error (according to the attached property) or is unparsable.
/// INVALID_MODIFICATION_ERR: Raised if the specified CSS string value represents a different type of values than the values allowed by the CSS property
/// NO_MODIFICATION_ALLOWED_ERR: Raised if this value is readonly.
public virtual string CssText
{
get
{
return _cssText;
}
set
{
if(ReadOnly)
{
throw new DomException(DomExceptionType.InvalidModificationErr, "The CssValue is read-only");
}
else
{
_cssText = value;
}
}
}
///
/// A code defining the type of the value as defined above
///
public virtual CssValueType CssValueType
{
get
{
return _cssValueType;
}
}
#endregion
}
}