1 //------------------------------------------------------------------------------
2 // <copyright file="SubMenuStyle.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.UI.WebControls {
8     using System.ComponentModel;
9     using System.Drawing;
10     using System.Globalization;
11     using System.Text;
12     using System.Web.UI;
13 
14     /// <devdoc>
15     ///    Specifies the style of a SubMenu.
16     /// </devdoc>
17     public class SubMenuStyle : Style, ICustomTypeDescriptor {
18         private const int PROP_VPADDING = 0x00010000;
19         private const int PROP_HPADDING = 0x00020000;
20 
SubMenuStyle()21         public SubMenuStyle() : base() {
22         }
23 
SubMenuStyle(StateBag bag)24         public SubMenuStyle(StateBag bag) : base(bag) {
25         }
26 
27         /// <devdoc>
28         /// Gets and sets the horizontal padding around the node text
29         /// </devdoc>
30         [
31         DefaultValue(typeof(Unit), ""),
32         WebCategory("Layout"),
33         NotifyParentProperty(true),
34         WebSysDescription(SR.SubMenuStyle_HorizontalPadding),
35         ]
36         public Unit HorizontalPadding {
37             get {
38                 if (IsSet(PROP_HPADDING)) {
39                     return (Unit)(ViewState["HorizontalPadding"]);
40                 }
41                 return Unit.Empty;
42             }
43             set {
44                 if ((value.Type == UnitType.Percentage) || (value.Value < 0)) {
45                     throw new ArgumentOutOfRangeException("value");
46                 }
47                 ViewState["HorizontalPadding"] = value;
48                 SetBit(PROP_HPADDING);
49             }
50         }
51 
52 
53         /// <devdoc>
54         /// Gets and sets the vertical padding around the node text
55         /// </devdoc>
56         [
57         DefaultValue(typeof(Unit), ""),
58         WebCategory("Layout"),
59         NotifyParentProperty(true),
60         WebSysDescription(SR.SubMenuStyle_VerticalPadding),
61         ]
62         public Unit VerticalPadding {
63             get {
64                 if (IsSet(PROP_VPADDING)) {
65                     return (Unit)(ViewState["VerticalPadding"]);
66                 }
67                 return Unit.Empty;
68             }
69             set {
70                 if ((value.Type == UnitType.Percentage) || (value.Value < 0)) {
71                     throw new ArgumentOutOfRangeException("value");
72                 }
73                 ViewState["VerticalPadding"] = value;
74                 SetBit(PROP_VPADDING);
75             }
76         }
77 
78 
79         /// <devdoc>
80         ///    Copies non-blank elements from the specified style, overwriting existing
81         ///    style elements if necessary.
82         /// </devdoc>
CopyFrom(Style s)83         public override void CopyFrom(Style s) {
84             if (s != null) {
85                 base.CopyFrom(s);
86 
87                 SubMenuStyle sms = s as SubMenuStyle;
88                 if (sms != null && !sms.IsEmpty) {
89                     // Only copy the paddings if they aren't in the source Style's registered CSS class
90                     if (s.RegisteredCssClass.Length != 0) {
91                         if (sms.IsSet(PROP_VPADDING)) {
92                             ViewState.Remove("VerticalPadding");
93                             ClearBit(PROP_VPADDING);
94                         }
95 
96                         if (sms.IsSet(PROP_HPADDING)) {
97                             ViewState.Remove("HorizontalPadding");
98                             ClearBit(PROP_HPADDING);
99                         }
100                     }
101                     else {
102                         if (sms.IsSet(PROP_VPADDING)) {
103                             this.VerticalPadding = sms.VerticalPadding;
104                         }
105 
106                         if (sms.IsSet(PROP_HPADDING)) {
107                             this.HorizontalPadding = sms.HorizontalPadding;
108                         }
109                     }
110                 }
111             }
112         }
113 
114 
FillStyleAttributes(CssStyleCollection attributes, IUrlResolutionService urlResolver)115         protected override void FillStyleAttributes(CssStyleCollection attributes, IUrlResolutionService urlResolver) {
116             // The style will be rendered on container elements that does not contain text directly.
117             // It does not render font and forecolor.
118             // Users should set font and forecolor on MenuItems styles.
119             // Copying the code from the base class, except for the part that deals with Font and ForeColor.
120             StateBag viewState = ViewState;
121             Color c;
122 
123             // BackColor
124             if (base.IsSet(PROP_BACKCOLOR)) {
125                 c = (Color)viewState["BackColor"];
126                 if (!c.IsEmpty) {
127                     attributes.Add(HtmlTextWriterStyle.BackgroundColor, ColorTranslator.ToHtml(c));
128                 }
129             }
130 
131             // BorderColor
132             if (base.IsSet(PROP_BORDERCOLOR)) {
133                 c = (Color)viewState["BorderColor"];
134                 if (!c.IsEmpty) {
135                     attributes.Add(HtmlTextWriterStyle.BorderColor, ColorTranslator.ToHtml(c));
136                 }
137             }
138 
139             BorderStyle bs = this.BorderStyle;
140             Unit bu = this.BorderWidth;
141             if (!bu.IsEmpty) {
142                 attributes.Add(HtmlTextWriterStyle.BorderWidth, bu.ToString(CultureInfo.InvariantCulture));
143                 if (bs == BorderStyle.NotSet) {
144                     if (bu.Value != 0.0) {
145                         attributes.Add(HtmlTextWriterStyle.BorderStyle, "solid");
146                     }
147                 }
148                 else {
149                     attributes.Add(HtmlTextWriterStyle.BorderStyle, borderStyles[(int)bs]);
150                 }
151             }
152             else {
153                 if (bs != BorderStyle.NotSet) {
154                     attributes.Add(HtmlTextWriterStyle.BorderStyle, borderStyles[(int)bs]);
155                 }
156             }
157 
158             Unit u;
159 
160             // Height
161             if (base.IsSet(PROP_HEIGHT)) {
162                 u = (Unit)viewState["Height"];
163                 if (!u.IsEmpty) {
164                     attributes.Add(HtmlTextWriterStyle.Height, u.ToString(CultureInfo.InvariantCulture));
165                 }
166             }
167 
168             // Width
169             if (base.IsSet(PROP_WIDTH)) {
170                 u = (Unit)viewState["Width"];
171                 if (!u.IsEmpty) {
172                     attributes.Add(HtmlTextWriterStyle.Width, u.ToString(CultureInfo.InvariantCulture));
173                 }
174             }
175 
176             if (!HorizontalPadding.IsEmpty || !VerticalPadding.IsEmpty) {
177                 attributes.Add(HtmlTextWriterStyle.Padding, string.Format(CultureInfo.InvariantCulture,
178                     "{0} {1} {0} {1}",
179                     VerticalPadding.IsEmpty ? Unit.Pixel(0) : VerticalPadding,
180                     HorizontalPadding.IsEmpty ? Unit.Pixel(0) : HorizontalPadding));
181             }
182         }
183 
184 
185         /// <devdoc>
186         ///    Copies non-blank elements from the specified style, but will not overwrite
187         ///    any existing style elements.
188         /// </devdoc>
MergeWith(Style s)189         public override void MergeWith(Style s) {
190             if (s != null) {
191                 if (IsEmpty) {
192                     // Merging with an empty style is equivalent to copying,
193                     // which is more efficient.
194                     CopyFrom(s);
195                     return;
196                 }
197 
198                 base.MergeWith(s);
199 
200                 SubMenuStyle sms = s as SubMenuStyle;
201                 // Since we're already copying the registered CSS class in base.MergeWith, we don't
202                 // need to any attributes that would be included in that class.
203                 if (sms != null && !sms.IsEmpty && s.RegisteredCssClass.Length == 0) {
204                     if (sms.IsSet(PROP_VPADDING) && !this.IsSet(PROP_VPADDING)) {
205                         this.VerticalPadding = sms.VerticalPadding;
206                     }
207 
208                     if (sms.IsSet(PROP_HPADDING) && !this.IsSet(PROP_HPADDING)) {
209                         this.HorizontalPadding = sms.HorizontalPadding;
210                     }
211                 }
212             }
213         }
214 
215 
216         /// <devdoc>
217         ///    Clears out any defined style elements from the state bag.
218         /// </devdoc>
Reset()219         public override void Reset() {
220             if (IsSet(PROP_VPADDING))
221                 ViewState.Remove("VerticalPadding");
222             if (IsSet(PROP_HPADDING))
223                 ViewState.Remove("HorizontalPadding");
224 
225             base.Reset();
226         }
227 
228 
229 		#region ICustomTypeDesciptor implementation
ICustomTypeDescriptor.GetAttributes()230 		System.ComponentModel.AttributeCollection ICustomTypeDescriptor.GetAttributes() {
231 			return TypeDescriptor.GetAttributes(this, true);
232 		}
233 
ICustomTypeDescriptor.GetClassName()234 		string ICustomTypeDescriptor.GetClassName() {
235 			return TypeDescriptor.GetClassName(this, true);
236 		}
237 
ICustomTypeDescriptor.GetComponentName()238 		string ICustomTypeDescriptor.GetComponentName() {
239 			return TypeDescriptor.GetComponentName(this, true);
240 		}
241 
ICustomTypeDescriptor.GetConverter()242 		TypeConverter ICustomTypeDescriptor.GetConverter() {
243 			return TypeDescriptor.GetConverter(this, true);
244 		}
245 
ICustomTypeDescriptor.GetDefaultEvent()246 		EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() {
247 			return TypeDescriptor.GetDefaultEvent(this, true);
248 		}
249 
ICustomTypeDescriptor.GetDefaultProperty()250 		PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() {
251 			return TypeDescriptor.GetDefaultProperty(this, true);
252 		}
253 
ICustomTypeDescriptor.GetEditor(Type editorBaseType)254 		object ICustomTypeDescriptor.GetEditor(Type editorBaseType) {
255 			return TypeDescriptor.GetEditor(this, editorBaseType, true);
256 		}
257 
ICustomTypeDescriptor.GetEvents()258 		EventDescriptorCollection ICustomTypeDescriptor.GetEvents() {
259 			return TypeDescriptor.GetEvents(this, true);
260 		}
261 
ICustomTypeDescriptor.GetEvents(Attribute[] attributes)262 		EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) {
263 			return TypeDescriptor.GetEvents(this, attributes, true);
264 		}
265 
ICustomTypeDescriptor.GetProperties()266 		PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() {
267 			return ((ICustomTypeDescriptor)this).GetProperties(null);
268 		}
269 
ICustomTypeDescriptor.GetProperties(Attribute[] attributes)270 		PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) {
271 			PropertyDescriptorCollection oldProperties = TypeDescriptor.GetProperties(GetType(), attributes);
272 			PropertyDescriptor[] newProperties = new PropertyDescriptor[oldProperties.Count];
273 
274 			PropertyDescriptor fontProperty = oldProperties["Font"];
275 			PropertyDescriptor forecolorProperty = oldProperties["ForeColor"];
276 
277 			Attribute[] newAttributes = new Attribute[] {
278                 new BrowsableAttribute(false),
279                 new EditorBrowsableAttribute(EditorBrowsableState.Never),
280                 new ThemeableAttribute(false),
281             };
282 
283 			for (int i = 0; i < oldProperties.Count; i++) {
284 				PropertyDescriptor property = oldProperties[i];
285 				if ((property == fontProperty) || (property == forecolorProperty)) {
286 					newProperties[i] = TypeDescriptor.CreateProperty(GetType(), property, newAttributes);
287 				}
288 				else {
289 					newProperties[i] = property;
290 				}
291 			}
292 
293 			return new PropertyDescriptorCollection(newProperties, true);
294 		}
295 
ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)296 		object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) {
297 			return this;
298 		}
299         #endregion //ICustomTypeDescriptor implementation
300 
301     }
302 }
303