Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorCss/Css/CssStyleDeclaration.cs @ 13398

Last change on this file since 13398 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 12.3 KB
Line 
1// <developer>niklas@protocol7.com</developer>
2// <completed>80</completed>
3
4using System;
5using System.Text;
6using System.Collections.Generic;
7using System.Text.RegularExpressions;
8
9namespace SharpVectors.Dom.Css
10{
11  /// <summary>
12  /// The CSSStyleDeclaration interface represents a single CSS declaration block. This interface may be used to determine the style properties currently set in a block or to set style properties explicitly within the block.
13  /// While an implementation may not recognize all CSS properties within a CSS declaration block, it is expected to provide access to all specified properties in the style sheet through the CSSStyleDeclaration interface. Furthermore, implementations that support a specific level of CSS should correctly handle CSS shorthand properties for that level. For a further discussion of shorthand properties, see the CSS2Properties interface.
14  /// This interface is also used to provide a read-only access to the computed values of an element. See also the ViewCSS interface.
15  /// Note: The CSS Object Model doesn't provide an access to the specified or actual values of the CSS cascade
16  /// </summary>
17  public class CssStyleDeclaration : ICssStyleDeclaration
18  {
19    #region Static Members
20
21    private static Regex styleRegex = new Regex(
22            @"^(?<name>[A-Za-z\-0-9]+)\s*:(?<value>[^;\}!]+)(!\s?(?<priority>important))?;?");
23   
24        #endregion
25
26        #region Private Fields
27
28        private bool _readOnly;
29        private CssStyleSheetType _origin;
30        private Dictionary<string, CssStyleBlock> styles = new Dictionary<string, CssStyleBlock>();
31
32        #endregion
33
34    #region Constructors
35    /// <summary>
36    /// The constructor used internally when collecting styles for a specified element
37    /// </summary>
38    internal CssStyleDeclaration()
39    {
40      _origin = CssStyleSheetType.Collector;
41      _readOnly = true;
42      _parentRule = null;
43    }
44
45    /// <summary>
46    /// The constructor for CssStyleDeclaration
47    /// </summary>
48    /// <param name="css">The string to parse for CSS</param>
49    /// <param name="parentRule">The parent rule or parent stylesheet</param>
50    /// <param name="readOnly">True if this instance is readonly</param>
51    /// <param name="origin">The type of CssStyleSheet</param>
52    public CssStyleDeclaration(ref string css, CssRule parentRule, bool readOnly, CssStyleSheetType origin)
53    {
54      _origin = origin;
55      _readOnly = readOnly;
56      _parentRule = parentRule;
57
58      css = parseString(css);
59    }
60
61    public CssStyleDeclaration(string css, CssRule parentRule, bool readOnly, CssStyleSheetType origin)
62    {
63      _origin = origin;
64      _readOnly = readOnly;
65      _parentRule = parentRule;
66
67      parseString(css);
68    }
69    #endregion
70
71        #region Public Properties
72
73        public bool ReadOnly
74    {
75      get
76      {
77        return _readOnly;
78      }
79    }
80
81    public CssStyleSheetType Origin
82    {
83      get
84      {
85        return _origin;
86      }
87        }
88
89        #endregion
90
91        #region Public Methods
92
93        /// <summary>
94    /// Used to find matching style rules in the cascading order
95    /// </summary>
96    internal void GetStylesForElement(CssCollectedStyleDeclaration csd, int specificity)
97    {
98            foreach (KeyValuePair<string, CssStyleBlock> de in styles)
99      {
100        CssStyleBlock scs = de.Value;
101        csd.CollectProperty(scs.Name, specificity,
102                    (CssValue)GetPropertyCssValue(scs.Name), scs.Origin, scs.Priority);
103      }
104    }
105
106    #endregion
107
108        #region Private Methods
109
110        private string parseString(string cssText)
111        {
112            bool startedWithABracket = false;
113
114            cssText = cssText.Trim();
115            if (cssText.StartsWith("{"))
116            {
117                cssText = cssText.Substring(1).Trim();
118                startedWithABracket = true;
119            }
120
121            Match match = styleRegex.Match(cssText);
122            while (match.Success)
123            {
124                string name = match.Groups["name"].Value;
125                string value = match.Groups["value"].Value;
126                if (_parentRule != null)
127                {
128                    value = ((CssRule)_parentRule).DeReplaceStrings(value);
129                }
130                string prio = match.Groups["priority"].Value;
131
132                CssStyleBlock style = new CssStyleBlock(name, value, prio, _origin);
133
134                bool addStyle = false;
135                if (styles.ContainsKey(name))
136                {
137                    string existingPrio = ((CssStyleBlock)styles[name]).Priority;
138
139                    if (existingPrio != "important" || prio == "important")
140                    {
141                        styles.Remove(name);
142                        addStyle = true;
143                    }
144                }
145                else
146                {
147                    addStyle = true;
148
149                }
150
151                if (addStyle)
152                {
153                    styles.Add(name, style);
154                }
155
156                cssText = cssText.Substring(match.Length).Trim();
157                match = styleRegex.Match(cssText);
158            }
159
160            cssText = cssText.Trim();
161            if (cssText.StartsWith("}"))
162            {
163                cssText = cssText.Substring(1);
164            }
165            else if (startedWithABracket)
166            {
167                throw new DomException(DomExceptionType.SyntaxErr, "Style declaration ending bracket missing");
168            }
169            return cssText;
170        }
171
172        #endregion
173
174    #region ICssStyleDeclaration Members
175
176    /// <summary>
177    /// Used to set a property value and priority within this declaration block
178    /// </summary>
179    /// <param name="propertyName">The name of the CSS property. See the CSS property index.</param>
180    /// <param name="value">The new value of the property.</param>
181    /// <param name="priority">The new priority of the property (e.g. "important").</param>
182    /// <exception cref="DomException">SYNTAX_ERR: Raised if the specified value has a syntax error and is unparsable.</exception>
183    /// <exception cref="DomException">NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is readonly or the property is readonly.</exception>
184    public void SetProperty(string propertyName, string value, string priority)
185    {
186            if (_readOnly)
187                throw new DomException(DomExceptionType.NoModificationAllowedErr);
188
189      styles[propertyName] = new CssStyleBlock(propertyName, value, priority, _origin);
190    }
191
192    /// <summary>
193    /// Used to retrieve the priority of a CSS property (e.g. the "important" qualifier) if the property has been explicitly set in this declaration block.
194    /// </summary>
195    /// <param name="propertyName">The name of the CSS property. See the CSS property index.</param>
196    /// <returns>A string representing the priority (e.g. "important") if one exists. The empty string if none exists.</returns>
197    public virtual string GetPropertyPriority(string propertyName)
198    {
199      return (styles.ContainsKey(propertyName)) ? styles[propertyName].Priority : String.Empty;
200    }
201
202    /// <summary>
203    /// Used to remove a CSS property if it has been explicitly set within this declaration block.
204    /// </summary>
205    /// <param name="propertyName">The name of the CSS property. See the CSS property index.</param>
206    /// <returns>Returns the value of the property if it has been explicitly set for this declaration block. Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property.</returns>
207    /// <exception cref="DomException">NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is readonly or the property is readonly.</exception>
208    public string RemoveProperty(string propertyName)
209    {
210      if (_readOnly)
211                throw new DomException(DomExceptionType.NoModificationAllowedErr);
212
213      if (styles.ContainsKey(propertyName))
214      {
215        CssStyleBlock s = styles[propertyName];
216        styles.Remove(propertyName);
217        return s.Value;
218      }
219     
220            return String.Empty;
221    }
222
223   
224   
225    /// <summary>
226    /// Used to retrieve the object representation of the value of a CSS property if it has been explicitly set within this declaration block. This method returns null if the property is a shorthand property. Shorthand property values can only be accessed and modified as strings, using the getPropertyValue and setProperty methods.
227    /// </summary>
228    /// <param name="propertyName">The name of the CSS property. See the CSS property index.</param>
229    /// <returns>Returns the value of the property if it has been explicitly set for this declaration block. Returns null if the property has not been set.</returns>
230    public virtual ICssValue GetPropertyCssValue(string propertyName)
231    {
232      if (styles.ContainsKey(propertyName))
233      {
234        CssStyleBlock scs = styles[propertyName];
235        if (scs.CssValue == null)
236        {
237          scs.CssValue = CssValue.GetCssValue(scs.Value, ReadOnly);
238        }
239        return scs.CssValue;
240      }
241      else
242      {
243        return null;
244      }
245    }
246
247    /// <summary>
248    /// Used to retrieve the value of a CSS property if it has been explicitly set within this declaration block.
249    /// </summary>
250    /// <param name="propertyName">The name of the CSS property. See the CSS property index.</param>
251    /// <returns>Returns the value of the property if it has been explicitly set for this declaration block. Returns the empty string if the property has not been set.</returns>
252    public virtual string GetPropertyValue(string propertyName)
253    {
254      return (styles.ContainsKey(propertyName)) ? styles[propertyName].Value : String.Empty;
255    }
256
257   
258    private ICssRule _parentRule;
259    /// <summary>
260    /// The CSS rule that contains this declaration block or null if this CSSStyleDeclaration is not attached to a CSSRule.
261    /// </summary>
262    public ICssRule ParentRule
263    {
264      get
265      {
266        return _parentRule;
267      }
268    }
269
270    /// <summary>
271    /// The number of properties that have been explicitly set in this declaration block. The range of valid indices is 0 to length-1 inclusive.
272    /// </summary>
273    public virtual ulong Length
274    {
275      get
276      {
277        return (ulong)styles.Count;
278      }
279    }
280
281    /// <summary>
282    /// The parsable textual representation of the declaration block (excluding the surrounding curly braces). Setting this attribute will result in the parsing of the new value and resetting of all the properties in the declaration block including the removal or addition of properties.
283    /// </summary>
284    /// <exception cref="DomException">SYNTAX_ERR: Raised if the specified CSS string value has a syntax error and is unparsable.</exception>
285    /// <exception cref="DomException">NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is readonly or a property is readonly.</exception>
286    public virtual string CssText
287    {
288      get
289      {
290                StringBuilder builder = new StringBuilder();
291
292        //string ret = String.Empty;
293       
294        IEnumerator<KeyValuePair<string, CssStyleBlock>> enu = styles.GetEnumerator();
295        while (enu.MoveNext())
296        {
297          CssStyleBlock style = enu.Current.Value;
298                    builder.Append(style.CssText);
299                    builder.Append(";");
300          //ret += style.CssText + ";";
301        }
302
303                return builder.ToString();
304      }
305      set
306      {
307        throw new NotImplementedException();
308      }
309    }
310
311    /// <summary>
312    /// Used to retrieve the properties that have been explicitly set in this declaration block. The order of the properties retrieved using this method does not have to be the order in which they were set. This method can be used to iterate over all properties in this declaration block.
313    /// The name of the property at this ordinal position. The empty string if no property exists at this position.
314    /// </summary>
315    public virtual string this[ulong index]
316    {
317      get
318      {
319        if(index>=Length) return String.Empty;
320        else
321        {
322          int ind = (int)index;
323                    IEnumerator<KeyValuePair<string, CssStyleBlock>> iterator = styles.GetEnumerator();
324                    iterator.MoveNext();
325                    KeyValuePair<string, CssStyleBlock> enu = iterator.Current;
326                    for (int i = 0; i < ind; i++)
327                    {
328                        iterator.MoveNext();
329                        enu = iterator.Current;
330                    }
331
332          return (string)enu.Key;
333        }
334      }
335    }
336    #endregion
337  }
338}
Note: See TracBrowser for help on using the repository browser.