New tests.
[mono.git] / mcs / class / System.Web / System.Web.UI / Control.cs
1 //
2 // System.Web.UI.Control.cs
3 //
4 // Authors:
5 //   Bob Smith <bob@thestuff.net>
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //   Sanjay Gupta (gsanjay@novell.com)
9 //   Marek Habersack <mhabersack@novell.com>
10 //
11 // (C) Bob Smith
12 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
13 // (C) 2004-2010 Novell, Inc. (http://www.novell.com)
14 //
15
16 //
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 // 
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 // 
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 //
36
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.ComponentModel;
40 using System.ComponentModel.Design;
41 using System.ComponentModel.Design.Serialization;
42 using System.Globalization;
43 using System.IO;
44 using System.Security.Permissions;
45 using System.Web;
46 using System.Web.Util;
47 using System.Web.UI.Adapters;
48
49 namespace System.Web.UI
50 {
51         // CAS
52         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
53         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
54         // attributes
55         [DefaultProperty ("ID"), DesignerCategory ("Code"), ToolboxItemFilter ("System.Web.UI", ToolboxItemFilterType.Require)]
56         [ToolboxItem ("System.Web.UI.Design.WebControlToolboxItem, " + Consts.AssemblySystem_Design)]
57         [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
58         [DesignerSerializer ("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, " + Consts.AssemblyMicrosoft_VisualStudio_Web,
59                                 "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
60         [Bindable (true)]
61         [Themeable (false)]
62         public partial class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor, IUrlResolutionService, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
63         {
64                 internal static readonly object DataBindingEvent = new object ();
65                 internal static readonly object DisposedEvent = new object ();
66                 internal static readonly object InitEvent = new object ();
67                 internal static readonly object LoadEvent = new object ();
68                 internal static readonly object PreRenderEvent = new object ();
69                 internal static readonly object UnloadEvent = new object ();
70                 internal static string [] defaultNameArray;
71                 /* */
72                 int event_mask;
73                 const int databinding_mask = 1;
74                 const int disposed_mask = 1 << 1;
75                 const int init_mask = 1 << 2;
76                 const int load_mask = 1 << 3;
77                 const int prerender_mask = 1 << 4;
78                 const int unload_mask = 1 << 5;
79                 /* */
80
81                 [ThreadStatic]
82                 static Dictionary <Type, bool> loadViewStateByIDCache;
83                 bool? loadViewStateByID;
84                 string uniqueID;
85                 string _userId;
86                 ControlCollection _controls;
87                 Control _namingContainer;
88                 Page _page;
89                 Control _parent;
90                 ISite _site;
91                 StateBag _viewState;
92                 EventHandlerList _events;
93                 RenderMethod _renderMethodDelegate;
94                 Hashtable _controlsCache;
95                 int defaultNumberID;
96
97                 DataBindingCollection dataBindings;
98                 Hashtable pendingVS; // may hold unused viewstate data from child controls
99                 TemplateControl _templateControl;
100                 bool _isChildControlStateCleared;
101                 string _templateSourceDirectory;
102
103                 /*************/
104                 int stateMask;
105                 const int ENABLE_VIEWSTATE = 1;
106                 const int VISIBLE = 1 << 1;
107                 const int AUTOID = 1 << 2;
108                 const int CREATING_CONTROLS = 1 << 3;
109                 const int BINDING_CONTAINER = 1 << 4;
110                 const int AUTO_EVENT_WIREUP = 1 << 5;
111                 const int IS_NAMING_CONTAINER = 1 << 6;
112                 const int VISIBLE_CHANGED = 1 << 7;
113                 const int TRACK_VIEWSTATE = 1 << 8;
114                 const int CHILD_CONTROLS_CREATED = 1 << 9;
115                 const int ID_SET = 1 << 10;
116                 const int INITED = 1 << 11;
117                 const int INITING = 1 << 12;
118                 const int VIEWSTATE_LOADED = 1 << 13;
119                 const int LOADED = 1 << 14;
120                 const int PRERENDERED = 1 << 15;
121                 const int ENABLE_THEMING = 1 << 16;
122                 const int AUTOID_SET = 1 << 17;
123                 const int REMOVED = 1 << 18;
124                 /*************/
125
126                 static Control ()
127                 {
128                         defaultNameArray = new string [100];
129                         for (int i = 0; i < 100; i++)
130                                 defaultNameArray [i] = String.Concat ("ctl", i.ToString ("D2"));
131                 }
132
133                 public Control ()
134                 {
135                         stateMask = ENABLE_VIEWSTATE | VISIBLE | AUTOID | BINDING_CONTAINER | AUTO_EVENT_WIREUP;
136                         if (this is INamingContainer)
137                                 stateMask |= IS_NAMING_CONTAINER;
138                 }
139                 
140                 ControlAdapter adapter;
141                 bool did_adapter_lookup;
142                 protected internal ControlAdapter Adapter {
143                         get {
144                                 if (!did_adapter_lookup) {
145                                         adapter = ResolveAdapter ();
146                                         if (adapter != null)
147                                                 adapter.control = this;
148                                         did_adapter_lookup = true;
149                                 }
150                                 return adapter;
151                         }
152                 }
153
154                 string _appRelativeTemplateSourceDirectory = null;
155
156                 [EditorBrowsable (EditorBrowsableState.Advanced)]
157                 [Browsable (false)]
158                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
159                 public string AppRelativeTemplateSourceDirectory {
160                         get {
161                                 if (_appRelativeTemplateSourceDirectory != null)
162                                         return _appRelativeTemplateSourceDirectory;
163
164                                 string tempSrcDir = null;
165                                 TemplateControl templateControl = TemplateControl;
166                                 if (templateControl != null) {
167                                         string templateVirtualPath = templateControl.AppRelativeVirtualPath;
168                                         if (!String.IsNullOrEmpty (templateVirtualPath))
169                                                 tempSrcDir = VirtualPathUtility.GetDirectory (templateVirtualPath, false);
170                                 }
171                                 
172                                 _appRelativeTemplateSourceDirectory = (tempSrcDir != null) ? tempSrcDir : VirtualPathUtility.ToAppRelative (TemplateSourceDirectory);
173                                 return _appRelativeTemplateSourceDirectory;
174                         }
175                         [EditorBrowsable (EditorBrowsableState.Never)]
176                         set {
177                                 _appRelativeTemplateSourceDirectory = value;
178                                 _templateSourceDirectory = null;
179                         }
180                 }
181
182                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
183                 [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]
184                 public Control BindingContainer {
185                         get {
186                                 Control container = NamingContainer;
187                                 if (container != null && container is INonBindingContainer || (stateMask & BINDING_CONTAINER) == 0)
188                                         container = container.BindingContainer;
189
190                                 return container;
191                         }
192                 }
193
194                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
195                 [Browsable (false)]
196                 [WebSysDescription ("An Identification of the control that is rendered.")]
197                 public virtual string ClientID {
198                         get {
199                                 string client = UniqueID;
200
201                                 if (client != null)
202                                         client = UniqueID2ClientID (client);
203
204                                 stateMask |= ID_SET;
205                                 return client;
206                         }
207                 }
208
209                 internal string UniqueID2ClientID (string uniqueId)
210                 {
211                         return uniqueId.Replace (IdSeparator, ClientIDSeparator);
212                 }
213
214                 protected char ClientIDSeparator {
215                         get { return '_'; }
216                 }
217
218
219                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220                 [Browsable (false)]
221                 [WebSysDescription ("The child controls of this control.")]
222                 public virtual ControlCollection Controls { //DIT
223                         get {
224                                 if (_controls == null)
225                                         _controls = CreateControlCollection ();
226                                 return _controls;
227                         }
228                 }
229
230                 [MonoTODO ("revisit once we have a real design strategy")]
231                 protected internal bool DesignMode {
232                         get { return false; }
233                 }
234
235                 [DefaultValue (true), WebCategory ("Behavior")]
236                 [WebSysDescription ("An Identification of the control that is rendered.")]
237                 [Themeable (false)]
238                 public virtual bool EnableViewState {
239                         get { return ((stateMask & ENABLE_VIEWSTATE) != 0); }
240                         set { SetMask (ENABLE_VIEWSTATE, value); }
241                 }
242
243                 [MergableProperty (false), ParenthesizePropertyName (true)]
244                 [WebSysDescription ("The name of the control that is rendered.")]
245                 [Filterable (false), Themeable (false)]
246                 public virtual string ID {
247                         get { return (((stateMask & ID_SET) != 0) ? _userId : null); }
248
249                         set {
250                                 if (value != null && value.Length == 0)
251                                         value = null;
252
253                                 stateMask |= ID_SET;
254                                 _userId = value;
255                                 NullifyUniqueID ();
256                         }
257                 }
258
259                 protected internal bool IsChildControlStateCleared {
260                         get { return _isChildControlStateCleared; }
261                 }
262
263                 protected bool LoadViewStateByID {
264                         get {
265                                 if (loadViewStateByID == null)
266                                         loadViewStateByID = IsLoadViewStateByID ();
267
268                                 return (bool)loadViewStateByID;
269                         }
270                 }
271
272                 protected internal bool IsViewStateEnabled {
273                         get {
274                                 for (Control control = this; control != null; control = control.Parent)
275                                         if (!control.EnableViewState)
276                                                 return false;
277
278                                 return true;
279                         }
280                 }
281
282                 protected char IdSeparator {
283                         get { return '$'; }
284                 }
285
286                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
287                 [Browsable (false)]
288                 [WebSysDescription ("The container that this control is part of. The control's name has to be unique within the container.")]
289                 public virtual Control NamingContainer {
290                         get {
291                                 if (_namingContainer == null && _parent != null) {
292                                         if ((_parent.stateMask & IS_NAMING_CONTAINER) == 0)
293                                                 _namingContainer = _parent.NamingContainer;
294                                         else
295                                                 _namingContainer = _parent;
296                                 }
297
298                                 return _namingContainer;
299                         }
300                 }
301
302                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
303                 [Browsable (false)]
304                 [WebSysDescription ("The webpage that this control resides on.")]
305                 [Bindable (false)]
306                 public virtual Page Page { //DIT
307                         get {
308                                 if (_page == null){
309                                         if (NamingContainer != null)
310                                                 _page = NamingContainer.Page;
311                                         else if (Parent != null)
312                                                 _page = Parent.Page;
313                                 }
314                                 return _page;
315                         }
316                         
317                         set { _page = value; }
318                 }
319
320                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
321                 [Browsable (false)]
322                 [WebSysDescription ("The parent control of this control.")]
323                 public virtual Control Parent { //DIT
324                         get { return _parent; }
325                 }
326
327                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
328                 [EditorBrowsable (EditorBrowsableState.Advanced), Browsable (false)]
329                 [WebSysDescription ("The site this control is part of.")]
330                 public ISite Site { //DIT
331                         get { return _site; }
332                         set { _site = value; }
333                 }
334
335                 [Browsable (false)]
336                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
337                 public TemplateControl TemplateControl {
338                         get { return TemplateControlInternal; }
339
340                         [EditorBrowsable (EditorBrowsableState.Never)]
341                         set { _templateControl = value; }
342                 }
343
344                 internal virtual TemplateControl TemplateControlInternal {
345                         get {
346                                 if (_templateControl != null)
347                                         return _templateControl;
348                                 if (_parent != null)
349                                         return _parent.TemplateControl;
350                                 return null;
351                         }
352                 }
353
354 #if !TARGET_J2EE
355                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
356                 [Browsable (false)]
357                 [WebSysDescription ("A virtual directory containing the parent of the control.")]
358                 public virtual string TemplateSourceDirectory {
359                         get {
360                                 if (_templateSourceDirectory == null) {
361                                         TemplateControl tc = TemplateControl;
362
363                                         if (tc == null) {
364                                                 HttpContext ctx = Context;
365                                                 if (ctx != null)
366                                                         _templateSourceDirectory = VirtualPathUtility.GetDirectory (ctx.Request.CurrentExecutionFilePath);
367                                         } else if (tc != this)
368                                                 _templateSourceDirectory = tc.TemplateSourceDirectory;
369
370                                         if (_templateSourceDirectory == null && this is TemplateControl) {
371                                                 string path = ((TemplateControl) this).AppRelativeVirtualPath;
372
373                                                 if (path != null) {
374                                                         string ret = VirtualPathUtility.GetDirectory (VirtualPathUtility.ToAbsolute (path));
375                                                         int len = ret.Length;
376                                                         if (len <= 1)
377                                                                 return ret;
378                                                         if (ret [--len] == '/')
379                                                                 _templateSourceDirectory = ret.Substring (0, len);
380                                                 } else
381                                                         _templateSourceDirectory = String.Empty;
382                                         }
383                                         if (_templateSourceDirectory == null)
384                                                 _templateSourceDirectory = String.Empty;
385                                 }
386
387                                 return _templateSourceDirectory;
388                         }
389                 }
390 #endif
391
392                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
393                 [Browsable (false)]
394                 [WebSysDescription ("The unique ID of the control.")]
395                 public virtual string UniqueID {
396                         get {
397                                 if (uniqueID != null)
398                                         return uniqueID;
399
400                                 if (NamingContainer == null)
401                                         return _userId;
402
403                                 EnsureIDInternal ();
404
405                                 string prefix = NamingContainer.UniqueID;
406                                 if (NamingContainer == Page || prefix == null) {
407                                         uniqueID = _userId;
408 #if TARGET_J2EE
409                                         if (getFacesContext () != null)
410                                                 uniqueID = getFacesContext ().getExternalContext ().encodeNamespace (uniqueID);
411 #endif
412                                         return uniqueID;
413                                 }
414
415                                 uniqueID = prefix + IdSeparator + _userId;
416                                 return uniqueID;
417                         }
418                 }
419
420                 void SetMask (int m, bool val) {
421                         if (val)
422                                 stateMask |= m;
423                         else
424                                 stateMask &= ~m;
425                 }
426
427                 [DefaultValue (true), Bindable (true), WebCategory ("Behavior")]
428                 [WebSysDescription ("Visiblity state of the control.")]
429                 public virtual bool Visible {
430                         get {
431                                 if ((stateMask & VISIBLE) == 0)
432                                         return false;
433
434                                 if (_parent != null)
435                                         return _parent.Visible;
436
437                                 return true;
438                         }
439
440                         set {
441                                 if ((value && (stateMask & VISIBLE) == 0) ||
442                                         (!value && (stateMask & VISIBLE) != 0)) {
443                                         if (IsTrackingViewState)
444                                                 stateMask |= VISIBLE_CHANGED;
445                                 }
446
447                                 SetMask (VISIBLE, value);
448                         }
449                 }
450
451                 protected bool ChildControlsCreated {
452                         get { return ((stateMask & CHILD_CONTROLS_CREATED) != 0); }
453                         set {
454                                 if (value == false && (stateMask & CHILD_CONTROLS_CREATED) != 0) {
455                                         ControlCollection cc = Controls;
456                                         if (cc != null)
457                                                 cc.Clear ();
458                                 }
459
460                                 SetMask (CHILD_CONTROLS_CREATED, value);
461                         }
462                 }
463
464                 [Browsable (false)]
465                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
466                 protected internal virtual HttpContext Context { //DIT
467                         get {
468                                 Page page = Page;
469                                 if (page != null)
470                                         return page.Context;
471                                 
472                                 return HttpContext.Current;
473                         }
474                 }
475
476                 protected EventHandlerList Events {
477                         get {
478                                 if (_events == null)
479                                         _events = new EventHandlerList ();
480                                 return _events;
481                         }
482                 }
483
484                 protected bool HasChildViewState {
485                         get { return (pendingVS != null && pendingVS.Count > 0); }
486                 }
487
488                 protected bool IsTrackingViewState {
489                         get { return ((stateMask & TRACK_VIEWSTATE) != 0); }
490                 }
491
492                 [Browsable (false)]
493                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
494                 [WebSysDescription ("ViewState")]
495                 protected virtual StateBag ViewState {
496                         get {
497                                 if (_viewState == null)
498                                         _viewState = new StateBag (ViewStateIgnoresCase);
499
500                                 if (IsTrackingViewState)
501                                         _viewState.TrackViewState ();
502
503                                 return _viewState;
504                         }
505                 }
506
507                 [Browsable (false)]
508                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
509                 protected virtual bool ViewStateIgnoresCase {
510                         get { return false; }
511                 }
512
513                 internal bool AutoEventWireup {
514                         get { return (stateMask & AUTO_EVENT_WIREUP) != 0; }
515                         set { SetMask (AUTO_EVENT_WIREUP, value); }
516                 }
517                 
518                 internal void SetBindingContainer (bool isBC)
519                 {
520                         SetMask (BINDING_CONTAINER, isBC);
521                 }
522
523                 internal void ResetChildNames ()
524                 {
525                         ResetChildNames (-1);
526                 }
527
528                 internal void ResetChildNames (int value)
529                 {
530                         if (value < 0)
531                                 defaultNumberID = 0;
532                         else
533                                 defaultNumberID = value;
534                 }
535
536                 internal int GetDefaultNumberID ()
537                 {
538                         return defaultNumberID;
539                 }
540
541                 string GetDefaultName ()
542                 {
543                         string defaultName;
544                         if (defaultNumberID > 99)
545                                 defaultName = "ctl" + defaultNumberID++;
546                         else
547                                 defaultName = defaultNameArray [defaultNumberID++];
548                         return defaultName;
549                 }
550
551                 void NullifyUniqueID ()
552                 {
553                         uniqueID = null;
554                         if (!HasControls ())
555                                 return;
556
557                         for (int i = 0; i < _controls.Count; i++)
558                                 _controls [i].NullifyUniqueID ();
559                 }
560
561                 bool IsLoadViewStateByID ()
562                 {
563                         if (loadViewStateByIDCache == null)
564                                 loadViewStateByIDCache = new Dictionary <Type, bool> ();
565
566                         bool ret;
567                         Type myType = GetType ();
568                         if (loadViewStateByIDCache.TryGetValue (myType, out ret))
569                                 return ret;
570
571                         System.ComponentModel.AttributeCollection attrs = TypeDescriptor.GetAttributes (myType);
572                         if (attrs != null || attrs.Count > 0) {
573                                 ret = false;
574                                 foreach (Attribute attr in attrs) {
575                                         if (attr is ViewStateModeByIdAttribute) {
576                                                 ret = true;
577                                                 break;
578                                         }
579                                 }
580                         } else
581                                 ret = false;
582                         
583                         loadViewStateByIDCache.Add (myType, ret);
584                         return ret;
585                 }
586                 
587                 protected internal virtual void AddedControl (Control control, int index)
588                 {
589                         ResetControlsCache ();
590
591                         /* Ensure the control don't have more than 1 parent */
592                         if (control._parent != null)
593                                 control._parent.Controls.Remove (control);
594
595                         control._parent = this;
596                         Control nc = ((stateMask & IS_NAMING_CONTAINER) != 0) ? this : NamingContainer;
597
598                         if ((stateMask & (INITING | INITED)) != 0) {
599                                 control.InitRecursive (nc);
600                                 control.SetMask (REMOVED, false);
601                         } else {
602                                 control.SetNamingContainer (nc);
603                                 control.SetMask (REMOVED, false);
604                                 return;
605                         }
606
607                         if ((stateMask & (VIEWSTATE_LOADED | LOADED)) != 0) {
608                                 if (pendingVS != null) {
609                                         object vs;
610                                         bool byId = LoadViewStateByID;
611                                         string id;
612                                         
613                                         if (byId) {
614                                                 control.EnsureID ();
615                                                 id = control.ID;
616                                                 vs = pendingVS [id];
617                                         } else {
618                                                 id = null;
619                                                 vs = pendingVS [index];
620                                         }
621                                         
622                                         if (vs != null) {
623                                                 if (byId)
624                                                         pendingVS.Remove (id);
625                                                 else
626                                                         pendingVS.Remove (index);
627                                                 
628                                                 if (pendingVS.Count == 0)
629                                                         pendingVS = null;
630
631                                                 control.LoadViewStateRecursive (vs);
632                                         }
633                                 }
634                         }
635
636                         if ((stateMask & LOADED) != 0)
637                                 control.LoadRecursive ();
638
639                         if ((stateMask & PRERENDERED) != 0)
640                                 control.PreRenderRecursiveInternal ();
641                 }
642                 
643                 void SetNamingContainer (Control nc)
644                 {
645                         if (nc != null) {
646                                 _namingContainer = nc;
647                                 if (AutoID)
648                                         EnsureIDInternal ();
649                         }
650                 }
651
652                 protected virtual void AddParsedSubObject (object obj) //DIT
653                 {
654                         Control c = obj as Control;
655                         if (c != null)
656                                 Controls.Add (c);
657                 }
658
659                 [EditorBrowsable (EditorBrowsableState.Advanced)]
660                 public virtual void ApplyStyleSheetSkin (Page page)
661                 {
662                         if (page == null)
663                                 return;
664
665                         if (!EnableTheming) /* this enough? */
666                                 return;
667
668                         /* apply the style sheet skin here */
669                         if (page.StyleSheetPageTheme != null) {
670                                 ControlSkin cs = page.StyleSheetPageTheme.GetControlSkin (GetType (), SkinID);
671                                 if (cs != null)
672                                         cs.ApplySkin (this);
673                         }
674                 }
675
676                 [MonoTODO]
677                 protected void BuildProfileTree (string parentId, bool calcViewState)
678                 {
679                 }
680
681                 protected void ClearChildControlState ()
682                 {
683                         _isChildControlStateCleared = true;
684                 }
685
686                 protected void ClearChildState ()
687                 {
688                         ClearChildViewState ();
689                         ClearChildControlState ();
690                 }
691
692                 protected void ClearChildViewState ()
693                 {
694                         pendingVS = null;
695                 }
696
697                 protected internal virtual void CreateChildControls () //DIT
698                 {
699                 }
700
701                 protected virtual ControlCollection CreateControlCollection () //DIT
702                 {
703                         return new ControlCollection (this);
704                 }
705
706                 protected virtual void EnsureChildControls ()
707                 {
708                         if (ChildControlsCreated == false && (stateMask & CREATING_CONTROLS) == 0) {
709                                 stateMask |= CREATING_CONTROLS;
710                                 if (Adapter != null)
711                                         Adapter.CreateChildControls ();
712                                 else
713                                         CreateChildControls ();
714                                 ChildControlsCreated = true;
715                                 stateMask &= ~CREATING_CONTROLS;
716                         }
717                 }
718
719                 void EnsureIDInternal ()
720                 {
721                         if (_userId != null)
722                                 return;
723
724                         _userId = NamingContainer.GetDefaultName ();
725                         SetMask (AUTOID_SET, true);
726                 }
727
728                 protected void EnsureID ()
729                 {
730                         if (NamingContainer == null)
731                                 return;
732                         EnsureIDInternal ();
733                         SetMask (ID_SET, true);
734                 }
735
736                 protected bool HasEvents ()
737                 {
738                         return _events != null;
739                 }
740
741                 void ResetControlsCache ()
742                 {
743                         _controlsCache = null;
744
745                         if ((this.stateMask & IS_NAMING_CONTAINER) == 0 && Parent != null)
746                                 Parent.ResetControlsCache ();
747                 }
748
749                 Hashtable InitControlsCache ()
750                 {
751                         if (_controlsCache != null)
752                                 return _controlsCache;
753
754                         if ((this.stateMask & IS_NAMING_CONTAINER) != 0 || Parent == null)
755                                 //LAMESPEC: MS' docs don't mention it, but FindControl is case insensitive.
756                                 _controlsCache = new Hashtable (StringComparer.OrdinalIgnoreCase);
757                         else
758                                 _controlsCache = Parent.InitControlsCache ();
759
760                         return _controlsCache;
761                 }
762
763                 void EnsureControlsCache ()
764                 {
765                         if (_controlsCache != null)
766                                 return;
767
768                         InitControlsCache ();
769
770                         FillControlCache (_controls);
771                 }
772
773                 void FillControlCache (ControlCollection controls)
774                 {
775                         if (controls == null || controls.Count == 0)
776                                 return;
777                         
778                         foreach (Control c in controls) {
779                                 try {
780                                         if (c._userId != null)
781                                                 _controlsCache.Add (c._userId, c);
782                                 } catch (ArgumentException) {
783                                         throw new HttpException (
784                                                 "Multiple controls with the same ID '" + 
785                                                 c._userId + 
786                                                 "' were found. FindControl requires that controls have unique IDs. ");
787                                 }
788
789                                 if ((c.stateMask & IS_NAMING_CONTAINER) == 0 && c.HasControls ())
790                                         FillControlCache (c.Controls);
791                         }
792                 }
793
794                 protected bool IsLiteralContent ()
795                 {
796                         if (_controls != null && _controls.Count == 1 && _controls [0] is LiteralControl)
797                                 return true;
798
799                         return false;
800                 }
801
802                 [WebSysDescription ("")]
803                 public virtual Control FindControl (string id)
804                 {
805                         return FindControl (id, 0);
806                 }
807
808                 Control LookForControlByName (string id)
809                 {
810                         EnsureControlsCache ();
811                         return (Control) _controlsCache [id];
812                 }
813
814                 protected virtual Control FindControl (string id, int pathOffset)
815                 {
816                         EnsureChildControls ();
817                         Control namingContainer = null;
818                         if ((stateMask & IS_NAMING_CONTAINER) == 0) {
819                                 namingContainer = NamingContainer;
820                                 if (namingContainer == null)
821                                         return null;
822                                 
823                                 return namingContainer.FindControl (id, pathOffset);
824                         }
825
826                         if (!HasControls ())
827                                 return null;
828                         
829                         int separatorIdx = id.IndexOf (IdSeparator, pathOffset);
830                         if (separatorIdx == -1)
831                                 return LookForControlByName (id.Substring (pathOffset));
832
833                         string idfound = id.Substring (pathOffset, separatorIdx - pathOffset);
834                         namingContainer = LookForControlByName (idfound);
835                         if (namingContainer == null)
836                                 return null;
837
838                         return namingContainer.FindControl (id, separatorIdx + 1);
839                 }
840
841                 protected virtual void LoadViewState (object savedState)
842                 {
843                         if (savedState != null) {
844                                 ViewState.LoadViewState (savedState);
845                                 object o = ViewState ["Visible"];
846                                 if (o != null) {
847                                         SetMask (VISIBLE, (bool) o);
848                                         stateMask |= VISIBLE_CHANGED;
849                                 }
850                         }
851                 }
852
853                 // [MonoTODO("Secure?")]
854                 protected string MapPathSecure (string virtualPath)
855                 {
856                         string combined = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
857                         return Context.Request.MapPath (combined);
858                 }
859
860                 protected virtual bool OnBubbleEvent (object source, EventArgs args) //DIT
861                 {
862 #if MONO_TRACE
863                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
864                         string type_name = null;
865                         if (trace != null) {
866                                 type_name = GetType ().Name;
867                                 trace.Write ("control", String.Concat ("OnBubbleEvent ", _userId, " ", type_name));
868                         }
869 #endif
870                         return false;
871                 }
872
873                 protected virtual void OnDataBinding (EventArgs e)
874                 {
875                         if ((event_mask & databinding_mask) != 0) {
876                                 EventHandler eh = (EventHandler) (_events [DataBindingEvent]);
877                                 if (eh != null) {
878 #if MONO_TRACE
879                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
880                                         string type_name = null;
881                                         if (trace != null) {
882                                                 type_name = GetType ().Name;
883                                                 trace.Write ("control", String.Concat ("OnDataBinding ", _userId, " ", type_name));
884                                         }
885 #endif
886                                         eh (this, e);
887                                 }
888                         }
889                 }
890
891                 protected internal virtual void OnInit (EventArgs e)
892                 {
893                         if ((event_mask & init_mask) != 0) {
894                                 EventHandler eh = (EventHandler) (_events [InitEvent]);
895                                 if (eh != null) {
896 #if MONO_TRACE
897                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
898                                         string type_name = null;
899                                         if (trace != null) {
900                                                 type_name = GetType ().Name;
901                                                 trace.Write ("control", String.Concat ("OnInit ", _userId, " ", type_name));
902                                         }
903 #endif
904                                         eh (this, e);
905                                 }
906                         }
907                 }
908
909                 protected internal virtual void OnLoad (EventArgs e)
910                 {
911                         if ((event_mask & load_mask) != 0) {
912                                 EventHandler eh = (EventHandler) (_events [LoadEvent]);
913                                 if (eh != null) {
914 #if MONO_TRACE
915                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
916                                         string type_name = null;
917                                         if (trace != null) {
918                                                 type_name = GetType ().Name;
919                                                 trace.Write ("control", String.Concat ("OnLoad ", _userId, " ", type_name));
920                                         }
921 #endif
922                                         eh (this, e);
923                                 }
924                         }
925                 }
926
927                 protected internal virtual void OnPreRender (EventArgs e)
928                 {
929                         if ((event_mask & prerender_mask) != 0) {
930                                 EventHandler eh = (EventHandler) (_events [PreRenderEvent]);
931                                 if (eh != null) {
932 #if MONO_TRACE
933                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
934                                         string type_name = null;
935                                         if (trace != null) {
936                                                 type_name = GetType ().Name;
937                                                 trace.Write ("control", String.Concat ("OnPreRender ", _userId, " ", type_name));
938                                         }
939 #endif
940                                         eh (this, e);
941                                 }
942                         }
943                 }
944
945                 protected internal virtual void OnUnload (EventArgs e)
946                 {
947                         if ((event_mask & unload_mask) != 0) {
948                                 EventHandler eh = (EventHandler) (_events [UnloadEvent]);
949                                 if (eh != null) {
950 #if MONO_TRACE
951                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
952                                         string type_name = null;
953                                         if (trace != null) {
954                                                 type_name = GetType ().Name;
955                                                 trace.Write ("control", String.Concat ("OnUnload ", _userId, " ", type_name));
956                                         }
957 #endif
958                                         eh (this, e);
959                                 }
960                         }
961                 }
962
963                 protected internal Stream OpenFile (string path)
964                 {
965                         try {
966                                 string filePath = Context.Server.MapPath (path);
967                                 return File.OpenRead (filePath);
968                         }
969                         catch (UnauthorizedAccessException) {
970                                 throw new HttpException ("Access to the specified file was denied.");
971                         }
972                 }
973
974                 internal string GetPhysicalFilePath (string virtualPath)
975                 {
976                         Page page = Page;
977
978                         if (VirtualPathUtility.IsAbsolute (virtualPath))
979                                 return page != null ? page.MapPath (virtualPath) : Context.Server.MapPath (virtualPath);
980
981                         // We need to determine whether one of our parents is a
982                         // master page. If so, we need to map the path
983                         // relatively to the master page and not our containing
984                         // page/control. This is necessary for cases when a
985                         // relative path is used in a control placed in a master
986                         // page and the master page is referenced from a
987                         // location other than its own. In such cases MS.NET looks
988                         // for the file in the directory where the master page
989                         // is.
990                         //
991                         // An example of where it is needed is at
992                         //
993                         // http://quickstarts.asp.net/QuickStartv20/aspnet/samples/masterpages/masterpages_cs/pages/default.aspx
994                         //
995                         MasterPage master = null;
996                         Control ctrl = Parent;
997
998                         while (ctrl != null) {
999                                 if (ctrl is MasterPage) {
1000                                         master = ctrl as MasterPage;
1001                                         break;
1002                                 }
1003                                 ctrl = ctrl.Parent;
1004                         }
1005
1006                         string path;
1007                         if (master != null)
1008                                 path = VirtualPathUtility.Combine (master.TemplateSourceDirectory + "/", virtualPath);
1009                         else
1010                                 path = VirtualPathUtility.Combine (TemplateSourceDirectory + "/", virtualPath);
1011                         
1012                         return page != null ? page.MapPath (path) : Context.Server.MapPath (path);
1013                 }
1014
1015                 protected void RaiseBubbleEvent (object source, EventArgs args)
1016                 {
1017                         Control c = Parent;
1018                         while (c != null) {
1019 #if MONO_TRACE
1020                                 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1021                                 string type_name = null;
1022                                 if (trace != null) {
1023                                         type_name = GetType ().Name;
1024                                         trace.Write ("control", String.Concat ("RaiseBubbleEvent ", _userId, " ", type_name));
1025                                 }
1026 #endif
1027                                 if (c.OnBubbleEvent (source, args)) {
1028 #if MONO_TRACE
1029                                         if (trace != null)
1030                                                 trace.Write ("control", String.Concat ("End RaiseBubbleEvent (false) ", _userId, " ", type_name));
1031 #endif
1032                                         break;
1033                                 }
1034 #if MONO_TRACE
1035                                 if (trace != null)
1036                                         trace.Write ("control", String.Concat ("End RaiseBubbleEvent (true) ", _userId, " ", type_name));
1037 #endif
1038                                 c = c.Parent;
1039                         }
1040                 }
1041
1042                 protected internal virtual void Render (HtmlTextWriter writer) //DIT
1043                 {
1044                         RenderChildren (writer);
1045                 }
1046
1047                 protected internal virtual void RenderChildren (HtmlTextWriter writer) //DIT
1048                 {
1049                         if (_renderMethodDelegate != null) {
1050                                 _renderMethodDelegate (writer, this);
1051                                 return;
1052                         }
1053
1054                         if (_controls == null)
1055                                 return;
1056
1057                         int len = _controls.Count;
1058                         Control c;
1059                         for (int i = 0; i < len; i++) {
1060                                 c = _controls [i];
1061                                 if (c == null)
1062                                         continue;
1063                                 ControlAdapter tmp = c.Adapter;
1064                                 if (tmp != null)
1065                                         c.RenderControl (writer, tmp);
1066                                 else
1067                                         c.RenderControl (writer);
1068                         }
1069                 }
1070
1071                 protected virtual ControlAdapter ResolveAdapter ()
1072                 {
1073                         HttpContext context = Context;
1074
1075                         if (context == null)
1076                                 return null;
1077
1078                         if (!context.Request.BrowserMightHaveAdapters)
1079                                 return null;
1080                                 
1081                         // Search up the type hierarchy until we find a control with an adapter.
1082                         IDictionary typeMap = context.Request.Browser.Adapters;
1083                         Type controlType = GetType ();
1084                         Type adapterType = (Type)typeMap [controlType];
1085                         while (adapterType == null && controlType != typeof (Control)) {
1086                                 controlType = controlType.BaseType;
1087                                 adapterType = (Type)typeMap [controlType];
1088                         }
1089
1090                         ControlAdapter a = null;
1091                         if (adapterType != null)
1092                                 a = (ControlAdapter)Activator.CreateInstance (adapterType);
1093                         return a;
1094                 }
1095
1096                 protected virtual object SaveViewState ()
1097                 {
1098                         if ((stateMask & VISIBLE_CHANGED) != 0) {
1099                                 ViewState ["Visible"] = (stateMask & VISIBLE) != 0;
1100                         } else if (_viewState == null) {
1101                                 return null;
1102                         }
1103
1104                         return _viewState.SaveViewState ();
1105                 }
1106
1107                 protected virtual void TrackViewState ()
1108                 {
1109                         if (_viewState != null)
1110                                 _viewState.TrackViewState ();
1111
1112                         stateMask |= TRACK_VIEWSTATE;
1113                 }
1114
1115                 public virtual void Dispose ()
1116                 {
1117                         if ((event_mask & disposed_mask) != 0) {
1118                                 EventHandler eh = (EventHandler) (_events [DisposedEvent]);
1119                                 if (eh != null)
1120                                         eh (this, EventArgs.Empty);
1121                         }
1122                 }
1123
1124                 [WebCategory ("FIXME")]
1125                 [WebSysDescription ("Raised when the contols databound properties are evaluated.")]
1126                 public event EventHandler DataBinding {
1127                         add {
1128                                 event_mask |= databinding_mask;
1129                                 Events.AddHandler (DataBindingEvent, value);
1130                         }
1131                         remove { Events.RemoveHandler (DataBindingEvent, value); }
1132                 }
1133
1134                 [WebSysDescription ("Raised when the contol is disposed.")]
1135                 public event EventHandler Disposed {
1136                         add {
1137                                 event_mask |= disposed_mask;
1138                                 Events.AddHandler (DisposedEvent, value);
1139                         }
1140                         remove { Events.RemoveHandler (DisposedEvent, value); }
1141                 }
1142
1143                 [WebSysDescription ("Raised when the page containing the control is initialized.")]
1144                 public event EventHandler Init {
1145                         add {
1146                                 event_mask |= init_mask;
1147                                 Events.AddHandler (InitEvent, value);
1148                         }
1149                         remove { Events.RemoveHandler (InitEvent, value); }
1150                 }
1151
1152                 [WebSysDescription ("Raised after the page containing the control has been loaded.")]
1153                 public event EventHandler Load {
1154                         add {
1155                                 event_mask |= load_mask;
1156                                 Events.AddHandler (LoadEvent, value);
1157                         }
1158                         remove { Events.RemoveHandler (LoadEvent, value); }
1159                 }
1160
1161                 [WebSysDescription ("Raised before the page containing the control is rendered.")]
1162                 public event EventHandler PreRender {
1163                         add {
1164                                 event_mask |= prerender_mask;
1165                                 Events.AddHandler (PreRenderEvent, value);
1166                         }
1167                         remove { Events.RemoveHandler (PreRenderEvent, value); }
1168                 }
1169
1170                 [WebSysDescription ("Raised when the page containing the control is unloaded.")]
1171                 public event EventHandler Unload {
1172                         add {
1173                                 event_mask |= unload_mask;
1174                                 Events.AddHandler (UnloadEvent, value);
1175                         }
1176                         remove { Events.RemoveHandler (UnloadEvent, value); }
1177                 }
1178
1179                 public virtual void DataBind () //DIT
1180                 {
1181                         DataBind (true);
1182                 }
1183
1184                 protected virtual void DataBindChildren ()
1185                 {
1186                         if (!HasControls ())
1187                                 return;
1188
1189                         int len = _controls != null ? _controls.Count : 0;
1190                         for (int i = 0; i < len; i++) {
1191                                 Control c = _controls [i];
1192                                 c.DataBind ();
1193                         }
1194                 }
1195
1196                 public virtual bool HasControls ()
1197                 {
1198                         return (_controls != null && _controls.Count > 0);
1199                 }
1200                 
1201                 public virtual void RenderControl (HtmlTextWriter writer)
1202                 {
1203                         if (this.adapter != null) {
1204                                 RenderControl (writer, this.adapter);
1205                                 return;
1206                         }
1207
1208                         if ((stateMask & VISIBLE) != 0) {
1209                                 HttpContext ctx = Context;
1210                                 TraceContext trace = (ctx != null) ? ctx.Trace : null;
1211                                 int pos = 0;
1212                                 if ((trace != null) && trace.IsEnabled)
1213                                         pos = ctx.Response.GetOutputByteCount ();
1214
1215                                 Render (writer);
1216                                 if ((trace != null) && trace.IsEnabled) {
1217                                         int size = ctx.Response.GetOutputByteCount () - pos;
1218                                         trace.SaveSize (this, size >= 0 ? size : 0);
1219                                 }
1220                         }
1221                 }
1222
1223                 protected void RenderControl (HtmlTextWriter writer, ControlAdapter adapter)
1224                 {
1225                         if ((stateMask & VISIBLE) != 0) {
1226                                 adapter.BeginRender (writer);
1227                                 adapter.Render (writer);
1228                                 adapter.EndRender (writer);
1229                         }
1230                 }
1231
1232                 public string ResolveUrl (string relativeUrl)
1233                 {
1234                         if (relativeUrl == null)
1235                                 throw new ArgumentNullException ("relativeUrl");
1236
1237                         if (relativeUrl == String.Empty)
1238                                 return relativeUrl;
1239
1240                         if (VirtualPathUtility.IsAbsolute (relativeUrl))
1241                                 return relativeUrl;
1242
1243                         if (relativeUrl [0] == '#')
1244                                 return relativeUrl;
1245
1246                         string ts = AppRelativeTemplateSourceDirectory;
1247                         HttpContext ctx = Context;
1248                         HttpResponse resp = ctx != null ? ctx.Response : null;
1249                         if (ts == null || ts.Length == 0 || resp == null || relativeUrl.IndexOf (':') >= 0)
1250                                 return relativeUrl;
1251                         
1252                         if (!VirtualPathUtility.IsAppRelative (relativeUrl))
1253                                 relativeUrl = VirtualPathUtility.Combine (VirtualPathUtility.AppendTrailingSlash (ts), relativeUrl);
1254                         
1255                         return resp.ApplyAppPathModifier (relativeUrl);
1256                 }
1257
1258
1259                 public string ResolveClientUrl (string relativeUrl)
1260                 {
1261                         if (relativeUrl == null)
1262                                 throw new ArgumentNullException ("relativeUrl");
1263
1264                         if (relativeUrl.Length == 0)
1265                                 return String.Empty;
1266
1267 #if TARGET_J2EE
1268                         relativeUrl = ResolveClientUrlInternal (relativeUrl);
1269
1270                         javax.faces.context.FacesContext faces = getFacesContext ();
1271                         if (faces == null)
1272                                 return relativeUrl;
1273
1274                         string url;
1275                         if (relativeUrl.IndexOf (':') >= 0)
1276                                 url = ResolveAppRelativeFromFullPath (relativeUrl);
1277                         else if (VirtualPathUtility.IsAbsolute (relativeUrl))
1278                                 url = VirtualPathUtility.ToAppRelative (relativeUrl);
1279                         else
1280                                 return faces.getApplication ().getViewHandler ().getResourceURL (faces, relativeUrl);
1281
1282                         if (VirtualPathUtility.IsAppRelative (url)) {
1283                                 url = url.Substring (1);
1284                                 url = url.Length == 0 ? "/" : url;
1285                                 return faces.getApplication ().getViewHandler ().getResourceURL (faces, url);
1286                         }
1287                         return relativeUrl;
1288                 }
1289                 
1290                 string ResolveClientUrlInternal (string relativeUrl) {
1291                         if (relativeUrl.StartsWith (J2EE.J2EEConsts.ACTION_URL_PREFIX, StringComparison.Ordinal))
1292                                 return CreateActionUrl (relativeUrl.Substring (J2EE.J2EEConsts.ACTION_URL_PREFIX.Length));
1293
1294                         if (relativeUrl.StartsWith (J2EE.J2EEConsts.RENDER_URL_PREFIX, StringComparison.Ordinal))
1295                                 return ResolveClientUrl (relativeUrl.Substring (J2EE.J2EEConsts.RENDER_URL_PREFIX.Length));
1296
1297 #endif
1298                         if (VirtualPathUtility.IsAbsolute (relativeUrl) || relativeUrl.IndexOf (':') >= 0)
1299                                 return relativeUrl;
1300
1301                         HttpContext context = Context;
1302                         HttpRequest req = context != null ? context.Request : null;
1303                         if (req != null) {
1304                                 string templateSourceDirectory = TemplateSourceDirectory;
1305                                 if (templateSourceDirectory == null || templateSourceDirectory.Length == 0)
1306                                         return relativeUrl;
1307
1308                                 string basePath = req.ClientFilePath;
1309
1310                                 if (basePath.Length > 1 && basePath [basePath.Length - 1] != '/')
1311                                         basePath = VirtualPathUtility.GetDirectory (basePath, false);
1312
1313                                 if (VirtualPathUtility.IsAppRelative (relativeUrl))
1314                                         return VirtualPathUtility.MakeRelative (basePath, relativeUrl);
1315
1316                                 string templatePath = VirtualPathUtility.AppendTrailingSlash (templateSourceDirectory);
1317
1318                                 if (basePath.Length == templatePath.Length && String.CompareOrdinal (basePath, templatePath) == 0)
1319                                         return relativeUrl;
1320
1321                                 relativeUrl = VirtualPathUtility.Combine (templatePath, relativeUrl);
1322                                 return VirtualPathUtility.MakeRelative (basePath, relativeUrl);
1323                         }
1324                         return relativeUrl;
1325                 }
1326
1327                 internal bool HasRenderMethodDelegate ()
1328                 {
1329                         return _renderMethodDelegate != null;
1330                 }
1331
1332                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1333                 public void SetRenderMethodDelegate (RenderMethod renderMethod) //DIT
1334                 {
1335                         _renderMethodDelegate = renderMethod;
1336                 }
1337
1338                 internal void LoadRecursive ()
1339                 {
1340 #if MONO_TRACE
1341                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1342                         string type_name = null;
1343                         if (trace != null) {
1344                                 type_name = GetType ().Name;
1345                                 trace.Write ("control", String.Concat ("LoadRecursive ", _userId, " ", type_name));
1346                         }
1347 #endif
1348                         if (Adapter != null)
1349                                 Adapter.OnLoad (EventArgs.Empty);
1350                         else
1351                                 OnLoad (EventArgs.Empty);
1352                         int ccount = _controls != null ? _controls.Count : 0;
1353                         for (int i = 0; i < ccount; i++) {
1354                                 Control c = _controls [i];
1355                                 c.LoadRecursive ();
1356                         }
1357
1358 #if MONO_TRACE
1359                         if (trace != null)
1360                                 trace.Write ("control", String.Concat ("End LoadRecursive ", _userId, " ", type_name));
1361 #endif
1362                         stateMask |= LOADED;
1363                 }
1364
1365                 internal void UnloadRecursive (Boolean dispose)
1366                 {
1367 #if MONO_TRACE
1368                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1369                         string type_name = null;
1370                         if (trace != null) {
1371                                 type_name = GetType ().Name;
1372                                 trace.Write ("control", String.Concat ("UnloadRecursive ", _userId, " ", type_name));
1373                         }
1374 #endif
1375                         int ccount = _controls != null ? _controls.Count : 0;
1376                         for (int i = 0; i < ccount; i++) {
1377                                 Control c = _controls [i];
1378                                 c.UnloadRecursive (dispose);
1379                         }
1380
1381 #if MONO_TRACE
1382                         if (trace != null)
1383                                 trace.Write ("control", String.Concat ("End UnloadRecursive ", _userId, " ", type_name));
1384 #endif
1385                         ControlAdapter tmp = Adapter;
1386                         if (tmp != null)
1387                                 tmp.OnUnload (EventArgs.Empty);
1388                         else
1389                                 OnUnload (EventArgs.Empty);
1390                         if (dispose)
1391                                 Dispose ();
1392                 }
1393
1394                 internal void PreRenderRecursiveInternal ()
1395                 {
1396                         bool visible;
1397
1398                         visible = Visible;                      
1399                         if (visible) {
1400                                 SetMask (VISIBLE, true);
1401                                 EnsureChildControls ();
1402 #if MONO_TRACE
1403                                 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1404                                 string type_name = null;
1405                                 if (trace != null) {
1406                                         type_name = GetType ().Name;
1407                                         trace.Write ("control", String.Concat ("PreRenderRecursive ", _userId, " ", type_name));
1408                                 }
1409 #endif
1410                                 if (Adapter != null)
1411                                         Adapter.OnPreRender (EventArgs.Empty);
1412                                 else
1413                                         OnPreRender (EventArgs.Empty);
1414                                 if (!HasControls ())
1415                                         return;
1416
1417                                 int len = _controls != null ? _controls.Count : 0;
1418                                 for (int i = 0; i < len; i++) {
1419                                         Control c = _controls [i];
1420                                         c.PreRenderRecursiveInternal ();
1421                                 }
1422 #if MONO_TRACE
1423                                 if (trace != null)
1424                                         trace.Write ("control", String.Concat ("End PreRenderRecursive ", _userId, " ", type_name));
1425 #endif
1426                         } else
1427                                 SetMask (VISIBLE, false);
1428                         
1429                         stateMask |= PRERENDERED;
1430                 }
1431
1432                 internal void InitRecursive (Control namingContainer)
1433                 {
1434 #if MONO_TRACE
1435                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1436                         string type_name = null;
1437                         if (trace != null) {
1438                                 type_name = GetType ().Name;
1439                                 trace.Write ("control", String.Concat ("InitRecursive ", _userId, " ", type_name));
1440                         }
1441 #endif
1442                         SetNamingContainer (namingContainer);
1443
1444                         if (HasControls ()) {
1445                                 if ((stateMask & IS_NAMING_CONTAINER) != 0)
1446                                         namingContainer = this;
1447
1448                                 int len = _controls != null ? _controls.Count : 0;
1449                                 for (int i = 0; i < len; i++) {
1450                                         Control c = _controls [i];
1451                                         c.InitRecursive (namingContainer);
1452                                 }
1453                         }
1454
1455                         if ((stateMask & REMOVED) == 0 && (stateMask & INITED) != INITED) {
1456                                 stateMask |= INITING;
1457                                 ApplyTheme ();
1458                                 ControlAdapter tmp = Adapter;
1459                                 if (tmp != null)
1460                                         tmp.OnInit (EventArgs.Empty);
1461                                 else
1462                                         OnInit (EventArgs.Empty);
1463                                 TrackViewState ();
1464                                 stateMask |= INITED;
1465                                 stateMask &= ~INITING;
1466                         }
1467                         
1468 #if MONO_TRACE
1469                         if (trace != null)
1470                                 trace.Write ("control", String.Concat ("End InitRecursive ", _userId, " ", type_name));
1471 #endif
1472                 }
1473
1474                 internal object SaveViewStateRecursive ()
1475                 {
1476                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1477 #if MONO_TRACE
1478                         string type_name = null;
1479                         if (trace != null) {
1480                                 type_name = GetType ().Name;
1481                                 trace.Write ("control", String.Concat ("SaveViewStateRecursive ", _userId, " ", type_name));
1482                         }
1483 #endif
1484
1485                         ArrayList controlStates = null;
1486                         bool byId = LoadViewStateByID;
1487                         if (HasControls ()) {
1488                                 int len = _controls != null ? _controls.Count : 0;
1489                                 for (int i = 0; i < len; i++) {
1490                                         Control ctrl = _controls [i];
1491                                         object ctrlState = ctrl.SaveViewStateRecursive ();
1492                                         if (ctrlState == null)
1493                                                 continue;
1494
1495                                         if (controlStates == null)
1496                                                 controlStates = new ArrayList ();
1497                                         if (byId) {
1498                                                 ctrl.EnsureID ();
1499                                                 controlStates.Add (new Pair (ctrl.ID, ctrlState));
1500                                         } else
1501                                                 controlStates.Add (new Pair (i, ctrlState));
1502                                 }
1503                         }
1504
1505                         object thisAdapterViewState = null;
1506                         if (Adapter != null)
1507                                 thisAdapterViewState = Adapter.SaveAdapterViewState ();
1508
1509                         object thisState = null;
1510
1511                         if (IsViewStateEnabled)
1512                                 thisState = SaveViewState ();
1513
1514                         if (thisState == null && controlStates == null) {
1515                                 if (trace != null) {
1516 #if MONO_TRACE
1517                                         trace.Write ("control", "End SaveViewStateRecursive " + _userId + " " + type_name + " saved nothing");
1518 #endif
1519                                         trace.SaveViewState (this, null);
1520                                 }
1521                                 return null;
1522                         }
1523
1524                         if (trace != null) {
1525 #if MONO_TRACE
1526                                 trace.Write ("control", "End SaveViewStateRecursive " + _userId + " " + type_name + " saved a Triplet");
1527 #endif
1528                                 trace.SaveViewState (this, thisState);
1529                         }
1530                         thisState = new object[] { thisState, thisAdapterViewState };
1531                         return new Pair (thisState, controlStates);
1532                 }
1533
1534                 internal void LoadViewStateRecursive (object savedState)
1535                 {
1536                         if (savedState == null)
1537                                 return;
1538
1539 #if MONO_TRACE
1540                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1541                         string type_name = null;
1542                         if (trace != null) {
1543                                 type_name = GetType ().Name;
1544                                 trace.Write ("control", String.Concat ("LoadViewStateRecursive ", _userId, " ", type_name));
1545                         }
1546 #endif
1547                         Pair savedInfo = (Pair) savedState;
1548                         object[] controlAndAdapterViewStates = (object [])savedInfo.First;
1549                         if (Adapter != null)
1550                                 Adapter.LoadAdapterViewState (controlAndAdapterViewStates [1]);
1551                         LoadViewState (controlAndAdapterViewStates [0]);
1552
1553                         ArrayList controlStates = savedInfo.Second as ArrayList;
1554                         if (controlStates == null)
1555                                 return;
1556
1557                         int nControls = controlStates.Count;
1558                         bool byId = LoadViewStateByID;
1559                         for (int i = 0; i < nControls; i++) {
1560                                 Pair p = controlStates [i] as Pair;
1561                                 if (p == null)
1562                                         continue;
1563
1564                                 if (byId) {
1565                                         string id = (string)p.First;
1566                                         bool found = false;
1567                                         
1568                                         foreach (Control c in Controls) {
1569                                                 c.EnsureID ();
1570                                                 if (c.ID == id) {
1571                                                         found = true;
1572                                                         c.LoadViewStateRecursive (p.Second);
1573                                                         break;
1574                                                 }
1575                                         }
1576
1577                                         if (!found) {
1578                                                 if (pendingVS == null)
1579                                                         pendingVS = new Hashtable ();
1580                                                 pendingVS [id] = p.Second;
1581                                         }
1582                                 } else {
1583                                         int k = (int) p.First;
1584                                         if (k < Controls.Count) {
1585                                                 Control c = Controls [k];
1586                                                 c.LoadViewStateRecursive (p.Second);
1587                                         } else {
1588                                                 if (pendingVS == null)
1589                                                         pendingVS = new Hashtable ();
1590
1591                                                 pendingVS [k] = p.Second;
1592                                         }
1593                                 }
1594                         }
1595
1596 #if MONO_TRACE
1597                         if (trace != null)
1598                                 trace.Write ("control", String.Concat ("End LoadViewStateRecursive ", _userId, " ", type_name));
1599 #endif
1600                         stateMask |= VIEWSTATE_LOADED;
1601                 }
1602
1603                 internal ControlSkin controlSkin;
1604
1605                 internal void ApplyTheme ()
1606                 {
1607 #if MONO_TRACE
1608                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1609                         string type_name = null;
1610                         if (trace != null) {
1611                                 type_name = GetType ().Name;
1612                                 trace.Write ("control", String.Concat ("ApplyThemeRecursive ", _userId, " ", type_name));
1613                         }
1614 #endif
1615                         Page page = Page;
1616                         if (page != null && page.PageTheme != null && EnableTheming) {
1617                                 ControlSkin controlSkin = page.PageTheme.GetControlSkin (GetType (), SkinID);
1618                                 if (controlSkin != null)
1619                                         controlSkin.ApplySkin (this);
1620                         }
1621
1622 #if MONO_TRACE
1623                         if (trace != null)
1624                                 trace.Write ("control", String.Concat ("End ApplyThemeRecursive ", _userId, " ", type_name));
1625 #endif
1626                 }
1627
1628                 internal bool AutoID {
1629                         get { return (stateMask & AUTOID) != 0; }
1630                         set {
1631                                 if (value == false && (stateMask & IS_NAMING_CONTAINER) != 0)
1632                                         return;
1633
1634                                 SetMask (AUTOID, value);
1635                         }
1636                 }
1637
1638                 protected internal virtual void RemovedControl (Control control)
1639                 {
1640                         control.UnloadRecursive (false);
1641                         control._parent = null;
1642                         control._page = null;
1643                         control._namingContainer = null;
1644                         if ((control.stateMask & AUTOID_SET) != 0) {
1645                                 control._userId = null;
1646                                 control.SetMask (ID_SET, false);
1647                         }
1648                         control.NullifyUniqueID ();
1649                         control.SetMask (REMOVED, true);
1650                         ResetControlsCache ();
1651                 }
1652                 
1653                 string skinId = string.Empty;
1654                 bool _enableTheming = true;
1655
1656                 [Browsable (false)]
1657                 [Themeable (false)]
1658                 [DefaultValue (true)]
1659                 public virtual bool EnableTheming {
1660                         get {
1661                                 if ((stateMask & ENABLE_THEMING) != 0)
1662                                         return _enableTheming;
1663
1664                                 if (_parent != null)
1665                                         return _parent.EnableTheming;
1666
1667                                 return true;
1668                         }
1669                         set {
1670                                 SetMask (ENABLE_THEMING, true);
1671                                 _enableTheming = value;
1672                         }
1673                 }
1674
1675                 [Browsable (false)]
1676                 [DefaultValue ("")]
1677                 [Filterable (false)]
1678                 public virtual string SkinID {
1679                         get { return skinId; }
1680                         set { skinId = value; }
1681                 }
1682
1683                 ControlBuilder IControlBuilderAccessor.ControlBuilder {
1684                         get { throw new NotImplementedException (); }
1685                 }
1686
1687                 IDictionary IControlDesignerAccessor.GetDesignModeState ()
1688                 {
1689                         throw new NotImplementedException ();
1690                 }
1691
1692                 void IControlDesignerAccessor.SetDesignModeState (IDictionary designData)
1693                 {
1694                         SetDesignModeState (designData);
1695                 }
1696
1697                 void IControlDesignerAccessor.SetOwnerControl (Control control)
1698                 {
1699                         throw new NotImplementedException ();
1700                 }
1701
1702                 IDictionary IControlDesignerAccessor.UserData {
1703                         get { throw new NotImplementedException (); }
1704                 }
1705
1706                 ExpressionBindingCollection expressionBindings;
1707
1708                 ExpressionBindingCollection IExpressionsAccessor.Expressions {
1709                         get {
1710                                 if (expressionBindings == null)
1711                                         expressionBindings = new ExpressionBindingCollection ();
1712                                 return expressionBindings;
1713                         }
1714                 }
1715
1716                 bool IExpressionsAccessor.HasExpressions {
1717                         get { return (expressionBindings != null && expressionBindings.Count > 0); }
1718                 }
1719
1720                 public virtual void Focus ()
1721                 {
1722                         Page.SetFocus (this);
1723                 }
1724
1725                 protected internal virtual void LoadControlState (object state)
1726                 {
1727                 }
1728
1729                 protected internal virtual object SaveControlState ()
1730                 {
1731                         return null;
1732                 }
1733
1734                 protected virtual void DataBind (bool raiseOnDataBinding)
1735                 {
1736                         bool foundDataItem = false;
1737
1738                         if ((stateMask & IS_NAMING_CONTAINER) != 0 && Page != null) {
1739                                 object o = DataBinder.GetDataItem (this, out foundDataItem);
1740                                 if (foundDataItem)
1741                                         Page.PushDataItemContext (o);
1742                         }
1743
1744                         try {
1745                                 if (raiseOnDataBinding)
1746                                         OnDataBinding (EventArgs.Empty);
1747                                 DataBindChildren ();
1748                         } finally {
1749                                 if (foundDataItem)
1750                                         Page.PopDataItemContext ();
1751                         }
1752                 }
1753
1754                 protected virtual IDictionary GetDesignModeState ()
1755                 {
1756                         throw new NotImplementedException ();
1757                 }
1758
1759                 protected virtual void SetDesignModeState (IDictionary data)
1760                 {
1761                         throw new NotImplementedException ();
1762                 }
1763
1764                 internal bool IsInited {
1765                         get { return (stateMask & INITED) != 0; }
1766                 }
1767
1768                 internal bool IsLoaded {
1769                         get { return (stateMask & LOADED) != 0; }
1770                 }
1771
1772                 internal bool IsPrerendered {
1773                         get { return (stateMask & PRERENDERED) != 0; }
1774                 }
1775
1776                 bool CheckForValidationSupport ()
1777                 {
1778                         return GetType ().GetCustomAttributes (typeof (SupportsEventValidationAttribute), false).Length > 0;
1779                 }
1780
1781                 //
1782                 // Apparently this is where .NET routes validation from all the controls which
1783                 // support it. See:
1784                 //
1785                 //  http://odetocode.com/Blogs/scott/archive/2006/03/20/3145.aspx
1786                 //    Sample in here contains ValidateEvent in the stack trace
1787                 //
1788                 //  http://odetocode.com/blogs/scott/archive/2006/03/21/3153.aspx
1789                 //
1790                 //  http://www.alexthissen.nl/blogs/main/archive/2005/12/13/event-validation-of-controls-in-asp-net-2-0.aspx
1791                 //
1792                 // It also seems that it's the control's responsibility to call this method or
1793                 // validation won't take place. Also, the SupportsEventValidation attribute must be
1794                 // present on the control for validation to take place.
1795                 //
1796                 internal void ValidateEvent (String uniqueId, String argument)
1797                 {
1798                         Page page = Page;
1799                         
1800                         if (page != null && CheckForValidationSupport ())
1801                                 page.ClientScript.ValidateEvent (uniqueId, argument);
1802                 }
1803
1804                 void IParserAccessor.AddParsedSubObject (object obj)
1805                 {
1806                         this.AddParsedSubObject (obj);
1807                 }
1808
1809                 DataBindingCollection IDataBindingsAccessor.DataBindings {
1810                         get {
1811                                 if (dataBindings == null) {
1812                                         dataBindings = new DataBindingCollection ();
1813                                 }
1814                                 return dataBindings;
1815                         }
1816                 }
1817
1818                 bool IDataBindingsAccessor.HasDataBindings {
1819                         get {
1820                                 if (dataBindings != null && dataBindings.Count > 0) {
1821                                         return true;
1822                                 }
1823                                 return false;
1824                         }
1825                 }
1826         }
1827 }