using System;
using System.Xml;
using System.Xml.XPath;
using System.Text.RegularExpressions;
using SharpVectors.Dom.Stylesheets;
using System.Collections;
using System.Collections.Generic;
namespace SharpVectors.Dom.Css
{
///
/// The CSSStyleRule interface represents a single rule set in a CSS style sheet.
///
/// niklas@protocol7.com
/// 80
public class CssStyleRule : CssRule,ICssStyleRule
{
#region Static members
internal static string nsPattern = @"([A-Za-z\*][A-Za-z0-9]*)?\|";
internal static string attributeValueCheck = "(?(" + nsPattern + ")?[a-zA-Z0-9]+)\\s*(?[\\~\\^\\$\\*\\|]?)=\\s*(\"|\')?(?.*?)(\"|\')?";
internal static string sSelector = "(?" + nsPattern + ")?" +
@"(?([A-Za-z\*][A-Za-z0-9]*))?" +
@"((?\.[A-Za-z][A-Za-z0-9]*)+)?" +
@"(?\#[A-Za-z][A-Za-z0-9]*)?" +
@"((?\[\s*(" +
@"(?(" + nsPattern + ")?[a-zA-Z0-9]+)" +
@"|" +
"(?" + attributeValueCheck + ")" +
@")\s*\])+)?" +
@"((?\:[a-z\-]+(\([^\)]+\))?)+)?" +
@"(?(\:\:[a-z\-]+)+)?" +
@"(?(\s*(\+|\>|\~)\s*)|(\s+))?";
private static string sStyleRule = "^((?(" + sSelector + @")+)(\s*,\s*)?)+";
private static Regex regex = new Regex(sStyleRule);
internal static CssRule Parse(ref string css, object parent, bool readOnly,
IList replacedStrings, CssStyleSheetType origin)
{
Match match = regex.Match(css);
if(match.Success && match.Length > 0)
{
CssStyleRule rule = new CssStyleRule(match, parent, readOnly, replacedStrings, origin);
css = css.Substring(match.Length);
rule._Style = new CssStyleDeclaration(ref css, rule, readOnly, origin);
return rule;
}
else
{
return null;
}
}
#endregion
#region Constructors
///
/// The constructor for CssStyleRule
///
/// The Regex match that found the charset rule
/// The parent rule or parent stylesheet
/// True if this instance is readonly
/// An array of strings that have been replaced in the string used for matching. These needs to be put back use the DereplaceStrings method
/// The type of CssStyleSheet
internal CssStyleRule(Match match, object parent, bool readOnly,
IList replacedStrings, CssStyleSheetType origin)
: base(parent, readOnly, replacedStrings, origin)
{
//SelectorText = DeReplaceStrings(match.Groups["selectors"].Value.Trim());
//_Style = new CssStyleDeclaration(match, this, readOnly, Origin);
Group selectorMatches = match.Groups["selector"];
int len = selectorMatches.Captures.Count;
ArrayList sels = new ArrayList();
for(int i = 0; i 0)
{
sels.Add(new CssXPathSelector(str));
}
}
XPathSelectors = (CssXPathSelector[])sels.ToArray(typeof(CssXPathSelector));
}
#endregion
#region Public methods
///
/// Used to find matching style rules in the cascading order
///
/// The element to find styles for
/// The pseudo-element to find styles for
/// The medialist that the document is using
/// A CssStyleDeclaration that holds the collected styles
protected internal override void GetStylesForElement(XmlElement elt, string pseudoElt, MediaList ml, CssCollectedStyleDeclaration csd)
{
XPathNavigator nav = elt.CreateNavigator();
foreach(CssXPathSelector sel in XPathSelectors)
{
// TODO: deal with pseudoElt
if(sel != null && sel.Matches(nav))
{
((CssStyleDeclaration)Style).GetStylesForElement(csd, sel.Specificity);
break;
}
}
}
#endregion
#region Private fields
private CssXPathSelector[] XPathSelectors;
#endregion
#region Implementation of ICssStyleRule
///
/// The textual representation of the selector for the rule set. The implementation may have stripped out insignificant whitespace while parsing the selector.
///
/// SYNTAX_ERR: Raised if the specified CSS string value has a syntax error and is unparsable.
/// NO_MODIFICATION_ALLOWED_ERR: Raised if this rule is readonly
public string SelectorText
{
get
{
string ret = String.Empty;
foreach(CssXPathSelector sel in XPathSelectors)
{
ret += sel.CssSelector + ",";
}
return ret.Substring(0, ret.Length-1);
}
set
{
// TODO: invalidate
throw new NotImplementedException("setting SelectorText");
}
}
///
/// The entire text of the CssStyleRule
///
public override string CssText
{
get
{
return SelectorText + "{" + ((CssStyleDeclaration)Style).CssText + "}";
}
}
private CssStyleDeclaration _Style;
///
/// The declaration-block of this rule set.
///
public ICssStyleDeclaration Style
{
get
{
return _Style;
}
}
#endregion
#region Implementation of ICssRule
///
/// The type of the rule. The expectation is that binding-specific casting methods can be used to cast down from an instance of the CSSRule interface to the specific derived interface implied by the type.
///
public override CssRuleType Type
{
get
{
return CssRuleType.StyleRule;
}
}
#endregion
}
}