2006-12-07 Igor Zelmanovich <igorz@mainsoft.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                 private 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
301                         if (Page != null) {
302                                 Page.RegisterRequiresPostBack (this);
303                         }
304                 }
305
306                 static bool IsInputOrCommonAttr (string attname)
307                 {
308                         attname = attname.ToUpper (CultureInfo.InvariantCulture);
309                         switch (attname) {
310                         case "VALUE":
311                         case "CHECKED":
312                         case "SIZE":
313                         case "MAXLENGTH":
314                         case "SRC":
315                         case "ALT":
316                         case "USEMAP":
317                         case "DISABLED":
318                         case "READONLY":
319                         case "ACCEPT":
320                         case "ACCESSKEY":
321                         case "TABINDEX":
322                         case "ONFOCUS":
323                         case "ONBLUR":
324                         case "ONSELECT":
325                         case "ONCHANGE":
326                         case "ONCLICK":
327                         case "ONDBLCLICK":
328                         case "ONMOUSEDOWN":
329                         case "ONMOUSEUP":
330                         case "ONMOUSEOVER":
331                         case "ONMOUSEMOVE":
332                         case "ONMOUSEOUT":
333                         case "ONKEYPRESS":
334                         case "ONKEYDOWN":
335                         case "ONKEYUP":
336                                 return true;
337                         default:
338                                 return false;
339                         }
340                 }
341
342                 void AddAttributesForSpan (HtmlTextWriter writer)
343                 {
344                         ICollection k = Attributes.Keys;
345                         string [] keys = new string [k.Count];
346                         k.CopyTo (keys, 0);
347                         foreach (string key in keys) {
348                                 if (!IsInputOrCommonAttr (key))
349                                         continue;
350                                 if (common_attrs == null)
351                                         common_attrs = new AttributeCollection (new StateBag ());
352                                 common_attrs [key] = Attributes [key];
353                                 Attributes.Remove (key);
354                         }
355                         Attributes.AddAttributes (writer);
356                 }
357 #if NET_2_0
358                 protected internal
359 #else           
360                 protected
361 #endif          
362                 override void Render (HtmlTextWriter w)
363                 {
364                         if (Page != null)
365                                 Page.VerifyRenderingInServerForm (this);
366                         
367                         bool need_span = ControlStyleCreated && !ControlStyle.IsEmpty;
368                         if (need_span)
369                                 ControlStyle.AddAttributesToRender (w, this);
370
371                         if (!Enabled) {
372                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled");
373                                 need_span = true;
374                         }
375
376                         string tt = ToolTip;
377                         if (tt != ""){
378                                 w.AddAttribute ("title", tt);
379                                 need_span = true;
380                         }
381
382                         if (Attributes.Count > 0){
383                                 AddAttributesForSpan (w);
384                                 need_span = true;
385                         }
386
387                         if (need_span)
388                                 w.RenderBeginTag (HtmlTextWriterTag.Span);
389
390                         TextAlign align = TextAlign;
391                         if (align == TextAlign.Right) {
392                                 RenderInput (w);
393                                 RenderLabel (w);
394                         } else {
395                                 RenderLabel (w);
396                                 RenderInput (w);
397                         }
398
399                         if (need_span)
400                                 w.RenderEndTag ();
401                 }
402
403                 private void RenderInput (HtmlTextWriter w) {
404
405                         if (ClientID != null && ClientID.Length > 0)
406                                 w.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
407                         w.AddAttribute (HtmlTextWriterAttribute.Type, render_type);
408                         string nameAttr = NameAttribute;
409                         if (nameAttr != null && nameAttr.Length > 0)
410                                 w.AddAttribute (HtmlTextWriterAttribute.Name, nameAttr);
411                         InternalAddAttributesToRender (w);
412 #if NET_2_0
413                         AddAttributesToRender (w);
414                         if (inputAttributes != null)
415                                 inputAttributes.AddAttributes (w);
416 #endif
417                         if (Checked)
418                                 w.AddAttribute (HtmlTextWriterAttribute.Checked, "checked");
419
420                         if (AutoPostBack) {
421 #if NET_2_0
422                                 w.AddAttribute (HtmlTextWriterAttribute.Onclick, Page.ClientScript.GetPostBackEventReference (GetPostBackOptions (), true));
423 #else
424                                         w.AddAttribute (HtmlTextWriterAttribute.Onclick,
425                                                         Page.ClientScript.GetPostBackEventReference (this, String.Empty));
426 #endif
427                                 w.AddAttribute ("language", "javascript");
428                         }
429
430                         if (AccessKey.Length > 0)
431                                 w.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
432
433                         if (TabIndex != 0)
434                                 w.AddAttribute (HtmlTextWriterAttribute.Tabindex,
435                                                          TabIndex.ToString (NumberFormatInfo.InvariantInfo));
436
437                         if (common_attrs != null)
438                                 common_attrs.AddAttributes (w);
439                         w.RenderBeginTag (HtmlTextWriterTag.Input);
440                         w.RenderEndTag ();
441                 }
442
443                 private void RenderLabel (HtmlTextWriter w) {
444                         string text = Text;
445                         if (text.Length > 0) {
446 #if NET_2_0
447                                 if (labelAttributes != null)
448                                         labelAttributes.AddAttributes (w);
449 #endif
450                                 w.AddAttribute (HtmlTextWriterAttribute.For, ClientID);
451                                 w.RenderBeginTag (HtmlTextWriterTag.Label);
452                                 w.Write (text);
453                                 w.RenderEndTag ();
454                         }
455                 }
456
457 #if NET_2_0
458                 protected virtual
459 #endif
460                 bool LoadPostData (string postDataKey, NameValueCollection postCollection)
461                 {
462                         if (!Enabled)
463                                 return false;
464
465                         string postedValue = postCollection[postDataKey];
466                         bool postedBool = ((postedValue != null) &&
467                                            (postedValue.Length > 0));
468                         
469                         if (Checked != postedBool) {
470                                 Checked = postedBool;
471                                 return (true);
472                         }
473
474                         return (false);
475                 }
476
477 #if NET_2_0
478                 protected virtual
479 #endif
480                 void RaisePostDataChangedEvent ()
481                 {
482 #if NET_2_0
483                         if (CausesValidation)
484                                 Page.Validate (ValidationGroup);
485 #endif
486                         OnCheckedChanged (EventArgs.Empty);
487                 }
488
489                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
490                 {
491                         return LoadPostData (postDataKey, postCollection);
492                 }
493                 
494                 void IPostBackDataHandler.RaisePostDataChangedEvent ()
495                 {
496                         RaisePostDataChangedEvent ();
497                 }
498
499 #if NET_2_0
500                 PostBackOptions GetPostBackOptions () {
501                         PostBackOptions options = new PostBackOptions (this);
502                         options.ActionUrl = null;
503                         options.ValidationGroup = null;
504                         options.Argument = "";
505                         options.RequiresJavaScriptProtocol = false;
506                         options.ClientSubmit = true;
507                         options.PerformValidation = CausesValidation && Page != null && Page.AreValidatorsUplevel (ValidationGroup);
508                         if (options.PerformValidation)
509                                 options.ValidationGroup = ValidationGroup;
510
511                         return options;
512                 }
513
514                 protected override void AddAttributesToRender (HtmlTextWriter writer)
515                 {
516                 }
517 #endif
518
519                 internal virtual void InternalAddAttributesToRender (HtmlTextWriter w)
520                 {
521                         if (!Enabled)
522                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled");
523                 }
524         }
525 }