0169ffa1e7a4687082cb8faff827ecb53c61784a
[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-2010 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 using System.Web.Util;
35
36 namespace System.Web.UI.WebControls
37 {
38         // CAS
39         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
40         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
41         // attributes
42         [Designer ("System.Web.UI.Design.WebControls.CheckBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43         [DataBindingHandler ("System.Web.UI.Design.TextDataBindingHandler, " + Consts.AssemblySystem_Design)]
44         [DefaultEvent ("CheckedChanged")]
45         [DefaultProperty ("Text")]
46         [ControlValueProperty ("Checked", null)]
47         [SupportsEventValidation]
48         public class CheckBox : WebControl, IPostBackDataHandler, ICheckBoxControl
49         {
50                 string render_type;
51                 AttributeCollection common_attrs;
52                 AttributeCollection inputAttributes;
53                 StateBag inputAttributesState;
54                 AttributeCollection labelAttributes;
55                 StateBag labelAttributesState;
56                 
57                 public CheckBox () : base (HtmlTextWriterTag.Input)
58                 {
59                         render_type = "checkbox";
60                 }
61
62                 internal CheckBox (string render_type) : base (HtmlTextWriterTag.Input)
63                 {
64                         this.render_type = render_type;
65                 }
66
67                 [DefaultValue (false)]
68                 [Themeable (false)]
69                 [WebSysDescription ("")]
70                 [WebCategory ("Behavior")]
71                 public virtual bool AutoPostBack {
72                         get { return (ViewState.GetBool ("AutoPostBack", false)); }
73                         set { ViewState["AutoPostBack"] = value; }
74                 }
75
76                 [DefaultValue (false)]
77                 [Themeable (false)]
78                 [WebSysDescription ("")]
79                 [WebCategory ("Behavior")]
80                 public virtual bool CausesValidation {
81                         get { return ViewState.GetBool ("CausesValidation", false); }
82                         set { ViewState ["CausesValidation"] = value; }
83                 }
84
85                 [DefaultValue (false)]
86                 [Bindable (true, BindingDirection.TwoWay)]
87                 [Themeable (false)]
88                 [WebSysDescription ("")]
89                 [WebCategory ("Behavior")]
90                 public virtual bool Checked {
91                         get { return (ViewState.GetBool ("Checked", false)); }
92                         set { ViewState["Checked"] = value; }
93                 }
94
95                 [Browsable (false)]
96                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
97                 public AttributeCollection InputAttributes {
98                         get {
99                                 if (inputAttributes == null) {
100                                         if (inputAttributesState == null) {
101                                                 inputAttributesState = new StateBag (true);
102                                                 if (IsTrackingViewState)
103                                                         inputAttributesState.TrackViewState();
104                                         }
105                                         inputAttributes = new AttributeCollection (inputAttributesState);
106                                 }
107                                 return inputAttributes;
108                         }
109                 }
110
111                 [Browsable (false)]
112                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
113                 public AttributeCollection LabelAttributes {
114                         get {
115                                 if (labelAttributes == null) {
116                                         if (labelAttributesState == null) {
117                                                 labelAttributesState = new StateBag (true);
118                                                 if (IsTrackingViewState)
119                                                         labelAttributesState.TrackViewState();
120                                         }
121                                         labelAttributes = new AttributeCollection (labelAttributesState);
122                                 }
123                                 return labelAttributes;
124                         }
125                 }
126
127                 [DefaultValue ("")]
128                 [Bindable (true)]
129                 [Localizable (true)]
130                 [WebSysDescription ("")]
131                 [WebCategory ("Appearance")]
132                 public virtual string Text {
133                         get { return (ViewState.GetString ("Text", String.Empty)); }
134                         set { ViewState["Text"] = value; }
135                 }
136
137                 [DefaultValue (TextAlign.Right)]
138                 [WebSysDescription ("")]
139                 [WebCategory ("Appearance")]
140                 public virtual TextAlign TextAlign {
141                         get { return (TextAlign) ViewState.GetInt ("TextAlign", (int)TextAlign.Right); }
142                         set {
143                                 if (value != TextAlign.Left &&
144                                     value != TextAlign.Right) {
145                                         throw new ArgumentOutOfRangeException ("value");
146                                 }
147                                 
148                                 ViewState["TextAlign"] = value;
149                         }
150                 }
151
152                 [Themeable (false)]
153                 [DefaultValue ("")]
154                 [WebSysDescription ("")]
155                 [WebCategoryAttribute ("Behavior")]
156                 public virtual string ValidationGroup {
157                         get { return ViewState.GetString ("ValidationGroup", String.Empty); }
158                         set { ViewState["ValidationGroup"] = value; }
159                 }
160
161                 static readonly object EventCheckedChanged = new object ();
162                 [WebSysDescription ("")]
163                 [WebCategory ("Action")]
164                 public event EventHandler CheckedChanged  {
165                         add { Events.AddHandler (EventCheckedChanged, value); }
166                         remove { Events.RemoveHandler (EventCheckedChanged, value); }
167                 }
168
169                 protected virtual void OnCheckedChanged (EventArgs e)
170                 {
171                         EventHandler handler = (EventHandler)Events[EventCheckedChanged];
172                         
173                         if (handler != null)
174                                 handler (this, e);
175                 }
176
177                 internal virtual string NameAttribute {
178                         get { return (this.UniqueID); }
179                 }
180                 
181                 protected override void LoadViewState (object savedState)
182                 {
183                         if (savedState == null) {
184                                 base.LoadViewState (null);
185                                 return;
186                         }
187
188                         Triplet saved = (Triplet) savedState;
189                         base.LoadViewState (saved.First);
190
191                         if (saved.Second != null) {
192                                 if (inputAttributesState == null) {
193                                         inputAttributesState = new StateBag(true);
194                                         inputAttributesState.TrackViewState ();
195                                 }
196                                 inputAttributesState.LoadViewState (saved.Second);
197                         }
198
199                         if (saved.Third != null) {
200                                 if (labelAttributesState == null) {
201                                         labelAttributesState = new StateBag(true);
202                                         labelAttributesState.TrackViewState ();
203                                 }
204                                 labelAttributesState.LoadViewState (saved.Third);
205                         }
206                 }
207
208                 protected override object SaveViewState ()
209                 {
210                         object baseView = base.SaveViewState ();
211                         object inputAttrView = null;
212                         object labelAttrView = null;
213
214                         if (inputAttributesState != null)
215                                 inputAttrView = inputAttributesState.SaveViewState ();
216
217                         if (labelAttributesState != null)
218                                 labelAttrView = labelAttributesState.SaveViewState ();
219
220                         if (baseView == null && inputAttrView == null && labelAttrView == null)
221                                 return null;
222
223                         return new Triplet (baseView, inputAttrView, labelAttrView);            
224                 }
225
226                 protected override void TrackViewState ()
227                 {
228                         base.TrackViewState();
229                         if (inputAttributesState != null)
230                                 inputAttributesState.TrackViewState ();
231                         if (labelAttributesState != null)
232                                 labelAttributesState.TrackViewState ();
233                 }
234
235                 protected internal override void OnPreRender (EventArgs e)
236                 {
237                         base.OnPreRender (e);
238                         Page page = Page;
239                         
240                         if (page != null && IsEnabled) {
241                                 page.RegisterRequiresPostBack (this);
242                                 page.RegisterEnabledControl (this);
243                         }
244                 }
245
246                 static bool IsInputOrCommonAttr (string attname)
247                 {
248                         attname = attname.ToUpper (Helpers.InvariantCulture);
249                         switch (attname) {
250                                 case "VALUE":
251                                 case "CHECKED":
252                                 case "SIZE":
253                                 case "MAXLENGTH":
254                                 case "SRC":
255                                 case "ALT":
256                                 case "USEMAP":
257                                 case "DISABLED":
258                                 case "READONLY":
259                                 case "ACCEPT":
260                                 case "ACCESSKEY":
261                                 case "TABINDEX":
262                                 case "ONFOCUS":
263                                 case "ONBLUR":
264                                 case "ONSELECT":
265                                 case "ONCHANGE":
266                                 case "ONCLICK":
267                                 case "ONDBLCLICK":
268                                 case "ONMOUSEDOWN":
269                                 case "ONMOUSEUP":
270                                 case "ONMOUSEOVER":
271                                 case "ONMOUSEMOVE":
272                                 case "ONMOUSEOUT":
273                                 case "ONKEYPRESS":
274                                 case "ONKEYDOWN":
275                                 case "ONKEYUP":
276                                         return true;
277                                 default:
278                                         return false;
279                         }
280                 }
281
282                 bool AddAttributesForSpan (HtmlTextWriter writer)
283                 {
284                         if (HasAttributes) {
285                                 AttributeCollection attributes = Attributes;
286                                 ICollection k = attributes.Keys;
287                                 string [] keys = new string [k.Count];
288                                 k.CopyTo (keys, 0);
289                                 foreach (string key in keys) {
290                                         if (!IsInputOrCommonAttr (key))
291                                                 continue;
292                                         if (common_attrs == null)
293                                                 common_attrs = new AttributeCollection (new StateBag ());
294                                         common_attrs [key] = Attributes [key];
295                                         attributes.Remove (key);
296                                 }
297                         
298                                 if (attributes.Count > 0) {
299                                         attributes.AddAttributes (writer);
300                                         return true;
301                                 }
302                         }
303                         
304                         return false;
305                 }
306
307                 protected internal override void Render (HtmlTextWriter w)
308                 {
309                         Page page = Page;
310                         if (page != null) {
311                                 page.VerifyRenderingInServerForm (this);
312                                 page.ClientScript.RegisterForEventValidation (UniqueID);
313                         }
314                         
315                         bool need_span = ControlStyleCreated && !ControlStyle.IsEmpty;
316                         bool enabled = IsEnabled;
317                         if (!enabled) {
318 #if NET_4_0
319                                 if (!RenderingCompatibilityLessThan40)
320                                         ControlStyle.PrependCssClass (DisabledCssClass);
321                                 else
322 #endif
323                                         w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
324                                 need_span = true;
325                         }
326
327                         if (need_span) {
328                                 AddDisplayStyleAttribute (w);
329                                 ControlStyle.AddAttributesToRender (w, this);
330                         }
331                         
332                         string tt = ToolTip;
333                         if (tt != null && tt.Length > 0){
334                                 w.AddAttribute ("title", tt);
335                                 need_span = true;
336                         }
337
338                         if (HasAttributes && AddAttributesForSpan (w))
339                                 need_span = true;
340                         
341                         if (need_span)
342                                 w.RenderBeginTag (HtmlTextWriterTag.Span);
343
344                         TextAlign align = TextAlign;
345                         if (align == TextAlign.Right) {
346                                 RenderInput (w, enabled);
347                                 RenderLabel (w);
348                         } else {
349                                 RenderLabel (w);
350                                 RenderInput (w, enabled);
351                         }
352
353                         if (need_span)
354                                 w.RenderEndTag ();
355                 }
356
357                 void RenderInput (HtmlTextWriter w, bool enabled)
358                 {
359                         if (ClientID != null && ClientID.Length > 0)
360                                 w.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
361                         w.AddAttribute (HtmlTextWriterAttribute.Type, render_type);
362                         string nameAttr = NameAttribute;
363                         if (nameAttr != null && nameAttr.Length > 0)
364                                 w.AddAttribute (HtmlTextWriterAttribute.Name, nameAttr);
365                         InternalAddAttributesToRender (w, enabled);
366                         AddAttributesToRender (w);
367                         
368                         if (Checked)
369                                 w.AddAttribute (HtmlTextWriterAttribute.Checked, "checked", false);
370
371                         if (AutoPostBack) {
372                                 Page page = Page;
373                                 string onclick = page != null ? page.ClientScript.GetPostBackEventReference (GetPostBackOptions (), true) : String.Empty;
374                                 onclick = String.Concat ("setTimeout('", onclick.Replace ("\\", "\\\\").Replace ("'", "\\'"), "', 0)");
375                                 w.AddAttribute (HtmlTextWriterAttribute.Onclick, BuildScriptAttribute ("onclick", onclick));
376                         }
377
378                         if (AccessKey.Length > 0)
379                                 w.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
380
381                         if (TabIndex != 0)
382                                 w.AddAttribute (HtmlTextWriterAttribute.Tabindex,
383                                                          TabIndex.ToString (NumberFormatInfo.InvariantInfo));
384
385                         if (common_attrs != null)
386                                 common_attrs.AddAttributes (w);
387
388                         if (inputAttributes != null)
389                                 inputAttributes.AddAttributes (w);
390                         
391                         w.RenderBeginTag (HtmlTextWriterTag.Input);
392                         w.RenderEndTag ();
393                 }
394
395                 void RenderLabel (HtmlTextWriter w)
396                 {
397                         string text = Text;
398                         if (text.Length > 0) {
399                                 if (labelAttributes != null)
400                                         labelAttributes.AddAttributes (w);
401                                 w.AddAttribute (HtmlTextWriterAttribute.For, ClientID);
402                                 w.RenderBeginTag (HtmlTextWriterTag.Label);
403                                 w.Write (text);
404                                 w.RenderEndTag ();
405                         }
406                 }
407
408                 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection)
409                 {
410                         if (!IsEnabled)
411                                 return false;
412
413                         string postedValue = postCollection[postDataKey];
414                         bool postedBool = ((postedValue != null) &&
415                                            (postedValue.Length > 0));
416                         
417                         if (Checked != postedBool) {
418                                 Checked = postedBool;
419                                 return (true);
420                         }
421
422                         return (false);
423                 }
424
425                 protected virtual void RaisePostDataChangedEvent ()
426                 {
427                         ValidateEvent (UniqueID, String.Empty);
428                         if (CausesValidation) {
429                                 Page page = Page;
430                                 if (page != null)
431                                         page.Validate (ValidationGroup);
432                         }
433                         
434                         OnCheckedChanged (EventArgs.Empty);
435                 }
436
437                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
438                 {
439                         return LoadPostData (postDataKey, postCollection);
440                 }
441                 
442                 void IPostBackDataHandler.RaisePostDataChangedEvent ()
443                 {
444                         RaisePostDataChangedEvent ();
445                 }
446
447                 PostBackOptions GetPostBackOptions ()
448                 {
449                         PostBackOptions options = new PostBackOptions (this);
450                         options.ActionUrl = null;
451                         options.ValidationGroup = null;
452                         options.Argument = String.Empty;
453                         options.RequiresJavaScriptProtocol = false;
454                         options.ClientSubmit = true;
455
456                         Page page = Page;
457                         options.PerformValidation = CausesValidation && page != null && page.AreValidatorsUplevel (ValidationGroup);
458                         if (options.PerformValidation)
459                                 options.ValidationGroup = ValidationGroup;
460
461                         return options;
462                 }
463
464                 protected override void AddAttributesToRender (HtmlTextWriter writer)
465                 {
466                 }
467
468                 internal virtual void InternalAddAttributesToRender (HtmlTextWriter w, bool enabled)
469                 {
470                         if (!enabled)
471                                 w.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
472                 }
473         }
474 }