2 // System.Web.Compilation.PageThemeCompiler
5 // Chris Toshok (toshok@ximian.com)
7 // (C) 2006 Novell, Inc (http://www.novell.com/)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
35 using System.Collections;
36 using System.Collections.Specialized;
37 using System.Reflection;
40 using System.Web.SessionState;
41 using System.Web.Util;
43 namespace System.Web.Compilation
45 class PageThemeCompiler : TemplateControlCompiler
47 PageThemeParser parser;
49 public PageThemeCompiler (PageThemeParser parser)
55 protected internal override void CreateMethods ()
58 CodeMemberProperty prop;
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; }
67 fld = new CodeMemberField (typeof (HybridDictionary), "__controlSkins");
68 fld.Attributes = MemberAttributes.Private;
69 fld.InitExpression = new CodeObjectCreateExpression (typeof (HybridDictionary));
70 mainClass.Members.Add (fld);
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);
79 /* LinkedStyleSheets */
80 fld = new CodeMemberField (typeof (string[]), "__linkedStyleSheets");
81 fld.Attributes = MemberAttributes.Private;
82 fld.InitExpression = CreateLinkedStyleSheets ();
83 mainClass.Members.Add (fld);
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);
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);
102 ControlBuilder builder = parser.RootBuilder;
103 if (builder.Children != null) {
104 foreach (object o in builder.Children) {
105 if (! (o is ControlBuilder))
107 if (o is CodeRenderBuilder)
110 ControlBuilder b = (ControlBuilder) o;
111 CreateControlSkinMethod (b);
116 private CodeExpression CreateLinkedStyleSheets ()
118 string [] lss = parser.LinkedStyleSheets;
120 return new CodePrimitiveExpression (null);
122 CodeExpression [] initializers = new CodeExpression [lss.Length];
123 for (int i = 0; i < lss.Length; i++)
124 initializers[i] = new CodePrimitiveExpression (lss[i]);
126 return new CodeArrayCreateExpression (typeof (string), initializers);
129 protected override string HandleUrlProperty (string str, MemberInfo member)
131 if (str.StartsWith ("~", StringComparison.Ordinal))
134 return "~/App_Themes/" + UrlUtils.Combine (
135 System.IO.Path.GetFileName (parser.InputFile), str);
138 void CreateControlSkinMethod (ControlBuilder builder)
140 if (builder.ControlType == null)
145 CodeMemberMethod method = new CodeMemberMethod ();
146 method.Name = "__BuildControl_" + builder.ID;
147 method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (Control), "ctrl"));
149 mainClass.Members.Add (method);
151 builder.method = method;
152 builder.methodStatements = method.Statements;
154 method.ReturnType = new CodeTypeReference (typeof (Control));
156 // _ctrl = ($controlType)(ctrl);
158 CodeCastExpression castExpr = new CodeCastExpression (builder.ControlType, new CodeVariableReferenceExpression ("ctrl"));
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);
166 CreateAssignStatementsFromAttributes (builder);
168 if (builder.Children != null) {
169 foreach (object o in builder.Children) {
170 if (! (o is ControlBuilder))
173 ControlBuilder b = (ControlBuilder) o;
174 if (b.ControlType == null)
177 if (b is CollectionBuilder) {
178 PropertyInfo itemsProp = null;
181 itemsProp = b.GetType().GetProperty ("Items");
182 } catch (Exception) {}
184 if (itemsProp != null) {
185 /* emit a prop.Clear call before populating the collection */;
186 CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar,
188 CodePropertyReferenceExpression items = new CodePropertyReferenceExpression (prop,
190 method.Statements.Add (new CodeMethodInvokeExpression (items, "Clear"));
194 CreateControlTree (b, false, builder.ChildrenAsProperties);
195 AddChildCall (builder, b);
199 builder.method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
202 protected override void AddClassAttributes ()
204 base.AddClassAttributes ();
207 protected override void CreateStaticFields ()
209 base.CreateStaticFields ();
210 ControlBuilder builder = parser.RootBuilder;
212 if (builder.Children != null) {
213 foreach (object o in builder.Children) {
214 if (o is string) /* literal stuff gets ignored */
216 if (o is CodeRenderBuilder)
218 ControlBuilder b = (ControlBuilder) o;
221 Type controlType = b.ControlType;
222 if (controlType == null)
226 string skinId = b.attribs != null ? b.attribs["skinid"] as string : null;
230 // private static object __BuildControl__$id_skinKey = System.Web.UI.PageTheme.CreateSkinKey(typeof($controlType), "$skinID")
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)),
237 new CodeTypeOfExpression (controlType),
238 new CodePrimitiveExpression (skinId));
240 mainClass.Members.Add (fld);
245 protected override void CreateConstructor (CodeStatementCollection localVars,
246 CodeStatementCollection trueStmt)
248 ControlBuilder builder = parser.RootBuilder;
250 if (builder.Children != null) {
251 foreach (object o in builder.Children) {
252 if (o is string) /* literal stuff gets ignored */
254 if (o is CodeRenderBuilder)
257 ControlBuilder b = (ControlBuilder) o;
258 Type controlType = b.ControlType;
259 if (controlType == null)
264 if (localVars == null)
265 localVars = new CodeStatementCollection ();
267 // this.__controlSkins[__BuildControl_$id_skinKey] = new System.Web.UI.ControlSkin(typeof ($controlType), this.__BuildControl__$id)
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))));
277 base.CreateConstructor (localVars, trueStmt);