[12762] | 1 | using System;
|
---|
| 2 | using System.Xml;
|
---|
| 3 |
|
---|
| 4 | using SharpVectors.Dom.Stylesheets;
|
---|
| 5 |
|
---|
| 6 | namespace SharpVectors.Dom.Css
|
---|
| 7 | {
|
---|
| 8 | public delegate void NodeChangeHandler(Object src, XmlNodeChangedEventArgs args);
|
---|
| 9 | public delegate void CssChangeHandler();
|
---|
| 10 |
|
---|
| 11 | public class CssXmlElement : Element, IElementCssInlineStyle
|
---|
| 12 | {
|
---|
| 13 | #region Constructors
|
---|
| 14 |
|
---|
| 15 | public CssXmlElement(string prefix, string localname, string ns,
|
---|
| 16 | CssXmlDocument doc) : base(prefix, localname, ns, doc)
|
---|
| 17 | {
|
---|
| 18 | }
|
---|
| 19 |
|
---|
| 20 | #endregion
|
---|
| 21 |
|
---|
| 22 | #region Style attribute
|
---|
| 23 |
|
---|
| 24 | private ICssStyleDeclaration style;
|
---|
| 25 |
|
---|
| 26 | public ICssStyleDeclaration Style
|
---|
| 27 | {
|
---|
| 28 | get
|
---|
| 29 | {
|
---|
| 30 | if(style == null)
|
---|
| 31 | {
|
---|
| 32 | style = new CssStyleDeclaration(GetAttribute("style", String.Empty), null, false, CssStyleSheetType.Inline);
|
---|
| 33 | }
|
---|
| 34 | return style;
|
---|
| 35 | }
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | #endregion
|
---|
| 39 |
|
---|
| 40 | #region GetComputedStyle
|
---|
| 41 |
|
---|
| 42 | protected ICssStyleDeclaration cachedCSD;
|
---|
| 43 |
|
---|
| 44 | public virtual ICssStyleDeclaration GetComputedStyle(string pseudoElt)
|
---|
| 45 | {
|
---|
| 46 | if(cachedCSD == null)
|
---|
| 47 | {
|
---|
| 48 | CssCollectedStyleDeclaration csd = new CssCollectedStyleDeclaration(this);
|
---|
| 49 | MediaList currentMedia = OwnerDocument.Media;
|
---|
| 50 |
|
---|
| 51 | if(OwnerDocument.UserAgentStyleSheet != null)
|
---|
| 52 | {
|
---|
| 53 | OwnerDocument.UserAgentStyleSheet.GetStylesForElement(this, pseudoElt, currentMedia, csd);
|
---|
| 54 | }
|
---|
| 55 | ((StyleSheetList)OwnerDocument.StyleSheets).GetStylesForElement(this, pseudoElt, csd);
|
---|
| 56 |
|
---|
| 57 | ((CssStyleDeclaration)Style).GetStylesForElement(csd, 0);
|
---|
| 58 |
|
---|
| 59 | if(OwnerDocument.UserStyleSheet != null)
|
---|
| 60 | {
|
---|
| 61 | OwnerDocument.UserStyleSheet.GetStylesForElement(this, pseudoElt, currentMedia, csd);
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | cachedCSD = csd;
|
---|
| 65 | }
|
---|
| 66 | return cachedCSD;
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | public virtual string GetComputedStringValue(string propertyName, string pseudoElt)
|
---|
| 70 | {
|
---|
| 71 | ICssStyleDeclaration csd = GetComputedStyle(pseudoElt);
|
---|
| 72 | return csd.GetPropertyValue(propertyName);
|
---|
| 73 |
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | public virtual ICssValue GetComputedCssValue(string propertyName, string pseudoElt)
|
---|
| 77 | {
|
---|
| 78 | ICssStyleDeclaration csd = GetComputedStyle(pseudoElt);
|
---|
| 79 | return csd.GetPropertyCssValue(propertyName);
|
---|
| 80 |
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | #endregion
|
---|
| 84 |
|
---|
| 85 | #region OwnerDocument
|
---|
| 86 |
|
---|
| 87 | public new CssXmlDocument OwnerDocument
|
---|
| 88 | {
|
---|
| 89 | get
|
---|
| 90 | {
|
---|
| 91 | return (CssXmlDocument)base.OwnerDocument;
|
---|
| 92 | }
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | #endregion
|
---|
| 96 |
|
---|
| 97 | #region Supports
|
---|
| 98 |
|
---|
| 99 | public override bool Supports(string feature, string version)
|
---|
| 100 | {
|
---|
| 101 | if ((feature == "StyleSheets" || feature == "CSS" ) && version == "2.0")
|
---|
| 102 | {
|
---|
| 103 | return true;
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | return base.Supports(feature, version);
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | #endregion
|
---|
| 110 |
|
---|
| 111 | #region Update handling
|
---|
| 112 | public virtual void CssInvalidate()
|
---|
| 113 | {
|
---|
| 114 | // TODO: why is this being called during load?
|
---|
| 115 | foreach(XmlNode child in ChildNodes)
|
---|
| 116 | {
|
---|
| 117 | if (child is CssXmlElement)
|
---|
| 118 | ((CssXmlElement)child).CssInvalidate();
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | // Kill the cache
|
---|
| 122 | cachedCSD = null;
|
---|
| 123 |
|
---|
| 124 | // Notify
|
---|
| 125 | FireCssChange();
|
---|
| 126 | }
|
---|
| 127 |
|
---|
| 128 | /// <summary>
|
---|
| 129 | /// Called when this element is changing in one of the following ways
|
---|
| 130 | /// <list type="">
|
---|
| 131 | /// <item>Text child added/removed/changed</item>
|
---|
| 132 | /// <item>Element moved in the tree</item>
|
---|
| 133 | /// </list>
|
---|
| 134 | /// </summary>
|
---|
| 135 | public virtual void ElementChange(Object src, XmlNodeChangedEventArgs args)
|
---|
| 136 | {
|
---|
| 137 | // Invalidate the CSS, the cascade for the CSS heirarchy will need to be recomputed
|
---|
| 138 | CssInvalidate();
|
---|
| 139 |
|
---|
| 140 | // Notify any listeners
|
---|
| 141 | FireElementChange(src, args);
|
---|
| 142 | FireParentNodeChange(src, args, false);
|
---|
| 143 | FireChildNodeChange(src, args, false);
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | /// <summary>
|
---|
| 147 | /// Called when any parent element is changing. If an element is moved the CSS heirarchy for that element
|
---|
| 148 | /// will need to change.
|
---|
| 149 | /// </summary>
|
---|
| 150 | public virtual void ParentNodeChange(Object src, XmlNodeChangedEventArgs args)
|
---|
| 151 | {
|
---|
| 152 | FireParentNodeChange(src, args, true);
|
---|
| 153 | }
|
---|
| 154 |
|
---|
| 155 | /// <summary>
|
---|
| 156 | /// Called when any attribute is changing. This is typically triggered by calls to
|
---|
| 157 | /// setAttribute() and should only be called from the CssXmlDocument.
|
---|
| 158 | /// </summary>
|
---|
| 159 | /// <see cref="CssXmlDocument"/>
|
---|
| 160 | public virtual void AttributeChange(Object src, XmlNodeChangedEventArgs args)
|
---|
| 161 | {
|
---|
| 162 | // Invalidate the CSS, the cascade for the CSS heirarchy will need to be recomputed
|
---|
| 163 | // We do this before and after the change because we need to invalidate the old and new locations
|
---|
| 164 | CssInvalidate();
|
---|
| 165 |
|
---|
| 166 | XmlAttribute attribute = src as XmlAttribute;
|
---|
| 167 |
|
---|
| 168 | if(attribute != null)
|
---|
| 169 | {
|
---|
| 170 | HandleAttributeChange(attribute);
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | // Notify any listeners
|
---|
| 174 | FireAttributeChange(src, args);
|
---|
| 175 | FireParentNodeChange(src, args, false);
|
---|
| 176 | FireChildNodeChange(src, args, false);
|
---|
| 177 |
|
---|
| 178 | // Invalidate the CSS, the cascade for the CSS heirarchy will need to be recomputed
|
---|
| 179 | CssInvalidate();
|
---|
| 180 | }
|
---|
| 181 |
|
---|
| 182 | /// <summary>
|
---|
| 183 | /// This function allows each element to handle it's own behaviors for
|
---|
| 184 | /// attribute changing. By default, the cached computed style is invalidated
|
---|
| 185 | /// because most attributes refer to style properties.
|
---|
| 186 | /// </summary>
|
---|
| 187 | /// <param name="attribute">The attribute that is changing.</param>
|
---|
| 188 | public virtual void HandleAttributeChange(XmlAttribute attribute)
|
---|
| 189 | {
|
---|
| 190 | if(attribute.NamespaceURI.Length == 0)
|
---|
| 191 | {
|
---|
| 192 | switch (attribute.LocalName)
|
---|
| 193 | {
|
---|
| 194 | case "style":
|
---|
| 195 | style = null;
|
---|
| 196 | break;
|
---|
| 197 | }
|
---|
| 198 | }
|
---|
| 199 | }
|
---|
| 200 |
|
---|
| 201 | /// <summary>
|
---|
| 202 | /// Called when any child node is changing. If an element is moved the CSS heirarchy for that element
|
---|
| 203 | /// will need to change. This is mainly useful when one of the child nodes parent is a
|
---|
| 204 | /// referenced node (for example in a <use> element.
|
---|
| 205 | /// </summary>
|
---|
| 206 | public virtual void ChildNodeChange(Object src, XmlNodeChangedEventArgs args)
|
---|
| 207 | {
|
---|
| 208 | FireChildNodeChange(src, args, true);
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 | protected void FireCssChange()
|
---|
| 212 | {
|
---|
| 213 | if (cssChangeHandler != null)
|
---|
| 214 | {
|
---|
| 215 | cssChangeHandler();
|
---|
| 216 | }
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | protected void FireAttributeChange(Object src, XmlNodeChangedEventArgs args)
|
---|
| 220 | {
|
---|
| 221 | if (attributeChangeHandler != null)
|
---|
| 222 | {
|
---|
| 223 | attributeChangeHandler(src, args);
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
| 226 |
|
---|
| 227 | protected void FireElementChange(Object src, XmlNodeChangedEventArgs args)
|
---|
| 228 | {
|
---|
| 229 | if (elementChangeHandler != null)
|
---|
| 230 | {
|
---|
| 231 | elementChangeHandler(src, args);
|
---|
| 232 | }
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 | protected void FireParentNodeChange(Object src, XmlNodeChangedEventArgs args, bool fireEvent)
|
---|
| 236 | {
|
---|
| 237 | if (fireEvent && parentNodeChangeHandler != null)
|
---|
| 238 | {
|
---|
| 239 | parentNodeChangeHandler(src, args);
|
---|
| 240 | }
|
---|
| 241 |
|
---|
| 242 | foreach(XmlNode child in ChildNodes)
|
---|
| 243 | {
|
---|
| 244 | if (child.NodeType != XmlNodeType.Element) continue;
|
---|
| 245 |
|
---|
| 246 | CssXmlElement cssChild = child as CssXmlElement;
|
---|
| 247 |
|
---|
| 248 | if(cssChild != null)
|
---|
| 249 | {
|
---|
| 250 | cssChild.ParentNodeChange(src, args);
|
---|
| 251 | }
|
---|
| 252 | }
|
---|
| 253 | }
|
---|
| 254 |
|
---|
| 255 | protected void FireChildNodeChange(Object src, XmlNodeChangedEventArgs args, bool fireEvent)
|
---|
| 256 | {
|
---|
| 257 | if (fireEvent && childNodeChangeHandler != null)
|
---|
| 258 | {
|
---|
| 259 | childNodeChangeHandler(src, args);
|
---|
| 260 | }
|
---|
| 261 |
|
---|
| 262 | CssXmlElement cssParent = ParentNode as CssXmlElement;
|
---|
| 263 |
|
---|
| 264 | if(cssParent != null)
|
---|
| 265 | {
|
---|
| 266 | cssParent.ChildNodeChange(src, args);
|
---|
| 267 | }
|
---|
| 268 | }
|
---|
| 269 |
|
---|
| 270 | public virtual event NodeChangeHandler attributeChangeHandler;
|
---|
| 271 | public virtual event NodeChangeHandler elementChangeHandler;
|
---|
| 272 | public virtual event NodeChangeHandler parentNodeChangeHandler;
|
---|
| 273 | public virtual event NodeChangeHandler childNodeChangeHandler;
|
---|
| 274 | public virtual event CssChangeHandler cssChangeHandler;
|
---|
| 275 |
|
---|
| 276 | #endregion
|
---|
| 277 | }
|
---|
| 278 | } |
---|