svn path=/branches/mono-1-1-9/mcs/; revision=51206
[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.Web.UI;
30 using System.Collections.Specialized;
31 using System.ComponentModel;
32
33 namespace System.Web.UI.WebControls {
34         [Designer ("System.Web.UI.Design.WebControls.CheckBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
35         [DataBindingHandler ("System.Web.UI.Design.TextDataBindingHandler, " + Consts.AssemblySystem_Design)]
36         [DefaultEvent ("CheckedChanged")]
37         [DefaultProperty ("Text")]
38 #if NET_2_0
39         [ControlValueProperty ("Checked", null)]
40 #endif          
41         public class CheckBox : WebControl, IPostBackDataHandler
42 #if NET_2_0
43         , ICheckBoxControl
44 #endif
45         {
46                 string render_type;
47
48 #if NET_2_0
49                 AttributeCollection inputAttributes;
50                 StateBag inputAttributesState;
51                 AttributeCollection labelAttributes;
52                 StateBag labelAttributesState;
53 #endif
54                 
55                 public CheckBox () : base (HtmlTextWriterTag.Input)
56                 {
57                         render_type = "checkbox";
58                 }
59
60                 internal CheckBox (string render_type) : base (HtmlTextWriterTag.Input)
61                 {
62                         this.render_type = render_type;
63                 }
64
65                 [DefaultValue (false)]
66 #if NET_2_0
67                 [Themeable (false)]
68 #endif          
69                 [WebSysDescription ("")]
70                 [WebCategory ("Behavior")]
71                 public virtual bool AutoPostBack 
72                 {
73                         get {
74                                 return (ViewState.GetBool ("AutoPostBack",
75                                                            false));
76                         }
77                         set {
78                                 ViewState["AutoPostBack"] = value;
79                         }
80                 }
81
82 #if NET_2_0
83                 [DefaultValue (false)]
84                 [Themeable (false)]
85                 [MonoTODO]
86                 [WebSysDescription ("")]
87                 [WebCategory ("Behavior")]
88                 public virtual bool CausesValidation 
89                 {
90                         get { return ViewState.GetBool ("CausesValidation", false); }
91                         set { ViewState ["CausesValidation"] = value; }
92                 }
93 #endif          
94                 
95
96                 [DefaultValue (false)]
97 #if NET_2_0
98                 [Bindable (true, BindingDirection.TwoWay)]
99                 [Themeable (false)]
100 #else           
101                 [Bindable (true)]
102 #endif          
103                 [WebSysDescription ("")]
104                 [WebCategory ("Behavior")]
105                 public virtual bool Checked 
106                 {
107                         get {
108                                 return (ViewState.GetBool ("Checked", false));
109                         }
110                         set {
111                                 ViewState["Checked"] = value;
112                         }
113                 }
114
115 #if NET_2_0
116                 [Browsable (false)]
117                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
118                 public AttributeCollection InputAttributes 
119                 {
120                         get {
121                                 if (inputAttributes == null) {
122                                         if (inputAttributesState == null) {
123                                                 inputAttributesState = new StateBag (true);
124                                                 if (IsTrackingViewState)
125                                                         inputAttributesState.TrackViewState();
126                                         }
127                                         inputAttributes = new AttributeCollection (inputAttributesState);
128                                 }
129                                 return inputAttributes;
130                         }
131                 }
132
133                 [Browsable (false)]
134                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
135                 public AttributeCollection LabelAttributes
136                 {
137                         get {
138                                 if (labelAttributes == null) {
139                                         if (labelAttributesState == null) {
140                                                 labelAttributesState = new StateBag (true);
141                                                 if (IsTrackingViewState)
142                                                         labelAttributesState.TrackViewState();
143                                         }
144                                         labelAttributes = new AttributeCollection (labelAttributesState);
145                                 }
146                                 return labelAttributes;
147                         }
148                 }
149 #endif          
150
151                 [DefaultValue ("")]
152                 [Bindable (true)]
153 #if NET_2_0
154                 [Localizable (true)]
155 #endif          
156                 [WebSysDescription ("")]
157                 [WebCategory ("Appearance")]
158                 public virtual string Text 
159                 {
160                         get {
161                                 return (ViewState.GetString ("Text",
162                                                              String.Empty));
163                         }
164                         set {
165                                 ViewState["Text"] = value;
166                         }
167                 }
168
169                 [DefaultValue (TextAlign.Right)]
170 #if ONLY_1_1
171                 [Bindable (true)]
172 #endif          
173                 [WebSysDescription ("")]
174                 [WebCategory ("Appearance")]
175                 public virtual TextAlign TextAlign
176                 {
177                         get {
178                                 object o = ViewState["TextAlign"];
179
180                                 if (o == null) {
181                                         return (TextAlign.Right);
182                                 } else {
183                                         return ((TextAlign)o);
184                                 }
185                         }
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 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                 protected override void AddAttributesToRender (HtmlTextWriter w)
238                 {
239                         if (Page != null)
240                                 Page.VerifyRenderingInServerForm (this);
241
242                         /* This is a nasty kludge to avoid rendering
243                          * "style" and the ControlStyle in checkboxes
244                          * (we use a surrounding <span> instead), but
245                          * still pass the unit test that shows the
246                          * style being rendered in multiple calls to
247                          * Render () (which means we can't just delete
248                          * Attributes["style"] or ControlStyle.Reset()
249                          * in Render ())
250                          */
251                         string css_style = Attributes ["style"];
252                         if (css_style != null) {
253                                 Attributes.Remove ("style");
254                         }
255
256                         Style style = new Style ();
257                         if (ControlStyleCreated) {
258                                 style.CopyFrom (ControlStyle);
259                                 ControlStyle.Reset ();
260                         }
261                         
262                         base.AddAttributesToRender (w);
263
264                         if (css_style != null) {
265                                 Attributes ["style"] = css_style;
266                         }
267                         if (!style.IsEmpty) {
268                                 ApplyStyle (style);
269                         }
270                         
271                         InternalAddAttributesToRender (w);
272                         
273                         w.AddAttribute (HtmlTextWriterAttribute.Type,
274                                         render_type);
275                         w.AddAttribute (HtmlTextWriterAttribute.Name,
276                                         NameAttribute);
277                         
278                         if (AutoPostBack) {
279                                 w.AddAttribute (HtmlTextWriterAttribute.Onclick, Page.ClientScript.GetPostBackClientHyperlink (this, ""));
280                         }
281
282                         if (Checked) {
283                                 w.AddAttribute (HtmlTextWriterAttribute.Checked, "checked");
284                         }
285                 }
286
287 #if NET_2_0
288                 protected override void LoadViewState (object savedState)
289                 {
290                         if (savedState == null) {
291                                 base.LoadViewState (null);
292                                 return;
293                         }
294
295                         Triplet saved = (Triplet) savedState;
296                         base.LoadViewState (saved.First);
297
298                         if (saved.Second != null) {
299                                 if (inputAttributesState == null) {
300                                         inputAttributesState = new StateBag(true);
301                                         inputAttributesState.TrackViewState ();
302                                 }
303                                 inputAttributesState.LoadViewState (saved.Second);
304                         }
305
306                         if (saved.Third != null) {
307                                 if (labelAttributesState == null) {
308                                         labelAttributesState = new StateBag(true);
309                                         labelAttributesState.TrackViewState ();
310                                 }
311                                 labelAttributesState.LoadViewState (saved.Third);
312                         }
313                 }
314
315                 protected override object SaveViewState ()
316                 {
317                         object baseView = base.SaveViewState ();
318                         object inputAttrView = null;
319                         object labelAttrView = null;
320
321                         if (inputAttributesState != null)
322                                 inputAttrView = inputAttributesState.SaveViewState ();
323
324                         if (labelAttributesState != null)
325                                 labelAttrView = labelAttributesState.SaveViewState ();
326
327                         if (baseView == null && inputAttrView == null && labelAttrView == null)
328                                 return null;
329
330                         return new Triplet (baseView, inputAttrView, labelAttrView);            
331                 }
332
333                 protected override void TrackViewState ()
334                 {
335                         base.TrackViewState();
336                         if (inputAttributesState != null)
337                                 inputAttributesState.TrackViewState ();
338                         if (labelAttributesState != null)
339                                 labelAttributesState.TrackViewState ();
340                 }
341 #endif          
342
343 #if NET_2_0
344                 protected internal
345 #else           
346                 protected
347 #endif          
348                 override void OnPreRender (EventArgs e)
349                 {
350                         base.OnPreRender (e);
351
352                         if (Page != null) {
353                                 Page.RegisterRequiresPostBack (this);
354                         }
355                 }
356
357                 void RenderLabel (HtmlTextWriter w)
358                 {
359                         if (Text.Length > 0) {
360 #if NET_2_0
361                                 if (labelAttributes != null)
362                                         labelAttributes.AddAttributes (w);
363 #endif
364                                 w.AddAttribute (HtmlTextWriterAttribute.For, ClientID);
365                                 w.RenderBeginTag (HtmlTextWriterTag.Label);
366                                 w.Write (this.Text);
367                                 w.RenderEndTag ();
368                         }
369                 }
370                 
371 #if NET_2_0
372                 protected internal
373 #else           
374                 protected
375 #endif          
376                 override void Render (HtmlTextWriter w)
377                 {
378                         bool control_style = false;
379                         
380                         /* Need to apply the styles around the text
381                          * label too
382                          */
383                         if (ControlStyleCreated) {
384                                 ControlStyle.AddAttributesToRender (w, this);
385                                 w.RenderBeginTag (HtmlTextWriterTag.Span);
386
387                                 control_style = true;
388                         } else if (Attributes ["style"] != null) {
389                                 /* TODO: check if this or the style
390                                  * has precendence, or if they should
391                                  * be merged (if I can figure out how
392                                  * to turn a CssStyleCollection into a
393                                  * Style)
394                                  */
395                                 CssStyleCollection style = Attributes.CssStyle;
396                                 
397                                 w.AddAttribute (HtmlTextWriterAttribute.Style,
398                                                 style.Value);
399                                 w.RenderBeginTag (HtmlTextWriterTag.Span);
400
401                                 control_style = true;
402                         }
403                         
404                         if (TextAlign == TextAlign.Left) {
405                                 RenderLabel (w);
406                                 base.Render (w);
407                         } else {
408                                 base.Render (w);
409                                 RenderLabel (w);
410                         }
411
412                         if (control_style) {
413                                 w.RenderEndTag ();
414                         }
415                 }
416
417 #if NET_2_0
418                 protected virtual
419 #endif
420                 bool LoadPostData (string postDataKey, NameValueCollection postCollection)
421                 {
422                         string postedValue = postCollection[postDataKey];
423                         bool postedBool = ((postedValue != null) &&
424                                            (postedValue.Length > 0));
425                         
426                         if (Checked != postedBool) {
427                                 Checked = postedBool;
428                                 return (true);
429                         }
430
431                         return (false);
432                 }
433
434 #if NET_2_0
435                 protected virtual
436 #endif
437                 void RaisePostDataChangedEvent ()
438                 {
439 #if NET_2_0
440                         if (CausesValidation)
441                                 Page.Validate (ValidationGroup);
442 #endif
443                         OnCheckedChanged (EventArgs.Empty);
444                 }
445
446                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
447                 {
448                         return LoadPostData (postDataKey, postCollection);
449                 }
450                 
451                 void IPostBackDataHandler.RaisePostDataChangedEvent ()
452                 {
453                         RaisePostDataChangedEvent ();
454                 }
455
456                 internal virtual void InternalAddAttributesToRender (HtmlTextWriter w)
457                 {
458                 }
459         }
460 }