1 //------------------------------------------------------------------------------
2 // <copyright file="PageTheme.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.UI {
8 
9     using System;
10     using System.Collections;
11     using System.Collections.Specialized;
12     using System.ComponentModel;
13     using System.Globalization;
14     using System.Web.UI.HtmlControls;
15     using System.Web.Util;
16     using System.Xml;
17     using System.Security.Permissions;
18 
19     internal class FileLevelPageThemeBuilder : RootBuilder {
20 
21         /// <devdoc>
22         ///    <para>[To be supplied.]</para>
23         /// </devdoc>
AppendLiteralString(string s)24         public override void AppendLiteralString(string s) {
25             // Don't allow any literal contents at theme top level
26             if (s != null) {
27                 if (!Util.IsWhiteSpaceString(s)) {
28                     throw new HttpException(SR.GetString(SR.Literal_content_not_allowed, SR.GetString(SR.Page_theme_skin_file), s.Trim()));
29                 }
30             }
31 
32             base.AppendLiteralString(s);
33         }
34 
35         /// <devdoc>
36         ///    <para>[To be supplied.]</para>
37         /// </devdoc>
AppendSubBuilder(ControlBuilder subBuilder)38         public override void AppendSubBuilder(ControlBuilder subBuilder) {
39             // Only allow controls at theme top level
40             Type ctrlType = subBuilder.ControlType;
41             if (!typeof(Control).IsAssignableFrom(ctrlType)) {
42                 throw new HttpException(SR.GetString(SR.Page_theme_only_controls_allowed, ctrlType == null ?
43                     String.Empty : ctrlType.ToString()));
44             }
45 
46             // Check if the control theme type is themeable.
47             if (InPageTheme && !ThemeableAttribute.IsTypeThemeable(subBuilder.ControlType)) {
48                 throw new HttpParseException(SR.GetString(SR.Type_theme_disabled, subBuilder.ControlType.FullName),
49                     null, subBuilder.VirtualPath, null, subBuilder.Line);
50             }
51 
52             base.AppendSubBuilder(subBuilder);
53         }
54     }
55 
56     [EditorBrowsable(EditorBrowsableState.Advanced)]
57     public abstract class PageTheme {
58 
59         private Page _page;
60         private bool _styleSheetTheme;
61 
62         protected abstract String[] LinkedStyleSheets { get; }
63 
64         protected abstract IDictionary ControlSkins { get; }
65 
66         protected abstract String AppRelativeTemplateSourceDirectory { get; }
67 
68         protected Page Page {
69             get {
70                 return _page;
71             }
72         }
73 
Initialize(Page page, bool styleSheetTheme)74         internal void Initialize(Page page, bool styleSheetTheme) {
75             Debug.Assert(page != null);
76             _page = page;
77             _styleSheetTheme = styleSheetTheme;
78         }
79 
Eval(string expression)80         protected object Eval(string expression) {
81             return Page.Eval(expression);
82         }
83 
Eval(string expression, string format)84         protected string Eval(string expression, string format) {
85             return Page.Eval(expression, format);
86         }
87 
CreateSkinKey(Type controlType, String skinID)88         public static object CreateSkinKey(Type controlType, String skinID) {
89             if (controlType == null) {
90                 throw new ArgumentNullException("controlType");
91             }
92 
93             return new SkinKey(controlType.ToString(), skinID);
94         }
95 
ApplyControlSkin(Control control)96         internal void ApplyControlSkin(Control control) {
97             if (control == null) {
98                 throw new ArgumentNullException("control");
99             }
100 
101             ControlSkin skin = null;
102             String skinId = control.SkinID;
103             skin = (ControlSkin)ControlSkins[CreateSkinKey(control.GetType(), skinId)];
104 
105             // Don't throw if ControlSkin corresponds to the skinID does not exist.
106             Debug.Assert(skin == null || skin.ControlType == control.GetType());
107 
108             if (skin != null) {
109                 skin.ApplySkin(control);
110             }
111         }
112 
SetStyleSheet()113         internal void SetStyleSheet() {
114             if (LinkedStyleSheets != null && LinkedStyleSheets.Length > 0) {
115                 if (Page.Header == null)
116                     throw new InvalidOperationException(SR.GetString(SR.Page_theme_requires_page_header));
117 
118                 int index = 0;
119                 foreach(string styleSheetPath in LinkedStyleSheets) {
120                     HtmlLink link = new HtmlLink();
121                     link.Href = styleSheetPath;
122                     link.Attributes["type"] = "text/css";
123                     link.Attributes["rel"] = "stylesheet";
124 
125                     if (_styleSheetTheme) {
126                         Page.Header.Controls.AddAt(index ++, link);
127                     }
128                     else {
129                         Page.Header.Controls.Add(link);
130                     }
131                 }
132             }
133         }
134 
TestDeviceFilter(string deviceFilterName)135         public bool TestDeviceFilter(string deviceFilterName) {
136             return Page.TestDeviceFilter(deviceFilterName);
137         }
138 
XPath(string xPathExpression)139         protected object XPath(string xPathExpression) {
140             return Page.XPath(xPathExpression);
141         }
142 
XPath(string xPathExpression, IXmlNamespaceResolver resolver)143         protected object XPath(string xPathExpression, IXmlNamespaceResolver resolver) {
144             return Page.XPath(xPathExpression, resolver);
145         }
146 
XPath(string xPathExpression, string format)147         protected string XPath(string xPathExpression, string format) {
148             return Page.XPath(xPathExpression, format);
149         }
150 
XPath(string xPathExpression, string format, IXmlNamespaceResolver resolver)151         protected string XPath(string xPathExpression, string format, IXmlNamespaceResolver resolver) {
152             return Page.XPath(xPathExpression, format, resolver);
153         }
154 
XPathSelect(string xPathExpression)155         protected IEnumerable XPathSelect(string xPathExpression) {
156             return Page.XPathSelect(xPathExpression);
157         }
158 
XPathSelect(string xPathExpression, IXmlNamespaceResolver resolver)159         protected IEnumerable XPathSelect(string xPathExpression, IXmlNamespaceResolver resolver) {
160             return Page.XPathSelect(xPathExpression, resolver);
161         }
162 
163         private class SkinKey {
164             private string _skinID;
165             private string _typeName;
166 
SkinKey(string typeName, string skinID)167             internal SkinKey(string typeName, string skinID) {
168                 _typeName = typeName;
169 
170                 if (String.IsNullOrEmpty(skinID)) {
171                     _skinID = null;
172                 }
173                 else {
174                     _skinID = skinID.ToLower(CultureInfo.InvariantCulture);
175                 }
176             }
177 
GetHashCode()178             public override int GetHashCode() {
179                 if (_skinID == null) {
180                    return _typeName.GetHashCode();
181                 }
182 
183                 return HashCodeCombiner.CombineHashCodes(_typeName.GetHashCode(), _skinID.GetHashCode());
184             }
185 
Equals(object o)186             public override bool Equals(object o) {
187                 SkinKey key = (SkinKey)o;
188 
189                 return (_typeName == key._typeName) &&
190                     (_skinID == key._skinID);
191             }
192         }
193     }
194 }
195