a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
283 lines
9.3 KiB
C#
283 lines
9.3 KiB
C#
//
|
|
// System.Web.Compilation.PageThemeCompiler
|
|
//
|
|
// Authors:
|
|
// Chris Toshok (toshok@ximian.com)
|
|
//
|
|
// (C) 2006-2009 Novell, Inc (http://www.novell.com/)
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
|
|
using System;
|
|
using System.CodeDom;
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Web.UI;
|
|
using System.Web.SessionState;
|
|
using System.Web.Util;
|
|
|
|
namespace System.Web.Compilation
|
|
{
|
|
class PageThemeCompiler : TemplateControlCompiler
|
|
{
|
|
PageThemeParser parser;
|
|
|
|
public PageThemeCompiler (PageThemeParser parser)
|
|
: base (parser)
|
|
{
|
|
this.parser = parser;
|
|
}
|
|
|
|
protected internal override void CreateMethods ()
|
|
{
|
|
CodeMemberField fld;
|
|
CodeMemberProperty prop;
|
|
|
|
/* override the following abstract PageTheme properties:
|
|
protected abstract string AppRelativeTemplateSourceDirectory { get; }
|
|
protected abstract IDictionary ControlSkins { get; }
|
|
protected abstract string[] LinkedStyleSheets { get; }
|
|
*/
|
|
|
|
/* ControlSkins */
|
|
fld = new CodeMemberField (typeof (HybridDictionary), "__controlSkins");
|
|
fld.Attributes = MemberAttributes.Private;
|
|
fld.InitExpression = new CodeObjectCreateExpression (typeof (HybridDictionary));
|
|
mainClass.Members.Add (fld);
|
|
|
|
prop = new CodeMemberProperty ();
|
|
prop.Name = "ControlSkins";
|
|
prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
|
|
prop.Type = new CodeTypeReference (typeof (IDictionary));
|
|
prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__controlSkins")));
|
|
mainClass.Members.Add (prop);
|
|
|
|
/* LinkedStyleSheets */
|
|
fld = new CodeMemberField (typeof (string[]), "__linkedStyleSheets");
|
|
fld.Attributes = MemberAttributes.Private;
|
|
fld.InitExpression = CreateLinkedStyleSheets ();
|
|
mainClass.Members.Add (fld);
|
|
|
|
prop = new CodeMemberProperty ();
|
|
prop.Name = "LinkedStyleSheets";
|
|
prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
|
|
prop.Type = new CodeTypeReference (typeof (string[]));
|
|
prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeVariableReferenceExpression ("__linkedStyleSheets")));
|
|
mainClass.Members.Add (prop);
|
|
|
|
/* AppRelativeTemplateSourceDirectory */
|
|
prop = new CodeMemberProperty ();
|
|
prop.Name = "AppRelativeTemplateSourceDirectory";
|
|
prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
|
|
prop.Type = new CodeTypeReference (typeof (string));
|
|
prop.GetStatements.Add (new CodeMethodReturnStatement (
|
|
new CodePrimitiveExpression (
|
|
VirtualPathUtility.ToAbsolute (parser.BaseVirtualDir))));
|
|
mainClass.Members.Add (prop);
|
|
|
|
ControlBuilder builder = parser.RootBuilder;
|
|
if (builder.Children != null) {
|
|
foreach (object o in builder.Children) {
|
|
if (! (o is ControlBuilder))
|
|
continue;
|
|
if (o is CodeRenderBuilder)
|
|
continue;
|
|
|
|
ControlBuilder b = (ControlBuilder) o;
|
|
CreateControlSkinMethod (b);
|
|
}
|
|
}
|
|
}
|
|
|
|
CodeExpression CreateLinkedStyleSheets ()
|
|
{
|
|
string [] lss = parser.LinkedStyleSheets;
|
|
if (lss == null)
|
|
return new CodePrimitiveExpression (null);
|
|
|
|
CodeExpression [] initializers = new CodeExpression [lss.Length];
|
|
for (int i = 0; i < lss.Length; i++)
|
|
initializers[i] = new CodePrimitiveExpression (lss[i]);
|
|
|
|
return new CodeArrayCreateExpression (typeof (string), initializers);
|
|
}
|
|
|
|
protected override string HandleUrlProperty (string str, MemberInfo member)
|
|
{
|
|
if (str.StartsWith ("~", StringComparison.Ordinal))
|
|
return str;
|
|
|
|
return "~/App_Themes/" + UrlUtils.Combine (
|
|
System.IO.Path.GetFileName (parser.InputFile), str);
|
|
}
|
|
|
|
void CreateControlSkinMethod (ControlBuilder builder)
|
|
{
|
|
if (builder.ControlType == null)
|
|
return;
|
|
|
|
EnsureID (builder);
|
|
|
|
CodeMemberMethod method = new CodeMemberMethod ();
|
|
method.Name = "__BuildControl_" + builder.ID;
|
|
method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (Control), "ctrl"));
|
|
|
|
mainClass.Members.Add (method);
|
|
|
|
builder.Method = method;
|
|
builder.MethodStatements = method.Statements;
|
|
|
|
method.ReturnType = new CodeTypeReference (typeof (Control));
|
|
|
|
// _ctrl = ($controlType)(ctrl);
|
|
//
|
|
CodeCastExpression castExpr = new CodeCastExpression (builder.ControlType, new CodeVariableReferenceExpression ("ctrl"));
|
|
|
|
method.Statements.Add (new CodeVariableDeclarationStatement (builder.ControlType, "__ctrl"));
|
|
CodeAssignStatement assign = new CodeAssignStatement ();
|
|
assign.Left = ctrlVar;
|
|
assign.Right = castExpr;
|
|
method.Statements.Add (assign);
|
|
|
|
CreateAssignStatementsFromAttributes (builder);
|
|
|
|
if (builder.Children != null) {
|
|
foreach (object o in builder.Children) {
|
|
if (! (o is ControlBuilder))
|
|
continue;
|
|
|
|
ControlBuilder b = (ControlBuilder) o;
|
|
if (b.ControlType == null)
|
|
continue;
|
|
|
|
if (b is CollectionBuilder) {
|
|
PropertyInfo itemsProp = null;
|
|
|
|
try {
|
|
itemsProp = b.GetType().GetProperty ("Items");
|
|
} catch (Exception) {}
|
|
|
|
if (itemsProp != null) {
|
|
/* emit a prop.Clear call before populating the collection */;
|
|
CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar,
|
|
b.TagName);
|
|
CodePropertyReferenceExpression items = new CodePropertyReferenceExpression (prop,
|
|
"Items");
|
|
method.Statements.Add (new CodeMethodInvokeExpression (items, "Clear"));
|
|
}
|
|
}
|
|
|
|
CreateControlTree (b, false, builder.ChildrenAsProperties);
|
|
AddChildCall (builder, b);
|
|
}
|
|
}
|
|
|
|
builder.Method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
|
|
}
|
|
|
|
protected override void AddClassAttributes ()
|
|
{
|
|
base.AddClassAttributes ();
|
|
}
|
|
|
|
protected override void CreateStaticFields ()
|
|
{
|
|
base.CreateStaticFields ();
|
|
ControlBuilder builder = parser.RootBuilder;
|
|
|
|
if (builder.Children != null) {
|
|
foreach (object o in builder.Children) {
|
|
if (o is string) /* literal stuff gets ignored */
|
|
continue;
|
|
if (o is CodeRenderBuilder)
|
|
continue;
|
|
ControlBuilder b = (ControlBuilder) o;
|
|
|
|
EnsureID (b);
|
|
Type controlType = b.ControlType;
|
|
if (controlType == null)
|
|
continue;
|
|
|
|
string id = b.ID;
|
|
string skinId = b.Attributes != null ? b.Attributes["skinid"] as string : null;
|
|
if (skinId == null)
|
|
skinId = "";
|
|
|
|
// private static object __BuildControl__$id_skinKey = System.Web.UI.PageTheme.CreateSkinKey(typeof($controlType), "$skinID")
|
|
//
|
|
CodeMemberField fld = new CodeMemberField (typeof (object), "__BuildControl_" + id + "_skinKey");
|
|
fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
|
|
fld.InitExpression = new CodeMethodInvokeExpression (
|
|
new CodeTypeReferenceExpression (typeof (PageTheme)),
|
|
"CreateSkinKey",
|
|
new CodeTypeOfExpression (controlType),
|
|
new CodePrimitiveExpression (skinId));
|
|
|
|
mainClass.Members.Add (fld);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void CreateConstructor (CodeStatementCollection localVars,
|
|
CodeStatementCollection trueStmt)
|
|
{
|
|
ControlBuilder builder = parser.RootBuilder;
|
|
|
|
if (builder.Children != null) {
|
|
foreach (object o in builder.Children) {
|
|
if (o is string) /* literal stuff gets ignored */
|
|
continue;
|
|
if (o is CodeRenderBuilder)
|
|
continue;
|
|
|
|
ControlBuilder b = (ControlBuilder) o;
|
|
Type controlType = b.ControlType;
|
|
if (controlType == null)
|
|
continue;
|
|
|
|
string id = b.ID;
|
|
|
|
if (localVars == null)
|
|
localVars = new CodeStatementCollection ();
|
|
|
|
// this.__controlSkins[__BuildControl_$id_skinKey] = new System.Web.UI.ControlSkin(typeof ($controlType), this.__BuildControl__$id)
|
|
//
|
|
localVars.Add (new CodeAssignStatement (new CodeIndexerExpression (new CodePropertyReferenceExpression (thisRef, "__controlSkins"),
|
|
new CodeVariableReferenceExpression ("__BuildControl_" + id + "_skinKey")),
|
|
new CodeObjectCreateExpression (typeof (ControlSkin),
|
|
new CodeTypeOfExpression (controlType),
|
|
new CodeDelegateCreateExpression (new CodeTypeReference (typeof (ControlSkinDelegate)),
|
|
thisRef, "__BuildControl_" + id))));
|
|
}
|
|
|
|
base.CreateConstructor (localVars, trueStmt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|