forgotten ifdefs
[mono.git] / mcs / class / System.Web / System.Web.Compilation / PageThemeCompiler.cs
1 //
2 // System.Web.Compilation.PageThemeCompiler
3 //
4 // Authors:
5 //      Chris Toshok (toshok@ximian.com)
6 //
7 // (C) 2006 Novell, Inc (http://www.novell.com/)
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 #if NET_2_0
32
33 using System;
34 using System.CodeDom;
35 using System.Collections;
36 using System.Collections.Specialized;
37 using System.Reflection;
38 using System.Text;
39 using System.Web.UI;
40 using System.Web.SessionState;
41 using System.Web.Util;
42
43 namespace System.Web.Compilation
44 {
45         class PageThemeCompiler : TemplateControlCompiler
46         {
47                 PageThemeParser parser;
48
49                 public PageThemeCompiler (PageThemeParser parser)
50                         : base (parser)
51                 {
52                         this.parser = parser;
53                 }
54
55                 protected internal override void CreateMethods ()
56                 {
57                         CodeMemberField fld;
58                         CodeMemberProperty prop;
59
60                         /* override the following abstract PageTheme properties:
61                            protected abstract string AppRelativeTemplateSourceDirectory { get; }
62                            protected abstract IDictionary ControlSkins { get; }
63                            protected abstract string[] LinkedStyleSheets { get; }
64                         */
65
66                         /* ControlSkins */
67                         fld = new CodeMemberField (typeof (HybridDictionary), "__controlSkins");
68                         fld.Attributes = MemberAttributes.Private;
69                         fld.InitExpression = new CodeObjectCreateExpression (typeof (HybridDictionary));
70                         mainClass.Members.Add (fld);
71
72                         prop = new CodeMemberProperty ();
73                         prop.Name = "ControlSkins";
74                         prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
75                         prop.Type = new CodeTypeReference (typeof (IDictionary));
76                         prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__controlSkins")));
77                         mainClass.Members.Add (prop);
78
79                         /* LinkedStyleSheets */
80                         fld = new CodeMemberField (typeof (string[]), "__linkedStyleSheets");
81                         fld.Attributes = MemberAttributes.Private;
82                         fld.InitExpression = CreateLinkedStyleSheets ();
83                         mainClass.Members.Add (fld);
84
85                         prop = new CodeMemberProperty ();
86                         prop.Name = "LinkedStyleSheets";
87                         prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
88                         prop.Type = new CodeTypeReference (typeof (string[]));
89                         prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__linkedStyleSheets")));
90                         mainClass.Members.Add (prop);
91
92                         /* AppRelativeTemplateSourceDirectory */
93                         prop = new CodeMemberProperty ();
94                         prop.Name = "AppRelativeTemplateSourceDirectory";
95                         prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
96                         prop.Type = new CodeTypeReference (typeof (string));
97                         prop.GetStatements.Add (new CodeMethodReturnStatement (
98                                                         new CodePrimitiveExpression (
99                                                                 VirtualPathUtility.ToAbsolute (parser.BaseVirtualDir))));
100                         mainClass.Members.Add (prop);
101
102                         ControlBuilder builder = parser.RootBuilder;
103                         if (builder.Children != null) {
104                                 foreach (object o in builder.Children) {
105                                         if (! (o is ControlBuilder))
106                                                 continue;
107                                         if (o is CodeRenderBuilder)
108                                                 continue;
109                                         
110                                         ControlBuilder b = (ControlBuilder) o;
111                                         CreateControlSkinMethod (b);
112                                 }
113                         }
114                 }
115
116                 private CodeExpression CreateLinkedStyleSheets ()
117                 {
118                         string [] lss = parser.LinkedStyleSheets;
119                         if (lss == null)
120                                 return new CodePrimitiveExpression (null);
121                         
122                         CodeExpression [] initializers = new CodeExpression [lss.Length];
123                         for (int i = 0; i < lss.Length; i++)
124                                 initializers[i] = new CodePrimitiveExpression (lss[i]);
125
126                         return new CodeArrayCreateExpression (typeof (string), initializers);
127                 }
128                 
129                 protected override string HandleUrlProperty (string str, MemberInfo member)
130                 {
131                         if (str.StartsWith ("~", StringComparison.Ordinal))
132                                 return str;
133                         
134                         return "~/App_Themes/" + UrlUtils.Combine (
135                                 System.IO.Path.GetFileName (parser.InputFile), str);
136                 }
137
138                 void CreateControlSkinMethod (ControlBuilder builder)
139                 {
140                         if (builder.ControlType == null)
141                                 return;
142                         
143                         EnsureID (builder);
144
145                         CodeMemberMethod method = new CodeMemberMethod ();
146                         method.Name = "__BuildControl_" + builder.ID;
147                         method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (Control), "ctrl"));
148
149                         mainClass.Members.Add (method);
150
151                         builder.method = method;
152                         builder.methodStatements = method.Statements;
153
154                         method.ReturnType = new CodeTypeReference (typeof (Control));
155
156                         // _ctrl = ($controlType)(ctrl);
157                         //
158                         CodeCastExpression castExpr = new CodeCastExpression (builder.ControlType, new CodeVariableReferenceExpression ("ctrl"));
159                         
160                         method.Statements.Add (new CodeVariableDeclarationStatement (builder.ControlType, "__ctrl"));
161                         CodeAssignStatement assign = new CodeAssignStatement ();
162                         assign.Left = ctrlVar;
163                         assign.Right = castExpr;
164                         method.Statements.Add (assign);
165
166                         CreateAssignStatementsFromAttributes (builder);
167
168                         if (builder.Children != null) {
169                                 foreach (object o in builder.Children) {
170                                         if (! (o is ControlBuilder))
171                                                 continue;
172
173                                         ControlBuilder b = (ControlBuilder) o;
174                                         if (b.ControlType == null)
175                                                 continue;
176                                         
177                                         if (b is CollectionBuilder) {
178                                                 PropertyInfo itemsProp = null;
179                                                 
180                                                 try {
181                                                         itemsProp = b.GetType().GetProperty ("Items");
182                                                 } catch (Exception) {}
183                                                 
184                                                 if (itemsProp != null) {
185                                                         /* emit a prop.Clear call before populating the collection */;
186                                                         CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar,
187                                                                                                                                                                                                                                                                                                                                                                         b.TagName);
188                                                         CodePropertyReferenceExpression items = new CodePropertyReferenceExpression (prop,
189                                                                                                                                                                                                                                                                                                                                                                          "Items");
190                                                         method.Statements.Add (new CodeMethodInvokeExpression (items, "Clear"));
191                                                 }
192                                         }
193
194                                         CreateControlTree (b, false, builder.ChildrenAsProperties);
195                                         AddChildCall (builder, b);
196                                 }
197                         }
198
199                         builder.method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
200                 }
201
202                 protected override void AddClassAttributes ()
203                 {
204                         base.AddClassAttributes ();
205                 }
206
207                 protected override void CreateStaticFields ()
208                 {
209                         base.CreateStaticFields ();
210                         ControlBuilder builder = parser.RootBuilder;
211
212                         if (builder.Children != null) {
213                                 foreach (object o in builder.Children) {
214                                         if (o is string) /* literal stuff gets ignored */
215                                                 continue;
216                                         if (o is CodeRenderBuilder)
217                                                 continue;
218                                         ControlBuilder b = (ControlBuilder) o;
219
220                                         EnsureID (b);
221                                         Type controlType = b.ControlType;
222                                         if (controlType == null)
223                                                 continue;
224                                         
225                                         string id = b.ID;
226                                         string skinId = b.attribs != null ? b.attribs["skinid"] as string : null;
227                                         if (skinId == null)
228                                                 skinId = "";
229
230                                         // private static object __BuildControl__$id_skinKey = System.Web.UI.PageTheme.CreateSkinKey(typeof($controlType), "$skinID")
231                                         //
232                                         CodeMemberField fld = new CodeMemberField (typeof (object), "__BuildControl_" + id + "_skinKey");
233                                         fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
234                                         fld.InitExpression = new CodeMethodInvokeExpression (
235                                                 new CodeTypeReferenceExpression (typeof (PageTheme)),
236                                                 "CreateSkinKey",
237                                                 new CodeTypeOfExpression (controlType),
238                                                 new CodePrimitiveExpression (skinId));
239
240                                         mainClass.Members.Add (fld);
241                                 }
242                         }
243                 }
244
245                 protected override void CreateConstructor (CodeStatementCollection localVars,
246                                                            CodeStatementCollection trueStmt)
247                 {
248                         ControlBuilder builder = parser.RootBuilder;
249
250                         if (builder.Children != null) {
251                                 foreach (object o in builder.Children) {
252                                         if (o is string) /* literal stuff gets ignored */
253                                                 continue;
254                                         if (o is CodeRenderBuilder)
255                                                 continue;
256                                         
257                                         ControlBuilder b = (ControlBuilder) o;
258                                         Type controlType = b.ControlType;
259                                         if (controlType == null)
260                                                 continue;
261
262                                         string id = b.ID;
263                                         
264                                         if (localVars == null)
265                                                 localVars = new CodeStatementCollection ();
266
267                                         // this.__controlSkins[__BuildControl_$id_skinKey] = new System.Web.UI.ControlSkin(typeof ($controlType), this.__BuildControl__$id)
268                                         //
269                                         localVars.Add (new CodeAssignStatement (new CodeIndexerExpression (new CodePropertyReferenceExpression (thisRef, "__controlSkins"),
270                                                                                                            new CodeVariableReferenceExpression ("__BuildControl_" + id + "_skinKey")),
271                                                                                 new CodeObjectCreateExpression (typeof (ControlSkin),
272                                                                                                                 new CodeTypeOfExpression (controlType),
273                                                                                                                 new CodeDelegateCreateExpression (new CodeTypeReference (typeof (ControlSkinDelegate)),
274                                                                                                                                                   thisRef, "__BuildControl_" + id))));
275                                 }
276
277                                 base.CreateConstructor (localVars, trueStmt);
278                         }
279                 }
280         }
281 }
282
283 #endif