2 // System.Web.Compilation.PageThemeCompiler
5 // Chris Toshok (toshok@ximian.com)
7 // (C) 2006-2009 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.
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Reflection;
39 using System.Web.SessionState;
40 using System.Web.Util;
42 namespace System.Web.Compilation
44 class PageThemeCompiler : TemplateControlCompiler
46 PageThemeParser parser;
48 public PageThemeCompiler (PageThemeParser parser)
54 protected internal override void CreateMethods ()
57 CodeMemberProperty prop;
59 /* override the following abstract PageTheme properties:
60 protected abstract string AppRelativeTemplateSourceDirectory { get; }
61 protected abstract IDictionary ControlSkins { get; }
62 protected abstract string[] LinkedStyleSheets { get; }
66 fld = new CodeMemberField (typeof (HybridDictionary), "__controlSkins");
67 fld.Attributes = MemberAttributes.Private;
68 fld.InitExpression = new CodeObjectCreateExpression (typeof (HybridDictionary));
69 mainClass.Members.Add (fld);
71 prop = new CodeMemberProperty ();
72 prop.Name = "ControlSkins";
73 prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
74 prop.Type = new CodeTypeReference (typeof (IDictionary));
75 prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__controlSkins")));
76 mainClass.Members.Add (prop);
78 /* LinkedStyleSheets */
79 fld = new CodeMemberField (typeof (string[]), "__linkedStyleSheets");
80 fld.Attributes = MemberAttributes.Private;
81 fld.InitExpression = CreateLinkedStyleSheets ();
82 mainClass.Members.Add (fld);
84 prop = new CodeMemberProperty ();
85 prop.Name = "LinkedStyleSheets";
86 prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
87 prop.Type = new CodeTypeReference (typeof (string[]));
88 prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__linkedStyleSheets")));
89 mainClass.Members.Add (prop);
91 /* AppRelativeTemplateSourceDirectory */
92 prop = new CodeMemberProperty ();
93 prop.Name = "AppRelativeTemplateSourceDirectory";
94 prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
95 prop.Type = new CodeTypeReference (typeof (string));
96 prop.GetStatements.Add (new CodeMethodReturnStatement (
97 new CodePrimitiveExpression (
98 VirtualPathUtility.ToAbsolute (parser.BaseVirtualDir))));
99 mainClass.Members.Add (prop);
101 ControlBuilder builder = parser.RootBuilder;
102 if (builder.Children != null) {
103 foreach (object o in builder.Children) {
104 if (! (o is ControlBuilder))
106 if (o is CodeRenderBuilder)
109 ControlBuilder b = (ControlBuilder) o;
110 CreateControlSkinMethod (b);
115 CodeExpression CreateLinkedStyleSheets ()
117 string [] lss = parser.LinkedStyleSheets;
119 return new CodePrimitiveExpression (null);
121 CodeExpression [] initializers = new CodeExpression [lss.Length];
122 for (int i = 0; i < lss.Length; i++)
123 initializers[i] = new CodePrimitiveExpression (lss[i]);
125 return new CodeArrayCreateExpression (typeof (string), initializers);
128 protected override string HandleUrlProperty (string str, MemberInfo member)
130 if (str.StartsWith ("~", StringComparison.Ordinal))
133 return "~/App_Themes/" + UrlUtils.Combine (
134 System.IO.Path.GetFileName (parser.InputFile), str);
137 void CreateControlSkinMethod (ControlBuilder builder)
139 if (builder.ControlType == null)
144 CodeMemberMethod method = new CodeMemberMethod ();
145 method.Name = "__BuildControl_" + builder.ID;
146 method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (Control), "ctrl"));
148 mainClass.Members.Add (method);
150 builder.Method = method;
151 builder.MethodStatements = method.Statements;
153 method.ReturnType = new CodeTypeReference (typeof (Control));
155 // _ctrl = ($controlType)(ctrl);
157 CodeCastExpression castExpr = new CodeCastExpression (builder.ControlType, new CodeVariableReferenceExpression ("ctrl"));
159 method.Statements.Add (new CodeVariableDeclarationStatement (builder.ControlType, "__ctrl"));
160 CodeAssignStatement assign = new CodeAssignStatement ();
161 assign.Left = ctrlVar;
162 assign.Right = castExpr;
163 method.Statements.Add (assign);
165 CreateAssignStatementsFromAttributes (builder);
167 if (builder.Children != null) {
168 foreach (object o in builder.Children) {
169 if (! (o is ControlBuilder))
172 ControlBuilder b = (ControlBuilder) o;
173 if (b.ControlType == null)
176 if (b is CollectionBuilder) {
177 PropertyInfo itemsProp = null;
180 itemsProp = b.GetType().GetProperty ("Items");
181 } catch (Exception) {}
183 if (itemsProp != null) {
184 /* emit a prop.Clear call before populating the collection */;
185 CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar,
187 CodePropertyReferenceExpression items = new CodePropertyReferenceExpression (prop,
189 method.Statements.Add (new CodeMethodInvokeExpression (items, "Clear"));
193 CreateControlTree (b, false, builder.ChildrenAsProperties);
194 AddChildCall (builder, b);
198 builder.Method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
201 protected override void AddClassAttributes ()
203 base.AddClassAttributes ();
206 protected override void CreateStaticFields ()
208 base.CreateStaticFields ();
209 ControlBuilder builder = parser.RootBuilder;
211 if (builder.Children != null) {
212 foreach (object o in builder.Children) {
213 if (o is string) /* literal stuff gets ignored */
215 if (o is CodeRenderBuilder)
217 ControlBuilder b = (ControlBuilder) o;
220 Type controlType = b.ControlType;
221 if (controlType == null)
225 string skinId = b.Attributes != null ? b.Attributes["skinid"] as string : null;
229 // private static object __BuildControl__$id_skinKey = System.Web.UI.PageTheme.CreateSkinKey(typeof($controlType), "$skinID")
231 CodeMemberField fld = new CodeMemberField (typeof (object), "__BuildControl_" + id + "_skinKey");
232 fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
233 fld.InitExpression = new CodeMethodInvokeExpression (
234 new CodeTypeReferenceExpression (typeof (PageTheme)),
236 new CodeTypeOfExpression (controlType),
237 new CodePrimitiveExpression (skinId));
239 mainClass.Members.Add (fld);
244 protected override void CreateConstructor (CodeStatementCollection localVars,
245 CodeStatementCollection trueStmt)
247 ControlBuilder builder = parser.RootBuilder;
249 if (builder.Children != null) {
250 foreach (object o in builder.Children) {
251 if (o is string) /* literal stuff gets ignored */
253 if (o is CodeRenderBuilder)
256 ControlBuilder b = (ControlBuilder) o;
257 Type controlType = b.ControlType;
258 if (controlType == null)
263 if (localVars == null)
264 localVars = new CodeStatementCollection ();
266 // this.__controlSkins[__BuildControl_$id_skinKey] = new System.Web.UI.ControlSkin(typeof ($controlType), this.__BuildControl__$id)
268 localVars.Add (new CodeAssignStatement (new CodeIndexerExpression (new CodePropertyReferenceExpression (thisRef, "__controlSkins"),
269 new CodeVariableReferenceExpression ("__BuildControl_" + id + "_skinKey")),
270 new CodeObjectCreateExpression (typeof (ControlSkin),
271 new CodeTypeOfExpression (controlType),
272 new CodeDelegateCreateExpression (new CodeTypeReference (typeof (ControlSkinDelegate)),
273 thisRef, "__BuildControl_" + id))));
276 base.CreateConstructor (localVars, trueStmt);