2002-06-17 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / Control.cs
1 //\r
2 // System.Web.UI.Control.cs\r
3 //\r
4 // Author:\r
5 //   Bob Smith <bob@thestuff.net>\r
6 //\r
7 // (C) Bob Smith\r
8 //\r
9 \r
10 /*\r
11  * Maintainer: bob@thestuff.net, gvaish@iitk.ac.in\r
12  * (C) Bob Smith, Gaurav Vaish\r
13  */\r
14 \r
15 //notes: view state only tracks changes after OnInit method is executed for the page request. You can read from it at any time, but cant write to it during rendering.\r
16 //even more notes: view state info in trackviewstate method description. read later.\r
17 //Ok, enough notes: what the heck is different between enable view state, and track view state.\r
18 //Well, maybe not. How does the ViewState know when to track changes? Does it look at the property\r
19 //on the owning control, or does it have a method/property of its own that gets called?\r
20 // I think this last question is solved in the Interface for it. Look into this.\r
21 \r
22 //cycle:\r
23 //init is called when control is first created.\r
24 //load view state ic called right after init to populate the view state.\r
25 //loadpostdata is called if ipostbackdatahandler is implemented.\r
26 //load is called when control is loaded into a page\r
27 //raisepostdatachangedevent if ipostbackdatahandler is implemented.\r
28 //raisepostbackevent if ipostbackeventhandler is implemented.\r
29 //prerender is called when the server is about to render its page object\r
30 //SaveViewState is called.\r
31 //Unload then dispose it apears. :)\r
32 \r
33 //Naming Container MUST have some methods. What are they? No clue. Help?\r
34 \r
35 //read this later. http://gotdotnet.com/quickstart/aspplus/\r
36 //This to: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconattributesdesign-timesupport.asp\r
37 //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpcontracefunctionality.asp\r
38 \r
39 // Isnt life grand? :)\r
40 // See the undocumented methods? Gota love um. ;)\r
41 // ASP.test4_aspx.Page_Load(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6\r
42 // System.Web.UI.Control.OnLoad(EventArgs e) +67\r
43 // System.Web.UI.Control.LoadRecursive() +73\r
44 // System.Web.UI.Page.ProcessRequestMain() +394\r
45 \r
46 // ASP.test4_aspx.Page_Unload(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6\r
47 // System.EventHandler.Invoke(Object sender, EventArgs e) +0\r
48 // System.Web.UI.Control.OnUnload(EventArgs e) +67\r
49 // System.Web.UI.Control.UnloadRecursive(Boolean dispose) +78\r
50 // System.Web.UI.Page.ProcessRequest() +194\r
51 // System.Web.UI.Page.ProcessRequest(HttpContext context) +18\r
52 // System.Web.CallHandlerExecutionStep.Execute() +179\r
53 // System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +87\r
54 \r
55 \r
56 // ASP.test4_aspx.Page_Unload(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6\r
57 // System.Web.UI.Control.OnUnload(EventArgs e) +67\r
58 // System.Web.UI.Control.UnloadRecursive(Boolean dispose) +78\r
59 // System.Web.UI.Page.ProcessRequest()\r
60 \r
61 // ASP.test4_aspx.Page_Kill(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6\r
62 // System.Web.UI.Control.OnPreRender(EventArgs e) +67\r
63 // System.Web.UI.Control.PreRenderRecursiveInternal() +61\r
64 // System.Web.UI.Page.ProcessRequestMain() +753\r
65 \r
66 // ASP.test4_aspx.OnInit(EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6\r
67 // System.Web.UI.Control.InitRecursive(Control namingContainer) +202\r
68 // System.Web.UI.Page.ProcessRequestMain() +120\r
69 \r
70 // ASP.test4_aspx.SaveViewState() in \\genfs2\www24\bobsmith11\test4.aspx:12\r
71 // System.Web.UI.Control.SaveViewStateRecursive() +51\r
72 // System.Web.UI.Page.SavePageViewState() +174\r
73 // System.Web.UI.Page.ProcessRequestMain() +861\r
74 \r
75 // ASP.test_aspx.LoadViewState(Object t) +28\r
76 // System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +125\r
77 // System.Web.UI.Page.LoadPageViewState() +182\r
78 // System.Web.UI.Page.ProcessRequestMain() +256\r
79 \r
80 using System;\r
81 using System.Collections;\r
82 using System.Web;\r
83 using System.ComponentModel;\r
84 \r
85 namespace System.Web.UI\r
86 {\r
87         public class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor\r
88         {\r
89                 private static readonly object DataBindingEvent = new object();\r
90                 private static readonly object DisposedEvent = new object();\r
91                 private static readonly object InitEvent = new object();\r
92                 private static readonly object LoadEvent = new object();\r
93                 private static readonly object PreRenderEvent = new object();\r
94                 private static readonly object UnloadEvent = new object();\r
95                 private string _userId = null;\r
96                 private string _cachedUserId = null;\r
97                 private string _cachedClientId = null;\r
98                 private ControlCollection _controls = null;\r
99                 private bool _enableViewState = true;\r
100                 private IDictionary _childViewStates = null; //TODO: Not sure datatype. Placeholder guess.\r
101                 private bool _isNamingContainer = false;\r
102                 private Control _namingContainer = null;\r
103                 private Page _page = null;\r
104                 private Control _parent = null;\r
105                 private ISite _site = null;\r
106                 private bool _visible = true;\r
107                 private HttpContext _context = null;\r
108                 private bool _childControlsCreated = false;\r
109                 private StateBag _viewState = null;\r
110                 private bool _trackViewState = false;\r
111                 private EventHandlerList _events = new EventHandlerList();\r
112                 private RenderMethod _renderMethodDelegate = null;\r
113                 private bool autoID = true;\r
114                 \r
115                     private DataBindingCollection dataBindings = null;\r
116 \r
117                 public Control()\r
118                 {\r
119                         if (this is INamingContainer) _isNamingContainer = true;\r
120                 }\r
121                 public virtual string ClientID //DIT\r
122                 {\r
123                         get\r
124                         {\r
125                                 if (_cachedUserId != null && _cachedClientId != null)\r
126                                         return _cachedClientId;\r
127                                 _cachedUserId = UniqueID.Replace(':', '_');\r
128                                 return _cachedUserId;\r
129                         }\r
130                 }\r
131                 public virtual ControlCollection Controls //DIT\r
132                 {\r
133                         get\r
134                         {\r
135                                 if (_controls == null) _controls = CreateControlCollection();\r
136                                 return _controls;\r
137                         }\r
138                 }\r
139                 public virtual bool EnableViewState //DIT\r
140                 {\r
141                         get\r
142                         {\r
143                                 return _enableViewState;\r
144                         }\r
145                         set\r
146                         {\r
147                                 _enableViewState = value;\r
148                         }\r
149                 }\r
150                 public virtual string ID\r
151                 {\r
152                         get //DIT\r
153                         {\r
154                                 return _userId;\r
155                         }\r
156                         set\r
157                         {\r
158                                 if (value == null || value == "") return;\r
159                                 _userId = value;\r
160                                 _cachedUserId = null;\r
161                                 //TODO: Some Naming Container stuff here I think.\r
162                         }\r
163                 }\r
164                 public virtual Control NamingContainer //DIT\r
165                 {\r
166                         get\r
167                         {\r
168                                 if (_namingContainer == null && _parent != null)\r
169                                 {\r
170                                         if (_parent._isNamingContainer == false)\r
171                                                 _namingContainer = _parent.NamingContainer;\r
172                                         else\r
173                                                 _namingContainer = _parent;\r
174                                 }\r
175                                 return _namingContainer;\r
176                         }\r
177                 }\r
178                 public virtual Page Page //DIT\r
179                 {\r
180                         get\r
181                         {\r
182                                 if (_page == null && _parent != null) _page = _parent.Page;\r
183                                 return _page;\r
184                         }\r
185                         set\r
186                         {\r
187                                 _page = value;\r
188                         }\r
189                 }\r
190                 public virtual Control Parent //DIT\r
191                 {\r
192                         get\r
193                         {\r
194                                 return _parent;\r
195                         }\r
196                 }\r
197                 public ISite Site //DIT\r
198                 {\r
199                         get\r
200                         {\r
201                                 return _site;\r
202                         }\r
203                         set\r
204                         {\r
205                                 _site = value;\r
206                         }\r
207                 }\r
208                 public virtual string TemplateSourceDirectory\r
209                 {\r
210                         get\r
211                         {\r
212                                 return Context.Request.ApplicationPath; //TODO: Dont think this is right.\r
213                         }\r
214                 }\r
215 \r
216                                 [MonoTODO]\r
217                 public virtual string UniqueID\r
218                 {\r
219                         get\r
220                         {\r
221                                 //TODO: Some Naming container methods here. What are they? Why arnt they declared?\r
222                                 //Note: Nuked the old stuff here. Was total crap. :)\r
223                                 return ID;\r
224                         }\r
225                 }\r
226                 public virtual bool Visible\r
227                 { //TODO: Are children visible when parents are not?\r
228                         get\r
229                         {\r
230                                 return _visible;\r
231                         }\r
232                         set\r
233                         {\r
234                                 _visible = value;\r
235                         }\r
236                 }\r
237                 protected bool ChildControlsCreated //DIT\r
238                 {\r
239                         get\r
240                         {\r
241                                 return _childControlsCreated;\r
242                         }\r
243                         set\r
244                         {\r
245                                 if (value == false && _childControlsCreated == true)\r
246                                         _controls.Clear();\r
247                                 _childControlsCreated = value;\r
248                         }\r
249                 }\r
250                 protected virtual HttpContext Context //DIT\r
251                 {\r
252                         get\r
253                         {\r
254                                 HttpContext context;\r
255                                 if (_context != null)\r
256                                         return _context;\r
257                                 if (_parent == null)\r
258                                         return HttpContext.Current;\r
259                                 context = _parent.Context;\r
260                                 if (context != null)\r
261                                         return context;\r
262                                 return HttpContext.Current;\r
263                         }\r
264                 }\r
265                 protected EventHandlerList Events //DIT\r
266                 {\r
267                         get\r
268                         {\r
269                                 if (_events == null)\r
270                                 {\r
271                                         _events = new EventHandlerList();\r
272                                 }\r
273                                 return _events;\r
274                         }\r
275                 }\r
276                 protected bool HasChildViewState //DIT\r
277                 {\r
278                         get\r
279                         {\r
280                                 if (_childViewStates == null) return false;\r
281                                 return true;\r
282                         }\r
283                 }\r
284                 protected bool IsTrackingViewState //DIT\r
285                 {\r
286                         get\r
287                         {\r
288                                 return _trackViewState;\r
289                         }\r
290                 }\r
291                 protected virtual StateBag ViewState\r
292                 {\r
293                         get\r
294                         {\r
295                                 if(_viewState == null)\r
296                                 {\r
297                                         _viewState = new StateBag(ViewStateIgnoresCase);\r
298                                 if(IsTrackingViewState)\r
299                                                 _viewState.TrackViewState();\r
300                                 }\r
301                                 return _viewState;\r
302                         }\r
303                 }\r
304                 protected virtual bool ViewStateIgnoresCase //DIT\r
305                 {\r
306                         get\r
307                         {\r
308                                 return true;\r
309                         }\r
310                 }\r
311                 protected virtual void AddParsedSubObject(object obj) //DIT\r
312                 {\r
313                         Control c = (Control)obj;\r
314                         if (c != null) Controls.Add(c);\r
315                 }\r
316                 protected void BuildProfileTree(string parentId, bool calcViewState)\r
317                 {\r
318                         //TODO\r
319                 }\r
320                 protected void ClearChildViewState()\r
321                 {\r
322                         //TODO\r
323                         //Not quite sure about this. an example clears children then calls this, so I think\r
324                         //view state is local to the current object, not children.\r
325                 }\r
326                 protected virtual void CreateChildControls() {} //DIT\r
327                 protected virtual ControlCollection CreateControlCollection() //DIT\r
328                 {\r
329                         return new ControlCollection(this);\r
330                 }\r
331                 protected virtual void EnsureChildControls() //DIT\r
332                 {\r
333                         if (_childControlsCreated == false)\r
334                         {\r
335                                 CreateChildControls();\r
336                                 ChildControlsCreated = true;\r
337                         }\r
338                 }\r
339                 protected virtual Control FindControl(string id, int pathOffset)\r
340                 {\r
341                         //TODO: I think there is Naming Container stuff here. Redo.\r
342                         int i;\r
343                         for (i = pathOffset; i < _controls.Count; i++)\r
344                                 if (_controls[i].ID == id) return _controls[i];\r
345                         return null;\r
346                 }\r
347                 protected virtual void LoadViewState(object savedState)\r
348                 {\r
349                         //TODO: What should I do by default?\r
350                 }\r
351                 \r
352                                 [MonoTODO]\r
353                 protected string MapPathSecure(string virtualPath)\r
354                 {\r
355                         //TODO: Need to read up on security+web.\r
356                         //Return the same path. So AdRotator can read its config file.\r
357                         return virtualPath;\r
358                 }\r
359                 protected virtual bool OnBubbleEvent(object source, EventArgs args) //DIT\r
360                 {\r
361                         return false;\r
362                 }\r
363                 protected virtual void OnDataBinding(EventArgs e) //DIT\r
364                 {\r
365                         if (_events != null)\r
366                         {\r
367                                 EventHandler eh = (EventHandler)(_events[DataBindingEvent]);\r
368                                 if (eh != null) eh(this, e);\r
369                         }\r
370                 }\r
371                 protected virtual void OnInit(EventArgs e) //DIT\r
372                 {\r
373                         if (_events != null)\r
374                         {\r
375                                 EventHandler eh = (EventHandler)(_events[InitEvent]);\r
376                                 if (eh != null) eh(this, e);\r
377                         }\r
378                 }\r
379                 protected virtual void OnLoad(EventArgs e) //DIT\r
380                 {\r
381                         if (_events != null)\r
382                         {\r
383                                 EventHandler eh = (EventHandler)(_events[LoadEvent]);\r
384                                 if (eh != null) eh(this, e);\r
385                         }\r
386                 }\r
387                 protected virtual void OnPreRender(EventArgs e) //DIT\r
388                 {\r
389                         if (_events != null)\r
390                         {\r
391                                 EventHandler eh = (EventHandler)(_events[PreRenderEvent]);\r
392                                 if (eh != null) eh(this, e);\r
393                         }\r
394                 }\r
395                 protected virtual void OnUnload(EventArgs e) //DIT\r
396                 {\r
397                         if (_events != null)\r
398                         {\r
399                                 EventHandler eh = (EventHandler)(_events[UnloadEvent]);\r
400                                 if (eh != null) eh(this, e);\r
401                         }\r
402                 }\r
403                 \r
404                                 [MonoTODO]\r
405                 protected void RaiseBubbleEvent(object source, EventArgs args)\r
406                 {\r
407                         throw new NotImplementedException();\r
408                         //return false;\r
409                 }\r
410                 protected virtual void Render(HtmlTextWriter writer) //DIT\r
411                 {\r
412                         RenderChildren(writer);\r
413                 }\r
414                 protected virtual void RenderChildren(HtmlTextWriter writer) //DIT\r
415                 {\r
416                         if (_renderMethodDelegate != null)\r
417                                 _renderMethodDelegate(writer, this);\r
418                         else if (_controls != null)\r
419                                 foreach (Control c in _controls)\r
420                                         c.RenderControl(writer);\r
421                 }\r
422                 protected virtual object SaveViewState()\r
423                 {\r
424                         return ViewState;\r
425                 }\r
426                 protected virtual void TrackViewState()\r
427                 {\r
428                         _trackViewState = true;\r
429                 }\r
430                 \r
431                                 [MonoTODO]\r
432                 public virtual void Dispose()\r
433                 {\r
434                         //TODO: nuke stuff.\r
435                         throw new NotImplementedException();\r
436                         /*\r
437                         if (_events != null)\r
438                         {\r
439                                 EventHandler eh = (EventHandler)(_events[DisposedEvent]);\r
440                                 if (eh != null) eh(this, e);\r
441                         }\r
442                     */\r
443                 }\r
444 \r
445                 public bool HasChildren\r
446                 {\r
447                         get { return (_controls != null && _controls.Count > 0); }\r
448                 }\r
449 \r
450                 public event EventHandler DataBinding //DIT\r
451                 {\r
452                         add\r
453                         {\r
454                                 Events.AddHandler(DataBindingEvent, value);\r
455                         }\r
456                         remove\r
457                         {\r
458                                 Events.RemoveHandler(DataBindingEvent, value);\r
459                         }\r
460                 }\r
461                 public event EventHandler Disposed //DIT\r
462                 {\r
463                         add\r
464                         {\r
465                                 Events.AddHandler(DisposedEvent, value);\r
466                         }\r
467                         remove\r
468                         {\r
469                                 Events.RemoveHandler(DisposedEvent, value);\r
470                         }\r
471                 }\r
472                 public event EventHandler Init //DIT\r
473                 {\r
474                         add\r
475                         {\r
476                                 Events.AddHandler(InitEvent, value);\r
477                         }\r
478                         remove\r
479                         {\r
480                                 Events.RemoveHandler(InitEvent, value);\r
481                         }\r
482                 }\r
483                 public event EventHandler Load //DIT\r
484                 {\r
485                         add\r
486                         {\r
487                                 Events.AddHandler(LoadEvent, value);\r
488                         }\r
489                         remove\r
490                         {\r
491                                 Events.RemoveHandler(LoadEvent, value);\r
492                         }\r
493                 }\r
494                 public event EventHandler PreRender //DIT\r
495                 {\r
496                         add\r
497                         {\r
498                                 Events.AddHandler(PreRenderEvent, value);\r
499                         }\r
500                         remove\r
501                         {\r
502                                 Events.RemoveHandler(PreRenderEvent, value);\r
503                         }\r
504                 }\r
505                 public event EventHandler Unload //DIT\r
506                 {\r
507                         add\r
508                         {\r
509                                 Events.AddHandler(UnloadEvent, value);\r
510                         }\r
511                         remove\r
512                         {\r
513                                 Events.RemoveHandler(UnloadEvent, value);\r
514                         }\r
515                 }\r
516                 public virtual void DataBind() //DIT\r
517                 {\r
518                         OnDataBinding(EventArgs.Empty);\r
519                         if (_controls != null)\r
520                                 foreach (Control c in _controls)\r
521                                         c.DataBind();\r
522                 }\r
523                 public virtual Control FindControl(string id) //DIT\r
524                 {\r
525                         return FindControl(id, 0);\r
526                 }\r
527                 public virtual bool HasControls() //DIT\r
528                 {\r
529                         if (_controls != null && _controls.Count >0) return true;\r
530                         return false;\r
531                 }\r
532                 public void RenderControl(HtmlTextWriter writer)\r
533                 {\r
534                         if (_visible)\r
535                         {\r
536                                 // By now, PreRender is fired here.\r
537                                 OnPreRender (EventArgs.Empty); //FIXME\r
538                                 //TODO: Something about tracing here.\r
539                                 Render(writer);\r
540                         }\r
541                 }\r
542                 \r
543                 [MonoTODO]\r
544                 public string ResolveUrl(string relativeUrl)\r
545                 {\r
546                         return relativeUrl;\r
547                 }\r
548                 public void SetRenderMethodDelegate(RenderMethod renderMethod) //DIT\r
549                 {\r
550                         _renderMethodDelegate = renderMethod;\r
551                 }\r
552                 protected void LoadRecursive()\r
553                 {\r
554                         OnLoad(EventArgs.Empty);\r
555                         if (_controls != null) foreach (Control c in _controls) c.LoadRecursive();\r
556                 }\r
557                 protected void UnloadRecursive(Boolean dispose)\r
558                 {\r
559                         OnUnload(EventArgs.Empty);\r
560                         if (_controls != null) foreach (Control c in _controls) c.UnloadRecursive(dispose);\r
561                         if (dispose) Dispose();\r
562                 }\r
563                 protected void PreRenderRecursiveInternal()\r
564                 {\r
565                         OnPreRender(EventArgs.Empty);\r
566                         if (_controls != null) foreach (Control c in _controls) c.PreRenderRecursiveInternal();\r
567                 }\r
568                 protected void InitRecursive(Control namingContainer)\r
569                 {\r
570                         if (_controls != null) foreach (Control c in _controls) c.InitRecursive(namingContainer);\r
571                         OnInit(EventArgs.Empty);\r
572                 }\r
573                 \r
574                 [MonoTODO]\r
575                 protected object SaveViewStateRecursive()\r
576                 {\r
577                         throw new NotImplementedException();\r
578                 }\r
579                 \r
580                 [MonoTODO]\r
581                 protected void LoadViewStateRecursive(Object savedState)\r
582                 {\r
583                         throw new NotImplementedException();\r
584                 }\r
585                 \r
586                 void IParserAccessor.AddParsedSubObject(object obj)\r
587                 {\r
588                         this.AddParsedSubObject(obj);\r
589                 }\r
590                 \r
591                 DataBindingCollection IDataBindingsAccessor.DataBindings\r
592                 {\r
593                         get\r
594                         {\r
595                                 if(dataBindings == null)\r
596                                         dataBindings = new DataBindingCollection();\r
597                                 return dataBindings;\r
598                         }\r
599                 }\r
600                 \r
601                 bool IDataBindingsAccessor.HasDataBindings\r
602                 {\r
603                         get\r
604                         {\r
605                                 return (dataBindings!=null && dataBindings.Count>0);\r
606                         }\r
607                 }\r
608                 \r
609                 internal bool AutoID\r
610                 {\r
611                         get { return autoID; }\r
612                         set { autoID = value; }\r
613                 }\r
614 \r
615                 internal void PreventAutoID()\r
616                 {\r
617                         AutoID = false;\r
618                 }\r
619                 \r
620                 //TODO: I think there are some needed Interface implementations to do here.\r
621                 //TODO: Find api for INamingContainer.\r
622         }\r
623 }\r