merge -r 60439:60440
[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                 [MonoTODO]
94                 [WebSysDescription ("")]
95                 [WebCategory ("Behavior")]
96                 public virtual bool CausesValidation 
97                 {
98                         get { return ViewState.GetBool ("CausesValidation", false); }
99                         set { ViewState ["CausesValidation"] = value; }
100                 }
101 #endif          
102                 
103
104                 [DefaultValue (false)]
105 #if NET_2_0
106                 [Bindable (true, BindingDirection.TwoWay)]
107                 [Themeable (false)]
108 #else           
109                 [Bindable (true)]
110 #endif          
111                 [WebSysDescription ("")]
112                 [WebCategory ("Behavior")]
113                 public virtual bool Checked 
114                 {
115                         get {
116                                 return (ViewState.GetBool ("Checked", false));
117                         }
118                         set {
119                                 ViewState["Checked"] = value;
120                         }
121                 }
122
123 #if NET_2_0
124                 [Browsable (false)]
125                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
126                 public AttributeCollection InputAttributes 
127                 {
128                         get {
129                                 if (inputAttributes == null) {
130                                         if (inputAttributesState == null) {
131                                                 inputAttributesState = new StateBag (true);
132                                                 if (IsTrackingViewState)
133                                                         inputAttributesState.TrackViewState();
134                                         }
135                                         inputAttributes = new AttributeCollection (inputAttributesState);
136                                 }
137                                 return inputAttributes;
138                         }
139                 }
140
141                 [Browsable (false)]
142                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
143                 public AttributeCollection LabelAttributes
144                 {
145                         get {
146                                 if (labelAttributes == null) {
147                                         if (labelAttributesState == null) {
148                                                 labelAttributesState = new StateBag (true);
149                                                 if (IsTrackingViewState)
150                                                         labelAttributesState.TrackViewState();
151                                         }
152                                         labelAttributes = new AttributeCollection (labelAttributesState);
153                                 }
154                                 return labelAttributes;
155                         }
156                 }
157 #endif          
158
159                 [DefaultValue ("")]
160                 [Bindable (true)]
161 #if NET_2_0
162                 [Localizable (true)]
163 #endif          
164                 [WebSysDescription ("")]
165                 [WebCategory ("Appearance")]
166                 public virtual string Text 
167                 {
168                         get {
169                                 return (ViewState.GetString ("Text",
170                                                              String.Empty));
171                         }
172                         set {
173                                 ViewState["Text"] = value;
174                         }
175                 }
176
177                 [DefaultValue (TextAlign.Right)]
178 #if ONLY_1_1
179                 [Bindable (true)]
180 #endif          
181                 [WebSysDescription ("")]
182                 [WebCategory ("Appearance")]
183                 public virtual TextAlign TextAlign
184                 {
185                         get { return (TextAlign) ViewState.GetInt ("TextAlign", (int)TextAlign.Right); }
186                         set {
187                                 if (value != TextAlign.Left &&
188                                     value != TextAlign.Right) {
189                                         throw new ArgumentOutOfRangeException ("value");
190                                 }
191                                 
192                                 ViewState["TextAlign"] = value;
193                         }
194                 }
195
196 #if NET_2_0
197                 [Themeable (false)]
198                 [DefaultValue ("")]
199                 [WebSysDescription ("")]
200                 [WebCategoryAttribute ("Behavior")]
201                 public virtual string ValidationGroup
202                 {
203                         get { return ViewState.GetString ("ValidationGroup", String.Empty); }
204                         set { ViewState["ValidationGroup"] = value; }
205                 }
206 #endif          
207
208                 private static readonly object EventCheckedChanged = new object ();
209                 [WebSysDescription ("")]
210                 [WebCategory ("Action")]
211                 public event EventHandler CheckedChanged 
212                 {
213                         add {
214                                 Events.AddHandler (EventCheckedChanged, value);
215                         }
216                         remove {
217                                 Events.RemoveHandler (EventCheckedChanged, value);
218                         }
219                 }
220
221                 protected virtual void OnCheckedChanged (EventArgs e)
222                 {
223                         EventHandler handler = (EventHandler)Events[EventCheckedChanged];
224                         
225                         if (handler != null) {
226                                 handler (this, e);
227                         }
228                 }
229
230                 internal virtual string NameAttribute 
231                 {
232                         get {
233                                 return (this.UniqueID);
234                         }
235                 }
236                 
237 #if NET_2_0
238                 protected override void LoadViewState (object savedState)
239                 {
240                         if (savedState == null) {
241                                 base.LoadViewState (null);
242                                 return;
243                         }
244
245                         Triplet saved = (Triplet) savedState;
246                         base.LoadViewState (saved.First);
247
248                         if (saved.Second != null) {
249                                 if (inputAttributesState == null) {
250                                         inputAttributesState = new StateBag(true);
251                                         inputAttributesState.TrackViewState ();
252                                 }
253                                 inputAttributesState.LoadViewState (saved.Second);
254                         }
255
256                         if (saved.Third != null) {
257                                 if (labelAttributesState == null) {
258                                         labelAttributesState = new StateBag(true);
259                                         labelAttributesState.TrackViewState ();
260                                 }
261                                 labelAttributesState.LoadViewState (saved.Third);
262                         }
263                 }
264
265                 protected override object SaveViewState ()
266                 {
267                         object baseView = base.SaveViewState ();
268                         object inputAttrView = null;
269                         object labelAttrView = null;
270
271                         if (inputAttributesState != null)
272                                 inputAttrView = inputAttributesState.SaveViewState ();
273
274                         if (labelAttributesState != null)
275                                 labelAttrView = labelAttributesState.SaveViewState ();
276
277                         if (baseView == null && inputAttrView == null && labelAttrView == null)
278                                 return null;
279
280                         return new Triplet (baseView, inputAttrView, labelAttrView);            
281                 }
282
283                 protected override void TrackViewState ()
284                 {
285                         base.TrackViewState();
286                         if (inputAttributesState != null)
287                                 inputAttributesState.TrackViewState ();
288                         if (labelAttributesState != null)
289                                 labelAttributesState.TrackViewState ();
290                 }
291 #endif          
292
293 #if NET_2_0
294                 protected internal
295 #else           
296                 protected
297 #endif          
298                 override void OnPreRender (EventArgs e)
299                 {
300                         base.OnPreRender (e);
301
302                         if (Page != null) {
303                                 Page.RegisterRequiresPostBack (this);
304                         }
305                 }
306
307                 static bool IsInputOrCommonAttr (string attname)
308                 {
309                         attname = attname.ToUpper (CultureInfo.InvariantCulture);
310                         switch (attname) {
311                         case "VALUE":
312                         case "CHECKED":
313                         case "SIZE":
314                         case "MAXLENGTH":
315                         case "SRC":
316                         case "ALT":
317                         case "USEMAP":
318                         case "DISABLED":
319                         case "READONLY":
320                         case "ACCEPT":
321                         case "ACCESSKEY":
322                         case "TABINDEX":
323                         case "ONFOCUS":
324                         case "ONBLUR":
325                         case "ONSELECT":
326                         case "ONCHANGE":
327                         case "ONCLICK":
328                         case "ONDBLCLICK":
329                         case "ONMOUSEDOWN":
330                         case "ONMOUSEUP":
331                         case "ONMOUSEOVER":
332                         case "ONMOUSEMOVE":
333                         case "ONMOUSEOUT":
334                         case "ONKEYPRESS":
335                         case "ONKEYDOWN":
336                         case "ONKEYUP":
337                                 return true;
338                         default:
339                                 return false;
340                         }
341                 }
342
343                 void AddAttributesForSpan (HtmlTextWriter writer)
344                 {
345                         ICollection k = Attributes.Keys;
346                         string [] keys = new string [k.Count];
347                         k.CopyTo (keys, 0);
348                         foreach (string key in keys) {
349                                 if (!IsInputOrCommonAttr (key))
350                                         continue;
351                                 if (common_attrs == null)
352                                         common_attrs = new AttributeCollection (new StateBag ());
353                                 common_attrs [key] = Attributes [key];
354                                 Attributes.Remove (key);
355                         }
356                         Attributes.AddAttributes (writer);
357                 }
358 #if NET_2_0
359                 protected internal
360 #else           
361                 protected
362 #endif          
363                 override void Render (HtmlTextWriter w)
364                 {
365                         if (Page != null)
366                                 Page.VerifyRenderingInServerForm (this);
367
368                         bool need_span = ControlStyleCreated && !ControlStyle.IsEmpty;
369                         if (need_span)
370                                 ControlStyle.AddAttributesToRender (w, this);
371
372                         if (!Enabled) {
373                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled");
374                                 need_span = true;
375                         }
376
377                         string tt = ToolTip;
378                         if (tt != ""){
379                                 w.AddAttribute ("title", tt);
380                                 need_span = true;
381                         }
382
383                         if (Attributes.Count > 0){
384                                 AddAttributesForSpan (w);
385                                 Attributes.AddAttributes (w);
386                                 need_span = true;
387                         }
388
389                         if (need_span)
390                                 w.RenderBeginTag (HtmlTextWriterTag.Span);
391
392                         TextAlign align = TextAlign;
393                         if (align == TextAlign.Right) {
394                                 w.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
395                                 w.AddAttribute (HtmlTextWriterAttribute.Type, render_type);
396                                 w.AddAttribute (HtmlTextWriterAttribute.Name, NameAttribute);
397                                 InternalAddAttributesToRender (w);
398                                 if (Checked)
399                                         w.AddAttribute (HtmlTextWriterAttribute.Checked, "checked");
400
401                                 if (AutoPostBack){
402                                         w.AddAttribute (HtmlTextWriterAttribute.Onclick,
403                                                         Page.ClientScript.GetPostBackEventReference (this, String.Empty));
404                                         w.AddAttribute ("language", "javascript");
405                                 }
406
407                                 if (AccessKey.Length > 0)
408                                         w.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
409
410                                 if (TabIndex != 0)
411                                         w.AddAttribute (HtmlTextWriterAttribute.Tabindex,
412                                                              TabIndex.ToString (CultureInfo.InvariantCulture));
413
414                                 if (common_attrs != null)
415                                         common_attrs.AddAttributes (w);
416                                 w.RenderBeginTag (HtmlTextWriterTag.Input);
417                                 w.RenderEndTag ();
418                                 string text = Text;
419                                 if (text != "") {
420 #if NET_2_0
421                                         if (labelAttributes != null)
422                                                 labelAttributes.AddAttributes (w);
423 #endif
424                                         w.AddAttribute (HtmlTextWriterAttribute.For, ClientID);
425                                         w.RenderBeginTag (HtmlTextWriterTag.Label);
426                                         w.Write (text);
427                                         w.RenderEndTag ();
428                                 }
429                         } else {
430                                 string text = Text;
431                                 if (text != "") {
432 #if NET_2_0
433                                         if (labelAttributes != null)
434                                                 labelAttributes.AddAttributes (w);
435 #endif
436                                         w.AddAttribute (HtmlTextWriterAttribute.For, ClientID);
437                                         w.RenderBeginTag (HtmlTextWriterTag.Label);
438                                         w.Write (text);
439                                         w.RenderEndTag ();
440                                 }
441
442                                 w.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
443                                 w.AddAttribute (HtmlTextWriterAttribute.Type, render_type);
444                                 w.AddAttribute (HtmlTextWriterAttribute.Name, NameAttribute);
445                                 InternalAddAttributesToRender (w);
446                                 if (Checked)
447                                         w.AddAttribute (HtmlTextWriterAttribute.Checked, "checked");
448
449                                 if (AutoPostBack){
450                                         w.AddAttribute (HtmlTextWriterAttribute.Onclick,
451                                                         Page.ClientScript.GetPostBackEventReference (this, String.Empty));
452                                         w.AddAttribute ("language", "javascript");
453                                 }
454
455                                 if (AccessKey.Length > 0)
456                                         w.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
457
458                                 if (TabIndex != 0)
459                                         w.AddAttribute (HtmlTextWriterAttribute.Tabindex,
460                                                              TabIndex.ToString (NumberFormatInfo.InvariantInfo));
461
462                                 if (common_attrs != null)
463                                         common_attrs.AddAttributes (w);
464                                 w.RenderBeginTag (HtmlTextWriterTag.Input);
465                                 w.RenderEndTag ();
466                         }
467
468                         if (need_span)
469                                 w.RenderEndTag ();
470                 }
471
472 #if NET_2_0
473                 protected virtual
474 #endif
475                 bool LoadPostData (string postDataKey, NameValueCollection postCollection)
476                 {
477                         string postedValue = postCollection[postDataKey];
478                         bool postedBool = ((postedValue != null) &&
479                                            (postedValue.Length > 0));
480                         
481                         if (Checked != postedBool) {
482                                 Checked = postedBool;
483                                 return (true);
484                         }
485
486                         return (false);
487                 }
488
489 #if NET_2_0
490                 protected virtual
491 #endif
492                 void RaisePostDataChangedEvent ()
493                 {
494 #if NET_2_0
495                         if (CausesValidation)
496                                 Page.Validate (ValidationGroup);
497 #endif
498                         OnCheckedChanged (EventArgs.Empty);
499                 }
500
501                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
502                 {
503                         return LoadPostData (postDataKey, postCollection);
504                 }
505                 
506                 void IPostBackDataHandler.RaisePostDataChangedEvent ()
507                 {
508                         RaisePostDataChangedEvent ();
509                 }
510
511 #if NET_2_0
512                 protected override void AddAttributesToRender (HtmlTextWriter writer)
513                 {
514                         base.AddAttributesToRender (writer);
515                 }
516 #endif
517
518                 internal virtual void InternalAddAttributesToRender (HtmlTextWriter w)
519                 {
520                         if (!Enabled)
521                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled");
522                 }
523         }
524 }