2003-08-01 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / BaseValidator.cs
1 //
2 // System.Web.UI.WebControls.BaseValidator.cs
3 //
4 // Authors:
5 //   Gaurav Vaish (gvaish@iitk.ac.in)
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //
9 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
10 // (C) Gaurav Vaish (2002)
11 // (C) 2003 Andreas Nahr
12 //\r
13
14 using System;
15 using System.ComponentModel;
16 using System.ComponentModel.Design;
17 using System.Web;
18 using System.Web.UI;
19 using System.Drawing;
20
21 namespace System.Web.UI.WebControls
22 {
23         [DefaultProperty("ErrorMessage")]
24         [Designer ("System.Web.UI.Design.WebControls.BaseValidatorDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
25         public abstract class BaseValidator: Label, IValidator
26         {
27                 private bool isValid;
28                 private bool isPreRenderCalled;
29                 private bool isPropertiesChecked;
30                 private bool propertiesValid;
31                 private bool renderUplevel;
32
33                 protected BaseValidator() : base()
34                 {
35                         isValid = true;
36                         ForeColor = Color.Red;
37                         propertiesValid = true;
38                         isPropertiesChecked = false;
39                         renderUplevel = false;
40                 }
41
42                 [DefaultValue (""), WebCategory ("Behavior")]
43                 [TypeConverter (typeof (ValidatedControlConverter))]
44                 [WebSysDescription ("The ID of the control to validate.")]
45                 public string ControlToValidate
46                 {
47                         get
48                         {
49                                 object o = ViewState["ControlToValidate"];
50                                 if(o != null)
51                                 {
52                                         return (string)o;
53                                 }
54                                 return String.Empty;
55                         }
56                         set
57                         {
58                                 ViewState["ControlToValidate"] = value;
59                         }
60                 }
61
62                 [DefaultValue (typeof (ValidatorDisplay), "Static"), Bindable (true), WebCategory ("Appearance")]
63                 [WebSysDescription ("Determines how the validator is displayed.")]
64                 public ValidatorDisplay Display
65                 {
66                         get
67                         {
68                                 object o = ViewState["Display"];
69                                 if(o != null)
70                                 {
71                                         return (ValidatorDisplay)o;
72                                 }
73                                 return ValidatorDisplay.Static;
74                         }
75                         set
76                         {
77                                 if(!Enum.IsDefined(typeof(ValidatorDisplay), value))
78                                 {
79                                         throw new ArgumentException();
80                                 }
81                                 ViewState["ValidatorDisplay"] = value;
82                         }
83                 }
84
85                 [DefaultValue (true), WebCategory ("Behavior")]
86                 [WebSysDescription ("Determines if client script is activated on uplevel browsers.")]
87                 public bool EnableClientScript
88                 {
89                         get
90                         {
91                                 object o = ViewState["EnableClientScript"];
92                                 if(o != null)
93                                 {
94                                         return (bool)o;
95                                 }
96                                 return true;
97                         }
98                         set
99                         {
100                                 ViewState["EnableClientScript"] = value;
101                         }
102                 }
103
104                 public override bool Enabled
105                 {
106                         get
107                         {
108                                 return base.Enabled;
109                         }
110                         set
111                         {
112                                 if (value == false)
113                                         isValid = true;
114                                 base.Enabled = value;
115                         }
116                 }
117
118                 [DefaultValue (""), Bindable (true), WebCategory ("Appearance")]
119                 [WebSysDescription ("An error message that is displayed if the control validates to false.")]
120                 public string ErrorMessage
121                 {
122                         get
123                         {
124                                 object o = ViewState["ErrorMessage"];
125                                 if(o != null)
126                                 {
127                                         return (string)o;
128                                 }
129                                 return String.Empty;
130                         }
131                         set
132                         {
133                                 ViewState["ErrorMessage"] = value;
134                         }
135                 }
136
137                 [DefaultValue (null)]
138                 public override Color ForeColor
139                 {
140                         get
141                         {
142                                 return base.ForeColor;
143                         }
144                         set
145                         {
146                                 base.ForeColor = value;
147                         }
148                 }
149
150                 [DefaultValue (true), Browsable (false), WebCategory ("Misc")]
151                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
152                 [WebSysDescription ("Indicates if the control validated to false.")]
153                 public bool IsValid
154                 {
155                         get { return isValid; }
156                         set { isValid = value; }
157                 }
158
159                 public static PropertyDescriptor GetValidationProperty(object component)
160                 {
161                         System.ComponentModel.AttributeCollection coll = TypeDescriptor.GetAttributes (component);
162                         Type type = typeof (ValidationPropertyAttribute);
163                         ValidationPropertyAttribute attrib = (ValidationPropertyAttribute) coll [type];
164                         if (attrib != null && attrib.Name != null)
165                                 return (TypeDescriptor.GetProperties (component)) [attrib.Name];
166                         return null;
167                 }
168
169                 public void Validate()
170                 {
171                         if(!Visible || (Visible && !Enabled))
172                         {
173                                 IsValid = true;
174                         }
175                         Control ctrl = Parent;
176                         while(ctrl != null)
177                         {
178                                 if(!ctrl.Visible)
179                                 {
180                                         IsValid = true;
181                                         return;
182                                 }
183                                 ctrl = ctrl.Parent;
184                         }
185                         isPropertiesChecked = false;
186                         if(!PropertiesValid)
187                         {
188                                 IsValid = true;
189                                 return;
190                         }
191                         IsValid = EvaluateIsValid();
192                 }
193
194                 protected bool PropertiesValid
195                 {
196                         get
197                         {
198                                 if(!isPropertiesChecked)
199                                 {
200                                         propertiesValid = ControlPropertiesValid();
201                                         isPropertiesChecked = true;
202                                 }
203                                 return propertiesValid;
204                         }
205                 }
206
207                 protected bool RenderUplevel
208                 {
209                         get
210                         {
211                                 return renderUplevel;
212                         }
213                 }
214
215                 protected override void AddAttributesToRender(HtmlTextWriter writer)
216                 {
217                         bool enabled = base.Enabled;
218                         if (enabled)
219                                 Enabled = true;
220
221                         base.AddAttributesToRender(writer);
222                         if(RenderUplevel)
223                         {
224                                 if(ID == null)
225                                 {
226                                         writer.AddAttribute("id", ClientID);
227                                 }
228                                 if(ControlToValidate.Length > 0)
229                                 {
230                                         writer.AddAttribute("controltovalidate", GetControlRenderID(ControlToValidate));
231                                 }
232                                 if(ErrorMessage.Length > 0)
233                                 {
234                                         writer.AddAttribute("errormessage", ErrorMessage, true);
235                                 }
236                                 if(Display == ValidatorDisplay.Static)
237                                 {
238                                         writer.AddAttribute("display", Enum.Format(typeof(ValidatorDisplay), Display, "G").Replace('_','-'));
239                                         //writer.AddAttribute("display", PropertyConverter.EnumToString(typeof(ValidatorDisplay), Display));
240                                 }
241                                 if(!IsValid)
242                                 {
243                                         writer.AddAttribute("isvalid", "False");
244                                 }
245
246                                 ControlStyle.AddAttributesToRender (writer, this);
247                                 if(!enabled)
248                                 {
249                                         writer.AddAttribute("enabled", "False");
250                                 }
251                         }
252
253                         if(enabled)
254                         {
255                                 Enabled = false;
256                         }
257                 }
258
259                 protected void CheckControlValidationProperty(string name, string propertyName)
260                 {
261                         Control ctrl = NamingContainer.FindControl(name);
262                         if(ctrl == null)
263                         {
264                                 throw new HttpException(HttpRuntime.FormatResourceString("Validator_control_not_found",
265                                                  name, propertyName/*, ID*/));
266                         }
267                         PropertyDescriptor pd = GetValidationProperty(ctrl);
268                         if(pd == null)
269                         {
270                                 throw new HttpException(HttpRuntime.FormatResourceString("Validator_bad_control_type",
271                                                  name, propertyName/*, ID*/));
272                         }
273                 }
274
275                 protected virtual bool ControlPropertiesValid()
276                 {
277                         if(ControlToValidate.Length == 0)
278                         {
279                                 throw new HttpException(HttpRuntime.FormatResourceString("Validator_control_blank", ID));
280                         }
281                         CheckControlValidationProperty(ControlToValidate, "ControlToValidate");
282                         return true;
283                 }
284
285                 [MonoTODO]
286                 protected virtual bool DetermineRenderUplevel()
287                 {
288                         Page page = Page;
289                         if(page == null || page.Request == null)
290                         {
291                                 return false;
292                         }
293
294                         if(EnableClientScript)
295                         {
296                                 // By now, return false
297                                 return false;
298                                 //throw new NotImplementedException();
299                                 ////TODO: I need to get the (Browser->Dom_version_major >= 4 &&
300                                 ////                         Brower->Ecma_script_version >= 1.2)
301                         }
302                         return false;
303                 }
304
305                 protected string GetControlRenderID(string name)
306                 {
307                         Control ctrl = FindControl(name);
308                         if(ctrl != null)
309                         {
310                                 return ctrl.ClientID;
311                         }
312                         return String.Empty;
313                 }
314
315                 protected string GetControlValidationValue(string name)
316                 {
317                         Control ctrl = NamingContainer.FindControl(name);
318                         if(ctrl != null)
319                         {
320                                 PropertyDescriptor pd = GetValidationProperty(ctrl);
321                                 if(pd != null)
322                                 {
323                                         object item = pd.GetValue (ctrl);
324                                         if (item is ListItem)
325                                                 return ((ListItem) item).Value;
326
327                                         if (item == null)
328                                                 return String.Empty;
329
330                                         return item.ToString ();
331                                 }
332                         }
333                         return null;
334                 }
335
336                 protected override void OnInit(EventArgs e)
337                 {
338                         base.OnInit(e);
339                         Page.Validators.Add(this);
340                 }
341
342                 protected override void OnPreRender(EventArgs e)
343                 {
344                         base.OnPreRender(e);
345                         isPreRenderCalled   = true;
346                         isPropertiesChecked = false;
347                         renderUplevel       = DetermineRenderUplevel();
348                         if(renderUplevel)
349                         {
350                                 RegisterValidatorCommonScript();
351                         }
352                 }
353
354                 protected override void OnUnload(EventArgs e)
355                 {
356                         if(Page != null)
357                         {
358                                 Page.Validators.Remove(this);
359                         }
360                         base.OnUnload(e);
361                 }
362
363                 [MonoTODO("Damn_This_Is_Really_Frustrating___by_Gaurav")]
364                 protected void RegisterValidatorCommonScript()
365                 {
366                         if(Page.IsClientScriptBlockRegistered("ValidatorIncludeScript"))
367                                 return;
368                         
369                         throw new NotImplementedException();
370                 }
371
372                 [MonoTODO("I_have_to_know_javascript_for_this_I_know_it_but_for_ALL_browsers_NO")]
373                 protected virtual void RegisterValidatorDeclaration()
374                 {
375                         throw new NotImplementedException();
376                         //TODO: Since I have to access document.<ClientID> and register
377                         // as page validator. Now this is Browser dependent :((
378
379                         // This does not render anything on Mozilla, and does on IE
380                 }
381
382                 [MonoTODO("Render_ing_always_left")]
383                 protected override void Render (HtmlTextWriter writer)
384                 {
385                         bool valid;
386
387                         if (!Enabled)
388                                 return;
389
390                         if (isPreRenderCalled) {
391                                 valid = IsValid;
392                         } else {
393                                 isPropertiesChecked = true;
394                                 propertiesValid     = true;
395                                 renderUplevel       = false;
396                                 valid               = true;
397                         }
398
399                         if (PropertiesValid) {
400                                 if (Page != null)
401                                         Page.VerifyRenderingInServerForm (this);
402
403                                 ValidatorDisplay dis = Display;
404                                 if (RenderUplevel) {
405                                         //FIXME: as of now, don't do client-side validation
406                                         throw new NotImplementedException();
407                                 }
408                                 
409                                 if (!valid) {
410                                         RenderBeginTag (writer);
411                                         if (Text.Trim ().Length > 0 || HasControls ()) {
412                                                 RenderContents (writer);
413                                                 RenderEndTag (writer);
414                                         } else {
415                                                 writer.Write (ErrorMessage);
416                                         }
417                                         RenderEndTag (writer);
418                                         return;
419                                 }
420                         } else {
421                                 writer.Write ("&nbsp;");
422                         }
423                 }
424
425                 protected abstract bool EvaluateIsValid();
426         }
427 }