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