Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / class / System.Web / System.Web.UI.HtmlControls / HtmlHead.cs
1 //
2 // System.Web.UI.HtmlControls.HtmlHead
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // Copyright (C) 2004-2010 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.ComponentModel;
30 using System.Collections;
31 using System.Security.Permissions;
32 using System.Web.UI.WebControls;
33
34 namespace System.Web.UI.HtmlControls
35 {
36         // CAS - no InheritanceDemand here as the class is sealed
37         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
38         // attributes
39         [ControlBuilder (typeof(HtmlHeadBuilder))]
40         public sealed class HtmlHead: HtmlGenericControl, IParserAccessor
41         {
42                 string descriptionText;
43                 string keywordsText;
44                 HtmlMeta descriptionMeta;
45                 HtmlMeta keywordsMeta;
46                 string titleText;
47                 HtmlTitle title;
48                 //Hashtable metadata;
49                 StyleSheetBag styleSheet;
50                 
51                 public HtmlHead(): base("head") {}
52
53                 public HtmlHead (string tag) : base (tag)
54                 {
55                 }
56                 
57                 protected internal override void OnInit (EventArgs e)
58                 {
59                         base.OnInit (e);
60                         Page page = Page;
61                         
62                         if (page == null)
63                                 throw new HttpException ("The <head runat=\"server\"> control requires a page.");
64                         
65                         //You can only have one <head runat="server"> control on a page.
66                         if(page.Header != null)
67                                 throw new HttpException ("You can only have one <head runat=\"server\"> control on a page.");
68                         page.SetHeader (this);
69                 }
70                 
71                 protected internal override void RenderChildren (HtmlTextWriter writer)
72                 {
73                         base.RenderChildren (writer);
74                         if (title == null) {
75                                 writer.RenderBeginTag (HtmlTextWriterTag.Title);
76                                 if (!String.IsNullOrEmpty (titleText))
77                                         writer.Write (titleText);
78                                 writer.RenderEndTag ();
79                         }
80                         if (descriptionMeta == null && descriptionText != null) {
81                                 writer.AddAttribute ("name", "description");
82                                 writer.AddAttribute ("content", HttpUtility.HtmlAttributeEncode (descriptionText));
83                                 writer.RenderBeginTag (HtmlTextWriterTag.Meta);
84                                 writer.RenderEndTag ();
85                         }
86
87                         if (keywordsMeta == null && keywordsText != null) {
88                                 writer.AddAttribute ("name", "keywords");
89                                 writer.AddAttribute ("content", HttpUtility.HtmlAttributeEncode (keywordsText));
90                                 writer.RenderBeginTag (HtmlTextWriterTag.Meta);
91                                 writer.RenderEndTag ();
92                         }
93                         if (styleSheet != null)
94                                 styleSheet.Render (writer);
95                 }
96                 
97                 protected internal override void AddedControl (Control control, int index)
98                 {
99                         //You can only have one <title> element within the <head> element.
100                         HtmlTitle t = control as HtmlTitle;
101                         if (t != null) {
102                                 if (title != null)
103                                         throw new HttpException ("You can only have one <title> element within the <head> element.");
104                                 title = t;
105                         }
106
107                         HtmlMeta meta = control as HtmlMeta;
108                         if (meta != null) {
109                                 if (String.Compare ("keywords", meta.Name, StringComparison.OrdinalIgnoreCase) == 0)
110                                         keywordsMeta = meta;
111                                 else if (String.Compare ("description", meta.Name, StringComparison.OrdinalIgnoreCase) == 0)
112                                         descriptionMeta = meta;
113                         }
114                         base.AddedControl (control, index);
115                 }
116
117                 protected internal override void RemovedControl (Control control)
118                 {
119                         if (title == control)
120                                 title = null;
121
122                         if (keywordsMeta == control)
123                                 keywordsMeta = null;
124                         else if (descriptionMeta == control)
125                                 descriptionMeta = null;
126                         base.RemovedControl (control);
127                 }
128                 public string Description {
129                         get {
130                                 if (descriptionMeta != null)
131                                         return descriptionMeta.Content;
132                                 return descriptionText;
133                         }
134                         
135                         set {
136                                 if (descriptionMeta != null)
137                                         descriptionMeta.Content = value;
138                                 else
139                                         descriptionText = value;
140                         }
141                 }
142
143                 public string Keywords {
144                         get {
145                                 if (keywordsMeta != null)
146                                         return keywordsMeta.Content;
147                                 return keywordsText;
148                         }
149                         
150                         set {
151                                 if (keywordsMeta != null)
152                                         keywordsMeta.Content = value;
153                                 else
154                                         keywordsText = value;
155                         }
156                 }
157                 
158                 public IStyleSheet StyleSheet {
159                         get {
160                                 if (styleSheet == null) styleSheet = new StyleSheetBag ();
161                                 return styleSheet;
162                         }
163                 }
164                 
165                 public string Title {
166                         get {
167                                 if (title != null)
168                                         return title.Text;
169                                 else
170                                         return titleText;
171                         }
172                         set {
173                                 if (title != null)
174                                         title.Text = value;
175                                 else
176                                         titleText = value;
177                         }
178                 }
179         }
180         
181         internal class StyleSheetBag: IStyleSheet
182         {
183                 ArrayList entries = new ArrayList ();
184                 
185                 internal class StyleEntry
186                 {
187                         public Style Style;
188                         public string Selection;
189                         public IUrlResolutionService UrlResolver;
190                 }
191                 
192                 public StyleSheetBag ()
193                 {
194                 }
195                 
196                 public void CreateStyleRule (Style style, IUrlResolutionService urlResolver, string selection)
197                 {
198                         StyleEntry entry = new StyleEntry ();
199                         entry.Style = style;
200                         entry.UrlResolver = urlResolver;
201                         entry.Selection = selection;
202                         entries.Add (entry);
203                 }
204                 
205                 public void RegisterStyle (Style style, IUrlResolutionService urlResolver)
206                 {
207                         for (int n=0; n<entries.Count; n++) {
208                                 if (((StyleEntry)entries[n]).Style == style)
209                                         return;
210                         }
211                         
212                         string name = "aspnet_" + entries.Count;
213                         style.SetRegisteredCssClass (name);
214                         CreateStyleRule (style, urlResolver, "." + name);
215                 }
216                 
217                 public void Render (HtmlTextWriter writer)
218                 {
219                         writer.AddAttribute ("type", "text/css", false);
220                         writer.RenderBeginTag (HtmlTextWriterTag.Style);
221
222                         foreach (StyleEntry entry in entries) {
223                                 CssStyleCollection sts = entry.Style.GetStyleAttributes (entry.UrlResolver);
224                                 writer.Write ("\n" + entry.Selection + " {" + sts.Value + "}");
225                         }
226
227                         writer.RenderEndTag ();
228                 }
229         }
230 }
231