2009-07-28 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / CheckBox.cs
1 //
2 // System.Web.UI.WebControls.CheckBox.cs
3 //
4 // Author:
5 //      Dick Porter  <dick@ximian.com>
6 //
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Collections;
30 using System.Collections.Specialized;
31 using System.ComponentModel;
32 using System.Globalization;
33 using System.Security.Permissions;
34
35 namespace System.Web.UI.WebControls {
36         // CAS
37         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
38         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
39         // attributes
40         [Designer ("System.Web.UI.Design.WebControls.CheckBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
41         [DataBindingHandler ("System.Web.UI.Design.TextDataBindingHandler, " + Consts.AssemblySystem_Design)]
42         [DefaultEvent ("CheckedChanged")]
43         [DefaultProperty ("Text")]
44 #if NET_2_0
45         [ControlValueProperty ("Checked", null)]
46         [SupportsEventValidation]
47 #endif          
48         public class CheckBox : WebControl, IPostBackDataHandler
49 #if NET_2_0
50         , ICheckBoxControl
51 #endif
52         {
53                 string render_type;
54                 AttributeCollection common_attrs;
55
56 #if NET_2_0
57                 AttributeCollection inputAttributes;
58                 StateBag inputAttributesState;
59                 AttributeCollection labelAttributes;
60                 StateBag labelAttributesState;
61 #endif
62                 
63                 public CheckBox () : base (HtmlTextWriterTag.Input)
64                 {
65                         render_type = "checkbox";
66                 }
67
68                 internal CheckBox (string render_type) : base (HtmlTextWriterTag.Input)
69                 {
70                         this.render_type = render_type;
71                 }
72
73                 [DefaultValue (false)]
74 #if NET_2_0
75                 [Themeable (false)]
76 #endif          
77                 [WebSysDescription ("")]
78                 [WebCategory ("Behavior")]
79                 public virtual bool AutoPostBack 
80                 {
81                         get {
82                                 return (ViewState.GetBool ("AutoPostBack",
83                                                            false));
84                         }
85                         set {
86                                 ViewState["AutoPostBack"] = value;
87                         }
88                 }
89
90 #if NET_2_0
91                 [DefaultValue (false)]
92                 [Themeable (false)]
93                 [WebSysDescription ("")]
94                 [WebCategory ("Behavior")]
95                 public virtual bool CausesValidation 
96                 {
97                         get { return ViewState.GetBool ("CausesValidation", false); }
98                         set { ViewState ["CausesValidation"] = value; }
99                 }
100 #endif          
101                 
102
103                 [DefaultValue (false)]
104 #if NET_2_0
105                 [Bindable (true, BindingDirection.TwoWay)]
106                 [Themeable (false)]
107 #else           
108                 [Bindable (true)]
109 #endif          
110                 [WebSysDescription ("")]
111                 [WebCategory ("Behavior")]
112                 public virtual bool Checked 
113                 {
114                         get {
115                                 return (ViewState.GetBool ("Checked", false));
116                         }
117                         set {
118                                 ViewState["Checked"] = value;
119                         }
120                 }
121
122 #if NET_2_0
123                 [Browsable (false)]
124                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
125                 public AttributeCollection InputAttributes 
126                 {
127                         get {
128                                 if (inputAttributes == null) {
129                                         if (inputAttributesState == null) {
130                                                 inputAttributesState = new StateBag (true);
131                                                 if (IsTrackingViewState)
132                                                         inputAttributesState.TrackViewState();
133                                         }
134                                         inputAttributes = new AttributeCollection (inputAttributesState);
135                                 }
136                                 return inputAttributes;
137                         }
138                 }
139
140                 [Browsable (false)]
141                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
142                 public AttributeCollection LabelAttributes
143                 {
144                         get {
145                                 if (labelAttributes == null) {
146                                         if (labelAttributesState == null) {
147                                                 labelAttributesState = new StateBag (true);
148                                                 if (IsTrackingViewState)
149                                                         labelAttributesState.TrackViewState();
150                                         }
151                                         labelAttributes = new AttributeCollection (labelAttributesState);
152                                 }
153                                 return labelAttributes;
154                         }
155                 }
156 #endif          
157
158                 [DefaultValue ("")]
159                 [Bindable (true)]
160 #if NET_2_0
161                 [Localizable (true)]
162 #endif          
163                 [WebSysDescription ("")]
164                 [WebCategory ("Appearance")]
165                 public virtual string Text 
166                 {
167                         get {
168                                 return (ViewState.GetString ("Text",
169                                                              String.Empty));
170                         }
171                         set {
172                                 ViewState["Text"] = value;
173                         }
174                 }
175
176                 [DefaultValue (TextAlign.Right)]
177 #if ONLY_1_1
178                 [Bindable (true)]
179 #endif          
180                 [WebSysDescription ("")]
181                 [WebCategory ("Appearance")]
182                 public virtual TextAlign TextAlign
183                 {
184                         get { return (TextAlign) ViewState.GetInt ("TextAlign", (int)TextAlign.Right); }
185                         set {
186                                 if (value != TextAlign.Left &&
187                                     value != TextAlign.Right) {
188                                         throw new ArgumentOutOfRangeException ("value");
189                                 }
190                                 
191                                 ViewState["TextAlign"] = value;
192                         }
193                 }
194
195 #if NET_2_0
196                 [Themeable (false)]
197                 [DefaultValue ("")]
198                 [WebSysDescription ("")]
199                 [WebCategoryAttribute ("Behavior")]
200                 public virtual string ValidationGroup
201                 {
202                         get { return ViewState.GetString ("ValidationGroup", String.Empty); }
203                         set { ViewState["ValidationGroup"] = value; }
204                 }
205 #endif          
206
207                 static readonly object EventCheckedChanged = new object ();
208                 [WebSysDescription ("")]
209                 [WebCategory ("Action")]
210                 public event EventHandler CheckedChanged 
211                 {
212                         add {
213                                 Events.AddHandler (EventCheckedChanged, value);
214                         }
215                         remove {
216                                 Events.RemoveHandler (EventCheckedChanged, value);
217                         }
218                 }
219
220                 protected virtual void OnCheckedChanged (EventArgs e)
221                 {
222                         EventHandler handler = (EventHandler)Events[EventCheckedChanged];
223                         
224                         if (handler != null) {
225                                 handler (this, e);
226                         }
227                 }
228
229                 internal virtual string NameAttribute 
230                 {
231                         get {
232                                 return (this.UniqueID);
233                         }
234                 }
235                 
236 #if NET_2_0
237                 protected override void LoadViewState (object savedState)
238                 {
239                         if (savedState == null) {
240                                 base.LoadViewState (null);
241                                 return;
242                         }
243
244                         Triplet saved = (Triplet) savedState;
245                         base.LoadViewState (saved.First);
246
247                         if (saved.Second != null) {
248                                 if (inputAttributesState == null) {
249                                         inputAttributesState = new StateBag(true);
250                                         inputAttributesState.TrackViewState ();
251                                 }
252                                 inputAttributesState.LoadViewState (saved.Second);
253                         }
254
255                         if (saved.Third != null) {
256                                 if (labelAttributesState == null) {
257                                         labelAttributesState = new StateBag(true);
258                                         labelAttributesState.TrackViewState ();
259                                 }
260                                 labelAttributesState.LoadViewState (saved.Third);
261                         }
262                 }
263
264                 protected override object SaveViewState ()
265                 {
266                         object baseView = base.SaveViewState ();
267                         object inputAttrView = null;
268                         object labelAttrView = null;
269
270                         if (inputAttributesState != null)
271                                 inputAttrView = inputAttributesState.SaveViewState ();
272
273                         if (labelAttributesState != null)
274                                 labelAttrView = labelAttributesState.SaveViewState ();
275
276                         if (baseView == null && inputAttrView == null && labelAttrView == null)
277                                 return null;
278
279                         return new Triplet (baseView, inputAttrView, labelAttrView);            
280                 }
281
282                 protected override void TrackViewState ()
283                 {
284                         base.TrackViewState();
285                         if (inputAttributesState != null)
286                                 inputAttributesState.TrackViewState ();
287                         if (labelAttributesState != null)
288                                 labelAttributesState.TrackViewState ();
289                 }
290 #endif          
291
292 #if NET_2_0
293                 protected internal
294 #else           
295                 protected
296 #endif          
297                 override void OnPreRender (EventArgs e)
298                 {
299                         base.OnPreRender (e);
300                         Page page = Page;
301                         bool enabled = Enabled;
302                         
303                         if (page != null && enabled) {
304                                 page.RegisterRequiresPostBack (this);
305                         }
306 #if NET_2_0
307                         if (Page != null && enabled)
308                                 page.RegisterEnabledControl (this);
309 #endif
310                 }
311
312                 static bool IsInputOrCommonAttr (string attname)
313                 {
314                         attname = attname.ToUpper (CultureInfo.InvariantCulture);
315                         switch (attname) {
316                         case "VALUE":
317                         case "CHECKED":
318                         case "SIZE":
319                         case "MAXLENGTH":
320                         case "SRC":
321                         case "ALT":
322                         case "USEMAP":
323                         case "DISABLED":
324                         case "READONLY":
325                         case "ACCEPT":
326                         case "ACCESSKEY":
327                         case "TABINDEX":
328                         case "ONFOCUS":
329                         case "ONBLUR":
330                         case "ONSELECT":
331                         case "ONCHANGE":
332                         case "ONCLICK":
333                         case "ONDBLCLICK":
334                         case "ONMOUSEDOWN":
335                         case "ONMOUSEUP":
336                         case "ONMOUSEOVER":
337                         case "ONMOUSEMOVE":
338                         case "ONMOUSEOUT":
339                         case "ONKEYPRESS":
340                         case "ONKEYDOWN":
341                         case "ONKEYUP":
342                                 return true;
343                         default:
344                                 return false;
345                         }
346                 }
347
348                 bool AddAttributesForSpan (HtmlTextWriter writer)
349                 {
350                         ICollection k = Attributes.Keys;
351                         string [] keys = new string [k.Count];
352                         k.CopyTo (keys, 0);
353                         foreach (string key in keys) {
354                                 if (!IsInputOrCommonAttr (key))
355                                         continue;
356                                 if (common_attrs == null)
357                                         common_attrs = new AttributeCollection (new StateBag ());
358                                 common_attrs [key] = Attributes [key];
359                                 Attributes.Remove (key);
360                         }
361                         if (Attributes.Count > 0) {
362                                 Attributes.AddAttributes (writer);
363                                 return true;
364                         }
365                         return false;
366                 }
367 #if NET_2_0
368                 protected internal
369 #else           
370                 protected
371 #endif          
372                 override void Render (HtmlTextWriter w)
373                 {
374                         Page page = Page;
375                         if (page != null) {
376                                 page.VerifyRenderingInServerForm (this);
377 #if NET_2_0
378                                 page.ClientScript.RegisterForEventValidation (UniqueID);
379 #endif
380                         }
381                         
382                         bool need_span = ControlStyleCreated && !ControlStyle.IsEmpty;
383                         if (need_span) {
384 #if NET_2_0
385                                 AddDisplayStyleAttribute (w);
386 #endif
387                                 ControlStyle.AddAttributesToRender (w, this);
388                         }
389
390                         if (!Enabled) {
391                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
392                                 need_span = true;
393                         }
394
395                         string tt = ToolTip;
396                         if (tt != null && tt.Length > 0){
397                                 w.AddAttribute ("title", tt);
398                                 need_span = true;
399                         }
400
401 #if NET_2_0
402                         if (HasAttributes && AddAttributesForSpan (w))
403                                 need_span = true;
404 #else
405                         if (Attributes.Count > 0 && AddAttributesForSpan (w))
406                                 need_span = true;
407 #endif
408
409                         if (need_span)
410                                 w.RenderBeginTag (HtmlTextWriterTag.Span);
411
412                         TextAlign align = TextAlign;
413                         if (align == TextAlign.Right) {
414                                 RenderInput (w);
415                                 RenderLabel (w);
416                         } else {
417                                 RenderLabel (w);
418                                 RenderInput (w);
419                         }
420
421                         if (need_span)
422                                 w.RenderEndTag ();
423                 }
424
425                 void RenderInput (HtmlTextWriter w) {
426
427                         if (ClientID != null && ClientID.Length > 0)
428                                 w.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
429                         w.AddAttribute (HtmlTextWriterAttribute.Type, render_type);
430                         string nameAttr = NameAttribute;
431                         if (nameAttr != null && nameAttr.Length > 0)
432                                 w.AddAttribute (HtmlTextWriterAttribute.Name, nameAttr);
433                         InternalAddAttributesToRender (w);
434 #if NET_2_0
435                         AddAttributesToRender (w);
436                         if (inputAttributes != null)
437                                 inputAttributes.AddAttributes (w);
438 #endif
439                         if (Checked)
440                                 w.AddAttribute (HtmlTextWriterAttribute.Checked, "checked", false);
441
442                         if (AutoPostBack) {
443 #if NET_2_0
444                                 string onclick = Page.ClientScript.GetPostBackEventReference (GetPostBackOptions (), true);
445                                 onclick = String.Concat ("setTimeout('", onclick.Replace ("\\", "\\\\").Replace ("'", "\\'"), "', 0)");
446                                 w.AddAttribute (HtmlTextWriterAttribute.Onclick, BuildScriptAttribute ("onclick", onclick));
447 #else
448                                         w.AddAttribute (HtmlTextWriterAttribute.Onclick,
449                                                         BuildScriptAttribute ("onclick", Page.ClientScript.GetPostBackEventReference (this, String.Empty)));
450                                         w.AddAttribute ("language", "javascript", false);
451 #endif
452                         }
453
454                         if (AccessKey.Length > 0)
455                                 w.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
456
457                         if (TabIndex != 0)
458                                 w.AddAttribute (HtmlTextWriterAttribute.Tabindex,
459                                                          TabIndex.ToString (NumberFormatInfo.InvariantInfo));
460
461                         if (common_attrs != null)
462                                 common_attrs.AddAttributes (w);
463                         w.RenderBeginTag (HtmlTextWriterTag.Input);
464                         w.RenderEndTag ();
465                 }
466
467                 void RenderLabel (HtmlTextWriter w) {
468                         string text = Text;
469                         if (text.Length > 0) {
470 #if NET_2_0
471                                 if (labelAttributes != null)
472                                         labelAttributes.AddAttributes (w);
473 #endif
474                                 w.AddAttribute (HtmlTextWriterAttribute.For, ClientID);
475                                 w.RenderBeginTag (HtmlTextWriterTag.Label);
476                                 w.Write (text);
477                                 w.RenderEndTag ();
478                         }
479                 }
480
481 #if NET_2_0
482                 protected virtual
483 #endif
484                 bool LoadPostData (string postDataKey, NameValueCollection postCollection)
485                 {
486                         if (!Enabled)
487                                 return false;
488
489                         string postedValue = postCollection[postDataKey];
490                         bool postedBool = ((postedValue != null) &&
491                                            (postedValue.Length > 0));
492                         
493                         if (Checked != postedBool) {
494                                 Checked = postedBool;
495                                 return (true);
496                         }
497
498                         return (false);
499                 }
500
501 #if NET_2_0
502                 protected virtual
503 #endif
504                 void RaisePostDataChangedEvent ()
505                 {
506 #if NET_2_0
507                         ValidateEvent (UniqueID, String.Empty);
508                         if (CausesValidation)
509                                 Page.Validate (ValidationGroup);
510 #endif
511                         OnCheckedChanged (EventArgs.Empty);
512                 }
513
514                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
515                 {
516                         return LoadPostData (postDataKey, postCollection);
517                 }
518                 
519                 void IPostBackDataHandler.RaisePostDataChangedEvent ()
520                 {
521                         RaisePostDataChangedEvent ();
522                 }
523
524 #if NET_2_0
525                 PostBackOptions GetPostBackOptions () {
526                         PostBackOptions options = new PostBackOptions (this);
527                         options.ActionUrl = null;
528                         options.ValidationGroup = null;
529                         options.Argument = String.Empty;
530                         options.RequiresJavaScriptProtocol = false;
531                         options.ClientSubmit = true;
532                         options.PerformValidation = CausesValidation && Page != null && Page.AreValidatorsUplevel (ValidationGroup);
533                         if (options.PerformValidation)
534                                 options.ValidationGroup = ValidationGroup;
535
536                         return options;
537                 }
538
539                 protected override void AddAttributesToRender (HtmlTextWriter writer)
540                 {
541                 }
542 #endif
543
544                 internal virtual void InternalAddAttributesToRender (HtmlTextWriter w)
545                 {
546                         if (!Enabled)
547                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
548                 }
549         }
550 }