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