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