2008-02-25 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / WebControl.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    (pbartok@novell.com)
24 //
25 //
26
27 using System.ComponentModel;
28 using System.Drawing;
29 using System.Security.Permissions;
30
31 namespace System.Web.UI.WebControls {
32
33         // CAS
34         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
35         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
36         // attributes
37         [ParseChildren (true)]
38 #if NET_2_0
39         [PersistChildrenAttribute (false, false)]
40         [Themeable (true)]
41 #else   
42         [PersistChildrenAttribute (false)]
43 #endif          
44         public class WebControl : Control, IAttributeAccessor {
45                 Style style;
46                 HtmlTextWriterTag tag;
47                 string tag_name;
48                 AttributeCollection attributes;
49                 StateBag attribute_state;
50                 bool enabled;
51                 bool track_enabled_state;
52
53                 public WebControl (HtmlTextWriterTag tag) 
54                 {
55                         this.tag = tag;
56                         this.enabled = true;
57                 }
58
59                 protected WebControl () : this (HtmlTextWriterTag.Span) 
60                 {
61                 }
62
63                 protected WebControl (string tag) 
64                 {
65                         this.tag = HtmlTextWriterTag.Unknown;
66                         this.tag_name = tag;
67                         this.enabled = true;
68                 }
69
70 #if ONLY_1_1
71                 [Bindable(true)]
72 #endif          
73                 [DefaultValue("")]
74                 [WebSysDescription ("")]
75                 [WebCategory ("Behavior")]
76                 public virtual string AccessKey {
77                         get {
78                                 return ViewState.GetString ("AccessKey", string.Empty);
79                         }
80                         set {
81                                 if (value == null || value.Length < 2)
82                                         ViewState ["AccessKey"] = value;
83                                 else
84                                         throw new ArgumentException ("AccessKey can only be null, empty or a single character", "value");
85                         }
86                 }
87
88                 [Browsable(false)]
89                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
90                 [WebSysDescription ("")]
91                 [WebCategory ("Behavior")]
92                 public AttributeCollection Attributes {
93                         get {
94                                 if (attributes == null) {
95                                         attribute_state = new StateBag (true);
96                                         if (IsTrackingViewState)
97                                                 attribute_state.TrackViewState ();
98                                         
99                                         attributes = new AttributeCollection (attribute_state);
100                                 }
101                                 return attributes;
102                         }
103                 }
104
105 #if ONLY_1_1
106                 [Bindable(true)]
107 #endif          
108                 [DefaultValue(typeof (Color), "")]
109                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
110                 [WebSysDescription ("")]
111                 [WebCategory ("Appearance")]
112                 public virtual Color BackColor {
113                         get {
114                                 if (style == null) 
115                                         return Color.Empty;
116                                 
117                                 return style.BackColor;
118                         }
119                         set {
120                                 ControlStyle.BackColor = value;
121                         }
122                 }
123
124 #if ONLY_1_1
125                 [Bindable(true)]
126 #endif          
127                 [DefaultValue(typeof (Color), "")]
128                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
129                 [WebSysDescription ("")]
130                 [WebCategory ("Appearance")]
131                 public virtual Color BorderColor {
132                         get {
133                                 if (style == null) 
134                                         return Color.Empty;
135
136                                 return style.BorderColor;
137                         }
138
139                         set {
140                                 ControlStyle.BorderColor = value;
141                         }
142                 }
143
144 #if ONLY_1_1
145                 [Bindable(true)]
146 #endif          
147                 [DefaultValue(BorderStyle.NotSet)]
148                 [WebSysDescription ("")]
149                 [WebCategory ("Appearance")]
150                 public virtual BorderStyle BorderStyle {
151                         get {
152                                 if (style == null) 
153                                         return BorderStyle.NotSet;
154                                 
155                                 return style.BorderStyle;
156                         }
157                         set {
158                                 if (value < BorderStyle.NotSet || value > BorderStyle.Outset)
159                                         throw new ArgumentOutOfRangeException ("value");
160
161                                 ControlStyle.BorderStyle = value;
162                         }
163                 }
164
165 #if ONLY_1_1
166                 [Bindable(true)]
167 #endif          
168                 [DefaultValue(typeof (Unit), "")]
169                 [WebSysDescription ("")]
170                 [WebCategory ("Appearance")]
171                 public virtual Unit BorderWidth {
172                         get {
173                                 if (style == null) 
174                                         return Unit.Empty;
175
176                                 return style.BorderWidth;
177                         }
178                         set {
179                                 ControlStyle.BorderWidth = value;
180                         }
181                 }
182
183                 [Browsable(false)]
184                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
185                 [WebSysDescription ("")]
186                 [WebCategory ("Appearance")]
187                 public Style ControlStyle {
188                         get {
189                                 if (style == null) {
190                                         style = this.CreateControlStyle ();
191
192                                         if (IsTrackingViewState)
193                                                 style.TrackViewState ();
194                                 }
195
196                                 return style;
197                         }
198                 }
199
200                 [Browsable(false)]
201                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
202 #if NET_2_0
203                 [EditorBrowsable (EditorBrowsableState.Never)]
204 #endif
205                 public bool ControlStyleCreated {
206                         get {
207                                 return style != null;
208                         }
209                 }
210
211 #if ONLY_1_1
212                 [Bindable(true)]
213 #endif          
214                 [DefaultValue("")]
215                 [WebSysDescription ("")]
216                 [WebCategory ("Appearance")]
217                 public virtual string CssClass {
218                         get {
219                                 if (style == null) 
220                                         return string.Empty;
221                                 
222                                 return style.CssClass;
223                         }
224                         set {
225                                 ControlStyle.CssClass = value;
226                         }
227                 }
228
229                 [Bindable(true)]
230                 [DefaultValue(true)]
231 #if NET_2_0
232                 [Themeable (false)]
233 #endif          
234                 public virtual bool Enabled {
235                         get {
236                                 return enabled;
237                         }
238
239                         set {
240                                 if (enabled != value) {
241                                         if (IsTrackingViewState)
242                                                 track_enabled_state = true;
243                                         enabled = value;
244                                 }
245                         }
246                 }
247
248 #if NET_2_0
249                 [Browsable (true)]
250                 public virtual new bool EnableTheming
251                 {
252                         get { return base.EnableTheming; }
253                         set { base.EnableTheming = value; }
254                 }
255 #endif          
256
257 #if ONLY_1_1
258                 [DefaultValue(null)]
259 #endif          
260                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
261                 [NotifyParentProperty(true)]
262                 [WebSysDescription ("")]
263                 [WebCategory ("Appearance")]
264                 public virtual FontInfo Font {
265                         get {
266                                 // Oddly enough, it looks like we have to let it create the style
267                                 // since we can't create a FontInfo without a style owner
268                                 return ControlStyle.Font;
269                         }
270                 }
271
272 #if ONLY_1_1
273                 [Bindable(true)]
274 #endif          
275                 [DefaultValue(typeof (Color), "")]
276                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
277                 [WebSysDescription ("")]
278                 [WebCategory ("Appearance")]
279                 public virtual Color ForeColor {
280                         get {
281                                 if (style == null) 
282                                         return Color.Empty;
283                                 
284                                 return style.ForeColor;
285                         }
286                         set {
287                                 ControlStyle.ForeColor = value;
288                         }
289                 }
290
291 #if NET_2_0
292                 [Browsable (false)]
293                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
294                 public bool HasAttributes 
295                 {
296                         get {
297                                 return (attributes != null && attributes.Count > 0);
298                         }
299                 }
300 #endif          
301                 
302 #if ONLY_1_1
303                 [Bindable(true)]
304 #endif          
305                 [DefaultValue(typeof (Unit), "")]
306                 [WebSysDescription ("")]
307                 [WebCategory ("Layout")]
308                 public virtual Unit Height {
309                         get {
310                                 if (style == null) 
311                                         return Unit.Empty;
312                                 
313                                 return style.Height;
314                         }
315                         set {
316                                 ControlStyle.Height = value;
317                         }
318                 }
319
320 #if NET_2_0
321                 [Browsable (true)]
322                 public virtual new string SkinID
323                 {
324                         get { return base.SkinID; }
325                         set { base.SkinID = value; }
326                 }
327 #endif          
328                 
329                 [Browsable(false)]
330                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
331                 [WebSysDescription ("")]
332                 [WebCategory ("Style")]
333                 public CssStyleCollection Style {
334                         get {
335                                 return Attributes.CssStyle;
336                         }
337                 }
338
339                 [DefaultValue((short)0)]
340                 [WebSysDescription ("")]
341                 [WebCategory ("Behavior")]
342                 public virtual short TabIndex {
343                         get {
344                                 return ViewState.GetShort ("TabIndex", 0);
345                         }
346                         set {
347                                 ViewState ["TabIndex"] = value;
348                         }
349                 }
350
351 #if ONLY_1_1
352                 [Bindable(true)]
353 #endif          
354                 [DefaultValue("")]
355 #if NET_2_0
356                 [Localizable (true)]
357 #endif          
358                 [WebSysDescription ("")]
359                 [WebCategory ("Behavior")]
360                 public virtual string ToolTip {
361                         get {
362                                 return ViewState.GetString ("ToolTip", string.Empty);
363                         }
364                         set {
365                                 ViewState ["ToolTip"] = value;
366                         }
367                 }
368
369 #if ONLY_1_1
370                 [Bindable(true)]
371 #endif          
372                 [DefaultValue(typeof (Unit), "")]
373                 [WebSysDescription ("")]
374                 [WebCategory ("Layout")]
375                 public virtual Unit Width {
376                         get {
377                                 if (style == null) 
378                                         return Unit.Empty;
379                                 
380                                 return style.Width;
381                         }
382                         set {
383                                 ControlStyle.Width = value;
384                         }
385                 }
386
387                 [Browsable(false)]
388                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
389                 protected virtual HtmlTextWriterTag TagKey {
390                         get {
391                                 return tag;
392                         }
393                 }
394
395                 [Browsable(false)]
396                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
397                 protected virtual string TagName {
398                         get {
399                                 // do this here to avoid potentially costly lookups on every control
400                                 if (tag_name == null)
401                                         tag_name = HtmlTextWriter.StaticGetTagName (TagKey);
402                                 
403                                 return tag_name;
404                         }
405                 }
406
407 #if NET_2_0
408                 protected internal bool IsEnabled 
409                 {
410                         get {
411                                 if (Enabled)
412                                         return true;
413                                 if(!HasControls())
414                                         return false;
415                                 for (int i = 0; i < Controls.Count; i++) {
416                                         WebControl wc = Controls [i] as WebControl;
417                                         if (wc != null && wc.IsEnabled)
418                                                 return true;
419                                 }
420                                 return false;
421                         }
422                 }
423 #endif          
424                 
425
426                 public void ApplyStyle (Style s) 
427                 {
428                         if (s != null && !s.IsEmpty)
429                                 ControlStyle.CopyFrom(s);
430                 }
431
432                 public void CopyBaseAttributes (WebControl controlSrc) 
433                 {
434                         object o;
435
436                         if (controlSrc == null) 
437                                 return;
438
439                         Enabled = controlSrc.Enabled;
440
441                         o = controlSrc.ViewState ["AccessKey"];
442                         if (o != null)
443                                 ViewState ["AccessKey"] = o;
444
445                         o = controlSrc.ViewState ["TabIndex"];
446                         if (o != null)
447                                 ViewState ["TabIndex"] = o;
448
449                         o = controlSrc.ViewState ["ToolTip"];
450                         if (o != null)
451                                 ViewState ["ToolTip"] = o;
452
453                         if (controlSrc.attributes != null)
454                                 foreach (string s in controlSrc.attributes.Keys)
455                                         Attributes [s] = controlSrc.attributes [s];
456                 }
457
458                 public void MergeStyle (Style s) 
459                 {
460                         if (s != null && !s.IsEmpty)
461                                 ControlStyle.MergeWith(s);
462                 }
463
464                 public virtual void RenderBeginTag (HtmlTextWriter writer)
465                 {
466                         AddAttributesToRender (writer);
467                         
468                         if (TagKey == HtmlTextWriterTag.Unknown)
469                                 writer.RenderBeginTag (TagName);
470                         else
471                                 writer.RenderBeginTag (TagKey);
472                         
473                 }
474
475                 public virtual void RenderEndTag (HtmlTextWriter writer) 
476                 {
477                         writer.RenderEndTag ();
478                 }
479
480                 static char[] _script_trim_chars = {';'};
481                 internal string BuildScriptAttribute (string name, string tail)
482                 {
483                         AttributeCollection attrs = Attributes;
484                         string attr = attrs [name];
485                         
486                         if (attr == null || attr.Length == 0)
487                                 return tail;
488                         if (attr [attr.Length - 1] == ';')
489                                 attr = attr.TrimEnd (_script_trim_chars);
490                         
491                         attr = String.Concat (attr, ";", tail);
492                         attrs.Remove (name);
493                         
494                         return attr;
495                 }
496                 
497 #if NET_2_0
498                 internal void AddDisplayStyleAttribute (HtmlTextWriter writer)
499                 {
500                         if (!ControlStyleCreated)
501                                 return;
502
503                         if (!ControlStyle.BorderWidth.IsEmpty ||
504                         (ControlStyle.BorderStyle != BorderStyle.None && ControlStyle.BorderStyle != BorderStyle.NotSet) ||
505                         !ControlStyle.Height.IsEmpty ||
506                         !ControlStyle.Width.IsEmpty)
507                                 writer.AddStyleAttribute (HtmlTextWriterStyle.Display, "inline-block");
508                 }
509 #endif
510
511                 protected virtual void AddAttributesToRender (HtmlTextWriter writer) 
512                 {
513                         if (ID != null)
514                                 writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
515
516                         if (AccessKey != string.Empty)
517                                 writer.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
518
519                         if (!enabled)
520                                 writer.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
521
522                         if (ToolTip != string.Empty)
523                                 writer.AddAttribute (HtmlTextWriterAttribute.Title, ToolTip);
524
525                         if (TabIndex != 0)
526                                 writer.AddAttribute (HtmlTextWriterAttribute.Tabindex, TabIndex.ToString ());
527
528                         if (style != null && !style.IsEmpty) {
529 #if NET_2_0
530                                 //unbelievable, but see WebControlTest.RenderBeginTag_BorderWidth_xxx
531                                 if (TagKey == HtmlTextWriterTag.Span)
532                                         AddDisplayStyleAttribute (writer);
533 #endif
534                                 style.AddAttributesToRender(writer, this);
535                         }
536
537                         if (attributes != null)
538                                 foreach(string s in attributes.Keys)
539                                         writer.AddAttribute (s, attributes [s]);
540                 }
541
542                 protected virtual Style CreateControlStyle() 
543                 {
544                         return new Style (ViewState);
545                 }
546
547                 protected override void LoadViewState (object savedState) 
548                 {
549                         if (savedState == null) {
550                                 base.LoadViewState (null);
551                                 return;
552                         }
553
554                         Pair pair = (Pair) savedState;
555                         
556                         base.LoadViewState (pair.First);
557                         if (ViewState [System.Web.UI.WebControls.Style.BitStateKey] != null)
558                                 ControlStyle.LoadBitState ();
559
560                         if (pair.Second != null) {
561                                 if (attribute_state == null) {
562                                         attribute_state = new StateBag ();
563                                         if (IsTrackingViewState) 
564                                                 attribute_state.TrackViewState ();
565                                 }
566                                 attribute_state.LoadViewState (pair.Second);
567                                 attributes = new AttributeCollection(attribute_state);
568                         }
569
570                         enabled = ViewState.GetBool ("Enabled", enabled);
571                 }
572
573 #if NET_2_0
574                 protected internal
575 #else           
576                 protected
577 #endif          
578                 override void Render (HtmlTextWriter writer)
579                 {
580                         RenderBeginTag (writer);
581                         RenderContents (writer);
582                         RenderEndTag (writer);
583                 }
584
585 #if NET_2_0
586                 protected internal
587 #else           
588                 protected
589 #endif          
590                 virtual void RenderContents (HtmlTextWriter writer)
591                 {
592                         base.Render (writer);
593                 }
594
595                 protected override object SaveViewState () 
596                 {
597                         if (track_enabled_state)
598                                 ViewState ["Enabled"] = enabled;
599
600                         object view_state;
601                         object attr_view_state = null;
602
603                         if (style != null)
604                                 style.SaveBitState ();
605                         view_state = base.SaveViewState ();
606
607                         if (attribute_state != null)
608                                 attr_view_state = attribute_state.SaveViewState ();
609                 
610                         if (view_state == null && attr_view_state == null)
611                                 return null;
612
613                         return new Pair (view_state, attr_view_state);
614                 }
615
616                 protected override void TrackViewState() 
617                 {
618                         if (style != null)
619                                 style.TrackViewState ();
620
621                         if (attribute_state != null)
622                                 attribute_state.TrackViewState ();
623
624                         base.TrackViewState ();
625                 }
626
627                 string IAttributeAccessor.GetAttribute (string key) 
628                 {
629                         if (attributes != null)
630                                 return attributes [key];
631
632                         return null;
633                 }
634
635                 void IAttributeAccessor.SetAttribute (string key, string value) 
636                 {
637                         Attributes [key] = value;
638                 }
639         }
640 }