Merge branch 'sgen-android'
[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 #if NET_4_0
43                 string descriptionText;
44                 string keywordsText;
45                 HtmlMeta descriptionMeta;
46                 HtmlMeta keywordsMeta;
47 #endif
48                 string titleText;
49                 HtmlTitle title;
50                 //Hashtable metadata;
51                 StyleSheetBag styleSheet;
52                 
53                 public HtmlHead(): base("head") {}
54
55                 public HtmlHead (string tag) : base (tag)
56                 {
57                 }
58                 
59                 protected internal override void OnInit (EventArgs e)
60                 {
61                         base.OnInit (e);
62                         Page page = Page;
63                         
64                         if (page == null)
65                                 throw new HttpException ("The <head runat=\"server\"> control requires a page.");
66                         
67                         //You can only have one <head runat="server"> control on a page.
68                         if(page.Header != null)
69                                 throw new HttpException ("You can only have one <head runat=\"server\"> control on a page.");
70                         page.SetHeader (this);
71                 }
72                 
73                 protected internal override void RenderChildren (HtmlTextWriter writer)
74                 {
75                         base.RenderChildren (writer);
76                         if (title == null) {
77                                 writer.RenderBeginTag (HtmlTextWriterTag.Title);
78                                 if (!String.IsNullOrEmpty (titleText))
79                                         writer.Write (titleText);
80                                 writer.RenderEndTag ();
81                         }
82 #if NET_4_0
83                         if (descriptionMeta == null && descriptionText != null) {
84                                 writer.AddAttribute ("name", "description");
85                                 writer.AddAttribute ("content", HttpUtility.HtmlAttributeEncode (descriptionText));
86                                 writer.RenderBeginTag (HtmlTextWriterTag.Meta);
87                                 writer.RenderEndTag ();
88                         }
89
90                         if (keywordsMeta == null && keywordsText != null) {
91                                 writer.AddAttribute ("name", "keywords");
92                                 writer.AddAttribute ("content", HttpUtility.HtmlAttributeEncode (keywordsText));
93                                 writer.RenderBeginTag (HtmlTextWriterTag.Meta);
94                                 writer.RenderEndTag ();
95                         }
96 #endif
97                         if (styleSheet != null)
98                                 styleSheet.Render (writer);
99                 }
100                 
101                 protected internal override void AddedControl (Control control, int index)
102                 {
103                         //You can only have one <title> element within the <head> element.
104                         HtmlTitle t = control as HtmlTitle;
105                         if (t != null) {
106                                 if (title != null)
107                                         throw new HttpException ("You can only have one <title> element within the <head> element.");
108                                 title = t;
109                         }
110
111 #if NET_4_0
112                         HtmlMeta meta = control as HtmlMeta;
113                         if (meta != null) {
114                                 if (String.Compare ("keywords", meta.Name, StringComparison.OrdinalIgnoreCase) == 0)
115                                         keywordsMeta = meta;
116                                 else if (String.Compare ("description", meta.Name, StringComparison.OrdinalIgnoreCase) == 0)
117                                         descriptionMeta = meta;
118                         }
119 #endif
120                         base.AddedControl (control, index);
121                 }
122
123                 protected internal override void RemovedControl (Control control)
124                 {
125                         if (title == control)
126                                 title = null;
127
128 #if NET_4_0
129                         if (keywordsMeta == control)
130                                 keywordsMeta = null;
131                         else if (descriptionMeta == control)
132                                 descriptionMeta = null;
133 #endif
134                         base.RemovedControl (control);
135                 }
136 #if NET_4_0
137                 public string Description {
138                         get {
139                                 if (descriptionMeta != null)
140                                         return descriptionMeta.Content;
141                                 return descriptionText;
142                         }
143                         
144                         set {
145                                 if (descriptionMeta != null)
146                                         descriptionMeta.Content = value;
147                                 else
148                                         descriptionText = value;
149                         }
150                 }
151
152                 public string Keywords {
153                         get {
154                                 if (keywordsMeta != null)
155                                         return keywordsMeta.Content;
156                                 return keywordsText;
157                         }
158                         
159                         set {
160                                 if (keywordsMeta != null)
161                                         keywordsMeta.Content = value;
162                                 else
163                                         keywordsText = value;
164                         }
165                 }
166 #endif
167                 
168                 public IStyleSheet StyleSheet {
169                         get {
170                                 if (styleSheet == null) styleSheet = new StyleSheetBag ();
171                                 return styleSheet;
172                         }
173                 }
174                 
175                 public string Title {
176                         get {
177                                 if (title != null)
178                                         return title.Text;
179                                 else
180                                         return titleText;
181                         }
182                         set {
183                                 if (title != null)
184                                         title.Text = value;
185                                 else
186                                         titleText = value;
187                         }
188                 }
189         }
190         
191         internal class StyleSheetBag: IStyleSheet
192         {
193                 ArrayList entries = new ArrayList ();
194                 
195                 internal class StyleEntry
196                 {
197                         public Style Style;
198                         public string Selection;
199                         public IUrlResolutionService UrlResolver;
200                 }
201                 
202                 public StyleSheetBag ()
203                 {
204                 }
205                 
206                 public void CreateStyleRule (Style style, IUrlResolutionService urlResolver, string selection)
207                 {
208                         StyleEntry entry = new StyleEntry ();
209                         entry.Style = style;
210                         entry.UrlResolver = urlResolver;
211                         entry.Selection = selection;
212                         entries.Add (entry);
213                 }
214                 
215                 public void RegisterStyle (Style style, IUrlResolutionService urlResolver)
216                 {
217                         for (int n=0; n<entries.Count; n++) {
218                                 if (((StyleEntry)entries[n]).Style == style)
219                                         return;
220                         }
221                         
222                         string name = "aspnet_" + entries.Count;
223                         style.SetRegisteredCssClass (name);
224                         CreateStyleRule (style, urlResolver, "." + name);
225                 }
226                 
227                 public void Render (HtmlTextWriter writer)
228                 {
229                         writer.AddAttribute ("type", "text/css", false);
230                         writer.RenderBeginTag (HtmlTextWriterTag.Style);
231
232                         foreach (StyleEntry entry in entries) {
233                                 CssStyleCollection sts = entry.Style.GetStyleAttributes (entry.UrlResolver);
234                                 writer.Write ("\n" + entry.Selection + " {" + sts.Value + "}");
235                         }
236
237                         writer.RenderEndTag ();
238                 }
239         }
240 }
241