2008-11-28 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                                 WebControl wc = this;
412                                 while (wc != null) {
413                                         if (!wc.Enabled)
414                                                 return false;
415                                         wc = wc.Parent as WebControl;
416                                 }
417                                 return true;
418                         }
419                 }
420 #endif          
421                 
422
423                 public void ApplyStyle (Style s) 
424                 {
425                         if (s != null && !s.IsEmpty)
426                                 ControlStyle.CopyFrom(s);
427                 }
428
429                 public void CopyBaseAttributes (WebControl controlSrc) 
430                 {
431                         object o;
432
433                         if (controlSrc == null) 
434                                 return;
435
436                         Enabled = controlSrc.Enabled;
437
438                         o = controlSrc.ViewState ["AccessKey"];
439                         if (o != null)
440                                 ViewState ["AccessKey"] = o;
441
442                         o = controlSrc.ViewState ["TabIndex"];
443                         if (o != null)
444                                 ViewState ["TabIndex"] = o;
445
446                         o = controlSrc.ViewState ["ToolTip"];
447                         if (o != null)
448                                 ViewState ["ToolTip"] = o;
449
450                         if (controlSrc.attributes != null)
451                                 foreach (string s in controlSrc.attributes.Keys)
452                                         Attributes [s] = controlSrc.attributes [s];
453                 }
454
455                 public void MergeStyle (Style s) 
456                 {
457                         if (s != null && !s.IsEmpty)
458                                 ControlStyle.MergeWith(s);
459                 }
460
461                 public virtual void RenderBeginTag (HtmlTextWriter writer)
462                 {
463                         AddAttributesToRender (writer);
464                         
465                         if (TagKey == HtmlTextWriterTag.Unknown)
466                                 writer.RenderBeginTag (TagName);
467                         else
468                                 writer.RenderBeginTag (TagKey);
469                         
470                 }
471
472                 public virtual void RenderEndTag (HtmlTextWriter writer) 
473                 {
474                         writer.RenderEndTag ();
475                 }
476
477                 static char[] _script_trim_chars = {';'};
478                 internal string BuildScriptAttribute (string name, string tail)
479                 {
480                         AttributeCollection attrs = Attributes;
481                         string attr = attrs [name];
482                         
483                         if (attr == null || attr.Length == 0)
484                                 return tail;
485                         if (attr [attr.Length - 1] == ';')
486                                 attr = attr.TrimEnd (_script_trim_chars);
487                         
488                         attr = String.Concat (attr, ";", tail);
489                         attrs.Remove (name);
490                         
491                         return attr;
492                 }
493                 
494 #if NET_2_0
495                 internal void AddDisplayStyleAttribute (HtmlTextWriter writer)
496                 {
497                         if (!ControlStyleCreated)
498                                 return;
499
500                         if (!ControlStyle.BorderWidth.IsEmpty ||
501                         (ControlStyle.BorderStyle != BorderStyle.None && ControlStyle.BorderStyle != BorderStyle.NotSet) ||
502                         !ControlStyle.Height.IsEmpty ||
503                         !ControlStyle.Width.IsEmpty)
504                                 writer.AddStyleAttribute (HtmlTextWriterStyle.Display, "inline-block");
505                 }
506 #endif
507
508                 protected virtual void AddAttributesToRender (HtmlTextWriter writer) 
509                 {
510                         if (ID != null)
511                                 writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
512
513                         if (AccessKey != string.Empty)
514                                 writer.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
515
516                         if (!enabled)
517                                 writer.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
518
519                         if (ToolTip != string.Empty)
520                                 writer.AddAttribute (HtmlTextWriterAttribute.Title, ToolTip);
521
522                         if (TabIndex != 0)
523                                 writer.AddAttribute (HtmlTextWriterAttribute.Tabindex, TabIndex.ToString ());
524
525                         if (style != null && !style.IsEmpty) {
526 #if NET_2_0
527                                 //unbelievable, but see WebControlTest.RenderBeginTag_BorderWidth_xxx
528                                 if (TagKey == HtmlTextWriterTag.Span)
529                                         AddDisplayStyleAttribute (writer);
530 #endif
531                                 style.AddAttributesToRender(writer, this);
532                         }
533
534                         if (attributes != null)
535                                 foreach(string s in attributes.Keys)
536                                         writer.AddAttribute (s, attributes [s]);
537                 }
538
539                 protected virtual Style CreateControlStyle() 
540                 {
541                         return new Style (ViewState);
542                 }
543
544                 protected override void LoadViewState (object savedState) 
545                 {
546                         if (savedState == null) {
547                                 base.LoadViewState (null);
548                                 return;
549                         }
550
551                         Pair pair = (Pair) savedState;
552                         
553                         base.LoadViewState (pair.First);
554                         if (ViewState [System.Web.UI.WebControls.Style.BitStateKey] != null)
555                                 ControlStyle.LoadBitState ();
556
557                         if (pair.Second != null) {
558                                 if (attribute_state == null) {
559                                         attribute_state = new StateBag ();
560                                         if (IsTrackingViewState) 
561                                                 attribute_state.TrackViewState ();
562                                 }
563                                 attribute_state.LoadViewState (pair.Second);
564                                 attributes = new AttributeCollection(attribute_state);
565                         }
566
567                         enabled = ViewState.GetBool ("Enabled", enabled);
568                 }
569
570 #if NET_2_0
571                 protected internal
572 #else           
573                 protected
574 #endif          
575                 override void Render (HtmlTextWriter writer)
576                 {
577 #if NET_2_0
578                         if (Adapter != null) {
579                                 Adapter.Render(writer);
580                                 return;
581                         }
582 #endif
583                         RenderBeginTag (writer);
584                         RenderContents (writer);
585                         RenderEndTag (writer);
586                 }
587
588 #if NET_2_0
589                 protected internal
590 #else           
591                 protected
592 #endif          
593                 virtual void RenderContents (HtmlTextWriter writer)
594                 {
595                         base.Render (writer);
596                 }
597
598                 protected override object SaveViewState () 
599                 {
600                         if (track_enabled_state)
601                                 ViewState ["Enabled"] = enabled;
602
603                         object view_state;
604                         object attr_view_state = null;
605
606                         if (style != null)
607                                 style.SaveBitState ();
608                         view_state = base.SaveViewState ();
609
610                         if (attribute_state != null)
611                                 attr_view_state = attribute_state.SaveViewState ();
612                 
613                         if (view_state == null && attr_view_state == null)
614                                 return null;
615
616                         return new Pair (view_state, attr_view_state);
617                 }
618
619                 protected override void TrackViewState() 
620                 {
621                         if (style != null)
622                                 style.TrackViewState ();
623
624                         if (attribute_state != null)
625                                 attribute_state.TrackViewState ();
626
627                         base.TrackViewState ();
628                 }
629
630                 string IAttributeAccessor.GetAttribute (string key) 
631                 {
632                         if (attributes != null)
633                                 return attributes [key];
634
635                         return null;
636                 }
637
638                 void IAttributeAccessor.SetAttribute (string key, string value) 
639                 {
640                         Attributes [key] = value;
641                 }
642         }
643 }