2002-10-29 Gaurav Vaish <gvaish_mono AT lycos.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 //
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                 protected virtual bool DetermineRenderUplevel()
286                 {
287                         Page page = Page;
288                         if(page == null || page.Request == null)
289                         {
290                                 return false;
291                         }
292
293                         if(EnableClientScript)
294                         {
295                                 if(page.Request.Browser.MSDomVersion.Major > 4)
296                                 {
297                                         return page.Request.Browser.EcmaScriptVersion.CompareTo(new Version(1,2)) >= 0;
298                                 }
299                                 return false;
300                         }
301                         return false;
302                 }
303
304                 protected string GetControlRenderID(string name)
305                 {
306                         Control ctrl = FindControl(name);
307                         if(ctrl != null)
308                         {
309                                 return ctrl.ClientID;
310                         }
311                         return String.Empty;
312                 }
313
314                 protected string GetControlValidationValue(string name)
315                 {
316                         Control ctrl = NamingContainer.FindControl(name);
317                         if(ctrl != null)
318                         {
319                                 PropertyDescriptor pd = GetValidationProperty(ctrl);
320                                 if(pd != null)
321                                 {
322                                         object item = pd.GetValue (ctrl);
323                                         if (item is ListItem)
324                                                 return ((ListItem) item).Value;
325
326                                         if (item == null)
327                                                 return String.Empty;
328
329                                         return item.ToString ();
330                                 }
331                         }
332                         return null;
333                 }
334
335                 protected override void OnInit(EventArgs e)
336                 {
337                         base.OnInit(e);
338                         Page.Validators.Add(this);
339                 }
340
341                 protected override void OnPreRender(EventArgs e)
342                 {
343                         base.OnPreRender(e);
344                         isPreRenderCalled   = true;
345                         isPropertiesChecked = false;
346                         renderUplevel       = DetermineRenderUplevel();
347                         if(renderUplevel)
348                         {
349                                 RegisterValidatorCommonScript();
350                         }
351                 }
352
353                 protected override void OnUnload(EventArgs e)
354                 {
355                         if(Page != null)
356                         {
357                                 Page.Validators.Remove(this);
358                         }
359                         base.OnUnload(e);
360                 }
361
362                 [MonoTODO("Damn_This_Is_Really_Frustrating___by_Gaurav")]
363                 protected void RegisterValidatorCommonScript()
364                 {
365                         if(Page.IsClientScriptBlockRegistered("ValidatorIncludeScript"))
366                                 return;
367                         
368                         string jsDirectory = System.Web.UI.Utils.GetScriptLocation(Context);
369                         string jsFile = jsDirectory + "/WebUIValidation.js";
370                         //TODO: Ok, now add the <script language="javascript"> etc
371                         //FIXME: Should I check for 'Explorer'? MS-Net seems to do it!
372                         throw new NotImplementedException();
373                 }
374
375                 [MonoTODO("I_have_to_know_javascript_for_this_I_know_it_but_for_ALL_browsers_NO")]
376                 protected virtual void RegisterValidatorDeclaration()
377                 {
378                         //FIXME: How to make is more abstract?
379                         //Browser Info... but future browsers???
380                         //I'm confused! This will make it work, at least on IE
381                         string val = "document.all[\"" + ClientID;
382                         val += "\"]";
383                         Page.RegisterArrayDeclaration("Page_Validators", val);
384                 }
385
386                 [MonoTODO("Render_ing_always_left")]
387                 protected override void Render (HtmlTextWriter writer)
388                 {
389                         bool valid;
390
391                         if (!Enabled)
392                                 return;
393
394                         if (isPreRenderCalled) {
395                                 valid = IsValid;
396                         } else {
397                                 isPropertiesChecked = true;
398                                 propertiesValid     = true;
399                                 renderUplevel       = false;
400                                 valid               = true;
401                         }
402
403                         if (PropertiesValid) {
404                                 if (Page != null)
405                                         Page.VerifyRenderingInServerForm (this);
406
407                                 ValidatorDisplay dis = Display;
408                                 if (RenderUplevel) {
409                                         //FIXME: as of now, don't do client-side validation
410                                         throw new NotImplementedException();
411                                 }
412                                 
413                                 if (!valid) {
414                                         RenderBeginTag (writer);
415                                         if (Text.Trim ().Length > 0 || HasControls ())
416                                                 RenderContents (writer);
417                                         else
418                                                 writer.Write (ErrorMessage);
419                                         RenderEndTag (writer);
420                                         return;
421                                 }
422                         } else {
423                                 writer.Write ("&nbsp;");
424                         }
425                 }
426
427                 protected abstract bool EvaluateIsValid();
428         }
429 }